Annotation of XNU/bsd/netinet/ip_input.c, revision 1.1.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.