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