Annotation of XNU/bsd/netinet/ip_icmp.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * The contents of this file constitute Original Code as defined in and
                      7:  * are subject to the Apple Public Source License Version 1.1 (the
                      8:  * "License").  You may not use this file except in compliance with the
                      9:  * License.  Please obtain a copy of the License at
                     10:  * http://www.apple.com/publicsource and read it before using this file.
                     11:  * 
                     12:  * This Original Code and all software distributed under the License are
                     13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     17:  * License for the specific language governing rights and limitations
                     18:  * under the License.
                     19:  * 
                     20:  * @APPLE_LICENSE_HEADER_END@
                     21:  */
                     22: /*
                     23:  * Copyright (c) 1982, 1986, 1988, 1993
                     24:  *     The Regents of the University of California.  All rights reserved.
                     25:  *
                     26:  * Redistribution and use in source and binary forms, with or without
                     27:  * modification, are permitted provided that the following conditions
                     28:  * are met:
                     29:  * 1. Redistributions of source code must retain the above copyright
                     30:  *    notice, this list of conditions and the following disclaimer.
                     31:  * 2. Redistributions in binary form must reproduce the above copyright
                     32:  *    notice, this list of conditions and the following disclaimer in the
                     33:  *    documentation and/or other materials provided with the distribution.
                     34:  * 3. All advertising materials mentioning features or use of this software
                     35:  *    must display the following acknowledgement:
                     36:  *     This product includes software developed by the University of
                     37:  *     California, Berkeley and its contributors.
                     38:  * 4. Neither the name of the University nor the names of its contributors
                     39:  *    may be used to endorse or promote products derived from this software
                     40:  *    without specific prior written permission.
                     41:  *
                     42:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     43:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     44:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     45:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     46:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     47:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     48:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     49:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     50:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     51:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     52:  * SUCH DAMAGE.
                     53:  *
                     54:  *     @(#)ip_icmp.c   8.2 (Berkeley) 1/4/94
                     55:  */
                     56: 
                     57: #include <sys/param.h>
                     58: #include <sys/systm.h>
                     59: #include <sys/mbuf.h>
                     60: #include <sys/protosw.h>
                     61: #include <sys/socket.h>
                     62: #include <sys/time.h>
                     63: #include <sys/kernel.h>
                     64: #include <sys/sysctl.h>
                     65: 
                     66: #include <net/if.h>
                     67: #include <net/route.h>
                     68: 
                     69: #define _IP_VHL
                     70: #include <netinet/in.h>
                     71: #include <netinet/in_systm.h>
                     72: #include <netinet/in_var.h>
                     73: #include <netinet/ip.h>
                     74: #include <netinet/ip_icmp.h>
                     75: #include <netinet/ip_var.h>
                     76: #include <netinet/icmp_var.h>
                     77: 
                     78: /*
                     79:  * ICMP routines: error generation, receive packet processing, and
                     80:  * routines to turnaround packets back to the originator, and
                     81:  * host table maintenance routines.
                     82:  */
                     83: 
                     84: static struct  icmpstat icmpstat;
                     85: SYSCTL_STRUCT(_net_inet_icmp, ICMPCTL_STATS, stats, CTLFLAG_RD,
                     86:        &icmpstat, icmpstat, "");
                     87: 
                     88: static int     icmpmaskrepl = 0;
                     89: SYSCTL_INT(_net_inet_icmp, ICMPCTL_MASKREPL, maskrepl, CTLFLAG_RW,
                     90:        &icmpmaskrepl, 0, "");
                     91: 
                     92: #if ICMP_BANDLIM 
                     93:  
                     94: /*    
                     95:  * ICMP error-response bandwidth limiting sysctl.  If not enabled, sysctl
                     96:  *      variable content is -1 and read-only.
                     97:  */     
                     98:     
                     99: static int      icmplim = 100;
                    100: SYSCTL_INT(_net_inet_icmp, ICMPCTL_ICMPLIM, icmplim, CTLFLAG_RW,
                    101:        &icmplim, 0, "");
                    102: #else
                    103: 
                    104: static int      icmplim = -1;
                    105: SYSCTL_INT(_net_inet_icmp, ICMPCTL_ICMPLIM, icmplim, CTLFLAG_RD,
                    106:        &icmplim, 0, "");
                    107:        
                    108: #endif 
                    109: 
                    110: /*
                    111:  * ICMP broadcast echo sysctl
                    112:  */
                    113: 
                    114: static int     icmpbmcastecho = 0;
                    115: SYSCTL_INT(_net_inet_icmp, OID_AUTO, bmcastecho, CTLFLAG_RW, &icmpbmcastecho,
                    116:           0, "");
                    117: 
                    118: 
                    119: #if ICMPPRINTFS
                    120: int    icmpprintfs = 0;
                    121: #endif
                    122: 
                    123: static void    icmp_reflect __P((struct mbuf *));
                    124: static void    icmp_send __P((struct mbuf *, struct mbuf *));
                    125: static int     ip_next_mtu __P((int, int));
                    126: 
                    127: extern struct protosw inetsw[];
                    128: 
                    129: /*
                    130:  * Generate an error packet of type error
                    131:  * in response to bad packet ip.
                    132:  */
                    133: void
                    134: icmp_error(n, type, code, dest, destifp)
                    135:        struct mbuf *n;
                    136:        int type, code;
                    137:        n_long dest;
                    138:        struct ifnet *destifp;
                    139: {
                    140:        register struct ip *oip = mtod(n, struct ip *), *nip;
                    141:        register unsigned oiplen = IP_VHL_HL(oip->ip_vhl) << 2;
                    142:        register struct icmp *icp;
                    143:        register struct mbuf *m;
                    144:        unsigned icmplen;
                    145: 
                    146: #if ICMPPRINTFS
                    147:        if (icmpprintfs)
                    148:                printf("icmp_error(%p, %x, %d)\n", oip, type, code);
                    149: #endif
                    150:        if (type != ICMP_REDIRECT)
                    151:                icmpstat.icps_error++;
                    152:        /*
                    153:         * Don't send error if not the first fragment of message.
                    154:         * Don't error if the old packet protocol was ICMP
                    155:         * error message, only known informational types.
                    156:         */
                    157:        if (oip->ip_off &~ (IP_MF|IP_DF))
                    158:                goto freeit;
                    159:        if (oip->ip_p == IPPROTO_ICMP && type != ICMP_REDIRECT &&
                    160:          n->m_len >= oiplen + ICMP_MINLEN &&
                    161:          !ICMP_INFOTYPE(((struct icmp *)((caddr_t)oip + oiplen))->icmp_type)) {
                    162:                icmpstat.icps_oldicmp++;
                    163:                goto freeit;
                    164:        }
                    165:        /* Don't send error in response to a multicast or broadcast packet */
                    166:        if (n->m_flags & (M_BCAST|M_MCAST))
                    167:                goto freeit;
                    168:        /*
                    169:         * First, formulate icmp message
                    170:         */
                    171:        m = m_gethdr(M_DONTWAIT, MT_HEADER);
                    172:        if (m == NULL)
                    173:                goto freeit;
                    174:        icmplen = oiplen + min(8, oip->ip_len);
                    175:        m->m_len = icmplen + ICMP_MINLEN;
                    176:        MH_ALIGN(m, m->m_len);
                    177:        icp = mtod(m, struct icmp *);
                    178:        if ((u_int)type > ICMP_MAXTYPE)
                    179:                panic("icmp_error");
                    180:        icmpstat.icps_outhist[type]++;
                    181:        icp->icmp_type = type;
                    182:        if (type == ICMP_REDIRECT)
                    183:                icp->icmp_gwaddr.s_addr = dest;
                    184:        else {
                    185:                icp->icmp_void = 0;
                    186:                /*
                    187:                 * The following assignments assume an overlay with the
                    188:                 * zeroed icmp_void field.
                    189:                 */
                    190:                if (type == ICMP_PARAMPROB) {
                    191:                        icp->icmp_pptr = code;
                    192:                        code = 0;
                    193:                } else if (type == ICMP_UNREACH &&
                    194:                        code == ICMP_UNREACH_NEEDFRAG && destifp) {
                    195:                        icp->icmp_nextmtu = htons(destifp->if_mtu);
                    196:                }
                    197:        }
                    198: 
                    199:        icp->icmp_code = code;
                    200:        bcopy((caddr_t)oip, (caddr_t)&icp->icmp_ip, icmplen);
                    201:        nip = &icp->icmp_ip;
                    202:        nip->ip_len = htons((u_short)(nip->ip_len + oiplen));
                    203: 
                    204:        /*
                    205:         * Now, copy old ip header (without options)
                    206:         * in front of icmp message.
                    207:         */
                    208:        if (m->m_data - sizeof(struct ip) < m->m_pktdat)
                    209:                panic("icmp len");
                    210:        m->m_data -= sizeof(struct ip);
                    211:        m->m_len += sizeof(struct ip);
                    212:        m->m_pkthdr.len = m->m_len;
                    213:        m->m_pkthdr.rcvif = n->m_pkthdr.rcvif;
                    214:        nip = mtod(m, struct ip *);
                    215:        bcopy((caddr_t)oip, (caddr_t)nip, sizeof(struct ip));
                    216:        nip->ip_len = m->m_len;
                    217:        nip->ip_vhl = IP_VHL_BORING;
                    218:        nip->ip_p = IPPROTO_ICMP;
                    219:        nip->ip_tos = 0;
                    220:        icmp_reflect(m);
                    221: 
                    222: freeit:
                    223:        m_freem(n);
                    224: }
                    225: 
                    226: static struct sockaddr_in icmpsrc = { sizeof (struct sockaddr_in), AF_INET };
                    227: static struct sockaddr_in icmpdst = { sizeof (struct sockaddr_in), AF_INET };
                    228: static struct sockaddr_in icmpgw = { sizeof (struct sockaddr_in), AF_INET };
                    229: 
                    230: /*
                    231:  * Process a received ICMP message.
                    232:  */
                    233: void
                    234: icmp_input(m, hlen)
                    235:        register struct mbuf *m;
                    236:        int hlen;
                    237: {
                    238:        register struct icmp *icp;
                    239:        register struct ip *ip = mtod(m, struct ip *);
                    240:        int icmplen = ip->ip_len;
                    241:        register int i;
                    242:        struct in_ifaddr *ia;
                    243:        void (*ctlfunc) __P((int, struct sockaddr *, void *));
                    244:        int code;
                    245: 
                    246:        /*
                    247:         * Locate icmp structure in mbuf, and check
                    248:         * that not corrupted and of at least minimum length.
                    249:         */
                    250: #if ICMPPRINTFS
                    251:        if (icmpprintfs) {
                    252:                char buf[4 * sizeof "123"];
                    253:                strcpy(buf, inet_ntoa(ip->ip_src));
                    254:                printf("icmp_input from %s to %s, len %d\n",
                    255:                       buf, inet_ntoa(ip->ip_dst), icmplen);
                    256:        }
                    257: #endif
                    258:        if (icmplen < ICMP_MINLEN) {
                    259:                icmpstat.icps_tooshort++;
                    260:                goto freeit;
                    261:        }
                    262:        i = hlen + min(icmplen, ICMP_ADVLENMIN);
                    263:        if (m->m_len < i && (m = m_pullup(m, i)) == 0)  {
                    264:                icmpstat.icps_tooshort++;
                    265:                return;
                    266:        }
                    267:        ip = mtod(m, struct ip *);
                    268:        m->m_len -= hlen;
                    269:        m->m_data += hlen;
                    270:        icp = mtod(m, struct icmp *);
                    271:        if (in_cksum(m, icmplen)) {
                    272:                icmpstat.icps_checksum++;
                    273:                goto freeit;
                    274:        }
                    275:        m->m_len += hlen;
                    276:        m->m_data -= hlen;
                    277: 
                    278: #if ICMPPRINTFS
                    279:        if (icmpprintfs)
                    280:                printf("icmp_input, type %d code %d\n", icp->icmp_type,
                    281:                    icp->icmp_code);
                    282: #endif
                    283: 
                    284:        /*
                    285:         * Message type specific processing.
                    286:         */
                    287:        if (icp->icmp_type > ICMP_MAXTYPE)
                    288:                goto raw;
                    289:        icmpstat.icps_inhist[icp->icmp_type]++;
                    290:        code = icp->icmp_code;
                    291:        switch (icp->icmp_type) {
                    292: 
                    293:        case ICMP_UNREACH:
                    294:                switch (code) {
                    295:                        case ICMP_UNREACH_NET:
                    296:                        case ICMP_UNREACH_HOST:
                    297:                        case ICMP_UNREACH_PROTOCOL:
                    298:                        case ICMP_UNREACH_PORT:
                    299:                        case ICMP_UNREACH_SRCFAIL:
                    300:                                code += PRC_UNREACH_NET;
                    301:                                break;
                    302: 
                    303:                        case ICMP_UNREACH_NEEDFRAG:
                    304:                                code = PRC_MSGSIZE;
                    305:                                break;
                    306: 
                    307:                        case ICMP_UNREACH_NET_UNKNOWN:
                    308:                        case ICMP_UNREACH_NET_PROHIB:
                    309:                        case ICMP_UNREACH_TOSNET:
                    310:                                code = PRC_UNREACH_NET;
                    311:                                break;
                    312: 
                    313:                        case ICMP_UNREACH_HOST_UNKNOWN:
                    314:                        case ICMP_UNREACH_ISOLATED:
                    315:                        case ICMP_UNREACH_HOST_PROHIB:
                    316:                        case ICMP_UNREACH_TOSHOST:
                    317:                                code = PRC_UNREACH_HOST;
                    318:                                break;
                    319: 
                    320:                        case ICMP_UNREACH_FILTER_PROHIB:
                    321:                        case ICMP_UNREACH_HOST_PRECEDENCE:
                    322:                        case ICMP_UNREACH_PRECEDENCE_CUTOFF:
                    323:                                code = PRC_UNREACH_PORT;
                    324:                                break;
                    325: 
                    326:                        default:
                    327:                                goto badcode;
                    328:                }
                    329:                goto deliver;
                    330: 
                    331:        case ICMP_TIMXCEED:
                    332:                if (code > 1)
                    333:                        goto badcode;
                    334:                code += PRC_TIMXCEED_INTRANS;
                    335:                goto deliver;
                    336: 
                    337:        case ICMP_PARAMPROB:
                    338:                if (code > 1)
                    339:                        goto badcode;
                    340:                code = PRC_PARAMPROB;
                    341:                goto deliver;
                    342: 
                    343:        case ICMP_SOURCEQUENCH:
                    344:                if (code)
                    345:                        goto badcode;
                    346:                code = PRC_QUENCH;
                    347:        deliver:
                    348:                /*
                    349:                 * Problem with datagram; advise higher level routines.
                    350:                 */
                    351:                if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp) ||
                    352:                    IP_VHL_HL(icp->icmp_ip.ip_vhl) < (sizeof(struct ip) >> 2)) {
                    353:                        icmpstat.icps_badlen++;
                    354:                        goto freeit;
                    355:                }
                    356:                NTOHS(icp->icmp_ip.ip_len);
                    357:                /* Discard ICMP's in response to multicast packets */
                    358:                if (IN_MULTICAST(ntohl(icp->icmp_ip.ip_dst.s_addr)))
                    359:                        goto badcode;
                    360: #if ICMPPRINTFS
                    361:                if (icmpprintfs)
                    362:                        printf("deliver to protocol %d\n", icp->icmp_ip.ip_p);
                    363: #endif
                    364:                icmpsrc.sin_addr = icp->icmp_ip.ip_dst;
                    365: #if 1
                    366:                /*
                    367:                 * MTU discovery:
                    368:                 * If we got a needfrag and there is a host route to the
                    369:                 * original destination, and the MTU is not locked, then
                    370:                 * set the MTU in the route to the suggested new value
                    371:                 * (if given) and then notify as usual.  The ULPs will
                    372:                 * notice that the MTU has changed and adapt accordingly.
                    373:                 * If no new MTU was suggested, then we guess a new one
                    374:                 * less than the current value.  If the new MTU is 
                    375:                 * unreasonably small (arbitrarily set at 296), then
                    376:                 * we reset the MTU to the interface value and enable the
                    377:                 * lock bit, indicating that we are no longer doing MTU
                    378:                 * discovery.
                    379:                 */
                    380:                if (code == PRC_MSGSIZE) {
                    381:                        struct rtentry *rt;
                    382:                        int mtu;
                    383: 
                    384:                        rt = rtalloc1((struct sockaddr *)&icmpsrc, 0,
                    385:                                      RTF_CLONING | RTF_PRCLONING);
                    386:                        if (rt && (rt->rt_flags & RTF_HOST)
                    387:                            && !(rt->rt_rmx.rmx_locks & RTV_MTU)) {
                    388:                                mtu = ntohs(icp->icmp_nextmtu);
                    389:                                if (!mtu)
                    390:                                        mtu = ip_next_mtu(rt->rt_rmx.rmx_mtu,
                    391:                                                          1);
                    392: #if DEBUG_MTUDISC
                    393:                                printf("MTU for %s reduced to %d\n",
                    394:                                        inet_ntoa(icmpsrc.sin_addr), mtu);
                    395: #endif
                    396:                                if (mtu < 296) {
                    397:                                        /* rt->rt_rmx.rmx_mtu =
                    398:                                                rt->rt_ifp->if_mtu; */
                    399:                                        rt->rt_rmx.rmx_locks |= RTV_MTU;
                    400:                                } else if (rt->rt_rmx.rmx_mtu > mtu) {
                    401:                                        rt->rt_rmx.rmx_mtu = mtu;
                    402:                                }
                    403:                        }
                    404:                        if (rt)
                    405:                                RTFREE(rt);
                    406:                }
                    407: 
                    408: #endif
                    409:                ctlfunc = ip_protox[icp->icmp_ip.ip_p]->pr_ctlinput;
                    410:                if (ctlfunc)
                    411:                        (*ctlfunc)(code, (struct sockaddr *)&icmpsrc,
                    412:                                   (void *)&icp->icmp_ip);
                    413:                break;
                    414: 
                    415:        badcode:
                    416:                icmpstat.icps_badcode++;
                    417:                break;
                    418: 
                    419:        case ICMP_ECHO:
                    420:                if (!icmpbmcastecho
                    421:                    && (m->m_flags & (M_MCAST | M_BCAST)) != 0) {
                    422:                        icmpstat.icps_bmcastecho++;
                    423:                        break;
                    424:                }
                    425:                icp->icmp_type = ICMP_ECHOREPLY;
                    426:                goto reflect;
                    427: 
                    428:        case ICMP_TSTAMP:
                    429:                if (!icmpbmcastecho
                    430:                    && (m->m_flags & (M_MCAST | M_BCAST)) != 0) {
                    431:                        icmpstat.icps_bmcasttstamp++;
                    432:                        break;
                    433:                }
                    434:                if (icmplen < ICMP_TSLEN) {
                    435:                        icmpstat.icps_badlen++;
                    436:                        break;
                    437:                }
                    438:                icp->icmp_type = ICMP_TSTAMPREPLY;
                    439:                icp->icmp_rtime = iptime();
                    440:                icp->icmp_ttime = icp->icmp_rtime;      /* bogus, do later! */
                    441:                goto reflect;
                    442: 
                    443:        case ICMP_MASKREQ:
                    444: #define        satosin(sa)     ((struct sockaddr_in *)(sa))
                    445:                if (icmpmaskrepl == 0)
                    446:                        break;
                    447:                /*
                    448:                 * We are not able to respond with all ones broadcast
                    449:                 * unless we receive it over a point-to-point interface.
                    450:                 */
                    451:                if (icmplen < ICMP_MASKLEN)
                    452:                        break;
                    453:                switch (ip->ip_dst.s_addr) {
                    454: 
                    455:                case INADDR_BROADCAST:
                    456:                case INADDR_ANY:
                    457:                        icmpdst.sin_addr = ip->ip_src;
                    458:                        break;
                    459: 
                    460:                default:
                    461:                        icmpdst.sin_addr = ip->ip_dst;
                    462:                }
                    463:                ia = (struct in_ifaddr *)ifaof_ifpforaddr(
                    464:                            (struct sockaddr *)&icmpdst, m->m_pkthdr.rcvif);
                    465:                if (ia == 0)
                    466:                        break;
                    467:                if (ia->ia_ifp == 0)
                    468:                        break;
                    469:                icp->icmp_type = ICMP_MASKREPLY;
                    470:                icp->icmp_mask = ia->ia_sockmask.sin_addr.s_addr;
                    471:                if (ip->ip_src.s_addr == 0) {
                    472:                        if (ia->ia_ifp->if_flags & IFF_BROADCAST)
                    473:                            ip->ip_src = satosin(&ia->ia_broadaddr)->sin_addr;
                    474:                        else if (ia->ia_ifp->if_flags & IFF_POINTOPOINT)
                    475:                            ip->ip_src = satosin(&ia->ia_dstaddr)->sin_addr;
                    476:                }
                    477: reflect:
                    478:                ip->ip_len += hlen;     /* since ip_input deducts this */
                    479:                icmpstat.icps_reflect++;
                    480:                icmpstat.icps_outhist[icp->icmp_type]++;
                    481:                icmp_reflect(m);
                    482:                return;
                    483: 
                    484:        case ICMP_REDIRECT:
                    485:                if (code > 3)
                    486:                        goto badcode;
                    487:                if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp) ||
                    488:                    IP_VHL_HL(icp->icmp_ip.ip_vhl) < (sizeof(struct ip) >> 2)) {
                    489:                        icmpstat.icps_badlen++;
                    490:                        break;
                    491:                }
                    492:                /*
                    493:                 * Short circuit routing redirects to force
                    494:                 * immediate change in the kernel's routing
                    495:                 * tables.  The message is also handed to anyone
                    496:                 * listening on a raw socket (e.g. the routing
                    497:                 * daemon for use in updating its tables).
                    498:                 */
                    499:                icmpgw.sin_addr = ip->ip_src;
                    500:                icmpdst.sin_addr = icp->icmp_gwaddr;
                    501: #if    ICMPPRINTFS
                    502:                if (icmpprintfs) {
                    503:                        char buf[4 * sizeof "123"];
                    504:                        strcpy(buf, inet_ntoa(icp->icmp_ip.ip_dst));
                    505: 
                    506:                        printf("redirect dst %s to %s\n",
                    507:                               buf, inet_ntoa(icp->icmp_gwaddr));
                    508:                }
                    509: #endif
                    510:                icmpsrc.sin_addr = icp->icmp_ip.ip_dst;
                    511:                rtredirect((struct sockaddr *)&icmpsrc,
                    512:                  (struct sockaddr *)&icmpdst,
                    513:                  (struct sockaddr *)0, RTF_GATEWAY | RTF_HOST,
                    514:                  (struct sockaddr *)&icmpgw, (struct rtentry **)0);
                    515:                pfctlinput(PRC_REDIRECT_HOST, (struct sockaddr *)&icmpsrc);
                    516:                break;
                    517: 
                    518:        /*
                    519:         * No kernel processing for the following;
                    520:         * just fall through to send to raw listener.
                    521:         */
                    522:        case ICMP_ECHOREPLY:
                    523:        case ICMP_ROUTERADVERT:
                    524:        case ICMP_ROUTERSOLICIT:
                    525:        case ICMP_TSTAMPREPLY:
                    526:        case ICMP_IREQREPLY:
                    527:        case ICMP_MASKREPLY:
                    528:        default:
                    529:                break;
                    530:        }
                    531: 
                    532: raw:
                    533:        rip_input(m, hlen);
                    534:        return;
                    535: 
                    536: freeit:
                    537:        m_freem(m);
                    538: }
                    539: 
                    540: /*
                    541:  * Reflect the ip packet back to the source
                    542:  */
                    543: static void
                    544: icmp_reflect(m)
                    545:        struct mbuf *m;
                    546: {
                    547:        register struct ip *ip = mtod(m, struct ip *);
                    548:        register struct in_ifaddr *ia;
                    549:        struct in_addr t;
                    550:        struct mbuf *opts = 0;
                    551:        int optlen = (IP_VHL_HL(ip->ip_vhl) << 2) - sizeof(struct ip);
                    552: 
                    553:        if (!in_canforward(ip->ip_src) &&
                    554:            ((ntohl(ip->ip_src.s_addr) & IN_CLASSA_NET) !=
                    555:             (IN_LOOPBACKNET << IN_CLASSA_NSHIFT))) {
                    556:                m_freem(m);     /* Bad return address */
                    557:                goto done;      /* Ip_output() will check for broadcast */
                    558:        }
                    559:        t = ip->ip_dst;
                    560:        ip->ip_dst = ip->ip_src;
                    561:        /*
                    562:         * If the incoming packet was addressed directly to us,
                    563:         * use dst as the src for the reply.  Otherwise (broadcast
                    564:         * or anonymous), use the address which corresponds
                    565:         * to the incoming interface.
                    566:         */
                    567:        for (ia = in_ifaddrhead.tqh_first; ia; ia = ia->ia_link.tqe_next) {
                    568:                if (t.s_addr == IA_SIN(ia)->sin_addr.s_addr)
                    569:                        break;
                    570:                if (ia->ia_ifp && (ia->ia_ifp->if_flags & IFF_BROADCAST) &&
                    571:                    t.s_addr == satosin(&ia->ia_broadaddr)->sin_addr.s_addr)
                    572:                        break;
                    573:        }
                    574:        icmpdst.sin_addr = t;
                    575:        if ((ia == (struct in_ifaddr *)0) && m->m_pkthdr.rcvif)
                    576:                ia = (struct in_ifaddr *)ifaof_ifpforaddr(
                    577:                        (struct sockaddr *)&icmpdst, m->m_pkthdr.rcvif);
                    578:        /*
                    579:         * The following happens if the packet was not addressed to us,
                    580:         * and was received on an interface with no IP address.
                    581:         */
                    582:        if (ia == (struct in_ifaddr *)0)
                    583:                ia = in_ifaddrhead.tqh_first;
                    584:        t = IA_SIN(ia)->sin_addr;
                    585:        ip->ip_src = t;
                    586:        ip->ip_ttl = MAXTTL;
                    587: 
                    588:        if (optlen > 0) {
                    589:                register u_char *cp;
                    590:                int opt, cnt;
                    591:                u_int len;
                    592: 
                    593:                /*
                    594:                 * Retrieve any source routing from the incoming packet;
                    595:                 * add on any record-route or timestamp options.
                    596:                 */
                    597:                cp = (u_char *) (ip + 1);
                    598:                if ((opts = ip_srcroute()) == 0 &&
                    599:                    (opts = m_gethdr(M_DONTWAIT, MT_HEADER))) {
                    600:                        opts->m_len = sizeof(struct in_addr);
                    601:                        mtod(opts, struct in_addr *)->s_addr = 0;
                    602:                }
                    603:                if (opts) {
                    604: #if ICMPPRINTFS
                    605:                    if (icmpprintfs)
                    606:                            printf("icmp_reflect optlen %d rt %d => ",
                    607:                                optlen, opts->m_len);
                    608: #endif
                    609:                    for (cnt = optlen; cnt > 0; cnt -= len, cp += len) {
                    610:                            opt = cp[IPOPT_OPTVAL];
                    611:                            if (opt == IPOPT_EOL)
                    612:                                    break;
                    613:                            if (opt == IPOPT_NOP)
                    614:                                    len = 1;
                    615:                            else {
                    616:                                    len = cp[IPOPT_OLEN];
                    617:                                    if (len <= 0 || len > cnt)
                    618:                                            break;
                    619:                            }
                    620:                            /*
                    621:                             * Should check for overflow, but it "can't happen"
                    622:                             */
                    623:                            if (opt == IPOPT_RR || opt == IPOPT_TS ||
                    624:                                opt == IPOPT_SECURITY) {
                    625:                                    bcopy((caddr_t)cp,
                    626:                                        mtod(opts, caddr_t) + opts->m_len, len);
                    627:                                    opts->m_len += len;
                    628:                            }
                    629:                    }
                    630:                    /* Terminate & pad, if necessary */
                    631:                    cnt = opts->m_len % 4;
                    632:                    if (cnt) {
                    633:                            for (; cnt < 4; cnt++) {
                    634:                                    *(mtod(opts, caddr_t) + opts->m_len) =
                    635:                                        IPOPT_EOL;
                    636:                                    opts->m_len++;
                    637:                            }
                    638:                    }
                    639: #if ICMPPRINTFS
                    640:                    if (icmpprintfs)
                    641:                            printf("%d\n", opts->m_len);
                    642: #endif
                    643:                }
                    644:                /*
                    645:                 * Now strip out original options by copying rest of first
                    646:                 * mbuf's data back, and adjust the IP length.
                    647:                 */
                    648:                ip->ip_len -= optlen;
                    649:                ip->ip_vhl = IP_VHL_BORING;
                    650:                m->m_len -= optlen;
                    651:                if (m->m_flags & M_PKTHDR)
                    652:                        m->m_pkthdr.len -= optlen;
                    653:                optlen += sizeof(struct ip);
                    654:                bcopy((caddr_t)ip + optlen, (caddr_t)(ip + 1),
                    655:                         (unsigned)(m->m_len - sizeof(struct ip)));
                    656:        }
                    657:        m->m_flags &= ~(M_BCAST|M_MCAST);
                    658:        icmp_send(m, opts);
                    659: done:
                    660:        if (opts)
                    661:                (void)m_free(opts);
                    662: }
                    663: 
                    664: /*
                    665:  * Send an icmp packet back to the ip level,
                    666:  * after supplying a checksum.
                    667:  */
                    668: static void
                    669: icmp_send(m, opts)
                    670:        register struct mbuf *m;
                    671:        struct mbuf *opts;
                    672: {
                    673:        register struct ip *ip = mtod(m, struct ip *);
                    674:        register int hlen;
                    675:        register struct icmp *icp;
                    676:        struct route ro;
                    677: 
                    678:        hlen = IP_VHL_HL(ip->ip_vhl) << 2;
                    679:        m->m_data += hlen;
                    680:        m->m_len -= hlen;
                    681:        icp = mtod(m, struct icmp *);
                    682:        icp->icmp_cksum = 0;
                    683:        icp->icmp_cksum = in_cksum(m, ip->ip_len - hlen);
                    684:        m->m_data -= hlen;
                    685:        m->m_len += hlen;
                    686: #if ICMPPRINTFS
                    687:        if (icmpprintfs) {
                    688:                char buf[4 * sizeof "123"];
                    689:                strcpy(buf, inet_ntoa(ip->ip_dst));
                    690:                printf("icmp_send dst %s src %s\n",
                    691:                       buf, inet_ntoa(ip->ip_src));
                    692:        }
                    693: #endif
                    694:        bzero(&ro, sizeof ro);
                    695:        (void) ip_output(m, opts, &ro, 0, NULL);
                    696:        if (ro.ro_rt)
                    697:                RTFREE(ro.ro_rt);
                    698: }
                    699: 
                    700: n_time
                    701: iptime()
                    702: {
                    703:        struct timeval atv;
                    704:        u_long t;
                    705: 
                    706:        microtime(&atv);
                    707:        t = (atv.tv_sec % (24*60*60)) * 1000 + atv.tv_usec / 1000;
                    708:        return (htonl(t));
                    709: }
                    710: 
                    711: #if 1
                    712: /*
                    713:  * Return the next larger or smaller MTU plateau (table from RFC 1191)
                    714:  * given current value MTU.  If DIR is less than zero, a larger plateau
                    715:  * is returned; otherwise, a smaller value is returned.
                    716:  */
                    717: static int
                    718: ip_next_mtu(mtu, dir)
                    719:        int mtu;
                    720:        int dir;
                    721: {
                    722:        static int mtutab[] = {
                    723:                65535, 32000, 17914, 8166, 4352, 2002, 1492, 1006, 508, 296,
                    724:                68, 0
                    725:        };
                    726:        int i;
                    727: 
                    728:        for (i = 0; i < (sizeof mtutab) / (sizeof mtutab[0]); i++) {
                    729:                if (mtu >= mtutab[i])
                    730:                        break;
                    731:        }
                    732: 
                    733:        if (dir < 0) {
                    734:                if (i == 0) {
                    735:                        return 0;
                    736:                } else {
                    737:                        return mtutab[i - 1];
                    738:                }
                    739:        } else {
                    740:                if (mtutab[i] == 0) {
                    741:                        return 0;
                    742:                } else if(mtu > mtutab[i]) {
                    743:                        return mtutab[i];
                    744:                } else {
                    745:                        return mtutab[i + 1];
                    746:                }
                    747:        }
                    748: }
                    749: #endif
                    750: 
                    751: #if ICMP_BANDLIM
                    752: 
                    753: /*
                    754:  * badport_bandlim() - check for ICMP bandwidth limit
                    755:  *
                    756:  *     Return 0 if it is ok to send an ICMP error response, -1 if we have
                    757:  *     hit our bandwidth limit and it is not ok.  
                    758:  *
                    759:  *     If icmplim is <= 0, the feature is disabled and 0 is returned.
                    760:  *
                    761:  *     For now we separate the TCP and UDP subsystems w/ different 'which'
                    762:  *     values.  We may eventually remove this separation (and simplify the
                    763:  *     code further).
                    764:  *
                    765:  *     Note that the printing of the error message is delayed so we can
                    766:  *     properly print the icmp error rate that the system was trying to do
                    767:  *     (i.e. 22000/100 pps, etc...).  This can cause long delays in printing
                    768:  *     the 'final' error, but it doesn't make sense to solve the printing 
                    769:  *     delay with more complex code.
                    770:  */
                    771: 
                    772: int
                    773: badport_bandlim(int which)
                    774: {
                    775:        static int lticks[2];
                    776:        static int lpackets[2];
                    777:        int dticks;
                    778: 
                    779:        /*
                    780:         * Return ok status if feature disabled or argument out of
                    781:         * ranage.
                    782:         */
                    783: 
                    784:        if (icmplim <= 0 || which >= 2 || which < 0)
                    785:                return(0);
                    786:        dticks = ticks - lticks[which];
                    787: 
                    788:        /*
                    789:         * reset stats when cumulative dt exceeds one second.
                    790:         */
                    791: 
                    792:        if ((unsigned int)dticks > hz) {
                    793:                if (lpackets[which] > icmplim) {
                    794:                        printf("icmp-response bandwidth limit %d/%d pps\n",
                    795:                                lpackets[which],
                    796:                                icmplim
                    797:                        );
                    798:                }
                    799:                lticks[which] = ticks;
                    800:                lpackets[which] = 0;
                    801:        }
                    802: 
                    803:        /*
                    804:         * bump packet count
                    805:         */
                    806: 
                    807:        if (++lpackets[which] > icmplim) {
                    808:                return(-1);
                    809:        }
                    810:        return(0);
                    811: }
                    812: 
                    813: #endif
                    814: 
                    815: 

unix.superglobalmegacorp.com

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