[BACK]Return to ip_input.c CVS log [TXT][DIR] Up to [local] / sys / netinet

Annotation of sys/netinet/ip_input.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: ip_input.c,v 1.151 2007/05/30 04:46:45 henning Exp $  */
                      2: /*     $NetBSD: ip_input.c,v 1.30 1996/03/16 23:53:58 christos Exp $   */
                      3:
                      4: /*
                      5:  * Copyright (c) 1982, 1986, 1988, 1993
                      6:  *     The Regents of the University of California.  All rights reserved.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
                     16:  * 3. Neither the name of the University nor the names of its contributors
                     17:  *    may be used to endorse or promote products derived from this software
                     18:  *    without specific prior written permission.
                     19:  *
                     20:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     21:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     22:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     23:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     24:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     25:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     26:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     27:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     28:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     29:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     30:  * SUCH DAMAGE.
                     31:  *
                     32:  *     @(#)ip_input.c  8.2 (Berkeley) 1/4/94
                     33:  */
                     34:
                     35: #include "pf.h"
                     36: #include "carp.h"
                     37:
                     38: #include <sys/param.h>
                     39: #include <sys/systm.h>
                     40: #include <sys/mbuf.h>
                     41: #include <sys/domain.h>
                     42: #include <sys/protosw.h>
                     43: #include <sys/socket.h>
                     44: #include <sys/socketvar.h>
                     45: #include <sys/syslog.h>
                     46: #include <sys/sysctl.h>
                     47:
                     48: #include <net/if.h>
                     49: #include <net/if_dl.h>
                     50: #include <net/route.h>
                     51:
                     52: #include <netinet/in.h>
                     53: #include <netinet/in_systm.h>
                     54: #include <netinet/if_ether.h>
                     55: #include <netinet/ip.h>
                     56: #include <netinet/in_pcb.h>
                     57: #include <netinet/in_var.h>
                     58: #include <netinet/ip_var.h>
                     59: #include <netinet/ip_icmp.h>
                     60:
                     61: #if NPF > 0
                     62: #include <net/pfvar.h>
                     63: #endif
                     64:
                     65: #ifdef IPSEC
                     66: #include <netinet/ip_ipsp.h>
                     67: #endif /* IPSEC */
                     68:
                     69: #if NCARP > 0
                     70: #include <net/if_types.h>
                     71: #include <netinet/ip_carp.h>
                     72: #endif
                     73:
                     74: #define IPMTUDISCTIMEOUT (10 * 60)     /* as per RFC 1191 */
                     75:
                     76: struct ipqhead ipq;
                     77:
                     78: int encdebug = 0;
                     79: int ipsec_keep_invalid = IPSEC_DEFAULT_EMBRYONIC_SA_TIMEOUT;
                     80: int ipsec_require_pfs = IPSEC_DEFAULT_PFS;
                     81: int ipsec_soft_allocations = IPSEC_DEFAULT_SOFT_ALLOCATIONS;
                     82: int ipsec_exp_allocations = IPSEC_DEFAULT_EXP_ALLOCATIONS;
                     83: int ipsec_soft_bytes = IPSEC_DEFAULT_SOFT_BYTES;
                     84: int ipsec_exp_bytes = IPSEC_DEFAULT_EXP_BYTES;
                     85: int ipsec_soft_timeout = IPSEC_DEFAULT_SOFT_TIMEOUT;
                     86: int ipsec_exp_timeout = IPSEC_DEFAULT_EXP_TIMEOUT;
                     87: int ipsec_soft_first_use = IPSEC_DEFAULT_SOFT_FIRST_USE;
                     88: int ipsec_exp_first_use = IPSEC_DEFAULT_EXP_FIRST_USE;
                     89: int ipsec_expire_acquire = IPSEC_DEFAULT_EXPIRE_ACQUIRE;
                     90: char ipsec_def_enc[20];
                     91: char ipsec_def_auth[20];
                     92: char ipsec_def_comp[20];
                     93:
                     94: /* values controllable via sysctl */
                     95: int    ipforwarding = 0;
                     96: int    ipmforwarding = 0;
                     97: int    ipmultipath = 0;
                     98: int    ipsendredirects = 1;
                     99: int    ip_dosourceroute = 0;
                    100: int    ip_defttl = IPDEFTTL;
                    101: int    ip_mtudisc = 1;
                    102: u_int  ip_mtudisc_timeout = IPMTUDISCTIMEOUT;
                    103: int    ip_directedbcast = 0;
                    104: #ifdef DIAGNOSTIC
                    105: int    ipprintfs = 0;
                    106: #endif
                    107:
                    108: struct rttimer_queue *ip_mtudisc_timeout_q = NULL;
                    109:
                    110: int    ipsec_auth_default_level = IPSEC_AUTH_LEVEL_DEFAULT;
                    111: int    ipsec_esp_trans_default_level = IPSEC_ESP_TRANS_LEVEL_DEFAULT;
                    112: int    ipsec_esp_network_default_level = IPSEC_ESP_NETWORK_LEVEL_DEFAULT;
                    113: int    ipsec_ipcomp_default_level = IPSEC_IPCOMP_LEVEL_DEFAULT;
                    114:
                    115: /* Keep track of memory used for reassembly */
                    116: int    ip_maxqueue = 300;
                    117: int    ip_frags = 0;
                    118:
                    119: /* from in_pcb.c */
                    120: extern int ipport_firstauto;
                    121: extern int ipport_lastauto;
                    122: extern int ipport_hifirstauto;
                    123: extern int ipport_hilastauto;
                    124: extern struct baddynamicports baddynamicports;
                    125:
                    126: int *ipctl_vars[IPCTL_MAXID] = IPCTL_VARS;
                    127:
                    128: extern struct domain inetdomain;
                    129: extern struct protosw inetsw[];
                    130: u_char ip_protox[IPPROTO_MAX];
                    131: int    ipqmaxlen = IFQ_MAXLEN;
                    132: struct in_ifaddrhead in_ifaddr;
                    133: struct ifqueue ipintrq;
                    134:
                    135: int    ipq_locked;
                    136: static __inline int ipq_lock_try(void);
                    137: static __inline void ipq_unlock(void);
                    138:
                    139: struct pool ipqent_pool;
                    140:
                    141: struct ipstat ipstat;
                    142:
                    143: static __inline int
                    144: ipq_lock_try()
                    145: {
                    146:        int s;
                    147:
                    148:        /* Use splvm() due to mbuf allocation. */
                    149:        s = splvm();
                    150:        if (ipq_locked) {
                    151:                splx(s);
                    152:                return (0);
                    153:        }
                    154:        ipq_locked = 1;
                    155:        splx(s);
                    156:        return (1);
                    157: }
                    158:
                    159: #define ipq_lock() ipq_lock_try()
                    160:
                    161: static __inline void
                    162: ipq_unlock()
                    163: {
                    164:        int s;
                    165:
                    166:        s = splvm();
                    167:        ipq_locked = 0;
                    168:        splx(s);
                    169: }
                    170:
                    171: char *
                    172: inet_ntoa(ina)
                    173:        struct in_addr ina;
                    174: {
                    175:        static char buf[4*sizeof "123"];
                    176:        unsigned char *ucp = (unsigned char *)&ina;
                    177:
                    178:        snprintf(buf, sizeof buf, "%d.%d.%d.%d",
                    179:            ucp[0] & 0xff, ucp[1] & 0xff,
                    180:            ucp[2] & 0xff, ucp[3] & 0xff);
                    181:        return (buf);
                    182: }
                    183:
                    184: /*
                    185:  * We need to save the IP options in case a protocol wants to respond
                    186:  * to an incoming packet over the same route if the packet got here
                    187:  * using IP source routing.  This allows connection establishment and
                    188:  * maintenance when the remote end is on a network that is not known
                    189:  * to us.
                    190:  */
                    191: int    ip_nhops = 0;
                    192: static struct ip_srcrt {
                    193:        struct  in_addr dst;                    /* final destination */
                    194:        char    nop;                            /* one NOP to align */
                    195:        char    srcopt[IPOPT_OFFSET + 1];       /* OPTVAL, OLEN and OFFSET */
                    196:        struct  in_addr route[MAX_IPOPTLEN/sizeof(struct in_addr)];
                    197: } ip_srcrt;
                    198:
                    199: void save_rte(u_char *, struct in_addr);
                    200: int ip_weadvertise(u_int32_t);
                    201:
                    202: /*
                    203:  * IP initialization: fill in IP protocol switch table.
                    204:  * All protocols not implemented in kernel go to raw IP protocol handler.
                    205:  */
                    206: void
                    207: ip_init()
                    208: {
                    209:        struct protosw *pr;
                    210:        int i;
                    211:        const u_int16_t defbaddynamicports_tcp[] = DEFBADDYNAMICPORTS_TCP;
                    212:        const u_int16_t defbaddynamicports_udp[] = DEFBADDYNAMICPORTS_UDP;
                    213:
                    214:        pool_init(&ipqent_pool, sizeof(struct ipqent), 0, 0, 0, "ipqepl",
                    215:            NULL);
                    216:
                    217:        pr = pffindproto(PF_INET, IPPROTO_RAW, SOCK_RAW);
                    218:        if (pr == 0)
                    219:                panic("ip_init");
                    220:        for (i = 0; i < IPPROTO_MAX; i++)
                    221:                ip_protox[i] = pr - inetsw;
                    222:        for (pr = inetdomain.dom_protosw;
                    223:            pr < inetdomain.dom_protoswNPROTOSW; pr++)
                    224:                if (pr->pr_domain->dom_family == PF_INET &&
                    225:                    pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW)
                    226:                        ip_protox[pr->pr_protocol] = pr - inetsw;
                    227:        LIST_INIT(&ipq);
                    228:        ipintrq.ifq_maxlen = ipqmaxlen;
                    229:        TAILQ_INIT(&in_ifaddr);
                    230:        if (ip_mtudisc != 0)
                    231:                ip_mtudisc_timeout_q =
                    232:                    rt_timer_queue_create(ip_mtudisc_timeout);
                    233:
                    234:        /* Fill in list of ports not to allocate dynamically. */
                    235:        bzero((void *)&baddynamicports, sizeof(baddynamicports));
                    236:        for (i = 0; defbaddynamicports_tcp[i] != 0; i++)
                    237:                DP_SET(baddynamicports.tcp, defbaddynamicports_tcp[i]);
                    238:        for (i = 0; defbaddynamicports_udp[i] != 0; i++)
                    239:                DP_SET(baddynamicports.udp, defbaddynamicports_udp[i]);
                    240:
                    241:        strlcpy(ipsec_def_enc, IPSEC_DEFAULT_DEF_ENC, sizeof(ipsec_def_enc));
                    242:        strlcpy(ipsec_def_auth, IPSEC_DEFAULT_DEF_AUTH, sizeof(ipsec_def_auth));
                    243:        strlcpy(ipsec_def_comp, IPSEC_DEFAULT_DEF_COMP, sizeof(ipsec_def_comp));
                    244: }
                    245:
                    246: struct sockaddr_in ipaddr = { sizeof(ipaddr), AF_INET };
                    247: struct route ipforward_rt;
                    248: int    ipforward_rtableid;
                    249:
                    250: void
                    251: ipintr()
                    252: {
                    253:        struct mbuf *m;
                    254:        int s;
                    255:
                    256:        while (ipintrq.ifq_head) {
                    257:                /*
                    258:                 * Get next datagram off input queue and get IP header
                    259:                 * in first mbuf.
                    260:                 */
                    261:                s = splnet();
                    262:                IF_DEQUEUE(&ipintrq, m);
                    263:                splx(s);
                    264:                if (m == 0)
                    265:                        return;
                    266: #ifdef DIAGNOSTIC
                    267:                if ((m->m_flags & M_PKTHDR) == 0)
                    268:                        panic("ipintr no HDR");
                    269: #endif
                    270:                ipv4_input(m);
                    271:        }
                    272: }
                    273:
                    274: /*
                    275:  * Ip input routine.  Checksum and byte swap header.  If fragmented
                    276:  * try to reassemble.  Process options.  Pass to next level.
                    277:  */
                    278: void
                    279: ipv4_input(m)
                    280:        struct mbuf *m;
                    281: {
                    282:        struct ip *ip;
                    283:        struct ipq *fp;
                    284:        struct in_ifaddr *ia;
                    285:        struct ipqent *ipqe;
                    286:        int hlen, mff, len;
                    287:        in_addr_t pfrdr = 0;
                    288: #ifdef IPSEC
                    289:        int error, s;
                    290:        struct tdb *tdb;
                    291:        struct tdb_ident *tdbi;
                    292:        struct m_tag *mtag;
                    293: #endif /* IPSEC */
                    294:
                    295:        /*
                    296:         * If no IP addresses have been set yet but the interfaces
                    297:         * are receiving, can't do anything with incoming packets yet.
                    298:         */
                    299:        if (TAILQ_EMPTY(&in_ifaddr))
                    300:                goto bad;
                    301:        ipstat.ips_total++;
                    302:        if (m->m_len < sizeof (struct ip) &&
                    303:            (m = m_pullup(m, sizeof (struct ip))) == NULL) {
                    304:                ipstat.ips_toosmall++;
                    305:                return;
                    306:        }
                    307:        ip = mtod(m, struct ip *);
                    308:        if (ip->ip_v != IPVERSION) {
                    309:                ipstat.ips_badvers++;
                    310:                goto bad;
                    311:        }
                    312:        hlen = ip->ip_hl << 2;
                    313:        if (hlen < sizeof(struct ip)) { /* minimum header length */
                    314:                ipstat.ips_badhlen++;
                    315:                goto bad;
                    316:        }
                    317:        if (hlen > m->m_len) {
                    318:                if ((m = m_pullup(m, hlen)) == NULL) {
                    319:                        ipstat.ips_badhlen++;
                    320:                        return;
                    321:                }
                    322:                ip = mtod(m, struct ip *);
                    323:        }
                    324:
                    325:        /* 127/8 must not appear on wire - RFC1122 */
                    326:        if ((ntohl(ip->ip_dst.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET ||
                    327:            (ntohl(ip->ip_src.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) {
                    328:                if ((m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) == 0) {
                    329:                        ipstat.ips_badaddr++;
                    330:                        goto bad;
                    331:                }
                    332:        }
                    333:
                    334:        if ((m->m_pkthdr.csum_flags & M_IPV4_CSUM_IN_OK) == 0) {
                    335:                if (m->m_pkthdr.csum_flags & M_IPV4_CSUM_IN_BAD) {
                    336:                        ipstat.ips_inhwcsum++;
                    337:                        ipstat.ips_badsum++;
                    338:                        goto bad;
                    339:                }
                    340:
                    341:                if (in_cksum(m, hlen) != 0) {
                    342:                        ipstat.ips_badsum++;
                    343:                        goto bad;
                    344:                }
                    345:        } else {
                    346:                m->m_pkthdr.csum_flags &= ~M_IPV4_CSUM_IN_OK;
                    347:                ipstat.ips_inhwcsum++;
                    348:        }
                    349:
                    350:        /* Retrieve the packet length. */
                    351:        len = ntohs(ip->ip_len);
                    352:
                    353:        /*
                    354:         * Convert fields to host representation.
                    355:         */
                    356:        if (len < hlen) {
                    357:                ipstat.ips_badlen++;
                    358:                goto bad;
                    359:        }
                    360:
                    361:        /*
                    362:         * Check that the amount of data in the buffers
                    363:         * is at least as much as the IP header would have us expect.
                    364:         * Trim mbufs if longer than we expect.
                    365:         * Drop packet if shorter than we expect.
                    366:         */
                    367:        if (m->m_pkthdr.len < len) {
                    368:                ipstat.ips_tooshort++;
                    369:                goto bad;
                    370:        }
                    371:        if (m->m_pkthdr.len > len) {
                    372:                if (m->m_len == m->m_pkthdr.len) {
                    373:                        m->m_len = len;
                    374:                        m->m_pkthdr.len = len;
                    375:                } else
                    376:                        m_adj(m, len - m->m_pkthdr.len);
                    377:        }
                    378:
                    379: #if NCARP > 0
                    380:        if (m->m_pkthdr.rcvif->if_type == IFT_CARP &&
                    381:            m->m_pkthdr.rcvif->if_flags & IFF_LINK0 &&
                    382:            ip->ip_p != IPPROTO_ICMP &&
                    383:            carp_lsdrop(m, AF_INET, &ip->ip_src.s_addr,
                    384:            &ip->ip_dst.s_addr))
                    385:                goto bad;
                    386: #endif
                    387:
                    388: #if NPF > 0
                    389:        /*
                    390:         * Packet filter
                    391:         */
                    392:        pfrdr = ip->ip_dst.s_addr;
                    393:        if (pf_test(PF_IN, m->m_pkthdr.rcvif, &m, NULL) != PF_PASS)
                    394:                goto bad;
                    395:        if (m == NULL)
                    396:                return;
                    397:
                    398:        ip = mtod(m, struct ip *);
                    399:        hlen = ip->ip_hl << 2;
                    400:        pfrdr = (pfrdr != ip->ip_dst.s_addr);
                    401: #endif
                    402:
                    403:        /*
                    404:         * Process options and, if not destined for us,
                    405:         * ship it on.  ip_dooptions returns 1 when an
                    406:         * error was detected (causing an icmp message
                    407:         * to be sent and the original packet to be freed).
                    408:         */
                    409:        ip_nhops = 0;           /* for source routed packets */
                    410:        if (hlen > sizeof (struct ip) && ip_dooptions(m)) {
                    411:                return;
                    412:        }
                    413:
                    414:        /*
                    415:         * Check our list of addresses, to see if the packet is for us.
                    416:         */
                    417:        if ((ia = in_iawithaddr(ip->ip_dst, m)) != NULL &&
                    418:            (ia->ia_ifp->if_flags & IFF_UP))
                    419:                goto ours;
                    420:
                    421:        if (IN_MULTICAST(ip->ip_dst.s_addr)) {
                    422:                struct in_multi *inm;
                    423: #ifdef MROUTING
                    424:                extern struct socket *ip_mrouter;
                    425:
                    426:                if (m->m_flags & M_EXT) {
                    427:                        if ((m = m_pullup(m, hlen)) == NULL) {
                    428:                                ipstat.ips_toosmall++;
                    429:                                return;
                    430:                        }
                    431:                        ip = mtod(m, struct ip *);
                    432:                }
                    433:                if (ipmforwarding && ip_mrouter) {
                    434:                        /*
                    435:                         * If we are acting as a multicast router, all
                    436:                         * incoming multicast packets are passed to the
                    437:                         * kernel-level multicast forwarding function.
                    438:                         * The packet is returned (relatively) intact; if
                    439:                         * ip_mforward() returns a non-zero value, the packet
                    440:                         * must be discarded, else it may be accepted below.
                    441:                         *
                    442:                         * (The IP ident field is put in the same byte order
                    443:                         * as expected when ip_mforward() is called from
                    444:                         * ip_output().)
                    445:                         */
                    446:                        if (ip_mforward(m, m->m_pkthdr.rcvif) != 0) {
                    447:                                ipstat.ips_cantforward++;
                    448:                                m_freem(m);
                    449:                                return;
                    450:                        }
                    451:
                    452:                        /*
                    453:                         * The process-level routing daemon needs to receive
                    454:                         * all multicast IGMP packets, whether or not this
                    455:                         * host belongs to their destination groups.
                    456:                         */
                    457:                        if (ip->ip_p == IPPROTO_IGMP)
                    458:                                goto ours;
                    459:                        ipstat.ips_forward++;
                    460:                }
                    461: #endif
                    462:                /*
                    463:                 * See if we belong to the destination multicast group on the
                    464:                 * arrival interface.
                    465:                 */
                    466:                IN_LOOKUP_MULTI(ip->ip_dst, m->m_pkthdr.rcvif, inm);
                    467:                if (inm == NULL) {
                    468:                        ipstat.ips_notmember++;
                    469:                        if (!IN_LOCAL_GROUP(ip->ip_dst.s_addr))
                    470:                                ipstat.ips_cantforward++;
                    471:                        m_freem(m);
                    472:                        return;
                    473:                }
                    474:                goto ours;
                    475:        }
                    476:        if (ip->ip_dst.s_addr == INADDR_BROADCAST ||
                    477:            ip->ip_dst.s_addr == INADDR_ANY)
                    478:                goto ours;
                    479:
                    480: #if NCARP > 0
                    481:        if (m->m_pkthdr.rcvif->if_type == IFT_CARP &&
                    482:            m->m_pkthdr.rcvif->if_flags & IFF_LINK0 &&
                    483:            ip->ip_p == IPPROTO_ICMP &&
                    484:            carp_lsdrop(m, AF_INET, &ip->ip_src.s_addr,
                    485:            &ip->ip_dst.s_addr))
                    486:                goto bad;
                    487: #endif
                    488:        /*
                    489:         * Not for us; forward if possible and desirable.
                    490:         */
                    491:        if (ipforwarding == 0) {
                    492:                ipstat.ips_cantforward++;
                    493:                m_freem(m);
                    494:                return;
                    495:        }
                    496: #ifdef IPSEC
                    497:        if (ipsec_in_use) {
                    498:                /*
                    499:                 * IPsec policy check for forwarded packets. Look at
                    500:                 * inner-most IPsec SA used.
                    501:                 */
                    502:                mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL);
                    503:                 s = splnet();
                    504:                if (mtag != NULL) {
                    505:                        tdbi = (struct tdb_ident *)(mtag + 1);
                    506:                        tdb = gettdb(tdbi->spi, &tdbi->dst, tdbi->proto);
                    507:                } else
                    508:                        tdb = NULL;
                    509:                ipsp_spd_lookup(m, AF_INET, hlen, &error,
                    510:                    IPSP_DIRECTION_IN, tdb, NULL);
                    511:                 splx(s);
                    512:
                    513:                /* Error or otherwise drop-packet indication */
                    514:                if (error) {
                    515:                        ipstat.ips_cantforward++;
                    516:                        m_freem(m);
                    517:                        return;
                    518:                }
                    519:
                    520:                /*
                    521:                 * Fall through, forward packet. Outbound IPsec policy
                    522:                 * checking will occur in ip_output().
                    523:                 */
                    524:        }
                    525: #endif /* IPSEC */
                    526:
                    527:        ip_forward(m, pfrdr);
                    528:        return;
                    529:
                    530: ours:
                    531:        /*
                    532:         * If offset or IP_MF are set, must reassemble.
                    533:         * Otherwise, nothing need be done.
                    534:         * (We could look in the reassembly queue to see
                    535:         * if the packet was previously fragmented,
                    536:         * but it's not worth the time; just let them time out.)
                    537:         */
                    538:        if (ip->ip_off &~ htons(IP_DF | IP_RF)) {
                    539:                if (m->m_flags & M_EXT) {               /* XXX */
                    540:                        if ((m = m_pullup(m, hlen)) == NULL) {
                    541:                                ipstat.ips_toosmall++;
                    542:                                return;
                    543:                        }
                    544:                        ip = mtod(m, struct ip *);
                    545:                }
                    546:
                    547:                /*
                    548:                 * Look for queue of fragments
                    549:                 * of this datagram.
                    550:                 */
                    551:                ipq_lock();
                    552:                LIST_FOREACH(fp, &ipq, ipq_q)
                    553:                        if (ip->ip_id == fp->ipq_id &&
                    554:                            ip->ip_src.s_addr == fp->ipq_src.s_addr &&
                    555:                            ip->ip_dst.s_addr == fp->ipq_dst.s_addr &&
                    556:                            ip->ip_p == fp->ipq_p)
                    557:                                goto found;
                    558:                fp = 0;
                    559: found:
                    560:
                    561:                /*
                    562:                 * Adjust ip_len to not reflect header,
                    563:                 * set ipqe_mff if more fragments are expected,
                    564:                 * convert offset of this to bytes.
                    565:                 */
                    566:                ip->ip_len = htons(ntohs(ip->ip_len) - hlen);
                    567:                mff = (ip->ip_off & htons(IP_MF)) != 0;
                    568:                if (mff) {
                    569:                        /*
                    570:                         * Make sure that fragments have a data length
                    571:                         * that's a non-zero multiple of 8 bytes.
                    572:                         */
                    573:                        if (ntohs(ip->ip_len) == 0 ||
                    574:                            (ntohs(ip->ip_len) & 0x7) != 0) {
                    575:                                ipstat.ips_badfrags++;
                    576:                                ipq_unlock();
                    577:                                goto bad;
                    578:                        }
                    579:                }
                    580:                ip->ip_off = htons(ntohs(ip->ip_off) << 3);
                    581:
                    582:                /*
                    583:                 * If datagram marked as having more fragments
                    584:                 * or if this is not the first fragment,
                    585:                 * attempt reassembly; if it succeeds, proceed.
                    586:                 */
                    587:                if (mff || ip->ip_off) {
                    588:                        ipstat.ips_fragments++;
                    589:                        if (ip_frags + 1 > ip_maxqueue) {
                    590:                                ip_flush();
                    591:                                ipstat.ips_rcvmemdrop++;
                    592:                                ipq_unlock();
                    593:                                goto bad;
                    594:                        }
                    595:
                    596:                        ipqe = pool_get(&ipqent_pool, PR_NOWAIT);
                    597:                        if (ipqe == NULL) {
                    598:                                ipstat.ips_rcvmemdrop++;
                    599:                                ipq_unlock();
                    600:                                goto bad;
                    601:                        }
                    602:                        ip_frags++;
                    603:                        ipqe->ipqe_mff = mff;
                    604:                        ipqe->ipqe_m = m;
                    605:                        ipqe->ipqe_ip = ip;
                    606:                        m = ip_reass(ipqe, fp);
                    607:                        if (m == 0) {
                    608:                                ipq_unlock();
                    609:                                return;
                    610:                        }
                    611:                        ipstat.ips_reassembled++;
                    612:                        ip = mtod(m, struct ip *);
                    613:                        hlen = ip->ip_hl << 2;
                    614:                        ip->ip_len = htons(ntohs(ip->ip_len) + hlen);
                    615:                } else
                    616:                        if (fp)
                    617:                                ip_freef(fp);
                    618:                ipq_unlock();
                    619:        }
                    620:
                    621: #ifdef IPSEC
                    622:        if (!ipsec_in_use)
                    623:                goto skipipsec;
                    624:
                    625:         /*
                    626:          * If it's a protected packet for us, skip the policy check.
                    627:          * That's because we really only care about the properties of
                    628:          * the protected packet, and not the intermediate versions.
                    629:          * While this is not the most paranoid setting, it allows
                    630:          * some flexibility in handling nested tunnels (in setting up
                    631:         * the policies).
                    632:          */
                    633:         if ((ip->ip_p == IPPROTO_ESP) || (ip->ip_p == IPPROTO_AH) ||
                    634:            (ip->ip_p == IPPROTO_IPCOMP))
                    635:           goto skipipsec;
                    636:
                    637:        /*
                    638:         * If the protected packet was tunneled, then we need to
                    639:         * verify the protected packet's information, not the
                    640:         * external headers. Thus, skip the policy lookup for the
                    641:         * external packet, and keep the IPsec information linked on
                    642:         * the packet header (the encapsulation routines know how
                    643:         * to deal with that).
                    644:         */
                    645:        if ((ip->ip_p == IPPROTO_IPIP) || (ip->ip_p == IPPROTO_IPV6))
                    646:          goto skipipsec;
                    647:
                    648:        /*
                    649:         * If the protected packet is TCP or UDP, we'll do the
                    650:         * policy check in the respective input routine, so we can
                    651:         * check for bypass sockets.
                    652:         */
                    653:        if ((ip->ip_p == IPPROTO_TCP) || (ip->ip_p == IPPROTO_UDP))
                    654:          goto skipipsec;
                    655:
                    656:        /*
                    657:         * IPsec policy check for local-delivery packets. Look at the
                    658:         * inner-most SA that protected the packet. This is in fact
                    659:         * a bit too restrictive (it could end up causing packets to
                    660:         * be dropped that semantically follow the policy, e.g., in
                    661:         * certain SA-bundle configurations); but the alternative is
                    662:         * very complicated (and requires keeping track of what
                    663:         * kinds of tunneling headers have been seen in-between the
                    664:         * IPsec headers), and I don't think we lose much functionality
                    665:         * that's needed in the real world (who uses bundles anyway ?).
                    666:         */
                    667:        mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL);
                    668:         s = splnet();
                    669:        if (mtag) {
                    670:                tdbi = (struct tdb_ident *)(mtag + 1);
                    671:                tdb = gettdb(tdbi->spi, &tdbi->dst, tdbi->proto);
                    672:        } else
                    673:                tdb = NULL;
                    674:        ipsp_spd_lookup(m, AF_INET, hlen, &error, IPSP_DIRECTION_IN,
                    675:            tdb, NULL);
                    676:         splx(s);
                    677:
                    678:        /* Error or otherwise drop-packet indication. */
                    679:        if (error) {
                    680:                ipstat.ips_cantforward++;
                    681:                m_freem(m);
                    682:                return;
                    683:        }
                    684:
                    685:  skipipsec:
                    686:        /* Otherwise, just fall through and deliver the packet */
                    687: #endif /* IPSEC */
                    688:
                    689:        /*
                    690:         * Switch out to protocol's input routine.
                    691:         */
                    692:        ipstat.ips_delivered++;
                    693:        (*inetsw[ip_protox[ip->ip_p]].pr_input)(m, hlen, NULL, 0);
                    694:        return;
                    695: bad:
                    696:        m_freem(m);
                    697: }
                    698:
                    699: struct in_ifaddr *
                    700: in_iawithaddr(ina, m)
                    701:        struct in_addr ina;
                    702:        struct mbuf *m;
                    703: {
                    704:        struct in_ifaddr *ia;
                    705:
                    706:        TAILQ_FOREACH(ia, &in_ifaddr, ia_list) {
                    707:                if ((ina.s_addr == ia->ia_addr.sin_addr.s_addr) ||
                    708:                    ((ia->ia_ifp->if_flags & (IFF_LOOPBACK|IFF_LINK1)) ==
                    709:                        (IFF_LOOPBACK|IFF_LINK1) &&
                    710:                     ia->ia_subnet == (ina.s_addr & ia->ia_subnetmask)))
                    711:                        return ia;
                    712:                if (((ip_directedbcast == 0) || (m && ip_directedbcast &&
                    713:                    ia->ia_ifp == m->m_pkthdr.rcvif)) &&
                    714:                    (ia->ia_ifp->if_flags & IFF_BROADCAST)) {
                    715:                        if (ina.s_addr == ia->ia_broadaddr.sin_addr.s_addr ||
                    716:                            ina.s_addr == ia->ia_netbroadcast.s_addr ||
                    717:                            /*
                    718:                             * Look for all-0's host part (old broadcast addr),
                    719:                             * either for subnet or net.
                    720:                             */
                    721:                            ina.s_addr == ia->ia_subnet ||
                    722:                            ina.s_addr == ia->ia_net) {
                    723:                                /* Make sure M_BCAST is set */
                    724:                                if (m)
                    725:                                        m->m_flags |= M_BCAST;
                    726:                                return ia;
                    727:                            }
                    728:                }
                    729:        }
                    730:
                    731:        return NULL;
                    732: }
                    733:
                    734: /*
                    735:  * Take incoming datagram fragment and try to
                    736:  * reassemble it into whole datagram.  If a chain for
                    737:  * reassembly of this datagram already exists, then it
                    738:  * is given as fp; otherwise have to make a chain.
                    739:  */
                    740: struct mbuf *
                    741: ip_reass(ipqe, fp)
                    742:        struct ipqent *ipqe;
                    743:        struct ipq *fp;
                    744: {
                    745:        struct mbuf *m = ipqe->ipqe_m;
                    746:        struct ipqent *nq, *p, *q;
                    747:        struct ip *ip;
                    748:        struct mbuf *t;
                    749:        int hlen = ipqe->ipqe_ip->ip_hl << 2;
                    750:        int i, next;
                    751:        u_int8_t ecn, ecn0;
                    752:
                    753:        /*
                    754:         * Presence of header sizes in mbufs
                    755:         * would confuse code below.
                    756:         */
                    757:        m->m_data += hlen;
                    758:        m->m_len -= hlen;
                    759:
                    760:        /*
                    761:         * If first fragment to arrive, create a reassembly queue.
                    762:         */
                    763:        if (fp == 0) {
                    764:                MALLOC(fp, struct ipq *, sizeof (struct ipq),
                    765:                    M_FTABLE, M_NOWAIT);
                    766:                if (fp == NULL)
                    767:                        goto dropfrag;
                    768:                LIST_INSERT_HEAD(&ipq, fp, ipq_q);
                    769:                fp->ipq_ttl = IPFRAGTTL;
                    770:                fp->ipq_p = ipqe->ipqe_ip->ip_p;
                    771:                fp->ipq_id = ipqe->ipqe_ip->ip_id;
                    772:                LIST_INIT(&fp->ipq_fragq);
                    773:                fp->ipq_src = ipqe->ipqe_ip->ip_src;
                    774:                fp->ipq_dst = ipqe->ipqe_ip->ip_dst;
                    775:                p = NULL;
                    776:                goto insert;
                    777:        }
                    778:
                    779:        /*
                    780:         * Handle ECN by comparing this segment with the first one;
                    781:         * if CE is set, do not lose CE.
                    782:         * drop if CE and not-ECT are mixed for the same packet.
                    783:         */
                    784:        ecn = ipqe->ipqe_ip->ip_tos & IPTOS_ECN_MASK;
                    785:        ecn0 = LIST_FIRST(&fp->ipq_fragq)->ipqe_ip->ip_tos & IPTOS_ECN_MASK;
                    786:        if (ecn == IPTOS_ECN_CE) {
                    787:                if (ecn0 == IPTOS_ECN_NOTECT)
                    788:                        goto dropfrag;
                    789:                if (ecn0 != IPTOS_ECN_CE)
                    790:                        LIST_FIRST(&fp->ipq_fragq)->ipqe_ip->ip_tos |= IPTOS_ECN_CE;
                    791:        }
                    792:        if (ecn == IPTOS_ECN_NOTECT && ecn0 != IPTOS_ECN_NOTECT)
                    793:                goto dropfrag;
                    794:
                    795:        /*
                    796:         * Find a segment which begins after this one does.
                    797:         */
                    798:        for (p = NULL, q = LIST_FIRST(&fp->ipq_fragq);
                    799:            q != LIST_END(&fp->ipq_fragq); p = q, q = LIST_NEXT(q, ipqe_q))
                    800:                if (ntohs(q->ipqe_ip->ip_off) > ntohs(ipqe->ipqe_ip->ip_off))
                    801:                        break;
                    802:
                    803:        /*
                    804:         * If there is a preceding segment, it may provide some of
                    805:         * our data already.  If so, drop the data from the incoming
                    806:         * segment.  If it provides all of our data, drop us.
                    807:         */
                    808:        if (p != NULL) {
                    809:                i = ntohs(p->ipqe_ip->ip_off) + ntohs(p->ipqe_ip->ip_len) -
                    810:                    ntohs(ipqe->ipqe_ip->ip_off);
                    811:                if (i > 0) {
                    812:                        if (i >= ntohs(ipqe->ipqe_ip->ip_len))
                    813:                                goto dropfrag;
                    814:                        m_adj(ipqe->ipqe_m, i);
                    815:                        ipqe->ipqe_ip->ip_off =
                    816:                            htons(ntohs(ipqe->ipqe_ip->ip_off) + i);
                    817:                        ipqe->ipqe_ip->ip_len =
                    818:                            htons(ntohs(ipqe->ipqe_ip->ip_len) - i);
                    819:                }
                    820:        }
                    821:
                    822:        /*
                    823:         * While we overlap succeeding segments trim them or,
                    824:         * if they are completely covered, dequeue them.
                    825:         */
                    826:        for (; q != NULL &&
                    827:            ntohs(ipqe->ipqe_ip->ip_off) + ntohs(ipqe->ipqe_ip->ip_len) >
                    828:            ntohs(q->ipqe_ip->ip_off); q = nq) {
                    829:                i = (ntohs(ipqe->ipqe_ip->ip_off) +
                    830:                    ntohs(ipqe->ipqe_ip->ip_len)) - ntohs(q->ipqe_ip->ip_off);
                    831:                if (i < ntohs(q->ipqe_ip->ip_len)) {
                    832:                        q->ipqe_ip->ip_len =
                    833:                            htons(ntohs(q->ipqe_ip->ip_len) - i);
                    834:                        q->ipqe_ip->ip_off =
                    835:                            htons(ntohs(q->ipqe_ip->ip_off) + i);
                    836:                        m_adj(q->ipqe_m, i);
                    837:                        break;
                    838:                }
                    839:                nq = LIST_NEXT(q, ipqe_q);
                    840:                m_freem(q->ipqe_m);
                    841:                LIST_REMOVE(q, ipqe_q);
                    842:                pool_put(&ipqent_pool, q);
                    843:                ip_frags--;
                    844:        }
                    845:
                    846: insert:
                    847:        /*
                    848:         * Stick new segment in its place;
                    849:         * check for complete reassembly.
                    850:         */
                    851:        if (p == NULL) {
                    852:                LIST_INSERT_HEAD(&fp->ipq_fragq, ipqe, ipqe_q);
                    853:        } else {
                    854:                LIST_INSERT_AFTER(p, ipqe, ipqe_q);
                    855:        }
                    856:        next = 0;
                    857:        for (p = NULL, q = LIST_FIRST(&fp->ipq_fragq);
                    858:            q != LIST_END(&fp->ipq_fragq); p = q, q = LIST_NEXT(q, ipqe_q)) {
                    859:                if (ntohs(q->ipqe_ip->ip_off) != next)
                    860:                        return (0);
                    861:                next += ntohs(q->ipqe_ip->ip_len);
                    862:        }
                    863:        if (p->ipqe_mff)
                    864:                return (0);
                    865:
                    866:        /*
                    867:         * Reassembly is complete.  Check for a bogus message size and
                    868:         * concatenate fragments.
                    869:         */
                    870:        q = LIST_FIRST(&fp->ipq_fragq);
                    871:        ip = q->ipqe_ip;
                    872:        if ((next + (ip->ip_hl << 2)) > IP_MAXPACKET) {
                    873:                ipstat.ips_toolong++;
                    874:                ip_freef(fp);
                    875:                return (0);
                    876:        }
                    877:        m = q->ipqe_m;
                    878:        t = m->m_next;
                    879:        m->m_next = 0;
                    880:        m_cat(m, t);
                    881:        nq = LIST_NEXT(q, ipqe_q);
                    882:        pool_put(&ipqent_pool, q);
                    883:        ip_frags--;
                    884:        for (q = nq; q != NULL; q = nq) {
                    885:                t = q->ipqe_m;
                    886:                nq = LIST_NEXT(q, ipqe_q);
                    887:                pool_put(&ipqent_pool, q);
                    888:                ip_frags--;
                    889:                m_cat(m, t);
                    890:        }
                    891:
                    892:        /*
                    893:         * Create header for new ip packet by
                    894:         * modifying header of first packet;
                    895:         * dequeue and discard fragment reassembly header.
                    896:         * Make header visible.
                    897:         */
                    898:        ip->ip_len = htons(next);
                    899:        ip->ip_src = fp->ipq_src;
                    900:        ip->ip_dst = fp->ipq_dst;
                    901:        LIST_REMOVE(fp, ipq_q);
                    902:        FREE(fp, M_FTABLE);
                    903:        m->m_len += (ip->ip_hl << 2);
                    904:        m->m_data -= (ip->ip_hl << 2);
                    905:        /* some debugging cruft by sklower, below, will go away soon */
                    906:        if (m->m_flags & M_PKTHDR) { /* XXX this should be done elsewhere */
                    907:                int plen = 0;
                    908:                for (t = m; t; t = t->m_next)
                    909:                        plen += t->m_len;
                    910:                m->m_pkthdr.len = plen;
                    911:        }
                    912:        return (m);
                    913:
                    914: dropfrag:
                    915:        ipstat.ips_fragdropped++;
                    916:        m_freem(m);
                    917:        pool_put(&ipqent_pool, ipqe);
                    918:        ip_frags--;
                    919:        return (0);
                    920: }
                    921:
                    922: /*
                    923:  * Free a fragment reassembly header and all
                    924:  * associated datagrams.
                    925:  */
                    926: void
                    927: ip_freef(fp)
                    928:        struct ipq *fp;
                    929: {
                    930:        struct ipqent *q, *p;
                    931:
                    932:        for (q = LIST_FIRST(&fp->ipq_fragq); q != LIST_END(&fp->ipq_fragq);
                    933:            q = p) {
                    934:                p = LIST_NEXT(q, ipqe_q);
                    935:                m_freem(q->ipqe_m);
                    936:                LIST_REMOVE(q, ipqe_q);
                    937:                pool_put(&ipqent_pool, q);
                    938:                ip_frags--;
                    939:        }
                    940:        LIST_REMOVE(fp, ipq_q);
                    941:        FREE(fp, M_FTABLE);
                    942: }
                    943:
                    944: /*
                    945:  * IP timer processing;
                    946:  * if a timer expires on a reassembly queue, discard it.
                    947:  * clear the forwarding cache, there might be a better route.
                    948:  */
                    949: void
                    950: ip_slowtimo()
                    951: {
                    952:        struct ipq *fp, *nfp;
                    953:        int s = splsoftnet();
                    954:
                    955:        ipq_lock();
                    956:        for (fp = LIST_FIRST(&ipq); fp != LIST_END(&ipq); fp = nfp) {
                    957:                nfp = LIST_NEXT(fp, ipq_q);
                    958:                if (--fp->ipq_ttl == 0) {
                    959:                        ipstat.ips_fragtimeout++;
                    960:                        ip_freef(fp);
                    961:                }
                    962:        }
                    963:        ipq_unlock();
                    964:        if (ipforward_rt.ro_rt) {
                    965:                RTFREE(ipforward_rt.ro_rt);
                    966:                ipforward_rt.ro_rt = 0;
                    967:        }
                    968:        splx(s);
                    969: }
                    970:
                    971: /*
                    972:  * Drain off all datagram fragments.
                    973:  */
                    974: void
                    975: ip_drain()
                    976: {
                    977:
                    978:        if (ipq_lock_try() == 0)
                    979:                return;
                    980:        while (!LIST_EMPTY(&ipq)) {
                    981:                ipstat.ips_fragdropped++;
                    982:                ip_freef(LIST_FIRST(&ipq));
                    983:        }
                    984:        ipq_unlock();
                    985: }
                    986:
                    987: /*
                    988:  * Flush a bunch of datagram fragments, till we are down to 75%.
                    989:  */
                    990: void
                    991: ip_flush()
                    992: {
                    993:        int max = 50;
                    994:
                    995:        /* ipq already locked */
                    996:        while (!LIST_EMPTY(&ipq) && ip_frags > ip_maxqueue * 3 / 4 && --max) {
                    997:                ipstat.ips_fragdropped++;
                    998:                ip_freef(LIST_FIRST(&ipq));
                    999:        }
                   1000: }
                   1001:
                   1002: /*
                   1003:  * Do option processing on a datagram,
                   1004:  * possibly discarding it if bad options are encountered,
                   1005:  * or forwarding it if source-routed.
                   1006:  * Returns 1 if packet has been forwarded/freed,
                   1007:  * 0 if the packet should be processed further.
                   1008:  */
                   1009: int
                   1010: ip_dooptions(m)
                   1011:        struct mbuf *m;
                   1012: {
                   1013:        struct ip *ip = mtod(m, struct ip *);
                   1014:        u_char *cp;
                   1015:        struct ip_timestamp ipt;
                   1016:        struct in_ifaddr *ia;
                   1017:        int opt, optlen, cnt, off, code, type = ICMP_PARAMPROB, forward = 0;
                   1018:        struct in_addr sin, dst;
                   1019:        n_time ntime;
                   1020:
                   1021:        dst = ip->ip_dst;
                   1022:        cp = (u_char *)(ip + 1);
                   1023:        cnt = (ip->ip_hl << 2) - sizeof (struct ip);
                   1024:
                   1025:        for (; cnt > 0; cnt -= optlen, cp += optlen) {
                   1026:                opt = cp[IPOPT_OPTVAL];
                   1027:                if (opt == IPOPT_EOL)
                   1028:                        break;
                   1029:                if (opt == IPOPT_NOP)
                   1030:                        optlen = 1;
                   1031:                else {
                   1032:                        if (cnt < IPOPT_OLEN + sizeof(*cp)) {
                   1033:                                code = &cp[IPOPT_OLEN] - (u_char *)ip;
                   1034:                                goto bad;
                   1035:                        }
                   1036:                        optlen = cp[IPOPT_OLEN];
                   1037:                        if (optlen < IPOPT_OLEN + sizeof(*cp) || optlen > cnt) {
                   1038:                                code = &cp[IPOPT_OLEN] - (u_char *)ip;
                   1039:                                goto bad;
                   1040:                        }
                   1041:                }
                   1042:
                   1043:                switch (opt) {
                   1044:
                   1045:                default:
                   1046:                        break;
                   1047:
                   1048:                /*
                   1049:                 * Source routing with record.
                   1050:                 * Find interface with current destination address.
                   1051:                 * If none on this machine then drop if strictly routed,
                   1052:                 * or do nothing if loosely routed.
                   1053:                 * Record interface address and bring up next address
                   1054:                 * component.  If strictly routed make sure next
                   1055:                 * address is on directly accessible net.
                   1056:                 */
                   1057:                case IPOPT_LSRR:
                   1058:                case IPOPT_SSRR:
                   1059:                        if (!ip_dosourceroute) {
                   1060:                                type = ICMP_UNREACH;
                   1061:                                code = ICMP_UNREACH_SRCFAIL;
                   1062:                                goto bad;
                   1063:                        }
                   1064:                        if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) {
                   1065:                                code = &cp[IPOPT_OFFSET] - (u_char *)ip;
                   1066:                                goto bad;
                   1067:                        }
                   1068:                        ipaddr.sin_addr = ip->ip_dst;
                   1069:                        ia = ifatoia(ifa_ifwithaddr(sintosa(&ipaddr)));
                   1070:                        if (ia == 0) {
                   1071:                                if (opt == IPOPT_SSRR) {
                   1072:                                        type = ICMP_UNREACH;
                   1073:                                        code = ICMP_UNREACH_SRCFAIL;
                   1074:                                        goto bad;
                   1075:                                }
                   1076:                                /*
                   1077:                                 * Loose routing, and not at next destination
                   1078:                                 * yet; nothing to do except forward.
                   1079:                                 */
                   1080:                                break;
                   1081:                        }
                   1082:                        off--;                  /* 0 origin */
                   1083:                        if ((off + sizeof(struct in_addr)) > optlen) {
                   1084:                                /*
                   1085:                                 * End of source route.  Should be for us.
                   1086:                                 */
                   1087:                                save_rte(cp, ip->ip_src);
                   1088:                                break;
                   1089:                        }
                   1090:
                   1091:                        /*
                   1092:                         * locate outgoing interface
                   1093:                         */
                   1094:                        bcopy((caddr_t)(cp + off), (caddr_t)&ipaddr.sin_addr,
                   1095:                            sizeof(ipaddr.sin_addr));
                   1096:                        if (opt == IPOPT_SSRR) {
                   1097: #define        INA     struct in_ifaddr *
                   1098: #define        SA      struct sockaddr *
                   1099:                            if ((ia = (INA)ifa_ifwithdstaddr((SA)&ipaddr)) == 0)
                   1100:                                ia = (INA)ifa_ifwithnet((SA)&ipaddr);
                   1101:                        } else
                   1102:                                ia = ip_rtaddr(ipaddr.sin_addr);
                   1103:                        if (ia == 0) {
                   1104:                                type = ICMP_UNREACH;
                   1105:                                code = ICMP_UNREACH_SRCFAIL;
                   1106:                                goto bad;
                   1107:                        }
                   1108:                        ip->ip_dst = ipaddr.sin_addr;
                   1109:                        bcopy((caddr_t)&ia->ia_addr.sin_addr,
                   1110:                            (caddr_t)(cp + off), sizeof(struct in_addr));
                   1111:                        cp[IPOPT_OFFSET] += sizeof(struct in_addr);
                   1112:                        /*
                   1113:                         * Let ip_intr's mcast routing check handle mcast pkts
                   1114:                         */
                   1115:                        forward = !IN_MULTICAST(ip->ip_dst.s_addr);
                   1116:                        break;
                   1117:
                   1118:                case IPOPT_RR:
                   1119:                        if (optlen < IPOPT_OFFSET + sizeof(*cp)) {
                   1120:                                code = &cp[IPOPT_OLEN] - (u_char *)ip;
                   1121:                                goto bad;
                   1122:                        }
                   1123:                        if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) {
                   1124:                                code = &cp[IPOPT_OFFSET] - (u_char *)ip;
                   1125:                                goto bad;
                   1126:                        }
                   1127:
                   1128:                        /*
                   1129:                         * If no space remains, ignore.
                   1130:                         */
                   1131:                        off--;                  /* 0 origin */
                   1132:                        if ((off + sizeof(struct in_addr)) > optlen)
                   1133:                                break;
                   1134:                        bcopy((caddr_t)(&ip->ip_dst), (caddr_t)&ipaddr.sin_addr,
                   1135:                            sizeof(ipaddr.sin_addr));
                   1136:                        /*
                   1137:                         * locate outgoing interface; if we're the destination,
                   1138:                         * use the incoming interface (should be same).
                   1139:                         */
                   1140:                        if ((ia = (INA)ifa_ifwithaddr((SA)&ipaddr)) == 0 &&
                   1141:                            (ia = ip_rtaddr(ipaddr.sin_addr)) == 0) {
                   1142:                                type = ICMP_UNREACH;
                   1143:                                code = ICMP_UNREACH_HOST;
                   1144:                                goto bad;
                   1145:                        }
                   1146:                        bcopy((caddr_t)&ia->ia_addr.sin_addr,
                   1147:                            (caddr_t)(cp + off), sizeof(struct in_addr));
                   1148:                        cp[IPOPT_OFFSET] += sizeof(struct in_addr);
                   1149:                        break;
                   1150:
                   1151:                case IPOPT_TS:
                   1152:                        code = cp - (u_char *)ip;
                   1153:                        if (optlen < sizeof(struct ip_timestamp))
                   1154:                                goto bad;
                   1155:                        bcopy(cp, &ipt, sizeof(struct ip_timestamp));
                   1156:                        if (ipt.ipt_ptr < 5 || ipt.ipt_len < 5)
                   1157:                                goto bad;
                   1158:                        if (ipt.ipt_ptr - 1 + sizeof(n_time) > ipt.ipt_len) {
                   1159:                                if (++ipt.ipt_oflw == 0)
                   1160:                                        goto bad;
                   1161:                                break;
                   1162:                        }
                   1163:                        bcopy(cp + ipt.ipt_ptr - 1, &sin, sizeof sin);
                   1164:                        switch (ipt.ipt_flg) {
                   1165:
                   1166:                        case IPOPT_TS_TSONLY:
                   1167:                                break;
                   1168:
                   1169:                        case IPOPT_TS_TSANDADDR:
                   1170:                                if (ipt.ipt_ptr - 1 + sizeof(n_time) +
                   1171:                                    sizeof(struct in_addr) > ipt.ipt_len)
                   1172:                                        goto bad;
                   1173:                                ipaddr.sin_addr = dst;
                   1174:                                ia = (INA)ifaof_ifpforaddr((SA)&ipaddr,
                   1175:                                                            m->m_pkthdr.rcvif);
                   1176:                                if (ia == 0)
                   1177:                                        continue;
                   1178:                                bcopy((caddr_t)&ia->ia_addr.sin_addr,
                   1179:                                    (caddr_t)&sin, sizeof(struct in_addr));
                   1180:                                ipt.ipt_ptr += sizeof(struct in_addr);
                   1181:                                break;
                   1182:
                   1183:                        case IPOPT_TS_PRESPEC:
                   1184:                                if (ipt.ipt_ptr - 1 + sizeof(n_time) +
                   1185:                                    sizeof(struct in_addr) > ipt.ipt_len)
                   1186:                                        goto bad;
                   1187:                                bcopy((caddr_t)&sin, (caddr_t)&ipaddr.sin_addr,
                   1188:                                    sizeof(struct in_addr));
                   1189:                                if (ifa_ifwithaddr((SA)&ipaddr) == 0)
                   1190:                                        continue;
                   1191:                                ipt.ipt_ptr += sizeof(struct in_addr);
                   1192:                                break;
                   1193:
                   1194:                        default:
                   1195:                                /* XXX can't take &ipt->ipt_flg */
                   1196:                                code = (u_char *)&ipt.ipt_ptr -
                   1197:                                    (u_char *)ip + 1;
                   1198:                                goto bad;
                   1199:                        }
                   1200:                        ntime = iptime();
                   1201:                        bcopy((caddr_t)&ntime, (caddr_t)cp + ipt.ipt_ptr - 1,
                   1202:                            sizeof(n_time));
                   1203:                        ipt.ipt_ptr += sizeof(n_time);
                   1204:                }
                   1205:        }
                   1206:        if (forward && ipforwarding) {
                   1207:                ip_forward(m, 1);
                   1208:                return (1);
                   1209:        }
                   1210:        return (0);
                   1211: bad:
                   1212:        icmp_error(m, type, code, 0, 0);
                   1213:        ipstat.ips_badoptions++;
                   1214:        return (1);
                   1215: }
                   1216:
                   1217: /*
                   1218:  * Given address of next destination (final or next hop),
                   1219:  * return internet address info of interface to be used to get there.
                   1220:  */
                   1221: struct in_ifaddr *
                   1222: ip_rtaddr(dst)
                   1223:         struct in_addr dst;
                   1224: {
                   1225:        struct sockaddr_in *sin;
                   1226:
                   1227:        sin = satosin(&ipforward_rt.ro_dst);
                   1228:
                   1229:        if (ipforward_rt.ro_rt == 0 || dst.s_addr != sin->sin_addr.s_addr) {
                   1230:                if (ipforward_rt.ro_rt) {
                   1231:                        RTFREE(ipforward_rt.ro_rt);
                   1232:                        ipforward_rt.ro_rt = 0;
                   1233:                }
                   1234:                sin->sin_family = AF_INET;
                   1235:                sin->sin_len = sizeof(*sin);
                   1236:                sin->sin_addr = dst;
                   1237:
                   1238:                rtalloc(&ipforward_rt);
                   1239:        }
                   1240:        if (ipforward_rt.ro_rt == 0)
                   1241:                return ((struct in_ifaddr *)0);
                   1242:        return (ifatoia(ipforward_rt.ro_rt->rt_ifa));
                   1243: }
                   1244:
                   1245: /*
                   1246:  * Save incoming source route for use in replies,
                   1247:  * to be picked up later by ip_srcroute if the receiver is interested.
                   1248:  */
                   1249: void
                   1250: save_rte(option, dst)
                   1251:        u_char *option;
                   1252:        struct in_addr dst;
                   1253: {
                   1254:        unsigned olen;
                   1255:
                   1256:        olen = option[IPOPT_OLEN];
                   1257: #ifdef DIAGNOSTIC
                   1258:        if (ipprintfs)
                   1259:                printf("save_rte: olen %d\n", olen);
                   1260: #endif /* 0 */
                   1261:        if (olen > sizeof(ip_srcrt) - (1 + sizeof(dst)))
                   1262:                return;
                   1263:        bcopy((caddr_t)option, (caddr_t)ip_srcrt.srcopt, olen);
                   1264:        ip_nhops = (olen - IPOPT_OFFSET - 1) / sizeof(struct in_addr);
                   1265:        ip_srcrt.dst = dst;
                   1266: }
                   1267:
                   1268: /*
                   1269:  * Check whether we do proxy ARP for this address and we point to ourselves.
                   1270:  * Code shamelessly copied from arplookup().
                   1271:  */
                   1272: int
                   1273: ip_weadvertise(addr)
                   1274:        u_int32_t addr;
                   1275: {
                   1276:        struct rtentry *rt;
                   1277:        struct ifnet *ifp;
                   1278:        struct ifaddr *ifa;
                   1279:        struct sockaddr_inarp sin;
                   1280:
                   1281:        sin.sin_len = sizeof(sin);
                   1282:        sin.sin_family = AF_INET;
                   1283:        sin.sin_addr.s_addr = addr;
                   1284:        sin.sin_other = SIN_PROXY;
                   1285:        rt = rtalloc1(sintosa(&sin), 0, 0);     /* XXX other tables? */
                   1286:        if (rt == 0)
                   1287:                return 0;
                   1288:
                   1289:        if ((rt->rt_flags & RTF_GATEWAY) || (rt->rt_flags & RTF_LLINFO) == 0 ||
                   1290:            rt->rt_gateway->sa_family != AF_LINK) {
                   1291:                RTFREE(rt);
                   1292:                return 0;
                   1293:        }
                   1294:
                   1295:        TAILQ_FOREACH(ifp, &ifnet, if_list)
                   1296:                TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
                   1297:                        if (ifa->ifa_addr->sa_family != rt->rt_gateway->sa_family)
                   1298:                                continue;
                   1299:
                   1300:                        if (!bcmp(LLADDR((struct sockaddr_dl *)ifa->ifa_addr),
                   1301:                            LLADDR((struct sockaddr_dl *)rt->rt_gateway),
                   1302:                            ETHER_ADDR_LEN)) {
                   1303:                                RTFREE(rt);
                   1304:                                return 1;
                   1305:                        }
                   1306:                }
                   1307:
                   1308:        RTFREE(rt);
                   1309:        return 0;
                   1310: }
                   1311:
                   1312: /*
                   1313:  * Retrieve incoming source route for use in replies,
                   1314:  * in the same form used by setsockopt.
                   1315:  * The first hop is placed before the options, will be removed later.
                   1316:  */
                   1317: struct mbuf *
                   1318: ip_srcroute()
                   1319: {
                   1320:        struct in_addr *p, *q;
                   1321:        struct mbuf *m;
                   1322:
                   1323:        if (ip_nhops == 0)
                   1324:                return ((struct mbuf *)0);
                   1325:        m = m_get(M_DONTWAIT, MT_SOOPTS);
                   1326:        if (m == 0)
                   1327:                return ((struct mbuf *)0);
                   1328:
                   1329: #define OPTSIZ (sizeof(ip_srcrt.nop) + sizeof(ip_srcrt.srcopt))
                   1330:
                   1331:        /* length is (nhops+1)*sizeof(addr) + sizeof(nop + srcrt header) */
                   1332:        m->m_len = ip_nhops * sizeof(struct in_addr) + sizeof(struct in_addr) +
                   1333:            OPTSIZ;
                   1334: #ifdef DIAGNOSTIC
                   1335:        if (ipprintfs)
                   1336:                printf("ip_srcroute: nhops %d mlen %d", ip_nhops, m->m_len);
                   1337: #endif
                   1338:
                   1339:        /*
                   1340:         * First save first hop for return route
                   1341:         */
                   1342:        p = &ip_srcrt.route[ip_nhops - 1];
                   1343:        *(mtod(m, struct in_addr *)) = *p--;
                   1344: #ifdef DIAGNOSTIC
                   1345:        if (ipprintfs)
                   1346:                printf(" hops %x", ntohl(mtod(m, struct in_addr *)->s_addr));
                   1347: #endif
                   1348:
                   1349:        /*
                   1350:         * Copy option fields and padding (nop) to mbuf.
                   1351:         */
                   1352:        ip_srcrt.nop = IPOPT_NOP;
                   1353:        ip_srcrt.srcopt[IPOPT_OFFSET] = IPOPT_MINOFF;
                   1354:        bcopy((caddr_t)&ip_srcrt.nop,
                   1355:            mtod(m, caddr_t) + sizeof(struct in_addr), OPTSIZ);
                   1356:        q = (struct in_addr *)(mtod(m, caddr_t) +
                   1357:            sizeof(struct in_addr) + OPTSIZ);
                   1358: #undef OPTSIZ
                   1359:        /*
                   1360:         * Record return path as an IP source route,
                   1361:         * reversing the path (pointers are now aligned).
                   1362:         */
                   1363:        while (p >= ip_srcrt.route) {
                   1364: #ifdef DIAGNOSTIC
                   1365:                if (ipprintfs)
                   1366:                        printf(" %x", ntohl(q->s_addr));
                   1367: #endif
                   1368:                *q++ = *p--;
                   1369:        }
                   1370:        /*
                   1371:         * Last hop goes to final destination.
                   1372:         */
                   1373:        *q = ip_srcrt.dst;
                   1374: #ifdef DIAGNOSTIC
                   1375:        if (ipprintfs)
                   1376:                printf(" %x\n", ntohl(q->s_addr));
                   1377: #endif
                   1378:        return (m);
                   1379: }
                   1380:
                   1381: /*
                   1382:  * Strip out IP options, at higher
                   1383:  * level protocol in the kernel.
                   1384:  * Second argument is buffer to which options
                   1385:  * will be moved, and return value is their length.
                   1386:  * XXX should be deleted; last arg currently ignored.
                   1387:  */
                   1388: void
                   1389: ip_stripoptions(m, mopt)
                   1390:        struct mbuf *m;
                   1391:        struct mbuf *mopt;
                   1392: {
                   1393:        int i;
                   1394:        struct ip *ip = mtod(m, struct ip *);
                   1395:        caddr_t opts;
                   1396:        int olen;
                   1397:
                   1398:        olen = (ip->ip_hl<<2) - sizeof (struct ip);
                   1399:        opts = (caddr_t)(ip + 1);
                   1400:        i = m->m_len - (sizeof (struct ip) + olen);
                   1401:        bcopy(opts  + olen, opts, (unsigned)i);
                   1402:        m->m_len -= olen;
                   1403:        if (m->m_flags & M_PKTHDR)
                   1404:                m->m_pkthdr.len -= olen;
                   1405:        ip->ip_hl = sizeof(struct ip) >> 2;
                   1406: }
                   1407:
                   1408: int inetctlerrmap[PRC_NCMDS] = {
                   1409:        0,              0,              0,              0,
                   1410:        0,              EMSGSIZE,       EHOSTDOWN,      EHOSTUNREACH,
                   1411:        EHOSTUNREACH,   EHOSTUNREACH,   ECONNREFUSED,   ECONNREFUSED,
                   1412:        EMSGSIZE,       EHOSTUNREACH,   0,              0,
                   1413:        0,              0,              0,              0,
                   1414:        ENOPROTOOPT
                   1415: };
                   1416:
                   1417: /*
                   1418:  * Forward a packet.  If some error occurs return the sender
                   1419:  * an icmp packet.  Note we can't always generate a meaningful
                   1420:  * icmp message because icmp doesn't have a large enough repertoire
                   1421:  * of codes and types.
                   1422:  *
                   1423:  * If not forwarding, just drop the packet.  This could be confusing
                   1424:  * if ipforwarding was zero but some routing protocol was advancing
                   1425:  * us as a gateway to somewhere.  However, we must let the routing
                   1426:  * protocol deal with that.
                   1427:  *
                   1428:  * The srcrt parameter indicates whether the packet is being forwarded
                   1429:  * via a source route.
                   1430:  */
                   1431: void
                   1432: ip_forward(m, srcrt)
                   1433:        struct mbuf *m;
                   1434:        int srcrt;
                   1435: {
                   1436:        struct ip *ip = mtod(m, struct ip *);
                   1437:        struct sockaddr_in *sin;
                   1438:        struct rtentry *rt;
                   1439:        int error, type = 0, code = 0, destmtu = 0, rtableid = 0;
                   1440:        struct mbuf *mcopy;
                   1441:        n_long dest;
                   1442:
                   1443:        dest = 0;
                   1444: #ifdef DIAGNOSTIC
                   1445:        if (ipprintfs)
                   1446:                printf("forward: src %x dst %x ttl %x\n", ip->ip_src.s_addr,
                   1447:                    ip->ip_dst.s_addr, ip->ip_ttl);
                   1448: #endif
                   1449:        if (m->m_flags & M_BCAST || in_canforward(ip->ip_dst) == 0) {
                   1450:                ipstat.ips_cantforward++;
                   1451:                m_freem(m);
                   1452:                return;
                   1453:        }
                   1454:        if (ip->ip_ttl <= IPTTLDEC) {
                   1455:                icmp_error(m, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS, dest, 0);
                   1456:                return;
                   1457:        }
                   1458:
                   1459: #if NPF > 0
                   1460:        rtableid = m->m_pkthdr.pf.rtableid;
                   1461: #endif
                   1462:
                   1463:        sin = satosin(&ipforward_rt.ro_dst);
                   1464:        if ((rt = ipforward_rt.ro_rt) == 0 ||
                   1465:            ip->ip_dst.s_addr != sin->sin_addr.s_addr ||
                   1466:            rtableid != ipforward_rtableid) {
                   1467:                if (ipforward_rt.ro_rt) {
                   1468:                        RTFREE(ipforward_rt.ro_rt);
                   1469:                        ipforward_rt.ro_rt = 0;
                   1470:                }
                   1471:                sin->sin_family = AF_INET;
                   1472:                sin->sin_len = sizeof(*sin);
                   1473:                sin->sin_addr = ip->ip_dst;
                   1474:
                   1475:                rtalloc_mpath(&ipforward_rt, &ip->ip_src.s_addr, rtableid);
                   1476:                if (ipforward_rt.ro_rt == 0) {
                   1477:                        icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, dest, 0);
                   1478:                        return;
                   1479:                }
                   1480:                ipforward_rtableid = rtableid;
                   1481:                rt = ipforward_rt.ro_rt;
                   1482:        }
                   1483:
                   1484:        /*
                   1485:         * Save at most 68 bytes of the packet in case
                   1486:         * we need to generate an ICMP message to the src.
                   1487:         * Pullup to avoid sharing mbuf cluster between m and mcopy.
                   1488:         */
                   1489:        mcopy = m_copym(m, 0, min(ntohs(ip->ip_len), 68), M_DONTWAIT);
                   1490:        if (mcopy)
                   1491:                mcopy = m_pullup(mcopy, min(ntohs(ip->ip_len), 68));
                   1492:
                   1493:        ip->ip_ttl -= IPTTLDEC;
                   1494:
                   1495:        /*
                   1496:         * If forwarding packet using same interface that it came in on,
                   1497:         * perhaps should send a redirect to sender to shortcut a hop.
                   1498:         * Only send redirect if source is sending directly to us,
                   1499:         * and if packet was not source routed (or has any options).
                   1500:         * Also, don't send redirect if forwarding using a default route
                   1501:         * or a route modified by a redirect.
                   1502:         * Don't send redirect if we advertise destination's arp address
                   1503:         * as ours (proxy arp).
                   1504:         */
                   1505:        if (rt->rt_ifp == m->m_pkthdr.rcvif &&
                   1506:            (rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0 &&
                   1507:            satosin(rt_key(rt))->sin_addr.s_addr != 0 &&
                   1508:            ipsendredirects && !srcrt &&
                   1509:            !ip_weadvertise(satosin(rt_key(rt))->sin_addr.s_addr)) {
                   1510:                if (rt->rt_ifa &&
                   1511:                    (ip->ip_src.s_addr & ifatoia(rt->rt_ifa)->ia_subnetmask) ==
                   1512:                    ifatoia(rt->rt_ifa)->ia_subnet) {
                   1513:                    if (rt->rt_flags & RTF_GATEWAY)
                   1514:                        dest = satosin(rt->rt_gateway)->sin_addr.s_addr;
                   1515:                    else
                   1516:                        dest = ip->ip_dst.s_addr;
                   1517:                    /* Router requirements says to only send host redirects */
                   1518:                    type = ICMP_REDIRECT;
                   1519:                    code = ICMP_REDIRECT_HOST;
                   1520: #ifdef DIAGNOSTIC
                   1521:                    if (ipprintfs)
                   1522:                        printf("redirect (%d) to %x\n", code, (u_int32_t)dest);
                   1523: #endif
                   1524:                }
                   1525:        }
                   1526:
                   1527:        error = ip_output(m, (struct mbuf *)NULL, &ipforward_rt,
                   1528:            (IP_FORWARDING | (ip_directedbcast ? IP_ALLOWBROADCAST : 0)),
                   1529:            (void *)NULL, (void *)NULL);
                   1530:        if (error)
                   1531:                ipstat.ips_cantforward++;
                   1532:        else {
                   1533:                ipstat.ips_forward++;
                   1534:                if (type)
                   1535:                        ipstat.ips_redirectsent++;
                   1536:                else
                   1537:                        goto freecopy;
                   1538:        }
                   1539:        if (mcopy == NULL)
                   1540:                goto freert;
                   1541:
                   1542:        switch (error) {
                   1543:
                   1544:        case 0:                         /* forwarded, but need redirect */
                   1545:                /* type, code set above */
                   1546:                break;
                   1547:
                   1548:        case ENETUNREACH:               /* shouldn't happen, checked above */
                   1549:        case EHOSTUNREACH:
                   1550:        case ENETDOWN:
                   1551:        case EHOSTDOWN:
                   1552:        default:
                   1553:                type = ICMP_UNREACH;
                   1554:                code = ICMP_UNREACH_HOST;
                   1555:                break;
                   1556:
                   1557:        case EMSGSIZE:
                   1558:                type = ICMP_UNREACH;
                   1559:                code = ICMP_UNREACH_NEEDFRAG;
                   1560:
                   1561: #ifdef IPSEC
                   1562:                if (ipforward_rt.ro_rt) {
                   1563:                        struct rtentry *rt = ipforward_rt.ro_rt;
                   1564:
                   1565:                        if (rt->rt_rmx.rmx_mtu)
                   1566:                                destmtu = rt->rt_rmx.rmx_mtu;
                   1567:                        else
                   1568:                                destmtu = ipforward_rt.ro_rt->rt_ifp->if_mtu;
                   1569:                }
                   1570: #endif /*IPSEC*/
                   1571:                ipstat.ips_cantfrag++;
                   1572:                break;
                   1573:
                   1574:        case ENOBUFS:
                   1575: #if 1
                   1576:                /*
                   1577:                 * a router should not generate ICMP_SOURCEQUENCH as
                   1578:                 * required in RFC1812 Requirements for IP Version 4 Routers.
                   1579:                 * source quench could be a big problem under DoS attacks,
                   1580:                 * or the underlying interface is rate-limited.
                   1581:                 */
                   1582:                goto freecopy;
                   1583: #else
                   1584:                type = ICMP_SOURCEQUENCH;
                   1585:                code = 0;
                   1586:                break;
                   1587: #endif
                   1588:        }
                   1589:
                   1590:        icmp_error(mcopy, type, code, dest, destmtu);
                   1591:        goto freert;
                   1592:
                   1593:  freecopy:
                   1594:        if (mcopy)
                   1595:                m_free(mcopy);
                   1596:  freert:
                   1597: #ifndef SMALL_KERNEL
                   1598:        if (ipmultipath && ipforward_rt.ro_rt &&
                   1599:            (ipforward_rt.ro_rt->rt_flags & RTF_MPATH)) {
                   1600:                RTFREE(ipforward_rt.ro_rt);
                   1601:                ipforward_rt.ro_rt = 0;
                   1602:        }
                   1603: #endif
                   1604:        return;
                   1605: }
                   1606:
                   1607: int
                   1608: ip_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
                   1609:        int *name;
                   1610:        u_int namelen;
                   1611:        void *oldp;
                   1612:        size_t *oldlenp;
                   1613:        void *newp;
                   1614:        size_t newlen;
                   1615: {
                   1616:        int error;
                   1617:
                   1618:        /* Almost all sysctl names at this level are terminal. */
                   1619:        if (namelen != 1 && name[0] != IPCTL_IFQUEUE)
                   1620:                return (ENOTDIR);
                   1621:
                   1622:        switch (name[0]) {
                   1623: #ifdef notyet
                   1624:        case IPCTL_DEFMTU:
                   1625:                return (sysctl_int(oldp, oldlenp, newp, newlen, &ip_mtu));
                   1626: #endif
                   1627:        case IPCTL_SOURCEROUTE:
                   1628:                /*
                   1629:                 * Don't allow this to change in a secure environment.
                   1630:                 */
                   1631:                if (newp && securelevel > 0)
                   1632:                        return (EPERM);
                   1633:                return (sysctl_int(oldp, oldlenp, newp, newlen,
                   1634:                    &ip_dosourceroute));
                   1635:        case IPCTL_MTUDISC:
                   1636:                error = sysctl_int(oldp, oldlenp, newp, newlen,
                   1637:                    &ip_mtudisc);
                   1638:                if (ip_mtudisc != 0 && ip_mtudisc_timeout_q == NULL) {
                   1639:                        ip_mtudisc_timeout_q =
                   1640:                            rt_timer_queue_create(ip_mtudisc_timeout);
                   1641:                } else if (ip_mtudisc == 0 && ip_mtudisc_timeout_q != NULL) {
                   1642:                        rt_timer_queue_destroy(ip_mtudisc_timeout_q, TRUE);
                   1643:                        Free(ip_mtudisc_timeout_q);
                   1644:                        ip_mtudisc_timeout_q = NULL;
                   1645:                }
                   1646:                return error;
                   1647:        case IPCTL_MTUDISCTIMEOUT:
                   1648:                error = sysctl_int(oldp, oldlenp, newp, newlen,
                   1649:                   &ip_mtudisc_timeout);
                   1650:                if (ip_mtudisc_timeout_q != NULL)
                   1651:                        rt_timer_queue_change(ip_mtudisc_timeout_q,
                   1652:                                              ip_mtudisc_timeout);
                   1653:                return (error);
                   1654:        case IPCTL_IPSEC_ENC_ALGORITHM:
                   1655:                return (sysctl_tstring(oldp, oldlenp, newp, newlen,
                   1656:                                       ipsec_def_enc, sizeof(ipsec_def_enc)));
                   1657:        case IPCTL_IPSEC_AUTH_ALGORITHM:
                   1658:                return (sysctl_tstring(oldp, oldlenp, newp, newlen,
                   1659:                                       ipsec_def_auth,
                   1660:                                       sizeof(ipsec_def_auth)));
                   1661:        case IPCTL_IPSEC_IPCOMP_ALGORITHM:
                   1662:                return (sysctl_tstring(oldp, oldlenp, newp, newlen,
                   1663:                                       ipsec_def_comp,
                   1664:                                       sizeof(ipsec_def_comp)));
                   1665:        case IPCTL_IFQUEUE:
                   1666:                return (sysctl_ifq(name + 1, namelen - 1,
                   1667:                    oldp, oldlenp, newp, newlen, &ipintrq));
                   1668:        default:
                   1669:                if (name[0] < IPCTL_MAXID)
                   1670:                        return (sysctl_int_arr(ipctl_vars, name, namelen,
                   1671:                            oldp, oldlenp, newp, newlen));
                   1672:                return (EOPNOTSUPP);
                   1673:        }
                   1674:        /* NOTREACHED */
                   1675: }
                   1676:
                   1677: void
                   1678: ip_savecontrol(struct inpcb *inp, struct mbuf **mp, struct ip *ip,
                   1679:     struct mbuf *m)
                   1680: {
                   1681: #ifdef SO_TIMESTAMP
                   1682:        if (inp->inp_socket->so_options & SO_TIMESTAMP) {
                   1683:                struct timeval tv;
                   1684:
                   1685:                microtime(&tv);
                   1686:                *mp = sbcreatecontrol((caddr_t) &tv, sizeof(tv),
                   1687:                    SCM_TIMESTAMP, SOL_SOCKET);
                   1688:                if (*mp)
                   1689:                        mp = &(*mp)->m_next;
                   1690:        }
                   1691: #endif
                   1692:        if (inp->inp_flags & INP_RECVDSTADDR) {
                   1693:                *mp = sbcreatecontrol((caddr_t) &ip->ip_dst,
                   1694:                    sizeof(struct in_addr), IP_RECVDSTADDR, IPPROTO_IP);
                   1695:                if (*mp)
                   1696:                        mp = &(*mp)->m_next;
                   1697:        }
                   1698: #ifdef notyet
                   1699:        /* this code is broken and will probably never be fixed. */
                   1700:        /* options were tossed already */
                   1701:        if (inp->inp_flags & INP_RECVOPTS) {
                   1702:                *mp = sbcreatecontrol((caddr_t) opts_deleted_above,
                   1703:                    sizeof(struct in_addr), IP_RECVOPTS, IPPROTO_IP);
                   1704:                if (*mp)
                   1705:                        mp = &(*mp)->m_next;
                   1706:        }
                   1707:        /* ip_srcroute doesn't do what we want here, need to fix */
                   1708:        if (inp->inp_flags & INP_RECVRETOPTS) {
                   1709:                *mp = sbcreatecontrol((caddr_t) ip_srcroute(),
                   1710:                    sizeof(struct in_addr), IP_RECVRETOPTS, IPPROTO_IP);
                   1711:                if (*mp)
                   1712:                        mp = &(*mp)->m_next;
                   1713:        }
                   1714: #endif
                   1715:        if (inp->inp_flags & INP_RECVIF) {
                   1716:                struct sockaddr_dl sdl;
                   1717:                struct ifnet *ifp;
                   1718:
                   1719:                if ((ifp = m->m_pkthdr.rcvif) == NULL ||
                   1720:                    ifp->if_sadl == NULL) {
                   1721:                        bzero(&sdl, sizeof(sdl));
                   1722:                        sdl.sdl_len = offsetof(struct sockaddr_dl, sdl_data[0]);
                   1723:                        sdl.sdl_family = AF_LINK;
                   1724:                        sdl.sdl_index = ifp != NULL ? ifp->if_index : 0;
                   1725:                        sdl.sdl_nlen = sdl.sdl_alen = sdl.sdl_slen = 0;
                   1726:                        *mp = sbcreatecontrol((caddr_t) &sdl, sdl.sdl_len,
                   1727:                            IP_RECVIF, IPPROTO_IP);
                   1728:                } else {
                   1729:                        *mp = sbcreatecontrol((caddr_t) ifp->if_sadl,
                   1730:                            ifp->if_sadl->sdl_len, IP_RECVIF, IPPROTO_IP);
                   1731:                }
                   1732:                if (*mp)
                   1733:                        mp = &(*mp)->m_next;
                   1734:        }
                   1735:        if (inp->inp_flags & INP_RECVTTL) {
                   1736:                *mp = sbcreatecontrol((caddr_t) &ip->ip_ttl,
                   1737:                    sizeof(u_char), IP_RECVTTL, IPPROTO_IP);
                   1738:                if (*mp)
                   1739:                        mp = &(*mp)->m_next;
                   1740:        }
                   1741: }
                   1742:

CVSweb