ip_input.c revision 1.72 1 /* $NetBSD: ip_input.c,v 1.72 1998/10/08 01:19:25 thorpej Exp $ */
2
3 /*
4 * Copyright (c) 1982, 1986, 1988, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 * @(#)ip_input.c 8.2 (Berkeley) 1/4/94
36 */
37
38 /*-
39 * Copyright (c) 1998 The NetBSD Foundation, Inc.
40 * All rights reserved.
41 *
42 * This code is derived from software contributed to The NetBSD Foundation
43 * by Public Access Networks Corporation ("Panix"). It was developed under
44 * contract to Panix by Eric Haszlakiewicz and Thor Lancelot Simon.
45 *
46 * Redistribution and use in source and binary forms, with or without
47 * modification, are permitted provided that the following conditions
48 * are met:
49 * 1. Redistributions of source code must retain the above copyright
50 * notice, this list of conditions and the following disclaimer.
51 * 2. Redistributions in binary form must reproduce the above copyright
52 * notice, this list of conditions and the following disclaimer in the
53 * documentation and/or other materials provided with the distribution.
54 * 3. All advertising materials mentioning features or use of this software
55 * must display the following acknowledgement:
56 * This product includes software developed by the NetBSD
57 * Foundation, Inc. and its contributors.
58 * 4. Neither the name of The NetBSD Foundation nor the names of its
59 * contributors may be used to endorse or promote products derived
60 * from this software without specific prior written permission.
61 *
62 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
63 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
64 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
65 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
66 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
67 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
68 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
69 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
70 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
71 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
72 * POSSIBILITY OF SUCH DAMAGE.
73 */
74
75 #include "opt_gateway.h"
76 #include "opt_pfil_hooks.h"
77 #include "opt_mrouting.h"
78
79 #include <sys/param.h>
80 #include <sys/systm.h>
81 #include <sys/malloc.h>
82 #include <sys/mbuf.h>
83 #include <sys/domain.h>
84 #include <sys/protosw.h>
85 #include <sys/socket.h>
86 #include <sys/socketvar.h>
87 #include <sys/errno.h>
88 #include <sys/time.h>
89 #include <sys/kernel.h>
90 #include <sys/proc.h>
91 #include <sys/pool.h>
92
93 #include <vm/vm.h>
94 #include <sys/sysctl.h>
95
96 #include <net/if.h>
97 #include <net/if_dl.h>
98 #include <net/route.h>
99 #include <net/pfil.h>
100
101 #include <netinet/in.h>
102 #include <netinet/in_systm.h>
103 #include <netinet/ip.h>
104 #include <netinet/in_pcb.h>
105 #include <netinet/in_var.h>
106 #include <netinet/ip_var.h>
107 #include <netinet/ip_icmp.h>
108
109 #ifndef IPFORWARDING
110 #ifdef GATEWAY
111 #define IPFORWARDING 1 /* forward IP packets not for us */
112 #else /* GATEWAY */
113 #define IPFORWARDING 0 /* don't forward IP packets not for us */
114 #endif /* GATEWAY */
115 #endif /* IPFORWARDING */
116 #ifndef IPSENDREDIRECTS
117 #define IPSENDREDIRECTS 1
118 #endif
119 #ifndef IPFORWSRCRT
120 #define IPFORWSRCRT 1 /* forward source-routed packets */
121 #endif
122 #ifndef IPALLOWSRCRT
123 #define IPALLOWSRCRT 1 /* allow source-routed packets */
124 #endif
125 #ifndef IPMTUDISC
126 #define IPMTUDISC 0
127 #endif
128 #ifndef IPMTUDISCTIMEOUT
129 #define IPMTUDISCTIMEOUT (10 * 60) /* as per RFC 1191 */
130 #endif
131
132 /*
133 * Note: DIRECTED_BROADCAST is handled this way so that previous
134 * configuration using this option will Just Work.
135 */
136 #ifndef IPDIRECTEDBCAST
137 #ifdef DIRECTED_BROADCAST
138 #define IPDIRECTEDBCAST 1
139 #else
140 #define IPDIRECTEDBCAST 0
141 #endif /* DIRECTED_BROADCAST */
142 #endif /* IPDIRECTEDBCAST */
143 int ipforwarding = IPFORWARDING;
144 int ipsendredirects = IPSENDREDIRECTS;
145 int ip_defttl = IPDEFTTL;
146 int ip_forwsrcrt = IPFORWSRCRT;
147 int ip_directedbcast = IPDIRECTEDBCAST;
148 int ip_allowsrcrt = IPALLOWSRCRT;
149 int ip_mtudisc = IPMTUDISC;
150 u_int ip_mtudisc_timeout = IPMTUDISCTIMEOUT;
151 #ifdef DIAGNOSTIC
152 int ipprintfs = 0;
153 #endif
154
155 struct rttimer_queue *ip_mtudisc_timeout_q = NULL;
156
157 extern struct domain inetdomain;
158 extern struct protosw inetsw[];
159 u_char ip_protox[IPPROTO_MAX];
160 int ipqmaxlen = IFQ_MAXLEN;
161 struct in_ifaddrhead in_ifaddr;
162 struct in_ifaddrhashhead *in_ifaddrhashtbl;
163 struct ifqueue ipintrq;
164 struct ipstat ipstat;
165 u_int16_t ip_id;
166 int ip_defttl;
167 struct ipqhead ipq;
168
169 struct pool ipqent_pool;
170
171 /*
172 * We need to save the IP options in case a protocol wants to respond
173 * to an incoming packet over the same route if the packet got here
174 * using IP source routing. This allows connection establishment and
175 * maintenance when the remote end is on a network that is not known
176 * to us.
177 */
178 int ip_nhops = 0;
179 static struct ip_srcrt {
180 struct in_addr dst; /* final destination */
181 char nop; /* one NOP to align */
182 char srcopt[IPOPT_OFFSET + 1]; /* OPTVAL, OLEN and OFFSET */
183 struct in_addr route[MAX_IPOPTLEN/sizeof(struct in_addr)];
184 } ip_srcrt;
185
186 static void save_rte __P((u_char *, struct in_addr));
187
188 /*
189 * IP initialization: fill in IP protocol switch table.
190 * All protocols not implemented in kernel go to raw IP protocol handler.
191 */
192 void
193 ip_init()
194 {
195 register struct protosw *pr;
196 register int i;
197
198 pool_init(&ipqent_pool, sizeof(struct ipqent), 0, 0, 0, "ipqepl",
199 0, NULL, NULL, M_IPQ);
200
201 pr = pffindproto(PF_INET, IPPROTO_RAW, SOCK_RAW);
202 if (pr == 0)
203 panic("ip_init");
204 for (i = 0; i < IPPROTO_MAX; i++)
205 ip_protox[i] = pr - inetsw;
206 for (pr = inetdomain.dom_protosw;
207 pr < inetdomain.dom_protoswNPROTOSW; pr++)
208 if (pr->pr_domain->dom_family == PF_INET &&
209 pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW)
210 ip_protox[pr->pr_protocol] = pr - inetsw;
211 LIST_INIT(&ipq);
212 ip_id = time.tv_sec & 0xffff;
213 ipintrq.ifq_maxlen = ipqmaxlen;
214 TAILQ_INIT(&in_ifaddr);
215 in_ifaddrhashtbl =
216 hashinit(IN_IFADDR_HASH_SIZE, M_IFADDR, M_WAITOK, &in_ifaddrhash);
217 if (ip_mtudisc != 0)
218 ip_mtudisc_timeout_q =
219 rt_timer_queue_create(ip_mtudisc_timeout);
220 }
221
222 struct sockaddr_in ipaddr = { sizeof(ipaddr), AF_INET };
223 struct route ipforward_rt;
224
225 /*
226 * Ip input routine. Checksum and byte swap header. If fragmented
227 * try to reassemble. Process options. Pass to next level.
228 */
229 void
230 ipintr()
231 {
232 register struct ip *ip = NULL;
233 register struct mbuf *m;
234 register struct ipq *fp;
235 register struct in_ifaddr *ia;
236 register struct ifaddr *ifa;
237 struct ipqent *ipqe;
238 int hlen = 0, mff, len, s;
239 #ifdef PFIL_HOOKS
240 struct packet_filter_hook *pfh;
241 struct mbuf *m0;
242 int rv;
243 #endif /* PFIL_HOOKS */
244
245 next:
246 /*
247 * Get next datagram off input queue and get IP header
248 * in first mbuf.
249 */
250 s = splimp();
251 IF_DEQUEUE(&ipintrq, m);
252 splx(s);
253 if (m == 0)
254 return;
255 #ifdef DIAGNOSTIC
256 if ((m->m_flags & M_PKTHDR) == 0)
257 panic("ipintr no HDR");
258 #endif
259 /*
260 * If no IP addresses have been set yet but the interfaces
261 * are receiving, can't do anything with incoming packets yet.
262 */
263 if (in_ifaddr.tqh_first == 0)
264 goto bad;
265 ipstat.ips_total++;
266 if (m->m_len < sizeof (struct ip) &&
267 (m = m_pullup(m, sizeof (struct ip))) == 0) {
268 ipstat.ips_toosmall++;
269 goto next;
270 }
271 ip = mtod(m, struct ip *);
272 if (ip->ip_v != IPVERSION) {
273 ipstat.ips_badvers++;
274 goto bad;
275 }
276 hlen = ip->ip_hl << 2;
277 if (hlen < sizeof(struct ip)) { /* minimum header length */
278 ipstat.ips_badhlen++;
279 goto bad;
280 }
281 if (hlen > m->m_len) {
282 if ((m = m_pullup(m, hlen)) == 0) {
283 ipstat.ips_badhlen++;
284 goto next;
285 }
286 ip = mtod(m, struct ip *);
287 }
288 if ((ip->ip_sum = in_cksum(m, hlen)) != 0) {
289 ipstat.ips_badsum++;
290 goto bad;
291 }
292
293 /*
294 * Convert fields to host representation.
295 */
296 NTOHS(ip->ip_len);
297 NTOHS(ip->ip_id);
298 NTOHS(ip->ip_off);
299 len = ip->ip_len;
300
301 /*
302 * Check that the amount of data in the buffers
303 * is as at least much as the IP header would have us expect.
304 * Trim mbufs if longer than we expect.
305 * Drop packet if shorter than we expect.
306 */
307 if (m->m_pkthdr.len < len) {
308 ipstat.ips_tooshort++;
309 goto bad;
310 }
311 if (m->m_pkthdr.len > len) {
312 if (m->m_len == m->m_pkthdr.len) {
313 m->m_len = len;
314 m->m_pkthdr.len = len;
315 } else
316 m_adj(m, len - m->m_pkthdr.len);
317 }
318
319 /*
320 * Assume that we can create a fast-forward IP flow entry
321 * based on this packet.
322 */
323 m->m_flags |= M_CANFASTFWD;
324
325 #ifdef PFIL_HOOKS
326 /*
327 * Run through list of hooks for input packets. If there are any
328 * filters which require that additional packets in the flow are
329 * not fast-forwarded, they must clear the M_CANFASTFWD flag.
330 * Note that filters must _never_ set this flag, as another filter
331 * in the list may have previously cleared it.
332 */
333 m0 = m;
334 for (pfh = pfil_hook_get(PFIL_IN); pfh; pfh = pfh->pfil_link.tqe_next)
335 if (pfh->pfil_func) {
336 rv = pfh->pfil_func(ip, hlen, m->m_pkthdr.rcvif, 0, &m0);
337 if (rv)
338 goto next;
339 m = m0;
340 if (m == NULL)
341 goto next;
342 ip = mtod(m, struct ip *);
343 }
344 #endif /* PFIL_HOOKS */
345
346 /*
347 * Process options and, if not destined for us,
348 * ship it on. ip_dooptions returns 1 when an
349 * error was detected (causing an icmp message
350 * to be sent and the original packet to be freed).
351 */
352 ip_nhops = 0; /* for source routed packets */
353 if (hlen > sizeof (struct ip) && ip_dooptions(m))
354 goto next;
355
356 /*
357 * Check our list of addresses, to see if the packet is for us.
358 */
359 INADDR_TO_IA(ip->ip_dst, ia);
360 if (ia != NULL) goto ours;
361 if (m->m_pkthdr.rcvif->if_flags & IFF_BROADCAST) {
362 for (ifa = m->m_pkthdr.rcvif->if_addrlist.tqh_first;
363 ifa != NULL; ifa = ifa->ifa_list.tqe_next) {
364 if (ifa->ifa_addr->sa_family != AF_INET) continue;
365 ia = ifatoia(ifa);
366 if (in_hosteq(ip->ip_dst, ia->ia_broadaddr.sin_addr) ||
367 in_hosteq(ip->ip_dst, ia->ia_netbroadcast) ||
368 /*
369 * Look for all-0's host part (old broadcast addr),
370 * either for subnet or net.
371 */
372 ip->ip_dst.s_addr == ia->ia_subnet ||
373 ip->ip_dst.s_addr == ia->ia_net)
374 goto ours;
375 /*
376 * An interface with IP address zero accepts
377 * all packets that arrive on that interface.
378 */
379 if (in_nullhost(ia->ia_addr.sin_addr))
380 goto ours;
381 }
382 }
383 if (IN_MULTICAST(ip->ip_dst.s_addr)) {
384 struct in_multi *inm;
385 #ifdef MROUTING
386 extern struct socket *ip_mrouter;
387
388 if (m->m_flags & M_EXT) {
389 if ((m = m_pullup(m, hlen)) == 0) {
390 ipstat.ips_toosmall++;
391 goto next;
392 }
393 ip = mtod(m, struct ip *);
394 }
395
396 if (ip_mrouter) {
397 /*
398 * If we are acting as a multicast router, all
399 * incoming multicast packets are passed to the
400 * kernel-level multicast forwarding function.
401 * The packet is returned (relatively) intact; if
402 * ip_mforward() returns a non-zero value, the packet
403 * must be discarded, else it may be accepted below.
404 *
405 * (The IP ident field is put in the same byte order
406 * as expected when ip_mforward() is called from
407 * ip_output().)
408 */
409 ip->ip_id = htons(ip->ip_id);
410 if (ip_mforward(m, m->m_pkthdr.rcvif) != 0) {
411 ipstat.ips_cantforward++;
412 m_freem(m);
413 goto next;
414 }
415 ip->ip_id = ntohs(ip->ip_id);
416
417 /*
418 * The process-level routing demon needs to receive
419 * all multicast IGMP packets, whether or not this
420 * host belongs to their destination groups.
421 */
422 if (ip->ip_p == IPPROTO_IGMP)
423 goto ours;
424 ipstat.ips_forward++;
425 }
426 #endif
427 /*
428 * See if we belong to the destination multicast group on the
429 * arrival interface.
430 */
431 IN_LOOKUP_MULTI(ip->ip_dst, m->m_pkthdr.rcvif, inm);
432 if (inm == NULL) {
433 ipstat.ips_cantforward++;
434 m_freem(m);
435 goto next;
436 }
437 goto ours;
438 }
439 if (ip->ip_dst.s_addr == INADDR_BROADCAST ||
440 in_nullhost(ip->ip_dst))
441 goto ours;
442
443 /*
444 * Not for us; forward if possible and desirable.
445 */
446 if (ipforwarding == 0) {
447 ipstat.ips_cantforward++;
448 m_freem(m);
449 } else
450 ip_forward(m, 0);
451 goto next;
452
453 ours:
454 /*
455 * If offset or IP_MF are set, must reassemble.
456 * Otherwise, nothing need be done.
457 * (We could look in the reassembly queue to see
458 * if the packet was previously fragmented,
459 * but it's not worth the time; just let them time out.)
460 */
461 if (ip->ip_off & ~(IP_DF|IP_RF)) {
462 /*
463 * Look for queue of fragments
464 * of this datagram.
465 */
466 for (fp = ipq.lh_first; fp != NULL; fp = fp->ipq_q.le_next)
467 if (ip->ip_id == fp->ipq_id &&
468 in_hosteq(ip->ip_src, fp->ipq_src) &&
469 in_hosteq(ip->ip_dst, fp->ipq_dst) &&
470 ip->ip_p == fp->ipq_p)
471 goto found;
472 fp = 0;
473 found:
474
475 /*
476 * Adjust ip_len to not reflect header,
477 * set ipqe_mff if more fragments are expected,
478 * convert offset of this to bytes.
479 */
480 ip->ip_len -= hlen;
481 mff = (ip->ip_off & IP_MF) != 0;
482 if (mff) {
483 /*
484 * Make sure that fragments have a data length
485 * that's a non-zero multiple of 8 bytes.
486 */
487 if (ip->ip_len == 0 || (ip->ip_len & 0x7) != 0) {
488 ipstat.ips_badfrags++;
489 goto bad;
490 }
491 }
492 ip->ip_off <<= 3;
493
494 /*
495 * If datagram marked as having more fragments
496 * or if this is not the first fragment,
497 * attempt reassembly; if it succeeds, proceed.
498 */
499 if (mff || ip->ip_off) {
500 ipstat.ips_fragments++;
501 ipqe = pool_get(&ipqent_pool, PR_NOWAIT);
502 if (ipqe == NULL) {
503 ipstat.ips_rcvmemdrop++;
504 goto bad;
505 }
506 ipqe->ipqe_mff = mff;
507 ipqe->ipqe_m = m;
508 ipqe->ipqe_ip = ip;
509 m = ip_reass(ipqe, fp);
510 if (m == 0)
511 goto next;
512 ipstat.ips_reassembled++;
513 ip = mtod(m, struct ip *);
514 } else
515 if (fp)
516 ip_freef(fp);
517 } else
518 ip->ip_len -= hlen;
519
520 /*
521 * Switch out to protocol's input routine.
522 */
523 ipstat.ips_delivered++;
524 (*inetsw[ip_protox[ip->ip_p]].pr_input)(m, hlen);
525 goto next;
526 bad:
527 m_freem(m);
528 goto next;
529 }
530
531 /*
532 * Take incoming datagram fragment and try to
533 * reassemble it into whole datagram. If a chain for
534 * reassembly of this datagram already exists, then it
535 * is given as fp; otherwise have to make a chain.
536 */
537 struct mbuf *
538 ip_reass(ipqe, fp)
539 register struct ipqent *ipqe;
540 register struct ipq *fp;
541 {
542 register struct mbuf *m = ipqe->ipqe_m;
543 register struct ipqent *nq, *p, *q;
544 struct ip *ip;
545 struct mbuf *t;
546 int hlen = ipqe->ipqe_ip->ip_hl << 2;
547 int i, next;
548
549 /*
550 * Presence of header sizes in mbufs
551 * would confuse code below.
552 */
553 m->m_data += hlen;
554 m->m_len -= hlen;
555
556 /*
557 * If first fragment to arrive, create a reassembly queue.
558 */
559 if (fp == 0) {
560 MALLOC(fp, struct ipq *, sizeof (struct ipq),
561 M_FTABLE, M_NOWAIT);
562 if (fp == NULL)
563 goto dropfrag;
564 LIST_INSERT_HEAD(&ipq, fp, ipq_q);
565 fp->ipq_ttl = IPFRAGTTL;
566 fp->ipq_p = ipqe->ipqe_ip->ip_p;
567 fp->ipq_id = ipqe->ipqe_ip->ip_id;
568 LIST_INIT(&fp->ipq_fragq);
569 fp->ipq_src = ipqe->ipqe_ip->ip_src;
570 fp->ipq_dst = ipqe->ipqe_ip->ip_dst;
571 p = NULL;
572 goto insert;
573 }
574
575 /*
576 * Find a segment which begins after this one does.
577 */
578 for (p = NULL, q = fp->ipq_fragq.lh_first; q != NULL;
579 p = q, q = q->ipqe_q.le_next)
580 if (q->ipqe_ip->ip_off > ipqe->ipqe_ip->ip_off)
581 break;
582
583 /*
584 * If there is a preceding segment, it may provide some of
585 * our data already. If so, drop the data from the incoming
586 * segment. If it provides all of our data, drop us.
587 */
588 if (p != NULL) {
589 i = p->ipqe_ip->ip_off + p->ipqe_ip->ip_len -
590 ipqe->ipqe_ip->ip_off;
591 if (i > 0) {
592 if (i >= ipqe->ipqe_ip->ip_len)
593 goto dropfrag;
594 m_adj(ipqe->ipqe_m, i);
595 ipqe->ipqe_ip->ip_off += i;
596 ipqe->ipqe_ip->ip_len -= i;
597 }
598 }
599
600 /*
601 * While we overlap succeeding segments trim them or,
602 * if they are completely covered, dequeue them.
603 */
604 for (; q != NULL && ipqe->ipqe_ip->ip_off + ipqe->ipqe_ip->ip_len >
605 q->ipqe_ip->ip_off; q = nq) {
606 i = (ipqe->ipqe_ip->ip_off + ipqe->ipqe_ip->ip_len) -
607 q->ipqe_ip->ip_off;
608 if (i < q->ipqe_ip->ip_len) {
609 q->ipqe_ip->ip_len -= i;
610 q->ipqe_ip->ip_off += i;
611 m_adj(q->ipqe_m, i);
612 break;
613 }
614 nq = q->ipqe_q.le_next;
615 m_freem(q->ipqe_m);
616 LIST_REMOVE(q, ipqe_q);
617 pool_put(&ipqent_pool, q);
618 }
619
620 insert:
621 /*
622 * Stick new segment in its place;
623 * check for complete reassembly.
624 */
625 if (p == NULL) {
626 LIST_INSERT_HEAD(&fp->ipq_fragq, ipqe, ipqe_q);
627 } else {
628 LIST_INSERT_AFTER(p, ipqe, ipqe_q);
629 }
630 next = 0;
631 for (p = NULL, q = fp->ipq_fragq.lh_first; q != NULL;
632 p = q, q = q->ipqe_q.le_next) {
633 if (q->ipqe_ip->ip_off != next)
634 return (0);
635 next += q->ipqe_ip->ip_len;
636 }
637 if (p->ipqe_mff)
638 return (0);
639
640 /*
641 * Reassembly is complete. Check for a bogus message size and
642 * concatenate fragments.
643 */
644 q = fp->ipq_fragq.lh_first;
645 ip = q->ipqe_ip;
646 if ((next + (ip->ip_hl << 2)) > IP_MAXPACKET) {
647 ipstat.ips_toolong++;
648 ip_freef(fp);
649 return (0);
650 }
651 m = q->ipqe_m;
652 t = m->m_next;
653 m->m_next = 0;
654 m_cat(m, t);
655 nq = q->ipqe_q.le_next;
656 pool_put(&ipqent_pool, q);
657 for (q = nq; q != NULL; q = nq) {
658 t = q->ipqe_m;
659 nq = q->ipqe_q.le_next;
660 pool_put(&ipqent_pool, q);
661 m_cat(m, t);
662 }
663
664 /*
665 * Create header for new ip packet by
666 * modifying header of first packet;
667 * dequeue and discard fragment reassembly header.
668 * Make header visible.
669 */
670 ip->ip_len = next;
671 ip->ip_src = fp->ipq_src;
672 ip->ip_dst = fp->ipq_dst;
673 LIST_REMOVE(fp, ipq_q);
674 FREE(fp, M_FTABLE);
675 m->m_len += (ip->ip_hl << 2);
676 m->m_data -= (ip->ip_hl << 2);
677 /* some debugging cruft by sklower, below, will go away soon */
678 if (m->m_flags & M_PKTHDR) { /* XXX this should be done elsewhere */
679 register int plen = 0;
680 for (t = m; t; t = t->m_next)
681 plen += t->m_len;
682 m->m_pkthdr.len = plen;
683 }
684 return (m);
685
686 dropfrag:
687 ipstat.ips_fragdropped++;
688 m_freem(m);
689 pool_put(&ipqent_pool, ipqe);
690 return (0);
691 }
692
693 /*
694 * Free a fragment reassembly header and all
695 * associated datagrams.
696 */
697 void
698 ip_freef(fp)
699 struct ipq *fp;
700 {
701 register struct ipqent *q, *p;
702
703 for (q = fp->ipq_fragq.lh_first; q != NULL; q = p) {
704 p = q->ipqe_q.le_next;
705 m_freem(q->ipqe_m);
706 LIST_REMOVE(q, ipqe_q);
707 pool_put(&ipqent_pool, q);
708 }
709 LIST_REMOVE(fp, ipq_q);
710 FREE(fp, M_FTABLE);
711 }
712
713 /*
714 * IP timer processing;
715 * if a timer expires on a reassembly
716 * queue, discard it.
717 */
718 void
719 ip_slowtimo()
720 {
721 register struct ipq *fp, *nfp;
722 int s = splsoftnet();
723
724 for (fp = ipq.lh_first; fp != NULL; fp = nfp) {
725 nfp = fp->ipq_q.le_next;
726 if (--fp->ipq_ttl == 0) {
727 ipstat.ips_fragtimeout++;
728 ip_freef(fp);
729 }
730 }
731 #ifdef GATEWAY
732 ipflow_slowtimo();
733 #endif
734 splx(s);
735 }
736
737 /*
738 * Drain off all datagram fragments.
739 */
740 void
741 ip_drain()
742 {
743
744 while (ipq.lh_first != NULL) {
745 ipstat.ips_fragdropped++;
746 ip_freef(ipq.lh_first);
747 }
748 }
749
750 /*
751 * Do option processing on a datagram,
752 * possibly discarding it if bad options are encountered,
753 * or forwarding it if source-routed.
754 * Returns 1 if packet has been forwarded/freed,
755 * 0 if the packet should be processed further.
756 */
757 int
758 ip_dooptions(m)
759 struct mbuf *m;
760 {
761 register struct ip *ip = mtod(m, struct ip *);
762 register u_char *cp;
763 register struct ip_timestamp *ipt;
764 register struct in_ifaddr *ia;
765 int opt, optlen, cnt, off, code, type = ICMP_PARAMPROB, forward = 0;
766 struct in_addr *sin, dst;
767 n_time ntime;
768
769 dst = ip->ip_dst;
770 cp = (u_char *)(ip + 1);
771 cnt = (ip->ip_hl << 2) - sizeof (struct ip);
772 for (; cnt > 0; cnt -= optlen, cp += optlen) {
773 opt = cp[IPOPT_OPTVAL];
774 if (opt == IPOPT_EOL)
775 break;
776 if (opt == IPOPT_NOP)
777 optlen = 1;
778 else {
779 optlen = cp[IPOPT_OLEN];
780 if (optlen <= 0 || optlen > cnt) {
781 code = &cp[IPOPT_OLEN] - (u_char *)ip;
782 goto bad;
783 }
784 }
785 switch (opt) {
786
787 default:
788 break;
789
790 /*
791 * Source routing with record.
792 * Find interface with current destination address.
793 * If none on this machine then drop if strictly routed,
794 * or do nothing if loosely routed.
795 * Record interface address and bring up next address
796 * component. If strictly routed make sure next
797 * address is on directly accessible net.
798 */
799 case IPOPT_LSRR:
800 case IPOPT_SSRR:
801 if (ip_allowsrcrt == 0) {
802 type = ICMP_UNREACH;
803 code = ICMP_UNREACH_NET_PROHIB;
804 goto bad;
805 }
806 if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) {
807 code = &cp[IPOPT_OFFSET] - (u_char *)ip;
808 goto bad;
809 }
810 ipaddr.sin_addr = ip->ip_dst;
811 ia = ifatoia(ifa_ifwithaddr(sintosa(&ipaddr)));
812 if (ia == 0) {
813 if (opt == IPOPT_SSRR) {
814 type = ICMP_UNREACH;
815 code = ICMP_UNREACH_SRCFAIL;
816 goto bad;
817 }
818 /*
819 * Loose routing, and not at next destination
820 * yet; nothing to do except forward.
821 */
822 break;
823 }
824 off--; /* 0 origin */
825 if (off > optlen - sizeof(struct in_addr)) {
826 /*
827 * End of source route. Should be for us.
828 */
829 save_rte(cp, ip->ip_src);
830 break;
831 }
832 /*
833 * locate outgoing interface
834 */
835 bcopy((caddr_t)(cp + off), (caddr_t)&ipaddr.sin_addr,
836 sizeof(ipaddr.sin_addr));
837 if (opt == IPOPT_SSRR) {
838 #define INA struct in_ifaddr *
839 #define SA struct sockaddr *
840 ia = (INA)ifa_ifwithladdr((SA)&ipaddr);
841 } else
842 ia = ip_rtaddr(ipaddr.sin_addr);
843 if (ia == 0) {
844 type = ICMP_UNREACH;
845 code = ICMP_UNREACH_SRCFAIL;
846 goto bad;
847 }
848 ip->ip_dst = ipaddr.sin_addr;
849 bcopy((caddr_t)&ia->ia_addr.sin_addr,
850 (caddr_t)(cp + off), sizeof(struct in_addr));
851 cp[IPOPT_OFFSET] += sizeof(struct in_addr);
852 /*
853 * Let ip_intr's mcast routing check handle mcast pkts
854 */
855 forward = !IN_MULTICAST(ip->ip_dst.s_addr);
856 break;
857
858 case IPOPT_RR:
859 if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) {
860 code = &cp[IPOPT_OFFSET] - (u_char *)ip;
861 goto bad;
862 }
863 /*
864 * If no space remains, ignore.
865 */
866 off--; /* 0 origin */
867 if (off > optlen - sizeof(struct in_addr))
868 break;
869 bcopy((caddr_t)(&ip->ip_dst), (caddr_t)&ipaddr.sin_addr,
870 sizeof(ipaddr.sin_addr));
871 /*
872 * locate outgoing interface; if we're the destination,
873 * use the incoming interface (should be same).
874 */
875 if ((ia = (INA)ifa_ifwithaddr((SA)&ipaddr)) == 0 &&
876 (ia = ip_rtaddr(ipaddr.sin_addr)) == 0) {
877 type = ICMP_UNREACH;
878 code = ICMP_UNREACH_HOST;
879 goto bad;
880 }
881 bcopy((caddr_t)&ia->ia_addr.sin_addr,
882 (caddr_t)(cp + off), sizeof(struct in_addr));
883 cp[IPOPT_OFFSET] += sizeof(struct in_addr);
884 break;
885
886 case IPOPT_TS:
887 code = cp - (u_char *)ip;
888 ipt = (struct ip_timestamp *)cp;
889 if (ipt->ipt_len < 5)
890 goto bad;
891 if (ipt->ipt_ptr > ipt->ipt_len - sizeof (int32_t)) {
892 if (++ipt->ipt_oflw == 0)
893 goto bad;
894 break;
895 }
896 sin = (struct in_addr *)(cp + ipt->ipt_ptr - 1);
897 switch (ipt->ipt_flg) {
898
899 case IPOPT_TS_TSONLY:
900 break;
901
902 case IPOPT_TS_TSANDADDR:
903 if (ipt->ipt_ptr - 1 + sizeof(n_time) +
904 sizeof(struct in_addr) > ipt->ipt_len)
905 goto bad;
906 ipaddr.sin_addr = dst;
907 ia = (INA)ifaof_ifpforaddr((SA)&ipaddr,
908 m->m_pkthdr.rcvif);
909 if (ia == 0)
910 continue;
911 bcopy((caddr_t)&ia->ia_addr.sin_addr,
912 (caddr_t)sin, sizeof(struct in_addr));
913 ipt->ipt_ptr += sizeof(struct in_addr);
914 break;
915
916 case IPOPT_TS_PRESPEC:
917 if (ipt->ipt_ptr - 1 + sizeof(n_time) +
918 sizeof(struct in_addr) > ipt->ipt_len)
919 goto bad;
920 bcopy((caddr_t)sin, (caddr_t)&ipaddr.sin_addr,
921 sizeof(struct in_addr));
922 if (ifa_ifwithaddr((SA)&ipaddr) == 0)
923 continue;
924 ipt->ipt_ptr += sizeof(struct in_addr);
925 break;
926
927 default:
928 goto bad;
929 }
930 ntime = iptime();
931 bcopy((caddr_t)&ntime, (caddr_t)cp + ipt->ipt_ptr - 1,
932 sizeof(n_time));
933 ipt->ipt_ptr += sizeof(n_time);
934 }
935 }
936 if (forward) {
937 if (ip_forwsrcrt == 0) {
938 type = ICMP_UNREACH;
939 code = ICMP_UNREACH_SRCFAIL;
940 goto bad;
941 }
942 ip_forward(m, 1);
943 return (1);
944 }
945 return (0);
946 bad:
947 ip->ip_len -= ip->ip_hl << 2; /* XXX icmp_error adds in hdr length */
948 icmp_error(m, type, code, 0, 0);
949 ipstat.ips_badoptions++;
950 return (1);
951 }
952
953 /*
954 * Given address of next destination (final or next hop),
955 * return internet address info of interface to be used to get there.
956 */
957 struct in_ifaddr *
958 ip_rtaddr(dst)
959 struct in_addr dst;
960 {
961 register struct sockaddr_in *sin;
962
963 sin = satosin(&ipforward_rt.ro_dst);
964
965 if (ipforward_rt.ro_rt == 0 || !in_hosteq(dst, sin->sin_addr)) {
966 if (ipforward_rt.ro_rt) {
967 RTFREE(ipforward_rt.ro_rt);
968 ipforward_rt.ro_rt = 0;
969 }
970 sin->sin_family = AF_INET;
971 sin->sin_len = sizeof(*sin);
972 sin->sin_addr = dst;
973
974 rtalloc(&ipforward_rt);
975 }
976 if (ipforward_rt.ro_rt == 0)
977 return ((struct in_ifaddr *)0);
978 return (ifatoia(ipforward_rt.ro_rt->rt_ifa));
979 }
980
981 /*
982 * Save incoming source route for use in replies,
983 * to be picked up later by ip_srcroute if the receiver is interested.
984 */
985 void
986 save_rte(option, dst)
987 u_char *option;
988 struct in_addr dst;
989 {
990 unsigned olen;
991
992 olen = option[IPOPT_OLEN];
993 #ifdef DIAGNOSTIC
994 if (ipprintfs)
995 printf("save_rte: olen %d\n", olen);
996 #endif
997 if (olen > sizeof(ip_srcrt) - (1 + sizeof(dst)))
998 return;
999 bcopy((caddr_t)option, (caddr_t)ip_srcrt.srcopt, olen);
1000 ip_nhops = (olen - IPOPT_OFFSET - 1) / sizeof(struct in_addr);
1001 ip_srcrt.dst = dst;
1002 }
1003
1004 /*
1005 * Retrieve incoming source route for use in replies,
1006 * in the same form used by setsockopt.
1007 * The first hop is placed before the options, will be removed later.
1008 */
1009 struct mbuf *
1010 ip_srcroute()
1011 {
1012 register struct in_addr *p, *q;
1013 register struct mbuf *m;
1014
1015 if (ip_nhops == 0)
1016 return ((struct mbuf *)0);
1017 m = m_get(M_DONTWAIT, MT_SOOPTS);
1018 if (m == 0)
1019 return ((struct mbuf *)0);
1020
1021 #define OPTSIZ (sizeof(ip_srcrt.nop) + sizeof(ip_srcrt.srcopt))
1022
1023 /* length is (nhops+1)*sizeof(addr) + sizeof(nop + srcrt header) */
1024 m->m_len = ip_nhops * sizeof(struct in_addr) + sizeof(struct in_addr) +
1025 OPTSIZ;
1026 #ifdef DIAGNOSTIC
1027 if (ipprintfs)
1028 printf("ip_srcroute: nhops %d mlen %d", ip_nhops, m->m_len);
1029 #endif
1030
1031 /*
1032 * First save first hop for return route
1033 */
1034 p = &ip_srcrt.route[ip_nhops - 1];
1035 *(mtod(m, struct in_addr *)) = *p--;
1036 #ifdef DIAGNOSTIC
1037 if (ipprintfs)
1038 printf(" hops %x", ntohl(mtod(m, struct in_addr *)->s_addr));
1039 #endif
1040
1041 /*
1042 * Copy option fields and padding (nop) to mbuf.
1043 */
1044 ip_srcrt.nop = IPOPT_NOP;
1045 ip_srcrt.srcopt[IPOPT_OFFSET] = IPOPT_MINOFF;
1046 bcopy((caddr_t)&ip_srcrt.nop,
1047 mtod(m, caddr_t) + sizeof(struct in_addr), OPTSIZ);
1048 q = (struct in_addr *)(mtod(m, caddr_t) +
1049 sizeof(struct in_addr) + OPTSIZ);
1050 #undef OPTSIZ
1051 /*
1052 * Record return path as an IP source route,
1053 * reversing the path (pointers are now aligned).
1054 */
1055 while (p >= ip_srcrt.route) {
1056 #ifdef DIAGNOSTIC
1057 if (ipprintfs)
1058 printf(" %x", ntohl(q->s_addr));
1059 #endif
1060 *q++ = *p--;
1061 }
1062 /*
1063 * Last hop goes to final destination.
1064 */
1065 *q = ip_srcrt.dst;
1066 #ifdef DIAGNOSTIC
1067 if (ipprintfs)
1068 printf(" %x\n", ntohl(q->s_addr));
1069 #endif
1070 return (m);
1071 }
1072
1073 /*
1074 * Strip out IP options, at higher
1075 * level protocol in the kernel.
1076 * Second argument is buffer to which options
1077 * will be moved, and return value is their length.
1078 * XXX should be deleted; last arg currently ignored.
1079 */
1080 void
1081 ip_stripoptions(m, mopt)
1082 register struct mbuf *m;
1083 struct mbuf *mopt;
1084 {
1085 register int i;
1086 struct ip *ip = mtod(m, struct ip *);
1087 register caddr_t opts;
1088 int olen;
1089
1090 olen = (ip->ip_hl<<2) - sizeof (struct ip);
1091 opts = (caddr_t)(ip + 1);
1092 i = m->m_len - (sizeof (struct ip) + olen);
1093 bcopy(opts + olen, opts, (unsigned)i);
1094 m->m_len -= olen;
1095 if (m->m_flags & M_PKTHDR)
1096 m->m_pkthdr.len -= olen;
1097 ip->ip_hl = sizeof(struct ip) >> 2;
1098 }
1099
1100 int inetctlerrmap[PRC_NCMDS] = {
1101 0, 0, 0, 0,
1102 0, EMSGSIZE, EHOSTDOWN, EHOSTUNREACH,
1103 EHOSTUNREACH, EHOSTUNREACH, ECONNREFUSED, ECONNREFUSED,
1104 EMSGSIZE, EHOSTUNREACH, 0, 0,
1105 0, 0, 0, 0,
1106 ENOPROTOOPT
1107 };
1108
1109 /*
1110 * Forward a packet. If some error occurs return the sender
1111 * an icmp packet. Note we can't always generate a meaningful
1112 * icmp message because icmp doesn't have a large enough repertoire
1113 * of codes and types.
1114 *
1115 * If not forwarding, just drop the packet. This could be confusing
1116 * if ipforwarding was zero but some routing protocol was advancing
1117 * us as a gateway to somewhere. However, we must let the routing
1118 * protocol deal with that.
1119 *
1120 * The srcrt parameter indicates whether the packet is being forwarded
1121 * via a source route.
1122 */
1123 void
1124 ip_forward(m, srcrt)
1125 struct mbuf *m;
1126 int srcrt;
1127 {
1128 register struct ip *ip = mtod(m, struct ip *);
1129 register struct sockaddr_in *sin;
1130 register struct rtentry *rt;
1131 int error, type = 0, code = 0;
1132 struct mbuf *mcopy;
1133 n_long dest;
1134 struct ifnet *destifp;
1135
1136 dest = 0;
1137 #ifdef DIAGNOSTIC
1138 if (ipprintfs)
1139 printf("forward: src %2.2x dst %2.2x ttl %x\n",
1140 ntohl(ip->ip_src.s_addr),
1141 ntohl(ip->ip_dst.s_addr), ip->ip_ttl);
1142 #endif
1143 if (m->m_flags & M_BCAST || in_canforward(ip->ip_dst) == 0) {
1144 ipstat.ips_cantforward++;
1145 m_freem(m);
1146 return;
1147 }
1148 HTONS(ip->ip_id);
1149 if (ip->ip_ttl <= IPTTLDEC) {
1150 icmp_error(m, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS, dest, 0);
1151 return;
1152 }
1153 ip->ip_ttl -= IPTTLDEC;
1154
1155 sin = satosin(&ipforward_rt.ro_dst);
1156 if ((rt = ipforward_rt.ro_rt) == 0 ||
1157 !in_hosteq(ip->ip_dst, sin->sin_addr)) {
1158 if (ipforward_rt.ro_rt) {
1159 RTFREE(ipforward_rt.ro_rt);
1160 ipforward_rt.ro_rt = 0;
1161 }
1162 sin->sin_family = AF_INET;
1163 sin->sin_len = sizeof(struct sockaddr_in);
1164 sin->sin_addr = ip->ip_dst;
1165
1166 rtalloc(&ipforward_rt);
1167 if (ipforward_rt.ro_rt == 0) {
1168 icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, dest, 0);
1169 return;
1170 }
1171 rt = ipforward_rt.ro_rt;
1172 }
1173
1174 /*
1175 * Save at most 68 bytes of the packet in case
1176 * we need to generate an ICMP message to the src.
1177 */
1178 mcopy = m_copy(m, 0, imin((int)ip->ip_len, 68));
1179
1180 /*
1181 * If forwarding packet using same interface that it came in on,
1182 * perhaps should send a redirect to sender to shortcut a hop.
1183 * Only send redirect if source is sending directly to us,
1184 * and if packet was not source routed (or has any options).
1185 * Also, don't send redirect if forwarding using a default route
1186 * or a route modified by a redirect.
1187 */
1188 if (rt->rt_ifp == m->m_pkthdr.rcvif &&
1189 (rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0 &&
1190 !in_nullhost(satosin(rt_key(rt))->sin_addr) &&
1191 ipsendredirects && !srcrt) {
1192 if (rt->rt_ifa &&
1193 (ip->ip_src.s_addr & ifatoia(rt->rt_ifa)->ia_subnetmask) ==
1194 ifatoia(rt->rt_ifa)->ia_subnet) {
1195 if (rt->rt_flags & RTF_GATEWAY)
1196 dest = satosin(rt->rt_gateway)->sin_addr.s_addr;
1197 else
1198 dest = ip->ip_dst.s_addr;
1199 /* Router requirements says to only send host redirects */
1200 type = ICMP_REDIRECT;
1201 code = ICMP_REDIRECT_HOST;
1202 #ifdef DIAGNOSTIC
1203 if (ipprintfs)
1204 printf("redirect (%d) to %x\n", code, (u_int32_t)dest);
1205 #endif
1206 }
1207 }
1208
1209 error = ip_output(m, (struct mbuf *)0, &ipforward_rt,
1210 (IP_FORWARDING | (ip_directedbcast ? IP_ALLOWBROADCAST : 0)), 0);
1211 if (error)
1212 ipstat.ips_cantforward++;
1213 else {
1214 ipstat.ips_forward++;
1215 if (type)
1216 ipstat.ips_redirectsent++;
1217 else {
1218 if (mcopy) {
1219 #ifdef GATEWAY
1220 if (mcopy->m_flags & M_CANFASTFWD)
1221 ipflow_create(&ipforward_rt, mcopy);
1222 #endif
1223 m_freem(mcopy);
1224 }
1225 return;
1226 }
1227 }
1228 if (mcopy == NULL)
1229 return;
1230 destifp = NULL;
1231
1232 switch (error) {
1233
1234 case 0: /* forwarded, but need redirect */
1235 /* type, code set above */
1236 break;
1237
1238 case ENETUNREACH: /* shouldn't happen, checked above */
1239 case EHOSTUNREACH:
1240 case ENETDOWN:
1241 case EHOSTDOWN:
1242 default:
1243 type = ICMP_UNREACH;
1244 code = ICMP_UNREACH_HOST;
1245 break;
1246
1247 case EMSGSIZE:
1248 type = ICMP_UNREACH;
1249 code = ICMP_UNREACH_NEEDFRAG;
1250 if (ipforward_rt.ro_rt)
1251 destifp = ipforward_rt.ro_rt->rt_ifp;
1252 ipstat.ips_cantfrag++;
1253 break;
1254
1255 case ENOBUFS:
1256 type = ICMP_SOURCEQUENCH;
1257 code = 0;
1258 break;
1259 }
1260 icmp_error(mcopy, type, code, dest, destifp);
1261 }
1262
1263 void
1264 ip_savecontrol(inp, mp, ip, m)
1265 register struct inpcb *inp;
1266 register struct mbuf **mp;
1267 register struct ip *ip;
1268 register struct mbuf *m;
1269 {
1270
1271 if (inp->inp_socket->so_options & SO_TIMESTAMP) {
1272 struct timeval tv;
1273
1274 microtime(&tv);
1275 *mp = sbcreatecontrol((caddr_t) &tv, sizeof(tv),
1276 SCM_TIMESTAMP, SOL_SOCKET);
1277 if (*mp)
1278 mp = &(*mp)->m_next;
1279 }
1280 if (inp->inp_flags & INP_RECVDSTADDR) {
1281 *mp = sbcreatecontrol((caddr_t) &ip->ip_dst,
1282 sizeof(struct in_addr), IP_RECVDSTADDR, IPPROTO_IP);
1283 if (*mp)
1284 mp = &(*mp)->m_next;
1285 }
1286 #ifdef notyet
1287 /*
1288 * XXX
1289 * Moving these out of udp_input() made them even more broken
1290 * than they already were.
1291 * - fenner (at) parc.xerox.com
1292 */
1293 /* options were tossed already */
1294 if (inp->inp_flags & INP_RECVOPTS) {
1295 *mp = sbcreatecontrol((caddr_t) opts_deleted_above,
1296 sizeof(struct in_addr), IP_RECVOPTS, IPPROTO_IP);
1297 if (*mp)
1298 mp = &(*mp)->m_next;
1299 }
1300 /* ip_srcroute doesn't do what we want here, need to fix */
1301 if (inp->inp_flags & INP_RECVRETOPTS) {
1302 *mp = sbcreatecontrol((caddr_t) ip_srcroute(),
1303 sizeof(struct in_addr), IP_RECVRETOPTS, IPPROTO_IP);
1304 if (*mp)
1305 mp = &(*mp)->m_next;
1306 }
1307 #endif
1308 if (inp->inp_flags & INP_RECVIF) {
1309 struct sockaddr_dl sdl;
1310
1311 sdl.sdl_len = offsetof(struct sockaddr_dl, sdl_data[0]);
1312 sdl.sdl_family = AF_LINK;
1313 sdl.sdl_index = m->m_pkthdr.rcvif ?
1314 m->m_pkthdr.rcvif->if_index : 0;
1315 sdl.sdl_nlen = sdl.sdl_alen = sdl.sdl_slen = 0;
1316 *mp = sbcreatecontrol((caddr_t) &sdl, sdl.sdl_len,
1317 IP_RECVIF, IPPROTO_IP);
1318 if (*mp)
1319 mp = &(*mp)->m_next;
1320 }
1321 }
1322
1323 int
1324 ip_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
1325 int *name;
1326 u_int namelen;
1327 void *oldp;
1328 size_t *oldlenp;
1329 void *newp;
1330 size_t newlen;
1331 {
1332 extern int subnetsarelocal;
1333
1334 int error, old;
1335
1336 /* All sysctl names at this level are terminal. */
1337 if (namelen != 1)
1338 return (ENOTDIR);
1339
1340 switch (name[0]) {
1341 case IPCTL_FORWARDING:
1342 return (sysctl_int(oldp, oldlenp, newp, newlen, &ipforwarding));
1343 case IPCTL_SENDREDIRECTS:
1344 return (sysctl_int(oldp, oldlenp, newp, newlen,
1345 &ipsendredirects));
1346 case IPCTL_DEFTTL:
1347 return (sysctl_int(oldp, oldlenp, newp, newlen, &ip_defttl));
1348 #ifdef notyet
1349 case IPCTL_DEFMTU:
1350 return (sysctl_int(oldp, oldlenp, newp, newlen, &ip_mtu));
1351 #endif
1352 case IPCTL_FORWSRCRT:
1353 /* Don't allow this to change in a secure environment. */
1354 if (securelevel > 0)
1355 return (sysctl_rdint(oldp, oldlenp, newp,
1356 ip_forwsrcrt));
1357 else
1358 return (sysctl_int(oldp, oldlenp, newp, newlen,
1359 &ip_forwsrcrt));
1360 case IPCTL_DIRECTEDBCAST:
1361 return (sysctl_int(oldp, oldlenp, newp, newlen,
1362 &ip_directedbcast));
1363 case IPCTL_ALLOWSRCRT:
1364 return (sysctl_int(oldp, oldlenp, newp, newlen,
1365 &ip_allowsrcrt));
1366 case IPCTL_SUBNETSARELOCAL:
1367 return (sysctl_int(oldp, oldlenp, newp, newlen,
1368 &subnetsarelocal));
1369 case IPCTL_MTUDISC:
1370 error = sysctl_int(oldp, oldlenp, newp, newlen,
1371 &ip_mtudisc);
1372 if (ip_mtudisc != 0 && ip_mtudisc_timeout_q == NULL) {
1373 ip_mtudisc_timeout_q =
1374 rt_timer_queue_create(ip_mtudisc_timeout);
1375 } else if (ip_mtudisc == 0 && ip_mtudisc_timeout_q != NULL) {
1376 rt_timer_queue_destroy(ip_mtudisc_timeout_q, TRUE);
1377 ip_mtudisc_timeout_q = NULL;
1378 }
1379 return error;
1380 case IPCTL_ANONPORTMIN:
1381 old = anonportmin;
1382 error = sysctl_int(oldp, oldlenp, newp, newlen, &anonportmin);
1383 if (anonportmin >= anonportmax || anonportmin > 65535
1384 #ifndef IPNOPRIVPORTS
1385 || anonportmin < IPPORT_RESERVED
1386 #endif
1387 ) {
1388 anonportmin = old;
1389 return (EINVAL);
1390 }
1391 return (error);
1392 case IPCTL_ANONPORTMAX:
1393 old = anonportmax;
1394 error = sysctl_int(oldp, oldlenp, newp, newlen, &anonportmax);
1395 if (anonportmin >= anonportmax || anonportmax > 65535
1396 #ifndef IPNOPRIVPORTS
1397 || anonportmax < IPPORT_RESERVED
1398 #endif
1399 ) {
1400 anonportmax = old;
1401 return (EINVAL);
1402 }
1403 return (error);
1404 case IPCTL_MTUDISCTIMEOUT:
1405 error = sysctl_int(oldp, oldlenp, newp, newlen,
1406 &ip_mtudisc_timeout);
1407 if (ip_mtudisc_timeout_q != NULL)
1408 rt_timer_queue_change(ip_mtudisc_timeout_q,
1409 ip_mtudisc_timeout);
1410 return (error);
1411 #ifdef GATEWAY
1412 case IPCTL_MAXFLOWS:
1413 {
1414 int s;
1415
1416 error = sysctl_int(oldp, oldlenp, newp, newlen,
1417 &ip_maxflows);
1418 s = splsoftnet();
1419 ipflow_reap(0);
1420 splx(s);
1421 return (error);
1422 }
1423 #endif
1424 default:
1425 return (EOPNOTSUPP);
1426 }
1427 /* NOTREACHED */
1428 }
1429