xref: /original-bsd/sys/netinet/ip_output.c (revision c0f053f7)
1 /*
2  * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  *
17  *	@(#)ip_output.c	7.15 (Berkeley) 04/25/89
18  */
19 
20 #include "param.h"
21 #include "malloc.h"
22 #include "mbuf.h"
23 #include "errno.h"
24 #include "protosw.h"
25 #include "socket.h"
26 #include "socketvar.h"
27 
28 #include "../net/if.h"
29 #include "../net/route.h"
30 
31 #include "in.h"
32 #include "in_pcb.h"
33 #include "in_systm.h"
34 #include "in_var.h"
35 #include "ip.h"
36 #include "ip_var.h"
37 
38 #ifdef vax
39 #include "machine/mtpr.h"
40 #endif
41 
42 struct mbuf *ip_insertoptions();
43 
44 /*
45  * IP output.  The packet in mbuf chain m contains a skeletal IP
46  * header (with len, off, ttl, proto, tos, src, dst).
47  * The mbuf chain containing the packet will be freed.
48  * The mbuf opt, if present, will not be freed.
49  */
50 ip_output(m0, opt, ro, flags)
51 	struct mbuf *m0;
52 	struct mbuf *opt;
53 	struct route *ro;
54 	int flags;
55 {
56 	register struct ip *ip, *mhip;
57 	register struct ifnet *ifp;
58 	register struct mbuf *m = m0;
59 	register int hlen = sizeof (struct ip);
60 	int len, off, error = 0;
61 	struct route iproute;
62 	struct sockaddr_in *dst;
63 
64 if ((m->m_flags & M_PKTHDR) == 0)
65 panic("ip_output no HDR");
66 	if (opt) {
67 		m = ip_insertoptions(m, opt, &len);
68 		hlen = len;
69 	}
70 	ip = mtod(m, struct ip *);
71 	/*
72 	 * Fill in IP header.
73 	 */
74 	if ((flags & IP_FORWARDING) == 0) {
75 		ip->ip_v = IPVERSION;
76 		ip->ip_off &= IP_DF;
77 		ip->ip_id = htons(ip_id++);
78 		ip->ip_hl = hlen >> 2;
79 	} else
80 		hlen = ip->ip_hl << 2;
81 
82 	/*
83 	 * Route packet.
84 	 */
85 	if (ro == 0) {
86 		ro = &iproute;
87 		bzero((caddr_t)ro, sizeof (*ro));
88 	}
89 	dst = (struct sockaddr_in *)&ro->ro_dst;
90 	/*
91 	 * If there is a cached route,
92 	 * check that it is to the same destination
93 	 * and is still up.  If not, free it and try again.
94 	 */
95 	if (ro->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 ||
96 	   dst->sin_addr.s_addr != ip->ip_dst.s_addr)) {
97 		RTFREE(ro->ro_rt);
98 		ro->ro_rt = (struct rtentry *)0;
99 	}
100 	if (ro->ro_rt == 0) {
101 		dst->sin_family = AF_INET;
102 		dst->sin_len = sizeof(*dst);
103 		dst->sin_addr = ip->ip_dst;
104 	}
105 	/*
106 	 * If routing to interface only,
107 	 * short circuit routing lookup.
108 	 */
109 	if (flags & IP_ROUTETOIF) {
110 		struct in_ifaddr *ia;
111 
112 		ia = (struct in_ifaddr *)ifa_ifwithdstaddr((struct sockaddr *)dst);
113 		if (ia == 0)
114 			ia = in_iaonnetof(in_netof(ip->ip_dst));
115 		if (ia == 0) {
116 			error = ENETUNREACH;
117 			goto bad;
118 		}
119 		ifp = ia->ia_ifp;
120 	} else {
121 		if (ro->ro_rt == 0)
122 			rtalloc(ro);
123 		if (ro->ro_rt == 0 || (ifp = ro->ro_rt->rt_ifp) == 0) {
124 			if (in_localaddr(ip->ip_dst))
125 				error = EHOSTUNREACH;
126 			else
127 				error = ENETUNREACH;
128 			goto bad;
129 		}
130 		ro->ro_rt->rt_use++;
131 		if (ro->ro_rt->rt_flags & RTF_GATEWAY)
132 			dst = (struct sockaddr_in *)ro->ro_rt->rt_gateway;
133 	}
134 #ifndef notdef
135 	/*
136 	 * If source address not specified yet, use address
137 	 * of outgoing interface.
138 	 */
139 	if (ip->ip_src.s_addr == INADDR_ANY) {
140 		register struct in_ifaddr *ia;
141 
142 		for (ia = in_ifaddr; ia; ia = ia->ia_next)
143 			if (ia->ia_ifp == ifp) {
144 				ip->ip_src = IA_SIN(ia)->sin_addr;
145 				break;
146 			}
147 	}
148 #endif
149 	/*
150 	 * Look for broadcast address and
151 	 * and verify user is allowed to send
152 	 * such a packet.
153 	 */
154 	if (in_broadcast(dst->sin_addr)) {
155 		if ((ifp->if_flags & IFF_BROADCAST) == 0) {
156 			error = EADDRNOTAVAIL;
157 			goto bad;
158 		}
159 		if ((flags & IP_ALLOWBROADCAST) == 0) {
160 			error = EACCES;
161 			goto bad;
162 		}
163 		/* don't allow broadcast messages to be fragmented */
164 		if (ip->ip_len > ifp->if_mtu) {
165 			error = EMSGSIZE;
166 			goto bad;
167 		}
168 		m->m_flags |= M_BCAST;
169 	}
170 
171 	/*
172 	 * If small enough for interface, can just send directly.
173 	 */
174 	if (ip->ip_len <= ifp->if_mtu) {
175 		ip->ip_len = htons((u_short)ip->ip_len);
176 		ip->ip_off = htons((u_short)ip->ip_off);
177 		ip->ip_sum = 0;
178 		ip->ip_sum = in_cksum(m, hlen);
179 		error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst);
180 		goto done;
181 	}
182 
183 	/*
184 	 * Too large for interface; fragment if possible.
185 	 * Must be able to put at least 8 bytes per fragment.
186 	 */
187 	if (ip->ip_off & IP_DF) {
188 		error = EMSGSIZE;
189 		goto bad;
190 	}
191 	len = (ifp->if_mtu - hlen) &~ 7;
192 	if (len < 8) {
193 		error = EMSGSIZE;
194 		goto bad;
195 	}
196 
197     {
198 	int mhlen, firstlen = len;
199 	struct mbuf **mnext = &m->m_nextpkt;
200 
201 	/*
202 	 * Loop through length of segment after first fragment,
203 	 * make new header and copy data of each part and link onto chain.
204 	 */
205 	m0 = m;
206 	mhlen = sizeof (struct ip);
207 	for (off = hlen + len; off < ip->ip_len; off += len) {
208 		MGETHDR(m, M_DONTWAIT, MT_HEADER);
209 		if (m == 0) {
210 			error = ENOBUFS;
211 			goto sendorfree;
212 		}
213 		m->m_data += max_linkhdr;
214 		mhip = mtod(m, struct ip *);
215 		*mhip = *ip;
216 		if (hlen > sizeof (struct ip)) {
217 			mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip);
218 			mhip->ip_hl = mhlen >> 2;
219 		}
220 		m->m_len = mhlen;
221 		mhip->ip_off = ((off - hlen) >> 3) + (ip->ip_off & ~IP_MF);
222 		if (ip->ip_off & IP_MF)
223 			mhip->ip_off |= IP_MF;
224 		if (off + len >= ip->ip_len)
225 			len = ip->ip_len - off;
226 		else
227 			mhip->ip_off |= IP_MF;
228 		mhip->ip_len = htons((u_short)(len + mhlen));
229 		m->m_next = m_copy(m0, off, len);
230 		if (m->m_next == 0) {
231 			error = ENOBUFS;	/* ??? */
232 			goto sendorfree;
233 		}
234 		m->m_pkthdr.len = mhlen + len;
235 		m->m_pkthdr.rcvif = (struct ifnet *)0;
236 		mhip->ip_off = htons((u_short)mhip->ip_off);
237 		mhip->ip_sum = 0;
238 		mhip->ip_sum = in_cksum(m, mhlen);
239 		*mnext = m;
240 		mnext = &m->m_nextpkt;
241 	}
242 	/*
243 	 * Update first fragment by trimming what's been copied out
244 	 * and updating header, then send each fragment (in order).
245 	 */
246 	m_adj(m0, hlen + firstlen - ip->ip_len);
247 	m->m_pkthdr.len = hlen + firstlen;
248 	ip->ip_len = htons((u_short)m->m_pkthdr.len);
249 	ip->ip_off = htons((u_short)(ip->ip_off | IP_MF));
250 	ip->ip_sum = 0;
251 	ip->ip_sum = in_cksum(m0, hlen);
252 sendorfree:
253 	for (m = m0; m; m = m0) {
254 		m0 = m->m_nextpkt;
255 		m->m_nextpkt = 0;
256 		if (error == 0)
257 			error = (*ifp->if_output)(ifp, m,
258 			    (struct sockaddr *)dst);
259 		else
260 			m_freem(m);
261 	}
262     }
263 done:
264 	if (ro == &iproute && (flags & IP_ROUTETOIF) == 0 && ro->ro_rt)
265 		RTFREE(ro->ro_rt);
266 	return (error);
267 bad:
268 	m_freem(m0);
269 	goto done;
270 }
271 
272 /*
273  * Insert IP options into preformed packet.
274  * Adjust IP destination as required for IP source routing,
275  * as indicated by a non-zero in_addr at the start of the options.
276  */
277 struct mbuf *
278 ip_insertoptions(m, opt, phlen)
279 	register struct mbuf *m;
280 	struct mbuf *opt;
281 	int *phlen;
282 {
283 	register struct ipoption *p = mtod(opt, struct ipoption *);
284 	struct mbuf *n;
285 	register struct ip *ip = mtod(m, struct ip *);
286 	unsigned optlen;
287 
288 	optlen = opt->m_len - sizeof(p->ipopt_dst);
289 	if (p->ipopt_dst.s_addr)
290 		ip->ip_dst = p->ipopt_dst;
291 	if (m->m_flags & M_EXT || m->m_data - optlen < m->m_pktdat) {
292 		MGETHDR(n, M_DONTWAIT, MT_HEADER);
293 		if (n == 0)
294 			return (m);
295 		n->m_pkthdr.len = m->m_pkthdr.len + optlen;
296 		m->m_len -= sizeof(struct ip);
297 		m->m_data += sizeof(struct ip);
298 		n->m_next = m;
299 		m = n;
300 		m->m_len = optlen + sizeof(struct ip);
301 		m->m_data += max_linkhdr;
302 		bcopy((caddr_t)ip, mtod(m, caddr_t), sizeof(struct ip));
303 	} else {
304 		m->m_data -= optlen;
305 		m->m_len += optlen;
306 		m->m_pkthdr.len += optlen;
307 		ovbcopy((caddr_t)ip, mtod(m, caddr_t), sizeof(struct ip));
308 	}
309 	ip = mtod(m, struct ip *);
310 	bcopy((caddr_t)p->ipopt_list, (caddr_t)(ip + 1), (unsigned)optlen);
311 	*phlen = sizeof(struct ip) + optlen;
312 	ip->ip_len += optlen;
313 	return (m);
314 }
315 
316 /*
317  * Copy options from ip to jp,
318  * omitting those not copied during fragmentation.
319  */
320 ip_optcopy(ip, jp)
321 	struct ip *ip, *jp;
322 {
323 	register u_char *cp, *dp;
324 	int opt, optlen, cnt;
325 
326 	cp = (u_char *)(ip + 1);
327 	dp = (u_char *)(jp + 1);
328 	cnt = (ip->ip_hl << 2) - sizeof (struct ip);
329 	for (; cnt > 0; cnt -= optlen, cp += optlen) {
330 		opt = cp[0];
331 		if (opt == IPOPT_EOL)
332 			break;
333 		if (opt == IPOPT_NOP)
334 			optlen = 1;
335 		else
336 			optlen = cp[IPOPT_OLEN];
337 		/* bogus lengths should have been caught by ip_dooptions */
338 		if (optlen > cnt)
339 			optlen = cnt;
340 		if (IPOPT_COPIED(opt)) {
341 			bcopy((caddr_t)cp, (caddr_t)dp, (unsigned)optlen);
342 			dp += optlen;
343 		}
344 	}
345 	for (optlen = dp - (u_char *)(jp+1); optlen & 0x3; optlen++)
346 		*dp++ = IPOPT_EOL;
347 	return (optlen);
348 }
349 
350 /*
351  * IP socket option processing.
352  */
353 ip_ctloutput(op, so, level, optname, m)
354 	int op;
355 	struct socket *so;
356 	int level, optname;
357 	struct mbuf **m;
358 {
359 	int error = 0;
360 	struct inpcb *inp = sotoinpcb(so);
361 
362 	if (level != IPPROTO_IP)
363 		error = EINVAL;
364 	else switch (op) {
365 
366 	case PRCO_SETOPT:
367 		switch (optname) {
368 		case IP_OPTIONS:
369 			return (ip_pcbopts(&inp->inp_options, *m));
370 
371 		default:
372 			error = EINVAL;
373 			break;
374 		}
375 		break;
376 
377 	case PRCO_GETOPT:
378 		switch (optname) {
379 		case IP_OPTIONS:
380 			*m = m_get(M_WAIT, MT_SOOPTS);
381 			if (inp->inp_options) {
382 				(*m)->m_len = inp->inp_options->m_len;
383 				bcopy(mtod(inp->inp_options, caddr_t),
384 				    mtod(*m, caddr_t), (unsigned)(*m)->m_len);
385 			} else
386 				(*m)->m_len = 0;
387 			break;
388 		default:
389 			error = EINVAL;
390 			break;
391 		}
392 		break;
393 	}
394 	if (op == PRCO_SETOPT && *m)
395 		(void)m_free(*m);
396 	return (error);
397 }
398 
399 /*
400  * Set up IP options in pcb for insertion in output packets.
401  * Store in mbuf with pointer in pcbopt, adding pseudo-option
402  * with destination address if source routed.
403  */
404 ip_pcbopts(pcbopt, m)
405 	struct mbuf **pcbopt;
406 	register struct mbuf *m;
407 {
408 	register cnt, optlen;
409 	register u_char *cp;
410 	u_char opt;
411 
412 	/* turn off any old options */
413 	if (*pcbopt)
414 		(void)m_free(*pcbopt);
415 	*pcbopt = 0;
416 	if (m == (struct mbuf *)0 || m->m_len == 0) {
417 		/*
418 		 * Only turning off any previous options.
419 		 */
420 		if (m)
421 			(void)m_free(m);
422 		return (0);
423 	}
424 
425 #ifndef	vax
426 	if (m->m_len % sizeof(long))
427 		goto bad;
428 #endif
429 	/*
430 	 * IP first-hop destination address will be stored before
431 	 * actual options; move other options back
432 	 * and clear it when none present.
433 	 */
434 	if (m->m_data + m->m_len + sizeof(struct in_addr) >= &m->m_dat[MLEN])
435 		goto bad;
436 	cnt = m->m_len;
437 	m->m_len += sizeof(struct in_addr);
438 	cp = mtod(m, u_char *) + sizeof(struct in_addr);
439 	ovbcopy(mtod(m, caddr_t), (caddr_t)cp, (unsigned)cnt);
440 	bzero(mtod(m, caddr_t), sizeof(struct in_addr));
441 
442 	for (; cnt > 0; cnt -= optlen, cp += optlen) {
443 		opt = cp[IPOPT_OPTVAL];
444 		if (opt == IPOPT_EOL)
445 			break;
446 		if (opt == IPOPT_NOP)
447 			optlen = 1;
448 		else {
449 			optlen = cp[IPOPT_OLEN];
450 			if (optlen <= IPOPT_OLEN || optlen > cnt)
451 				goto bad;
452 		}
453 		switch (opt) {
454 
455 		default:
456 			break;
457 
458 		case IPOPT_LSRR:
459 		case IPOPT_SSRR:
460 			/*
461 			 * user process specifies route as:
462 			 *	->A->B->C->D
463 			 * D must be our final destination (but we can't
464 			 * check that since we may not have connected yet).
465 			 * A is first hop destination, which doesn't appear in
466 			 * actual IP option, but is stored before the options.
467 			 */
468 			if (optlen < IPOPT_MINOFF - 1 + sizeof(struct in_addr))
469 				goto bad;
470 			m->m_len -= sizeof(struct in_addr);
471 			cnt -= sizeof(struct in_addr);
472 			optlen -= sizeof(struct in_addr);
473 			cp[IPOPT_OLEN] = optlen;
474 			/*
475 			 * Move first hop before start of options.
476 			 */
477 			bcopy((caddr_t)&cp[IPOPT_OFFSET+1], mtod(m, caddr_t),
478 			    sizeof(struct in_addr));
479 			/*
480 			 * Then copy rest of options back
481 			 * to close up the deleted entry.
482 			 */
483 			ovbcopy((caddr_t)(&cp[IPOPT_OFFSET+1] +
484 			    sizeof(struct in_addr)),
485 			    (caddr_t)&cp[IPOPT_OFFSET+1],
486 			    (unsigned)cnt + sizeof(struct in_addr));
487 			break;
488 		}
489 	}
490 	if (m->m_len > MAX_IPOPTLEN + sizeof(struct in_addr))
491 		goto bad;
492 	*pcbopt = m;
493 	return (0);
494 
495 bad:
496 	(void)m_free(m);
497 	return (EINVAL);
498 }
499