xref: /csrg-svn/sys/netinet/ip_output.c (revision 5061)
1 #define IMPLOOP
2 /*	ip_output.c	1.19	81/11/24	*/
3 
4 #include "../h/param.h"
5 #include "../h/mbuf.h"
6 #include "../h/mtpr.h"
7 #include "../h/socket.h"
8 #include "../h/socketvar.h"
9 #include "../net/inet.h"
10 #include "../net/inet_systm.h"
11 #include "../net/imp.h"
12 #include "../net/ip.h"
13 #include "../net/ip_var.h"
14 
15 ip_output(m)
16 	struct mbuf *m;
17 {
18 	register struct ip *ip = mtod(m, struct ip *);
19 	int len, hlen = ip->ip_hl << 2, off;
20 
21 COUNT(IP_OUTPUT);
22 	/*
23 	 * Fill in IP header.
24 	 */
25 	ip->ip_v = IPVERSION;
26 	ip->ip_hl = hlen >> 2;
27 	ip->ip_off &= IP_DF;
28 	ip->ip_id = ip_id++;
29 
30 	/*
31 	 * If small enough for interface, can just send directly.
32 	 */
33 	if (ip->ip_len <= MTU) {
34 		ip_send(ip);
35 		return;
36 	}
37 
38 	/*
39 	 * Too large for interface; fragment if possible.
40 	 * Must be able to put at least 8 bytes per fragment.
41 	 */
42 	if (ip->ip_off & IP_DF)
43 		goto bad;
44 	len = (MTU-hlen) &~ 7;
45 	if (len < 8)
46 		goto bad;
47 
48 	/*
49 	 * Discard IP header from logical mbuf for m_copy's sake.
50 	 * Loop through length of segment, make a copy of each
51 	 * part and output.
52 	 */
53 	m->m_len -= sizeof (struct ip);
54 	m->m_off += sizeof (struct ip);
55 	for (off = 0; off < ip->ip_len; off += len) {
56 		struct mbuf *mh = m_get(0);
57 		struct ip *mhip;
58 
59 		if (mh == 0)
60 			goto bad;
61 		mh->m_off = MMAXOFF - hlen;
62 		mhip = mtod(mh, struct ip *);
63 		*mhip = *ip;
64 		if (hlen > sizeof (struct ip)) {
65 			int olen = ip_optcopy(ip, mhip, off);
66 			mh->m_len = sizeof (struct ip) + olen;
67 		} else
68 			mh->m_len = sizeof (struct ip);
69 		mhip->ip_off = off;
70 		if (off + len >= ip->ip_len)
71 			mhip->ip_len = ip->ip_len - off;
72 		else {
73 			mhip->ip_len = len;
74 			mhip->ip_off |= IP_MF;
75 		}
76 		mhip->ip_len += sizeof (struct ip);
77 		mh->m_next = m_copy(m, off, len);
78 		if (mh->m_next == 0) {
79 			(void) m_free(mh);
80 			goto bad;
81 		}
82 		ip_send(mhip);
83 	}
84 bad:
85 	m_freem(m);
86 }
87 
88 /*
89  * Copy options from ip to jp.
90  * If off is 0 all options are copied
91  * otherwise copy selectively.
92  */
93 ip_optcopy(ip, jp, off)
94 	struct ip *ip, *jp;
95 	int off;
96 {
97 	register u_char *cp, *dp;
98 	int opt, optlen, cnt;
99 
100 COUNT(IP_OPTCOPY);
101 	cp = (u_char *)(ip + 1);
102 	dp = (u_char *)(jp + 1);
103 	cnt = (ip->ip_hl << 2) - sizeof (struct ip);
104 	for (; cnt > 0; cnt -= optlen, cp += optlen) {
105 		opt = cp[0];
106 		if (opt == IPOPT_EOL)
107 			break;
108 		if (opt == IPOPT_NOP)
109 			optlen = 1;
110 		else
111 			optlen = cp[1];
112 		if (optlen > cnt)			/* XXX */
113 			optlen = cnt;			/* XXX */
114 		if (off == 0 || IPOPT_COPIED(opt)) {
115 			bcopy((caddr_t)cp, (caddr_t)dp, (unsigned)optlen);
116 			dp += optlen;
117 		}
118 	}
119 	for (optlen = dp - (u_char *)(jp+1); optlen & 0x3; optlen++)
120 		*dp++ = IPOPT_EOL;
121 	return (optlen);
122 }
123 
124 /* REST OF CODE HERE IS GARBAGE */
125 
126 ip_send(ip)
127 	register struct ip *ip;
128 {
129 	register struct mbuf *m;
130 	register struct imp *l;
131 	int hlen = ip->ip_hl << 2;
132 	int s;
133 COUNT(IP_SEND);
134 
135 	m = dtom(ip);
136 	l = (struct imp *)(mtod(m, caddr_t) - L1822);
137 	l->i_shost = ip->ip_src.s_host;
138 	l->i_dhost = ip->ip_dst.s_host;
139 	l->i_type = IPTYPE;
140 	ip->ip_sum = 0;
141 	ip->ip_len = htons((u_short)ip->ip_len);
142 	ip->ip_id = htons(ip->ip_id);
143 	ip->ip_off = htons((u_short)ip->ip_off);
144 	ip->ip_sum = inet_cksum(m, hlen);
145 	m->m_off -= L1822;
146 	m->m_len += L1822;
147 	m->m_act = NULL;
148 #ifndef IMPLOOP
149 	s = splimp();
150 	if (imp_stat.outq_head != NULL)
151 		imp_stat.outq_tail->m_act = m;
152 	else
153 		imp_stat.outq_head = m;
154 	imp_stat.outq_tail = m;
155 	splx(s);
156 	if (!imp_stat.outactive)
157 		enstart(0);
158 #else
159 	if (imp_stat.inq_head != NULL)
160 		imp_stat.inq_tail->m_act = m;
161 	else
162 		imp_stat.inq_head = m;
163 	imp_stat.inq_tail = m;
164 	setsoftnet();
165 #endif IMPLOOP
166 }
167 
168 /* END GARBAGE */
169