Annotation of kernel/bsd/netinet/ip_icmp.c, revision 1.1

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

unix.superglobalmegacorp.com

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