Annotation of XNU/bsd/netinet/ip_input.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * The contents of this file constitute Original Code as defined in and
        !             7:  * are subject to the Apple Public Source License Version 1.1 (the
        !             8:  * "License").  You may not use this file except in compliance with the
        !             9:  * License.  Please obtain a copy of the License at
        !            10:  * http://www.apple.com/publicsource and read it before using this file.
        !            11:  * 
        !            12:  * This Original Code and all software distributed under the License are
        !            13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            17:  * License for the specific language governing rights and limitations
        !            18:  * under the License.
        !            19:  * 
        !            20:  * @APPLE_LICENSE_HEADER_END@
        !            21:  */
        !            22: /*
        !            23:  * Copyright (c) 1982, 1986, 1988, 1993
        !            24:  *     The Regents of the University of California.  All rights reserved.
        !            25:  *
        !            26:  * Redistribution and use in source and binary forms, with or without
        !            27:  * modification, are permitted provided that the following conditions
        !            28:  * are met:
        !            29:  * 1. Redistributions of source code must retain the above copyright
        !            30:  *    notice, this list of conditions and the following disclaimer.
        !            31:  * 2. Redistributions in binary form must reproduce the above copyright
        !            32:  *    notice, this list of conditions and the following disclaimer in the
        !            33:  *    documentation and/or other materials provided with the distribution.
        !            34:  * 3. All advertising materials mentioning features or use of this software
        !            35:  *    must display the following acknowledgement:
        !            36:  *     This product includes software developed by the University of
        !            37:  *     California, Berkeley and its contributors.
        !            38:  * 4. Neither the name of the University nor the names of its contributors
        !            39:  *    may be used to endorse or promote products derived from this software
        !            40:  *    without specific prior written permission.
        !            41:  *
        !            42:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            43:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            44:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            45:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            46:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            47:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            48:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            49:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            50:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            51:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            52:  * SUCH DAMAGE.
        !            53:  *
        !            54:  *     @(#)ip_input.c  8.2 (Berkeley) 1/4/94
        !            55:  *     $ANA: ip_input.c,v 1.5 1996/09/18 14:34:59 wollman Exp $
        !            56:  */
        !            57: 
        !            58: #define        _IP_VHL
        !            59: 
        !            60: #include <stddef.h>
        !            61: 
        !            62: #include <sys/param.h>
        !            63: #include <sys/systm.h>
        !            64: #include <sys/mbuf.h>
        !            65: #include <sys/malloc.h>
        !            66: #include <sys/domain.h>
        !            67: #include <sys/protosw.h>
        !            68: #include <sys/socket.h>
        !            69: #include <sys/time.h>
        !            70: #include <sys/kernel.h>
        !            71: #include <sys/syslog.h>
        !            72: #include <sys/sysctl.h>
        !            73: 
        !            74: #include <kern/queue.h>
        !            75: 
        !            76: #include <net/if.h>
        !            77: #include <net/if_var.h>
        !            78: #include <net/if_dl.h>
        !            79: #include <net/route.h>
        !            80: #include <net/netisr.h>
        !            81: 
        !            82: #include <netinet/in.h>
        !            83: #include <netinet/in_systm.h>
        !            84: #include <netinet/in_var.h>
        !            85: #include <netinet/ip.h>
        !            86: #include <netinet/in_pcb.h>
        !            87: #include <netinet/ip_var.h>
        !            88: #include <netinet/ip_icmp.h>
        !            89: #include <sys/socketvar.h>
        !            90: 
        !            91: #if IPFIREWALL
        !            92: #include <netinet/ip_fw.h>
        !            93: #endif
        !            94: 
        !            95: #if DUMMYNET
        !            96: #include <netinet/ip_dummynet.h>
        !            97: #endif
        !            98: 
        !            99: int rsvp_on = 0;
        !           100: static int ip_rsvp_on;
        !           101: struct socket *ip_rsvpd;
        !           102: 
        !           103: int    ipforwarding = 0;
        !           104: SYSCTL_INT(_net_inet_ip, IPCTL_FORWARDING, forwarding, CTLFLAG_RW,
        !           105:        &ipforwarding, 0, "");
        !           106: 
        !           107: static int     ipsendredirects = 1; /* XXX */
        !           108: SYSCTL_INT(_net_inet_ip, IPCTL_SENDREDIRECTS, redirect, CTLFLAG_RW,
        !           109:        &ipsendredirects, 0, "");
        !           110: 
        !           111: int    ip_defttl = IPDEFTTL;
        !           112: SYSCTL_INT(_net_inet_ip, IPCTL_DEFTTL, ttl, CTLFLAG_RW,
        !           113:        &ip_defttl, 0, "");
        !           114: 
        !           115: static int     ip_dosourceroute = 0;
        !           116: SYSCTL_INT(_net_inet_ip, IPCTL_SOURCEROUTE, sourceroute, CTLFLAG_RW,
        !           117:        &ip_dosourceroute, 0, "");
        !           118: 
        !           119: static int     ip_acceptsourceroute = 0;
        !           120: SYSCTL_INT(_net_inet_ip, IPCTL_ACCEPTSOURCEROUTE, accept_sourceroute,
        !           121:        CTLFLAG_RW, &ip_acceptsourceroute, 0, "");
        !           122: #if DIAGNOSTIC
        !           123: static int     ipprintfs = 0;
        !           124: #endif
        !           125: 
        !           126: extern struct domain inetdomain;
        !           127: extern struct protosw inetsw[];
        !           128: struct protosw *ip_protox[IPPROTO_MAX];
        !           129: static int     ipqmaxlen = IFQ_MAXLEN;
        !           130: struct in_ifaddrhead in_ifaddrhead; /* first inet address */
        !           131: struct ifqueue ipintrq;
        !           132: SYSCTL_INT(_net_inet_ip, IPCTL_INTRQMAXLEN, intr_queue_maxlen, CTLFLAG_RD,
        !           133:        &ipintrq.ifq_maxlen, 0, "");
        !           134: SYSCTL_INT(_net_inet_ip, IPCTL_INTRQDROPS, intr_queue_drops, CTLFLAG_RD,
        !           135:        &ipintrq.ifq_drops, 0, "");
        !           136: 
        !           137: struct ipstat ipstat;
        !           138: SYSCTL_STRUCT(_net_inet_ip, IPCTL_STATS, stats, CTLFLAG_RD,
        !           139:        &ipstat, ipstat, "");
        !           140: 
        !           141: /* Packet reassembly stuff */
        !           142: #define IPREASS_NHASH_LOG2      6
        !           143: #define IPREASS_NHASH           (1 << IPREASS_NHASH_LOG2)
        !           144: #define IPREASS_HMASK           (IPREASS_NHASH - 1)
        !           145: #define IPREASS_HASH(x,y) \
        !           146:        ((((x) & 0xF | ((((x) >> 8) & 0xF) << 4)) ^ (y)) & IPREASS_HMASK)
        !           147: 
        !           148: static struct ipq ipq[IPREASS_NHASH];
        !           149: static int    nipq = 0;         /* total # of reass queues */
        !           150: static int    maxnipq;
        !           151: 
        !           152: #if IPCTL_DEFMTU
        !           153: SYSCTL_INT(_net_inet_ip, IPCTL_DEFMTU, mtu, CTLFLAG_RW,
        !           154:        &ip_mtu, 0, "");
        !           155: #endif
        !           156: 
        !           157: #if !defined(COMPAT_IPFW) || COMPAT_IPFW == 1
        !           158: #undef COMPAT_IPFW
        !           159: #define COMPAT_IPFW 1
        !           160: #else
        !           161: #undef COMPAT_IPFW
        !           162: #endif
        !           163: 
        !           164: #if COMPAT_IPFW
        !           165: 
        !           166: #include <netinet/ip_fw.h>
        !           167: 
        !           168: /* Firewall hooks */
        !           169: ip_fw_chk_t *ip_fw_chk_ptr;
        !           170: ip_fw_ctl_t *ip_fw_ctl_ptr;
        !           171: 
        !           172: #if DUMMYNET
        !           173: ip_dn_ctl_t *ip_dn_ctl_ptr;
        !           174: #endif
        !           175: 
        !           176: /* IP Network Address Translation (NAT) hooks */ 
        !           177: ip_nat_t *ip_nat_ptr;
        !           178: ip_nat_ctl_t *ip_nat_ctl_ptr;
        !           179: #endif
        !           180: 
        !           181: #if defined(IPFILTER_LKM) || defined(IPFILTER)
        !           182: int iplattach __P((void));
        !           183: int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **)) = NULL;
        !           184: #endif
        !           185: 
        !           186: 
        !           187: /*
        !           188:  * We need to save the IP options in case a protocol wants to respond
        !           189:  * to an incoming packet over the same route if the packet got here
        !           190:  * using IP source routing.  This allows connection establishment and
        !           191:  * maintenance when the remote end is on a network that is not known
        !           192:  * to us.
        !           193:  */
        !           194: static int     ip_nhops = 0;
        !           195: static struct ip_srcrt {
        !           196:        struct  in_addr dst;                    /* final destination */
        !           197:        char    nop;                            /* one NOP to align */
        !           198:        char    srcopt[IPOPT_OFFSET + 1];       /* OPTVAL, OLEN and OFFSET */
        !           199:        struct  in_addr route[MAX_IPOPTLEN/sizeof(struct in_addr)];
        !           200: } ip_srcrt;
        !           201: 
        !           202: #if IPDIVERT
        !           203: /*
        !           204:  * Shared variable between ip_input() and ip_reass() to communicate
        !           205:  * about which packets, once assembled from fragments, get diverted,
        !           206:  * and to which port.
        !           207:  */
        !           208: static u_short frag_divert_port;
        !           209: #endif
        !           210: 
        !           211: struct sockaddr_in *ip_fw_fwd_addr;
        !           212: 
        !           213: static void save_rte __P((u_char *, struct in_addr));
        !           214: static int      ip_dooptions __P((struct mbuf *));
        !           215: static void     ip_forward __P((struct mbuf *, int));
        !           216: static void     ip_freef __P((struct ipq *));
        !           217: static struct ip *
        !           218:         ip_reass __P((struct mbuf *, struct ipq *, struct ipq *));
        !           219: static struct in_ifaddr *
        !           220:         ip_rtaddr __P((struct in_addr));
        !           221: void   ipintr __P((void));
        !           222: /*
        !           223:  * IP initialization: fill in IP protocol switch table.
        !           224:  * All protocols not implemented in kernel go to raw IP protocol handler.
        !           225:  */
        !           226: void
        !           227: ip_init()
        !           228: {
        !           229:        register struct protosw *pr;
        !           230:        register int i;
        !           231:        static ip_initialized = 0;
        !           232: 
        !           233:        if (!ip_initialized)
        !           234:        {
        !           235:                TAILQ_INIT(&in_ifaddrhead);
        !           236:                pr = pffindproto(PF_INET, IPPROTO_RAW, SOCK_RAW);
        !           237:                if (pr == 0)
        !           238:                        panic("ip_init");
        !           239:                for (i = 0; i < IPPROTO_MAX; i++)
        !           240:                        ip_protox[i] = pr;
        !           241:                for (pr = inetdomain.dom_protosw; pr; pr = pr->pr_next)
        !           242:                {       if(!((unsigned int)pr->pr_domain)) continue;    /* If uninitialized, skip */
        !           243:                        if (pr->pr_domain->dom_family == PF_INET &&
        !           244:                            pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW)
        !           245:                                ip_protox[pr->pr_protocol] = pr;
        !           246:                }
        !           247:                for (i = 0; i < IPREASS_NHASH; i++)
        !           248:                    ipq[i].next = ipq[i].prev = &ipq[i];
        !           249: 
        !           250:                maxnipq = nmbclusters/4;
        !           251: 
        !           252:                ip_id = time_second & 0xffff;
        !           253:                ipintrq.ifq_maxlen = ipqmaxlen;
        !           254: #if DUMMYNET
        !           255:                ip_dn_init();
        !           256: #endif
        !           257: #if IPNAT
        !           258:                ip_nat_init();
        !           259: #endif
        !           260: #if IPFILTER
        !           261:                iplattach();
        !           262: #endif
        !           263:                ip_initialized = 1;
        !           264:        }
        !           265: }
        !           266: 
        !           267: /* Initialize the PF_INET domain, and add in the pre-defined protos */
        !           268: void
        !           269: in_dinit()
        !           270: {      register int i;
        !           271:        register struct protosw *pr;
        !           272:        register struct domain *dp;
        !           273:        static inetdomain_initted = 0;
        !           274:        extern int in_proto_count; 
        !           275: 
        !           276:        if (!inetdomain_initted)
        !           277:        {       kprintf("Initing %d protosw entries\n", in_proto_count);
        !           278:                dp = &inetdomain;
        !           279: 
        !           280:                for (i=0, pr = &inetsw[0]; i<in_proto_count; i++, pr++)
        !           281:                        net_add_proto(pr, dp);
        !           282:                inetdomain_initted = 1;
        !           283:        }
        !           284: }
        !           285: 
        !           286: static struct  sockaddr_in ipaddr = { sizeof(ipaddr), AF_INET };
        !           287: static struct  route ipforward_rt;
        !           288: 
        !           289: /*
        !           290:  * Ip input routine.  Checksum and byte swap header.  If fragmented
        !           291:  * try to reassemble.  Process options.  Pass to next level.
        !           292:  */
        !           293: void
        !           294: ip_input(struct mbuf *m)
        !           295: {
        !           296:        struct ip *ip;
        !           297:        struct ipq *fp;
        !           298:        struct in_ifaddr *ia;
        !           299:        int    i, hlen, mff;
        !           300:        u_short sum;
        !           301: #if !IPDIVERT /* dummy variable for the firewall code to play with */
        !           302:         u_short ip_divert_cookie = 0 ;
        !           303: #endif
        !           304: #if COMPAT_IPFW
        !           305:        struct ip_fw_chain *rule = NULL ;
        !           306: #endif
        !           307: 
        !           308: #if IPFIREWALL && DUMMYNET
        !           309:         /*
        !           310:          * dummynet packet are prepended a vestigial mbuf with
        !           311:          * m_type = MT_DUMMYNET and m_data pointing to the matching
        !           312:          * rule.
        !           313:          */
        !           314:         if (m->m_type == MT_DUMMYNET) {
        !           315:             struct mbuf *m0 = m ;
        !           316:             rule = (struct ip_fw_chain *)(m->m_data) ;
        !           317:             m = m->m_next ;
        !           318:             FREE(m0, M_IPFW);
        !           319:             ip = mtod(m, struct ip *);
        !           320:             hlen = IP_VHL_HL(ip->ip_vhl) << 2;
        !           321:             goto iphack ;
        !           322:         } else
        !           323:             rule = NULL ;
        !           324: #endif
        !           325: 
        !           326: #if    DIAGNOSTIC
        !           327:        if (m == NULL || (m->m_flags & M_PKTHDR) == 0)
        !           328:                panic("ip_input no HDR");
        !           329: #endif
        !           330:        /*
        !           331:         * If no IP addresses have been set yet but the interfaces
        !           332:         * are receiving, can't do anything with incoming packets yet.
        !           333:         * XXX This is broken! We should be able to receive broadcasts
        !           334:         * and multicasts even without any local addresses configured.
        !           335:         */
        !           336:        if (TAILQ_EMPTY(&in_ifaddrhead))
        !           337:                goto bad;
        !           338:        ipstat.ips_total++;
        !           339: 
        !           340:        if (m->m_pkthdr.len < sizeof(struct ip))
        !           341:                goto tooshort;
        !           342: 
        !           343:        if (m->m_len < sizeof (struct ip) &&
        !           344:            (m = m_pullup(m, sizeof (struct ip))) == 0) {
        !           345:                ipstat.ips_toosmall++;
        !           346:                return;
        !           347:        }
        !           348:        ip = mtod(m, struct ip *);
        !           349: 
        !           350:        if (IP_VHL_V(ip->ip_vhl) != IPVERSION) {
        !           351:                ipstat.ips_badvers++;
        !           352:                goto bad;
        !           353:        }
        !           354: 
        !           355:        hlen = IP_VHL_HL(ip->ip_vhl) << 2;
        !           356:        if (hlen < sizeof(struct ip)) { /* minimum header length */
        !           357:                ipstat.ips_badhlen++;
        !           358:                goto bad;
        !           359:        }
        !           360:        if (hlen > m->m_len) {
        !           361:                if ((m = m_pullup(m, hlen)) == 0) {
        !           362:                        ipstat.ips_badhlen++;
        !           363:                        return;
        !           364:                }
        !           365:                ip = mtod(m, struct ip *);
        !           366:        }
        !           367: 
        !           368:        sum = in_cksum(m, hlen);
        !           369: 
        !           370:        if (sum) {
        !           371:                ipstat.ips_badsum++;
        !           372:                goto bad;
        !           373:        }
        !           374: 
        !           375:        /*
        !           376:         * Convert fields to host representation.
        !           377:         */
        !           378:        NTOHS(ip->ip_len);
        !           379:        if (ip->ip_len < hlen) {
        !           380:                ipstat.ips_badlen++;
        !           381:                goto bad;
        !           382:        }
        !           383:        NTOHS(ip->ip_id);
        !           384:        NTOHS(ip->ip_off);
        !           385: 
        !           386:        /*
        !           387:         * Check that the amount of data in the buffers
        !           388:         * is as at least much as the IP header would have us expect.
        !           389:         * Trim mbufs if longer than we expect.
        !           390:         * Drop packet if shorter than we expect.
        !           391:         */
        !           392:        if (m->m_pkthdr.len < ip->ip_len) {
        !           393: tooshort:
        !           394:                ipstat.ips_tooshort++;
        !           395:                goto bad;
        !           396:        }
        !           397:        if (m->m_pkthdr.len > ip->ip_len) {
        !           398:                if (m->m_len == m->m_pkthdr.len) {
        !           399:                        m->m_len = ip->ip_len;
        !           400:                        m->m_pkthdr.len = ip->ip_len;
        !           401:                } else
        !           402:                        m_adj(m, ip->ip_len - m->m_pkthdr.len);
        !           403:        }
        !           404:        /*
        !           405:         * IpHack's section.
        !           406:         * Right now when no processing on packet has done
        !           407:         * and it is still fresh out of network we do our black
        !           408:         * deals with it.
        !           409:         * - Firewall: deny/allow/divert
        !           410:         * - Xlate: translate packet's addr/port (NAT).
        !           411:         * - Pipe: pass pkt through dummynet.
        !           412:         * - Wrap: fake packet's addr/port <unimpl.>
        !           413:         * - Encapsulate: put it in another IP and send out. <unimp.>
        !           414:         */
        !           415: 
        !           416: #if defined(IPFIREWALL) && defined(DUMMYNET)
        !           417: iphack:
        !           418: #endif
        !           419: #if defined(IPFILTER) || defined(IPFILTER_LKM)
        !           420:        /*
        !           421:         * Check if we want to allow this packet to be processed.
        !           422:         * Consider it to be bad if not.
        !           423:         */
        !           424:        if (fr_checkp) {
        !           425:                struct  mbuf    *m1 = m;
        !           426: 
        !           427:                if ((*fr_checkp)(ip, hlen, m->m_pkthdr.rcvif, 0, &m1) || !m1)
        !           428:                        return;
        !           429:                ip = mtod(m = m1, struct ip *);
        !           430:        }
        !           431: #endif
        !           432: #if COMPAT_IPFW
        !           433:        if (ip_fw_chk_ptr) {
        !           434: #if IPFIREWALL_FORWARD
        !           435:                /*
        !           436:                 * If we've been forwarded from the output side, then
        !           437:                 * skip the firewall a second time
        !           438:                 */
        !           439:                if (ip_fw_fwd_addr)
        !           440:                        goto ours;
        !           441: #endif /* IPFIREWALL_FORWARD */
        !           442:                i = (*ip_fw_chk_ptr)(&ip, hlen, NULL, &ip_divert_cookie,
        !           443:                                        &m, &rule, &ip_fw_fwd_addr);
        !           444:                /*
        !           445:                 * see the comment in ip_output for the return values
        !           446:                 * produced by the firewall.
        !           447:                 */
        !           448:                if (!m) /* packet discarded by firewall */
        !           449:                        return ;
        !           450:                if (i == 0 && ip_fw_fwd_addr == NULL) /* common case */
        !           451:                        goto pass ;
        !           452: #if DUMMYNET
        !           453:                 if (i & 0x10000) {
        !           454:                         /* send packet to the appropriate pipe */
        !           455:                         dummynet_io(i&0xffff,DN_TO_IP_IN,m,NULL,NULL,0, rule);
        !           456:                        return ;
        !           457:                }
        !           458: #endif
        !           459: #if IPDIVERT
        !           460:                if (i > 0 && i < 0x10000) {
        !           461:                        /* Divert packet */
        !           462:                        frag_divert_port = i & 0xffff ;
        !           463:                        goto ours;
        !           464:                }
        !           465: #endif
        !           466: #if IPFIREWALL_FORWARD
        !           467:                if (i == 0 && ip_fw_fwd_addr != NULL)
        !           468:                        goto pass ;
        !           469: #endif
        !           470:                /*
        !           471:                 * if we get here, the packet must be dropped
        !           472:                 */
        !           473:                        m_freem(m);
        !           474:                        return;
        !           475:        }
        !           476: pass:
        !           477: 
        !           478:         if (ip_nat_ptr && !(*ip_nat_ptr)(&ip, &m, m->m_pkthdr.rcvif, IP_NAT_IN))
        !           479:                return;
        !           480: #endif /* !COMPAT_IPFW */
        !           481: 
        !           482:        /*
        !           483:         * Process options and, if not destined for us,
        !           484:         * ship it on.  ip_dooptions returns 1 when an
        !           485:         * error was detected (causing an icmp message
        !           486:         * to be sent and the original packet to be freed).
        !           487:         */
        !           488:        ip_nhops = 0;           /* for source routed packets */
        !           489:        if (hlen > sizeof (struct ip) && ip_dooptions(m))
        !           490:                return;
        !           491: 
        !           492:         /* greedy RSVP, snatches any PATH packet of the RSVP protocol and no
        !           493:          * matter if it is destined to another node, or whether it is 
        !           494:          * a multicast one, RSVP wants it! and prevents it from being forwarded
        !           495:          * anywhere else. Also checks if the rsvp daemon is running before
        !           496:         * grabbing the packet.
        !           497:          */
        !           498:        if (rsvp_on && ip->ip_p==IPPROTO_RSVP) 
        !           499:                goto ours;
        !           500: 
        !           501:        /*
        !           502:         * Check our list of addresses, to see if the packet is for us.
        !           503:         */
        !           504:        for (ia = TAILQ_FIRST(&in_ifaddrhead); ia;
        !           505:                                        ia = TAILQ_NEXT(ia, ia_link)) {
        !           506: #define        satosin(sa)     ((struct sockaddr_in *)(sa))
        !           507: 
        !           508:                if (IA_SIN(ia)->sin_addr.s_addr == ip->ip_dst.s_addr)
        !           509:                        goto ours;
        !           510: 
        !           511:                if (IA_SIN(ia)->sin_addr.s_addr == INADDR_ANY)
        !           512:                        goto ours;
        !           513: 
        !           514: #if IPFIREWALL_FORWARD
        !           515:                /*
        !           516:                 * If the addr to forward to is one of ours, we pretend to
        !           517:                 * be the destination for this packet.
        !           518:                 */
        !           519:                if (ip_fw_fwd_addr != NULL &&
        !           520:                        IA_SIN(ia)->sin_addr.s_addr ==
        !           521:                                         ip_fw_fwd_addr->sin_addr.s_addr)
        !           522:                        goto ours;
        !           523: #endif
        !           524:                if (ia->ia_ifp && ia->ia_ifp->if_flags & IFF_BROADCAST) {
        !           525:                        if (satosin(&ia->ia_broadaddr)->sin_addr.s_addr ==
        !           526:                            ip->ip_dst.s_addr)
        !           527:                                goto ours;
        !           528:                        if (ip->ip_dst.s_addr == ia->ia_netbroadcast.s_addr)
        !           529:                                goto ours;
        !           530:                }
        !           531:        }
        !           532:        if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) {
        !           533:                struct in_multi *inm;
        !           534:                if (ip_mrouter) {
        !           535:                        /*
        !           536:                         * If we are acting as a multicast router, all
        !           537:                         * incoming multicast packets are passed to the
        !           538:                         * kernel-level multicast forwarding function.
        !           539:                         * The packet is returned (relatively) intact; if
        !           540:                         * ip_mforward() returns a non-zero value, the packet
        !           541:                         * must be discarded, else it may be accepted below.
        !           542:                         *
        !           543:                         * (The IP ident field is put in the same byte order
        !           544:                         * as expected when ip_mforward() is called from
        !           545:                         * ip_output().)
        !           546:                         */
        !           547:                        ip->ip_id = htons(ip->ip_id);
        !           548:                        if (ip_mforward(ip, m->m_pkthdr.rcvif, m, 0) != 0) {
        !           549:                                ipstat.ips_cantforward++;
        !           550:                                m_freem(m);
        !           551:                                return;
        !           552:                        }
        !           553:                        ip->ip_id = ntohs(ip->ip_id);
        !           554: 
        !           555:                        /*
        !           556:                         * The process-level routing demon needs to receive
        !           557:                         * all multicast IGMP packets, whether or not this
        !           558:                         * host belongs to their destination groups.
        !           559:                         */
        !           560:                        if (ip->ip_p == IPPROTO_IGMP)
        !           561:                                goto ours;
        !           562:                        ipstat.ips_forward++;
        !           563:                }
        !           564:                /*
        !           565:                 * See if we belong to the destination multicast group on the
        !           566:                 * arrival interface.
        !           567:                 */
        !           568:                IN_LOOKUP_MULTI(ip->ip_dst, m->m_pkthdr.rcvif, inm);
        !           569:                if (inm == NULL) {
        !           570:                        ipstat.ips_notmember++;
        !           571:                        m_freem(m);
        !           572:                        return;
        !           573:                }
        !           574:                goto ours;
        !           575:        }
        !           576:        if (ip->ip_dst.s_addr == (u_long)INADDR_BROADCAST)
        !           577:                goto ours;
        !           578:        if (ip->ip_dst.s_addr == INADDR_ANY)
        !           579:                goto ours;
        !           580: 
        !           581:        /*
        !           582:         * Not for us; forward if possible and desirable.
        !           583:         */
        !           584:        if (ipforwarding == 0) {
        !           585:                ipstat.ips_cantforward++;
        !           586:                m_freem(m);
        !           587:        } else
        !           588:                ip_forward(m, 0);
        !           589:        return;
        !           590: 
        !           591: ours:
        !           592: 
        !           593:        /*
        !           594:         * If offset or IP_MF are set, must reassemble.
        !           595:         * Otherwise, nothing need be done.
        !           596:         * (We could look in the reassembly queue to see
        !           597:         * if the packet was previously fragmented,
        !           598:         * but it's not worth the time; just let them time out.)
        !           599:         */
        !           600:        if (ip->ip_off & (IP_MF | IP_OFFMASK | IP_RF)) {
        !           601:                if (m->m_flags & M_EXT) {               /* XXX */
        !           602:                        if ((m = m_pullup(m, hlen)) == 0) {
        !           603:                                ipstat.ips_toosmall++;
        !           604: #if IPDIVERT
        !           605:                                frag_divert_port = 0;
        !           606:                                ip_divert_cookie = 0;
        !           607: #endif
        !           608:                                return;
        !           609:                        }
        !           610:                        ip = mtod(m, struct ip *);
        !           611:                }
        !           612:                sum = IPREASS_HASH(ip->ip_src.s_addr, ip->ip_id);
        !           613:                /*
        !           614:                 * Look for queue of fragments
        !           615:                 * of this datagram.
        !           616:                 */
        !           617:                for (fp = ipq[sum].next; fp != &ipq[sum]; fp = fp->next)
        !           618:                        if (ip->ip_id == fp->ipq_id &&
        !           619:                            ip->ip_src.s_addr == fp->ipq_src.s_addr &&
        !           620:                            ip->ip_dst.s_addr == fp->ipq_dst.s_addr &&
        !           621:                            ip->ip_p == fp->ipq_p)
        !           622:                                goto found;
        !           623: 
        !           624:                fp = 0;
        !           625: 
        !           626:                /* check if there's a place for the new queue */
        !           627:                if (nipq > maxnipq) {
        !           628:                    /*
        !           629:                     * drop something from the tail of the current queue
        !           630:                     * before proceeding further
        !           631:                     */
        !           632:                    if (ipq[sum].prev == &ipq[sum]) {   /* gak */
        !           633:                        for (i = 0; i < IPREASS_NHASH; i++) {
        !           634:                            if (ipq[i].prev != &ipq[i]) {
        !           635:                                ip_freef(ipq[i].prev);
        !           636:                                break;
        !           637:                            }
        !           638:                        }
        !           639:                    } else
        !           640:                        ip_freef(ipq[sum].prev);
        !           641:                }
        !           642: found:
        !           643:                /*
        !           644:                 * Adjust ip_len to not reflect header,
        !           645:                 * set ip_mff if more fragments are expected,
        !           646:                 * convert offset of this to bytes.
        !           647:                 */
        !           648:                ip->ip_len -= hlen;
        !           649:                mff = (ip->ip_off & IP_MF) != 0;
        !           650:                if (mff) {
        !           651:                        /*
        !           652:                         * Make sure that fragments have a data length
        !           653:                         * that's a non-zero multiple of 8 bytes.
        !           654:                         */
        !           655:                        if (ip->ip_len == 0 || (ip->ip_len & 0x7) != 0) {
        !           656:                                ipstat.ips_toosmall++; /* XXX */
        !           657:                                goto bad;
        !           658:                        }
        !           659:                        m->m_flags |= M_FRAG;
        !           660:                }
        !           661:                ip->ip_off <<= 3;
        !           662: 
        !           663:                /*
        !           664:                 * If datagram marked as having more fragments
        !           665:                 * or if this is not the first fragment,
        !           666:                 * attempt reassembly; if it succeeds, proceed.
        !           667:                 */
        !           668:                if (mff || ip->ip_off) {
        !           669:                        ipstat.ips_fragments++;
        !           670:                        m->m_pkthdr.header = ip;
        !           671:                        ip = ip_reass(m, fp, &ipq[sum]);
        !           672:                        if (ip == 0) {
        !           673: #if    IPFIREWALL_FORWARD
        !           674:                                ip_fw_fwd_addr = NULL;
        !           675: #endif
        !           676:                                return;
        !           677:                        }
        !           678:                        /* Get the length of the reassembled packets header */
        !           679:                        hlen = IP_VHL_HL(ip->ip_vhl) << 2;
        !           680:                        ipstat.ips_reassembled++;
        !           681:                        m = dtom(ip);
        !           682: #if IPDIVERT
        !           683:                        if (frag_divert_port) {
        !           684:                                struct mbuf m;
        !           685:                                m.m_next = 0;
        !           686:                                m.m_len = hlen;
        !           687:                                m.m_data = (char *) ip;
        !           688:                                ip->ip_len += hlen;
        !           689:                                HTONS(ip->ip_len);
        !           690:                                HTONS(ip->ip_off);
        !           691:                                HTONS(ip->ip_id);
        !           692:                                ip->ip_sum = 0;
        !           693:                                ip->ip_sum = in_cksum(&m, hlen);
        !           694:                                NTOHS(ip->ip_id);
        !           695:                                NTOHS(ip->ip_off);
        !           696:                                NTOHS(ip->ip_len);
        !           697:                                ip->ip_len -= hlen;
        !           698:                        }
        !           699: #endif
        !           700:                } else
        !           701:                        if (fp)
        !           702:                                ip_freef(fp);
        !           703:        } else
        !           704:                ip->ip_len -= hlen;
        !           705: 
        !           706: #if IPDIVERT
        !           707:        /*
        !           708:         * Divert reassembled packets to the divert protocol if required
        !           709:         *  If divert port is null then cookie should be too,
        !           710:         * so we shouldn't need to clear them here. Assume ip_divert does so.
        !           711:         */
        !           712:        if (frag_divert_port) {
        !           713:                ipstat.ips_delivered++;
        !           714:                ip_divert_port = frag_divert_port;
        !           715:                frag_divert_port = 0;
        !           716:                (*ip_protox[IPPROTO_DIVERT]->pr_input)(m, hlen);
        !           717:                return;
        !           718:        }
        !           719: 
        !           720:        /* Don't let packets divert themselves */
        !           721:        if (ip->ip_p == IPPROTO_DIVERT) {
        !           722:                ipstat.ips_noproto++;
        !           723:                goto bad;
        !           724:        }
        !           725: 
        !           726: #endif
        !           727: 
        !           728:        /*
        !           729:         * Switch out to protocol's input routine.
        !           730:         */
        !           731:        ipstat.ips_delivered++;
        !           732:        (*ip_protox[ip->ip_p]->pr_input)(m, hlen);
        !           733: #if    IPFIREWALL_FORWARD
        !           734:        ip_fw_fwd_addr = NULL;  /* tcp needed it */
        !           735: #endif
        !           736:        return;
        !           737: bad:
        !           738: #if    IPFIREWALL_FORWARD
        !           739:        ip_fw_fwd_addr = NULL;
        !           740: #endif
        !           741:        m_freem(m);
        !           742: }
        !           743: 
        !           744: /*
        !           745:  * IP software interrupt routine - to go away sometime soon
        !           746:  */
        !           747: void
        !           748: ipintr(void)
        !           749: {
        !           750:        int s;
        !           751:        struct mbuf *m;
        !           752: 
        !           753:        while(1) {
        !           754:                s = splimp();
        !           755:                IF_DEQUEUE(&ipintrq, m);
        !           756:                splx(s);
        !           757:                if (m == 0) 
        !           758:                    return;
        !           759: 
        !           760:                ip_input(m);
        !           761:        }
        !           762: }
        !           763: 
        !           764: NETISR_SET(NETISR_IP, ipintr);
        !           765:   
        !           766: /*
        !           767:  * Take incoming datagram fragment and try to
        !           768:  * reassemble it into whole datagram.  If a chain for
        !           769:  * reassembly of this datagram already exists, then it
        !           770:  * is given as fp; otherwise have to make a chain.
        !           771:  */
        !           772: static struct ip *
        !           773: ip_reass(m, fp, where)
        !           774:        register struct mbuf *m;
        !           775:        register struct ipq *fp;
        !           776:        struct   ipq    *where;
        !           777: {
        !           778:        struct ip *ip = mtod(m, struct ip *);
        !           779:        register struct mbuf *p = 0, *q, *nq;
        !           780:        struct mbuf *t;
        !           781:        int hlen = IP_VHL_HL(ip->ip_vhl) << 2;
        !           782:        int i, next;
        !           783: 
        !           784:        /*
        !           785:         * Presence of header sizes in mbufs
        !           786:         * would confuse code below.
        !           787:         */
        !           788:        m->m_data += hlen;
        !           789:        m->m_len -= hlen;
        !           790: 
        !           791:        /*
        !           792:         * If first fragment to arrive, create a reassembly queue.
        !           793:         */
        !           794:        if (fp == 0) {
        !           795:                if ((t = m_get(M_DONTWAIT, MT_FTABLE)) == NULL)
        !           796:                        goto dropfrag;
        !           797:                fp = mtod(t, struct ipq *);
        !           798:                insque((void *) fp, (void *) where);
        !           799:                nipq++;
        !           800:                fp->ipq_ttl = IPFRAGTTL;
        !           801:                fp->ipq_p = ip->ip_p;
        !           802:                fp->ipq_id = ip->ip_id;
        !           803:                fp->ipq_src = ip->ip_src;
        !           804:                fp->ipq_dst = ip->ip_dst;
        !           805:                fp->ipq_frags = m;
        !           806:                m->m_nextpkt = NULL;
        !           807: #if IPDIVERT
        !           808:                fp->ipq_divert = 0;
        !           809:                fp->ipq_div_cookie = 0;
        !           810: #endif
        !           811:                goto inserted;
        !           812:        }
        !           813: 
        !           814: #define GETIP(m)       ((struct ip*)((m)->m_pkthdr.header))
        !           815: 
        !           816:        /*
        !           817:         * Find a segment which begins after this one does.
        !           818:         */
        !           819:        for (p = NULL, q = fp->ipq_frags; q; p = q, q = q->m_nextpkt)
        !           820:                if (GETIP(q)->ip_off > ip->ip_off)
        !           821:                        break;
        !           822: 
        !           823:        /*
        !           824:         * If there is a preceding segment, it may provide some of
        !           825:         * our data already.  If so, drop the data from the incoming
        !           826:         * segment.  If it provides all of our data, drop us, otherwise
        !           827:         * stick new segment in the proper place.
        !           828:         */
        !           829:        if (p) {
        !           830:                i = GETIP(p)->ip_off + GETIP(p)->ip_len - ip->ip_off;
        !           831:                if (i > 0) {
        !           832:                        if (i >= ip->ip_len)
        !           833:                                goto dropfrag;
        !           834:                        m_adj(dtom(ip), i);
        !           835:                        ip->ip_off += i;
        !           836:                        ip->ip_len -= i;
        !           837:                }
        !           838:                m->m_nextpkt = p->m_nextpkt;
        !           839:                p->m_nextpkt = m;
        !           840:        } else {
        !           841:                m->m_nextpkt = fp->ipq_frags;
        !           842:                fp->ipq_frags = m;
        !           843:        }
        !           844: 
        !           845:        /*
        !           846:         * While we overlap succeeding segments trim them or,
        !           847:         * if they are completely covered, dequeue them.
        !           848:         */
        !           849:        for (; q != NULL && ip->ip_off + ip->ip_len > GETIP(q)->ip_off;
        !           850:             q = nq) {
        !           851:                i = (ip->ip_off + ip->ip_len) -
        !           852:                    GETIP(q)->ip_off;
        !           853:                if (i < GETIP(q)->ip_len) {
        !           854:                        GETIP(q)->ip_len -= i;
        !           855:                        GETIP(q)->ip_off += i;
        !           856:                        m_adj(q, i);
        !           857:                        break;
        !           858:                }
        !           859:                nq = q->m_nextpkt;
        !           860:                m->m_nextpkt = nq;
        !           861:                m_freem(q);
        !           862:        }
        !           863: 
        !           864: inserted:
        !           865: 
        !           866: #if IPDIVERT
        !           867:        /*
        !           868:         * Any fragment diverting causes the whole packet to divert
        !           869:         */
        !           870:        if (frag_divert_port) {
        !           871:                fp->ipq_divert = frag_divert_port;
        !           872:                fp->ipq_div_cookie = ip_divert_cookie;
        !           873:        }
        !           874:        frag_divert_port = 0;
        !           875:        ip_divert_cookie = 0;
        !           876: #endif
        !           877: 
        !           878:        /*
        !           879:         * Check for complete reassembly.
        !           880:         */
        !           881:        next = 0;
        !           882:        for (p = NULL, q = fp->ipq_frags; q; p = q, q = q->m_nextpkt) {
        !           883:                if (GETIP(q)->ip_off != next)
        !           884:                        return (0);
        !           885:                next += GETIP(q)->ip_len;
        !           886:        }
        !           887:        /* Make sure the last packet didn't have the IP_MF flag */
        !           888:        if (p->m_flags & M_FRAG)
        !           889:                return (0);
        !           890: 
        !           891:        /*
        !           892:         * Reassembly is complete.  Make sure the packet is a sane size.
        !           893:         */
        !           894:        q = fp->ipq_frags;
        !           895:        ip = GETIP(q);
        !           896:        if (next + (IP_VHL_HL(ip->ip_vhl) << 2) > IP_MAXPACKET) {
        !           897:                ipstat.ips_toolong++;
        !           898:                ip_freef(fp);
        !           899:                return (0);
        !           900:        }
        !           901: 
        !           902:        /*
        !           903:         * Concatenate fragments.
        !           904:         */
        !           905:        m = q;
        !           906:        t = m->m_next;
        !           907:        m->m_next = 0;
        !           908:        m_cat(m, t);
        !           909:        nq = q->m_nextpkt;
        !           910:        q->m_nextpkt = 0;
        !           911:        for (q = nq; q != NULL; q = nq) {
        !           912:                nq = q->m_nextpkt;
        !           913:                q->m_nextpkt = NULL;
        !           914:                m_cat(m, q);
        !           915:        }
        !           916: 
        !           917: #if IPDIVERT
        !           918:        /*
        !           919:         * extract divert port for packet, if any
        !           920:         */
        !           921:        frag_divert_port = fp->ipq_divert;
        !           922:        ip_divert_cookie = fp->ipq_div_cookie;
        !           923: #endif
        !           924: 
        !           925:        /*
        !           926:         * Create header for new ip packet by
        !           927:         * modifying header of first packet;
        !           928:         * dequeue and discard fragment reassembly header.
        !           929:         * Make header visible.
        !           930:         */
        !           931:        ip->ip_len = next;
        !           932:        ip->ip_src = fp->ipq_src;
        !           933:        ip->ip_dst = fp->ipq_dst;
        !           934:        remque((void *) fp);
        !           935:        nipq--;
        !           936:        (void) m_free(dtom(fp));
        !           937:        m->m_len += (IP_VHL_HL(ip->ip_vhl) << 2);
        !           938:        m->m_data -= (IP_VHL_HL(ip->ip_vhl) << 2);
        !           939:        /* some debugging cruft by sklower, below, will go away soon */
        !           940:        if (m->m_flags & M_PKTHDR) { /* XXX this should be done elsewhere */
        !           941:                register int plen = 0;
        !           942:                for (t = m; m; m = m->m_next)
        !           943:                        plen += m->m_len;
        !           944:                t->m_pkthdr.len = plen;
        !           945:        }
        !           946:        return (ip);
        !           947: 
        !           948: dropfrag:
        !           949: #if IPDIVERT
        !           950:        frag_divert_port = 0;
        !           951:        ip_divert_cookie = 0;
        !           952: #endif
        !           953:        ipstat.ips_fragdropped++;
        !           954:        m_freem(m);
        !           955:        return (0);
        !           956: 
        !           957: #undef GETIP
        !           958: }
        !           959: 
        !           960: /*
        !           961:  * Free a fragment reassembly header and all
        !           962:  * associated datagrams.
        !           963:  */
        !           964: static void
        !           965: ip_freef(fp)
        !           966:        struct ipq *fp;
        !           967: {
        !           968:        register struct mbuf *q;
        !           969: 
        !           970:        while (fp->ipq_frags) {
        !           971:                q = fp->ipq_frags;
        !           972:                fp->ipq_frags = q->m_nextpkt;
        !           973:                m_freem(q);
        !           974:        }
        !           975:        remque((void *) fp);
        !           976:        (void) m_free(dtom(fp));
        !           977:        nipq--;
        !           978: }
        !           979: 
        !           980: /*
        !           981:  * IP timer processing;
        !           982:  * if a timer expires on a reassembly
        !           983:  * queue, discard it.
        !           984:  */
        !           985: void
        !           986: ip_slowtimo()
        !           987: {
        !           988:        register struct ipq *fp;
        !           989:        int s = splnet();
        !           990:        int i;
        !           991: 
        !           992:        for (i = 0; i < IPREASS_NHASH; i++) {
        !           993:                fp = ipq[i].next;
        !           994:                if (fp == 0)
        !           995:                        continue;
        !           996:                while (fp != &ipq[i]) {
        !           997:                        --fp->ipq_ttl;
        !           998:                        fp = fp->next;
        !           999:                        if (fp->prev->ipq_ttl == 0) {
        !          1000:                                ipstat.ips_fragtimeout++;
        !          1001:                                ip_freef(fp->prev);
        !          1002:                        }
        !          1003:                }
        !          1004:        }
        !          1005:        ipflow_slowtimo();
        !          1006:        splx(s);
        !          1007: }
        !          1008: 
        !          1009: /*
        !          1010:  * Drain off all datagram fragments.
        !          1011:  */
        !          1012: void
        !          1013: ip_drain()
        !          1014: {
        !          1015:        int     i;
        !          1016: 
        !          1017:        for (i = 0; i < IPREASS_NHASH; i++) {
        !          1018:                while (ipq[i].next != &ipq[i]) {
        !          1019:                        ipstat.ips_fragdropped++;
        !          1020:                        ip_freef(ipq[i].next);
        !          1021:                }
        !          1022:        }
        !          1023:        in_rtqdrain();
        !          1024: }
        !          1025: 
        !          1026: /*
        !          1027:  * Do option processing on a datagram,
        !          1028:  * possibly discarding it if bad options are encountered,
        !          1029:  * or forwarding it if source-routed.
        !          1030:  * Returns 1 if packet has been forwarded/freed,
        !          1031:  * 0 if the packet should be processed further.
        !          1032:  */
        !          1033: static int
        !          1034: ip_dooptions(m)
        !          1035:        struct mbuf *m;
        !          1036: {
        !          1037:        register struct ip *ip = mtod(m, struct ip *);
        !          1038:        register u_char *cp;
        !          1039:        register struct ip_timestamp *ipt;
        !          1040:        register struct in_ifaddr *ia;
        !          1041:        int opt, optlen, cnt, off, code, type = ICMP_PARAMPROB, forward = 0;
        !          1042:        struct in_addr *sin, dst;
        !          1043:        n_time ntime;
        !          1044: 
        !          1045:        dst = ip->ip_dst;
        !          1046:        cp = (u_char *)(ip + 1);
        !          1047:        cnt = (IP_VHL_HL(ip->ip_vhl) << 2) - sizeof (struct ip);
        !          1048:        for (; cnt > 0; cnt -= optlen, cp += optlen) {
        !          1049:                opt = cp[IPOPT_OPTVAL];
        !          1050:                if (opt == IPOPT_EOL)
        !          1051:                        break;
        !          1052:                if (opt == IPOPT_NOP)
        !          1053:                        optlen = 1;
        !          1054:                else {
        !          1055:                        optlen = cp[IPOPT_OLEN];
        !          1056:                        if (optlen <= 0 || optlen > cnt) {
        !          1057:                                code = &cp[IPOPT_OLEN] - (u_char *)ip;
        !          1058:                                goto bad;
        !          1059:                        }
        !          1060:                }
        !          1061:                switch (opt) {
        !          1062: 
        !          1063:                default:
        !          1064:                        break;
        !          1065: 
        !          1066:                /*
        !          1067:                 * Source routing with record.
        !          1068:                 * Find interface with current destination address.
        !          1069:                 * If none on this machine then drop if strictly routed,
        !          1070:                 * or do nothing if loosely routed.
        !          1071:                 * Record interface address and bring up next address
        !          1072:                 * component.  If strictly routed make sure next
        !          1073:                 * address is on directly accessible net.
        !          1074:                 */
        !          1075:                case IPOPT_LSRR:
        !          1076:                case IPOPT_SSRR:
        !          1077:                        if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) {
        !          1078:                                code = &cp[IPOPT_OFFSET] - (u_char *)ip;
        !          1079:                                goto bad;
        !          1080:                        }
        !          1081:                        ipaddr.sin_addr = ip->ip_dst;
        !          1082:                        ia = (struct in_ifaddr *)
        !          1083:                                ifa_ifwithaddr((struct sockaddr *)&ipaddr);
        !          1084:                        if (ia == 0) {
        !          1085:                                if (opt == IPOPT_SSRR) {
        !          1086:                                        type = ICMP_UNREACH;
        !          1087:                                        code = ICMP_UNREACH_SRCFAIL;
        !          1088:                                        goto bad;
        !          1089:                                }
        !          1090:                                if (!ip_dosourceroute)
        !          1091:                                        goto nosourcerouting;
        !          1092:                                /*
        !          1093:                                 * Loose routing, and not at next destination
        !          1094:                                 * yet; nothing to do except forward.
        !          1095:                                 */
        !          1096:                                break;
        !          1097:                        }
        !          1098:                        off--;                  /* 0 origin */
        !          1099:                        if (off > optlen - sizeof(struct in_addr)) {
        !          1100:                                /*
        !          1101:                                 * End of source route.  Should be for us.
        !          1102:                                 */
        !          1103:                                if (!ip_acceptsourceroute)
        !          1104:                                        goto nosourcerouting;
        !          1105:                                save_rte(cp, ip->ip_src);
        !          1106:                                break;
        !          1107:                        }
        !          1108: 
        !          1109:                        if (!ip_dosourceroute) {
        !          1110:                                if (ipforwarding) {
        !          1111:                                        char buf[16]; /* aaa.bbb.ccc.ddd\0 */
        !          1112:                                        /*
        !          1113:                                         * Acting as a router, so generate ICMP
        !          1114:                                         */
        !          1115: nosourcerouting:
        !          1116:                                        strcpy(buf, inet_ntoa(ip->ip_dst));
        !          1117:                                        log(LOG_WARNING, 
        !          1118:                                            "attempted source route from %s to %s\n",
        !          1119:                                            inet_ntoa(ip->ip_src), buf);
        !          1120:                                        type = ICMP_UNREACH;
        !          1121:                                        code = ICMP_UNREACH_SRCFAIL;
        !          1122:                                        goto bad;
        !          1123:                                } else {
        !          1124:                                        /*
        !          1125:                                         * Not acting as a router, so silently drop.
        !          1126:                                         */
        !          1127:                                        ipstat.ips_cantforward++;
        !          1128:                                        m_freem(m);
        !          1129:                                        return (1);
        !          1130:                                }
        !          1131:                        }
        !          1132: 
        !          1133:                        /*
        !          1134:                         * locate outgoing interface
        !          1135:                         */
        !          1136:                        (void)memcpy(&ipaddr.sin_addr, cp + off,
        !          1137:                            sizeof(ipaddr.sin_addr));
        !          1138: 
        !          1139:                        if (opt == IPOPT_SSRR) {
        !          1140: #define        INA     struct in_ifaddr *
        !          1141: #define        SA      struct sockaddr *
        !          1142:                            if ((ia = (INA)ifa_ifwithdstaddr((SA)&ipaddr)) == 0)
        !          1143:                                ia = (INA)ifa_ifwithnet((SA)&ipaddr);
        !          1144:                        } else
        !          1145:                                ia = ip_rtaddr(ipaddr.sin_addr);
        !          1146:                        if (ia == 0) {
        !          1147:                                type = ICMP_UNREACH;
        !          1148:                                code = ICMP_UNREACH_SRCFAIL;
        !          1149:                                goto bad;
        !          1150:                        }
        !          1151:                        ip->ip_dst = ipaddr.sin_addr;
        !          1152:                        (void)memcpy(cp + off, &(IA_SIN(ia)->sin_addr),
        !          1153:                            sizeof(struct in_addr));
        !          1154:                        cp[IPOPT_OFFSET] += sizeof(struct in_addr);
        !          1155:                        /*
        !          1156:                         * Let ip_intr's mcast routing check handle mcast pkts
        !          1157:                         */
        !          1158:                        forward = !IN_MULTICAST(ntohl(ip->ip_dst.s_addr));
        !          1159:                        break;
        !          1160: 
        !          1161:                case IPOPT_RR:
        !          1162:                        if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) {
        !          1163:                                code = &cp[IPOPT_OFFSET] - (u_char *)ip;
        !          1164:                                goto bad;
        !          1165:                        }
        !          1166:                        /*
        !          1167:                         * If no space remains, ignore.
        !          1168:                         */
        !          1169:                        off--;                  /* 0 origin */
        !          1170:                        if (off > optlen - sizeof(struct in_addr))
        !          1171:                                break;
        !          1172:                        (void)memcpy(&ipaddr.sin_addr, &ip->ip_dst,
        !          1173:                            sizeof(ipaddr.sin_addr));
        !          1174:                        /*
        !          1175:                         * locate outgoing interface; if we're the destination,
        !          1176:                         * use the incoming interface (should be same).
        !          1177:                         */
        !          1178:                        if ((ia = (INA)ifa_ifwithaddr((SA)&ipaddr)) == 0 &&
        !          1179:                            (ia = ip_rtaddr(ipaddr.sin_addr)) == 0) {
        !          1180:                                type = ICMP_UNREACH;
        !          1181:                                code = ICMP_UNREACH_HOST;
        !          1182:                                goto bad;
        !          1183:                        }
        !          1184:                        (void)memcpy(cp + off, &(IA_SIN(ia)->sin_addr),
        !          1185:                            sizeof(struct in_addr));
        !          1186:                        cp[IPOPT_OFFSET] += sizeof(struct in_addr);
        !          1187:                        break;
        !          1188: 
        !          1189:                case IPOPT_TS:
        !          1190:                        code = cp - (u_char *)ip;
        !          1191:                        ipt = (struct ip_timestamp *)cp;
        !          1192:                        if (ipt->ipt_len < 5)
        !          1193:                                goto bad;
        !          1194:                        if (ipt->ipt_ptr > ipt->ipt_len - sizeof(int32_t)) {
        !          1195:                                if (++ipt->ipt_oflw == 0)
        !          1196:                                        goto bad;
        !          1197:                                break;
        !          1198:                        }
        !          1199:                        sin = (struct in_addr *)(cp + ipt->ipt_ptr - 1);
        !          1200:                        switch (ipt->ipt_flg) {
        !          1201: 
        !          1202:                        case IPOPT_TS_TSONLY:
        !          1203:                                break;
        !          1204: 
        !          1205:                        case IPOPT_TS_TSANDADDR:
        !          1206:                                if (ipt->ipt_ptr - 1 + sizeof(n_time) +
        !          1207:                                    sizeof(struct in_addr) > ipt->ipt_len)
        !          1208:                                        goto bad;
        !          1209:                                ipaddr.sin_addr = dst;
        !          1210:                                ia = (INA)ifaof_ifpforaddr((SA)&ipaddr,
        !          1211:                                                            m->m_pkthdr.rcvif);
        !          1212:                                if (ia == 0)
        !          1213:                                        continue;
        !          1214:                                (void)memcpy(sin, &IA_SIN(ia)->sin_addr,
        !          1215:                                    sizeof(struct in_addr));
        !          1216:                                ipt->ipt_ptr += sizeof(struct in_addr);
        !          1217:                                break;
        !          1218: 
        !          1219:                        case IPOPT_TS_PRESPEC:
        !          1220:                                if (ipt->ipt_ptr - 1 + sizeof(n_time) +
        !          1221:                                    sizeof(struct in_addr) > ipt->ipt_len)
        !          1222:                                        goto bad;
        !          1223:                                (void)memcpy(&ipaddr.sin_addr, sin,
        !          1224:                                    sizeof(struct in_addr));
        !          1225:                                if (ifa_ifwithaddr((SA)&ipaddr) == 0)
        !          1226:                                        continue;
        !          1227:                                ipt->ipt_ptr += sizeof(struct in_addr);
        !          1228:                                break;
        !          1229: 
        !          1230:                        default:
        !          1231:                                goto bad;
        !          1232:                        }
        !          1233:                        ntime = iptime();
        !          1234:                        (void)memcpy(cp + ipt->ipt_ptr - 1, &ntime,
        !          1235:                            sizeof(n_time));
        !          1236:                        ipt->ipt_ptr += sizeof(n_time);
        !          1237:                }
        !          1238:        }
        !          1239:        if (forward && ipforwarding) {
        !          1240:                ip_forward(m, 1);
        !          1241:                return (1);
        !          1242:        }
        !          1243:        return (0);
        !          1244: bad:
        !          1245:        ip->ip_len -= IP_VHL_HL(ip->ip_vhl) << 2;   /* XXX icmp_error adds in hdr length */
        !          1246:        icmp_error(m, type, code, 0, 0);
        !          1247:        ipstat.ips_badoptions++;
        !          1248:        return (1);
        !          1249: }
        !          1250: 
        !          1251: /*
        !          1252:  * Given address of next destination (final or next hop),
        !          1253:  * return internet address info of interface to be used to get there.
        !          1254:  */
        !          1255: static struct in_ifaddr *
        !          1256: ip_rtaddr(dst)
        !          1257:         struct in_addr dst;
        !          1258: {
        !          1259:        register struct sockaddr_in *sin;
        !          1260: 
        !          1261:        sin = (struct sockaddr_in *) &ipforward_rt.ro_dst;
        !          1262: 
        !          1263:        if (ipforward_rt.ro_rt == 0 || dst.s_addr != sin->sin_addr.s_addr) {
        !          1264:                if (ipforward_rt.ro_rt) {
        !          1265:                        RTFREE(ipforward_rt.ro_rt);
        !          1266:                        ipforward_rt.ro_rt = 0;
        !          1267:                }
        !          1268:                sin->sin_family = AF_INET;
        !          1269:                sin->sin_len = sizeof(*sin);
        !          1270:                sin->sin_addr = dst;
        !          1271: 
        !          1272:                rtalloc_ign(&ipforward_rt, RTF_PRCLONING);
        !          1273:        }
        !          1274:        if (ipforward_rt.ro_rt == 0)
        !          1275:                return ((struct in_ifaddr *)0);
        !          1276:        return ((struct in_ifaddr *) ipforward_rt.ro_rt->rt_ifa);
        !          1277: }
        !          1278: 
        !          1279: /*
        !          1280:  * Save incoming source route for use in replies,
        !          1281:  * to be picked up later by ip_srcroute if the receiver is interested.
        !          1282:  */
        !          1283: void
        !          1284: save_rte(option, dst)
        !          1285:        u_char *option;
        !          1286:        struct in_addr dst;
        !          1287: {
        !          1288:        unsigned olen;
        !          1289: 
        !          1290:        olen = option[IPOPT_OLEN];
        !          1291: #if DIAGNOSTIC
        !          1292:        if (ipprintfs)
        !          1293:                printf("save_rte: olen %d\n", olen);
        !          1294: #endif
        !          1295:        if (olen > sizeof(ip_srcrt) - (1 + sizeof(dst)))
        !          1296:                return;
        !          1297:        bcopy(option, ip_srcrt.srcopt, olen);
        !          1298:        ip_nhops = (olen - IPOPT_OFFSET - 1) / sizeof(struct in_addr);
        !          1299:        ip_srcrt.dst = dst;
        !          1300: }
        !          1301: 
        !          1302: /*
        !          1303:  * Retrieve incoming source route for use in replies,
        !          1304:  * in the same form used by setsockopt.
        !          1305:  * The first hop is placed before the options, will be removed later.
        !          1306:  */
        !          1307: struct mbuf *
        !          1308: ip_srcroute()
        !          1309: {
        !          1310:        register struct in_addr *p, *q;
        !          1311:        register struct mbuf *m;
        !          1312: 
        !          1313:        if (ip_nhops == 0)
        !          1314:                return ((struct mbuf *)0);
        !          1315:        m = m_get(M_DONTWAIT, MT_HEADER);
        !          1316:        if (m == 0)
        !          1317:                return ((struct mbuf *)0);
        !          1318: 
        !          1319: #define OPTSIZ (sizeof(ip_srcrt.nop) + sizeof(ip_srcrt.srcopt))
        !          1320: 
        !          1321:        /* length is (nhops+1)*sizeof(addr) + sizeof(nop + srcrt header) */
        !          1322:        m->m_len = ip_nhops * sizeof(struct in_addr) + sizeof(struct in_addr) +
        !          1323:            OPTSIZ;
        !          1324: #if DIAGNOSTIC
        !          1325:        if (ipprintfs)
        !          1326:                printf("ip_srcroute: nhops %d mlen %d", ip_nhops, m->m_len);
        !          1327: #endif
        !          1328: 
        !          1329:        /*
        !          1330:         * First save first hop for return route
        !          1331:         */
        !          1332:        p = &ip_srcrt.route[ip_nhops - 1];
        !          1333:        *(mtod(m, struct in_addr *)) = *p--;
        !          1334: #if DIAGNOSTIC
        !          1335:        if (ipprintfs)
        !          1336:                printf(" hops %lx", (u_long)ntohl(mtod(m, struct in_addr *)->s_addr));
        !          1337: #endif
        !          1338: 
        !          1339:        /*
        !          1340:         * Copy option fields and padding (nop) to mbuf.
        !          1341:         */
        !          1342:        ip_srcrt.nop = IPOPT_NOP;
        !          1343:        ip_srcrt.srcopt[IPOPT_OFFSET] = IPOPT_MINOFF;
        !          1344:        (void)memcpy(mtod(m, caddr_t) + sizeof(struct in_addr),
        !          1345:            &ip_srcrt.nop, OPTSIZ);
        !          1346:        q = (struct in_addr *)(mtod(m, caddr_t) +
        !          1347:            sizeof(struct in_addr) + OPTSIZ);
        !          1348: #undef OPTSIZ
        !          1349:        /*
        !          1350:         * Record return path as an IP source route,
        !          1351:         * reversing the path (pointers are now aligned).
        !          1352:         */
        !          1353:        while (p >= ip_srcrt.route) {
        !          1354: #if DIAGNOSTIC
        !          1355:                if (ipprintfs)
        !          1356:                        printf(" %lx", (u_long)ntohl(q->s_addr));
        !          1357: #endif
        !          1358:                *q++ = *p--;
        !          1359:        }
        !          1360:        /*
        !          1361:         * Last hop goes to final destination.
        !          1362:         */
        !          1363:        *q = ip_srcrt.dst;
        !          1364: #if DIAGNOSTIC
        !          1365:        if (ipprintfs)
        !          1366:                printf(" %lx\n", (u_long)ntohl(q->s_addr));
        !          1367: #endif
        !          1368:        return (m);
        !          1369: }
        !          1370: 
        !          1371: /*
        !          1372:  * Strip out IP options, at higher
        !          1373:  * level protocol in the kernel.
        !          1374:  * Second argument is buffer to which options
        !          1375:  * will be moved, and return value is their length.
        !          1376:  * XXX should be deleted; last arg currently ignored.
        !          1377:  */
        !          1378: void
        !          1379: ip_stripoptions(m, mopt)
        !          1380:        register struct mbuf *m;
        !          1381:        struct mbuf *mopt;
        !          1382: {
        !          1383:        register int i;
        !          1384:        struct ip *ip = mtod(m, struct ip *);
        !          1385:        register caddr_t opts;
        !          1386:        int olen;
        !          1387: 
        !          1388:        olen = (IP_VHL_HL(ip->ip_vhl) << 2) - sizeof (struct ip);
        !          1389:        opts = (caddr_t)(ip + 1);
        !          1390:        i = m->m_len - (sizeof (struct ip) + olen);
        !          1391:        bcopy(opts + olen, opts, (unsigned)i);
        !          1392:        m->m_len -= olen;
        !          1393:        if (m->m_flags & M_PKTHDR)
        !          1394:                m->m_pkthdr.len -= olen;
        !          1395:        ip->ip_vhl = IP_MAKE_VHL(IPVERSION, sizeof(struct ip) >> 2);
        !          1396: }
        !          1397: 
        !          1398: u_char inetctlerrmap[PRC_NCMDS] = {
        !          1399:        0,              0,              0,              0,
        !          1400:        0,              EMSGSIZE,       EHOSTDOWN,      EHOSTUNREACH,
        !          1401:        EHOSTUNREACH,   EHOSTUNREACH,   ECONNREFUSED,   ECONNREFUSED,
        !          1402:        EMSGSIZE,       EHOSTUNREACH,   0,              0,
        !          1403:        0,              0,              0,              0,
        !          1404:        ENOPROTOOPT
        !          1405: };
        !          1406: 
        !          1407: /*
        !          1408:  * Forward a packet.  If some error occurs return the sender
        !          1409:  * an icmp packet.  Note we can't always generate a meaningful
        !          1410:  * icmp message because icmp doesn't have a large enough repertoire
        !          1411:  * of codes and types.
        !          1412:  *
        !          1413:  * If not forwarding, just drop the packet.  This could be confusing
        !          1414:  * if ipforwarding was zero but some routing protocol was advancing
        !          1415:  * us as a gateway to somewhere.  However, we must let the routing
        !          1416:  * protocol deal with that.
        !          1417:  *
        !          1418:  * The srcrt parameter indicates whether the packet is being forwarded
        !          1419:  * via a source route.
        !          1420:  */
        !          1421: static void
        !          1422: ip_forward(m, srcrt)
        !          1423:        struct mbuf *m;
        !          1424:        int srcrt;
        !          1425: {
        !          1426:        register struct ip *ip = mtod(m, struct ip *);
        !          1427:        register struct sockaddr_in *sin;
        !          1428:        register struct rtentry *rt;
        !          1429:        int error, type = 0, code = 0;
        !          1430:        struct mbuf *mcopy;
        !          1431:        n_long dest;
        !          1432:        struct ifnet *destifp;
        !          1433: 
        !          1434:        dest = 0;
        !          1435: #if DIAGNOSTIC
        !          1436:        if (ipprintfs)
        !          1437:                printf("forward: src %lx dst %lx ttl %x\n",
        !          1438:                    (u_long)ip->ip_src.s_addr, (u_long)ip->ip_dst.s_addr,
        !          1439:                    ip->ip_ttl);
        !          1440: #endif
        !          1441: 
        !          1442: 
        !          1443:        if (m->m_flags & M_BCAST || in_canforward(ip->ip_dst) == 0) {
        !          1444:                ipstat.ips_cantforward++;
        !          1445:                m_freem(m);
        !          1446:                return;
        !          1447:        }
        !          1448:        HTONS(ip->ip_id);
        !          1449:        if (ip->ip_ttl <= IPTTLDEC) {
        !          1450:                icmp_error(m, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS, dest, 0);
        !          1451:                return;
        !          1452:        }
        !          1453:        ip->ip_ttl -= IPTTLDEC;
        !          1454: 
        !          1455:        sin = (struct sockaddr_in *)&ipforward_rt.ro_dst;
        !          1456:        if ((rt = ipforward_rt.ro_rt) == 0 ||
        !          1457:            ip->ip_dst.s_addr != sin->sin_addr.s_addr) {
        !          1458:                if (ipforward_rt.ro_rt) {
        !          1459:                        RTFREE(ipforward_rt.ro_rt);
        !          1460:                        ipforward_rt.ro_rt = 0;
        !          1461:                }
        !          1462:                sin->sin_family = AF_INET;
        !          1463:                sin->sin_len = sizeof(*sin);
        !          1464:                sin->sin_addr = ip->ip_dst;
        !          1465: 
        !          1466:                rtalloc_ign(&ipforward_rt, RTF_PRCLONING);
        !          1467:                if (ipforward_rt.ro_rt == 0) {
        !          1468:                        icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, dest, 0);
        !          1469:                        return;
        !          1470:                }
        !          1471:                rt = ipforward_rt.ro_rt;
        !          1472:        }
        !          1473: 
        !          1474:        /*
        !          1475:         * Save at most 64 bytes of the packet in case
        !          1476:         * we need to generate an ICMP message to the src.
        !          1477:         */
        !          1478:        mcopy = m_copy(m, 0, imin((int)ip->ip_len, 64));
        !          1479: 
        !          1480:        /*
        !          1481:         * If forwarding packet using same interface that it came in on,
        !          1482:         * perhaps should send a redirect to sender to shortcut a hop.
        !          1483:         * Only send redirect if source is sending directly to us,
        !          1484:         * and if packet was not source routed (or has any options).
        !          1485:         * Also, don't send redirect if forwarding using a default route
        !          1486:         * or a route modified by a redirect.
        !          1487:         */
        !          1488: #define        satosin(sa)     ((struct sockaddr_in *)(sa))
        !          1489:        if (rt->rt_ifp == m->m_pkthdr.rcvif &&
        !          1490:            (rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0 &&
        !          1491:            satosin(rt_key(rt))->sin_addr.s_addr != 0 &&
        !          1492:            ipsendredirects && !srcrt) {
        !          1493: #define        RTA(rt) ((struct in_ifaddr *)(rt->rt_ifa))
        !          1494:                u_long src = ntohl(ip->ip_src.s_addr);
        !          1495: 
        !          1496:                if (RTA(rt) &&
        !          1497:                    (src & RTA(rt)->ia_subnetmask) == RTA(rt)->ia_subnet) {
        !          1498:                    if (rt->rt_flags & RTF_GATEWAY)
        !          1499:                        dest = satosin(rt->rt_gateway)->sin_addr.s_addr;
        !          1500:                    else
        !          1501:                        dest = ip->ip_dst.s_addr;
        !          1502:                    /* Router requirements says to only send host redirects */
        !          1503:                    type = ICMP_REDIRECT;
        !          1504:                    code = ICMP_REDIRECT_HOST;
        !          1505: #if DIAGNOSTIC
        !          1506:                    if (ipprintfs)
        !          1507:                        printf("redirect (%d) to %lx\n", code, (u_long)dest);
        !          1508: #endif
        !          1509:                }
        !          1510:        }
        !          1511: 
        !          1512:        error = ip_output(m, (struct mbuf *)0, &ipforward_rt, 
        !          1513:                          IP_FORWARDING, 0);
        !          1514:        if (error)
        !          1515:                ipstat.ips_cantforward++;
        !          1516:        else {
        !          1517:                ipstat.ips_forward++;
        !          1518:                if (type)
        !          1519:                        ipstat.ips_redirectsent++;
        !          1520:                else {
        !          1521:                        if (mcopy) {
        !          1522:                                ipflow_create(&ipforward_rt, mcopy);
        !          1523:                                m_freem(mcopy);
        !          1524:                        }
        !          1525:                        return;
        !          1526:                }
        !          1527:        }
        !          1528:        if (mcopy == NULL)
        !          1529:                return;
        !          1530:        destifp = NULL;
        !          1531: 
        !          1532:        switch (error) {
        !          1533: 
        !          1534:        case 0:                         /* forwarded, but need redirect */
        !          1535:                /* type, code set above */
        !          1536:                break;
        !          1537: 
        !          1538:        case ENETUNREACH:               /* shouldn't happen, checked above */
        !          1539:        case EHOSTUNREACH:
        !          1540:        case ENETDOWN:
        !          1541:        case EHOSTDOWN:
        !          1542:        default:
        !          1543:                type = ICMP_UNREACH;
        !          1544:                code = ICMP_UNREACH_HOST;
        !          1545:                break;
        !          1546: 
        !          1547:        case EMSGSIZE:
        !          1548:                type = ICMP_UNREACH;
        !          1549:                code = ICMP_UNREACH_NEEDFRAG;
        !          1550:                if (ipforward_rt.ro_rt)
        !          1551:                        destifp = ipforward_rt.ro_rt->rt_ifp;
        !          1552:                ipstat.ips_cantfrag++;
        !          1553:                break;
        !          1554: 
        !          1555:        case ENOBUFS:
        !          1556:                type = ICMP_SOURCEQUENCH;
        !          1557:                code = 0;
        !          1558:                break;
        !          1559:        }
        !          1560:        icmp_error(mcopy, type, code, dest, destifp);
        !          1561: }
        !          1562: 
        !          1563: void
        !          1564: ip_savecontrol(inp, mp, ip, m)
        !          1565:        register struct inpcb *inp;
        !          1566:        register struct mbuf **mp;
        !          1567:        register struct ip *ip;
        !          1568:        register struct mbuf *m;
        !          1569: {
        !          1570:        if (inp->inp_socket->so_options & SO_TIMESTAMP) {
        !          1571:                struct timeval tv;
        !          1572: 
        !          1573:                microtime(&tv);
        !          1574:                *mp = sbcreatecontrol((caddr_t) &tv, sizeof(tv),
        !          1575:                        SCM_TIMESTAMP, SOL_SOCKET);
        !          1576:                if (*mp)
        !          1577:                        mp = &(*mp)->m_next;
        !          1578:        }
        !          1579:        if (inp->inp_flags & INP_RECVDSTADDR) {
        !          1580:                *mp = sbcreatecontrol((caddr_t) &ip->ip_dst,
        !          1581:                    sizeof(struct in_addr), IP_RECVDSTADDR, IPPROTO_IP);
        !          1582:                if (*mp)
        !          1583:                        mp = &(*mp)->m_next;
        !          1584:        }
        !          1585: #ifdef notyet
        !          1586:        /* XXX
        !          1587:         * Moving these out of udp_input() made them even more broken
        !          1588:         * than they already were.
        !          1589:         */
        !          1590:        /* options were tossed already */
        !          1591:        if (inp->inp_flags & INP_RECVOPTS) {
        !          1592:                *mp = sbcreatecontrol((caddr_t) opts_deleted_above,
        !          1593:                    sizeof(struct in_addr), IP_RECVOPTS, IPPROTO_IP);
        !          1594:                if (*mp)
        !          1595:                        mp = &(*mp)->m_next;
        !          1596:        }
        !          1597:        /* ip_srcroute doesn't do what we want here, need to fix */
        !          1598:        if (inp->inp_flags & INP_RECVRETOPTS) {
        !          1599:                *mp = sbcreatecontrol((caddr_t) ip_srcroute(),
        !          1600:                    sizeof(struct in_addr), IP_RECVRETOPTS, IPPROTO_IP);
        !          1601:                if (*mp)
        !          1602:                        mp = &(*mp)->m_next;
        !          1603:        }
        !          1604: #endif
        !          1605:        if (inp->inp_flags & INP_RECVIF) {
        !          1606:                struct ifnet *ifp;
        !          1607:                struct sdlbuf {
        !          1608:                        struct sockaddr_dl sdl;
        !          1609:                        u_char  pad[32];
        !          1610:                } sdlbuf;
        !          1611:                struct sockaddr_dl *sdp;
        !          1612:                struct sockaddr_dl *sdl2 = &sdlbuf.sdl;
        !          1613: 
        !          1614:                if (((ifp = m->m_pkthdr.rcvif)) 
        !          1615:                && ( ifp->if_index && (ifp->if_index <= if_index))) {
        !          1616:                        sdp = (struct sockaddr_dl *)(ifnet_addrs
        !          1617:                                        [ifp->if_index - 1]->ifa_addr);
        !          1618:                        /*
        !          1619:                         * Change our mind and don't try copy.
        !          1620:                         */
        !          1621:                        if ((sdp->sdl_family != AF_LINK)
        !          1622:                        || (sdp->sdl_len > sizeof(sdlbuf))) {
        !          1623:                                goto makedummy;
        !          1624:                        }
        !          1625:                        bcopy(sdp, sdl2, sdp->sdl_len);
        !          1626:                } else {
        !          1627: makedummy:     
        !          1628:                        sdl2->sdl_len
        !          1629:                                = offsetof(struct sockaddr_dl, sdl_data[0]);
        !          1630:                        sdl2->sdl_family = AF_LINK;
        !          1631:                        sdl2->sdl_index = 0;
        !          1632:                        sdl2->sdl_nlen = sdl2->sdl_alen = sdl2->sdl_slen = 0;
        !          1633:                }
        !          1634:                *mp = sbcreatecontrol((caddr_t) sdl2, sdl2->sdl_len,
        !          1635:                        IP_RECVIF, IPPROTO_IP);
        !          1636:                if (*mp)
        !          1637:                        mp = &(*mp)->m_next;
        !          1638:        }
        !          1639: }
        !          1640: 
        !          1641: int
        !          1642: ip_rsvp_init(struct socket *so)
        !          1643: {
        !          1644:        if (so->so_type != SOCK_RAW ||
        !          1645:            so->so_proto->pr_protocol != IPPROTO_RSVP)
        !          1646:          return EOPNOTSUPP;
        !          1647: 
        !          1648:        if (ip_rsvpd != NULL)
        !          1649:          return EADDRINUSE;
        !          1650: 
        !          1651:        ip_rsvpd = so;
        !          1652:        /*
        !          1653:         * This may seem silly, but we need to be sure we don't over-increment
        !          1654:         * the RSVP counter, in case something slips up.
        !          1655:         */
        !          1656:        if (!ip_rsvp_on) {
        !          1657:                ip_rsvp_on = 1;
        !          1658:                rsvp_on++;
        !          1659:        }
        !          1660: 
        !          1661:        return 0;
        !          1662: }
        !          1663: 
        !          1664: int
        !          1665: ip_rsvp_done(void)
        !          1666: {
        !          1667:        ip_rsvpd = NULL;
        !          1668:        /*
        !          1669:         * This may seem silly, but we need to be sure we don't over-decrement
        !          1670:         * the RSVP counter, in case something slips up.
        !          1671:         */
        !          1672:        if (ip_rsvp_on) {
        !          1673:                ip_rsvp_on = 0;
        !          1674:                rsvp_on--;
        !          1675:        }
        !          1676:        return 0;
        !          1677: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.