Annotation of Net2/netinet/ip_icmp.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
        !             3:  * All rights reserved.
        !             4:  *
        !             5:  * Redistribution and use in source and binary forms, with or without
        !             6:  * modification, are permitted provided that the following conditions
        !             7:  * are met:
        !             8:  * 1. Redistributions of source code must retain the above copyright
        !             9:  *    notice, this list of conditions and the following disclaimer.
        !            10:  * 2. Redistributions in binary form must reproduce the above copyright
        !            11:  *    notice, this list of conditions and the following disclaimer in the
        !            12:  *    documentation and/or other materials provided with the distribution.
        !            13:  * 3. All advertising materials mentioning features or use of this software
        !            14:  *    must display the following acknowledgement:
        !            15:  *     This product includes software developed by the University of
        !            16:  *     California, Berkeley and its contributors.
        !            17:  * 4. Neither the name of the University nor the names of its contributors
        !            18:  *    may be used to endorse or promote products derived from this software
        !            19:  *    without specific prior written permission.
        !            20:  *
        !            21:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            22:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            23:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            24:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            25:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            26:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            27:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            28:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            29:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            30:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            31:  * SUCH DAMAGE.
        !            32:  *
        !            33:  *     @(#)ip_icmp.c   7.15 (Berkeley) 4/20/91
        !            34:  */
        !            35: 
        !            36: #include "param.h"
        !            37: #include "systm.h"
        !            38: #include "malloc.h"
        !            39: #include "mbuf.h"
        !            40: #include "protosw.h"
        !            41: #include "socket.h"
        !            42: #include "time.h"
        !            43: #include "kernel.h"
        !            44: 
        !            45: #include "../net/route.h"
        !            46: #include "../net/if.h"
        !            47: 
        !            48: #include "in.h"
        !            49: #include "in_systm.h"
        !            50: #include "in_var.h"
        !            51: #include "ip.h"
        !            52: #include "ip_icmp.h"
        !            53: #include "icmp_var.h"
        !            54: 
        !            55: /*
        !            56:  * ICMP routines: error generation, receive packet processing, and
        !            57:  * routines to turnaround packets back to the originator, and
        !            58:  * host table maintenance routines.
        !            59:  */
        !            60: #ifdef ICMPPRINTFS
        !            61: int    icmpprintfs = 0;
        !            62: #endif
        !            63: 
        !            64: extern struct protosw inetsw[];
        !            65: 
        !            66: /*
        !            67:  * Generate an error packet of type error
        !            68:  * in response to bad packet ip.
        !            69:  */
        !            70: /*VARARGS3*/
        !            71: icmp_error(n, type, code, dest)
        !            72:        struct mbuf *n;
        !            73:        int type, code;
        !            74:        struct in_addr dest;
        !            75: {
        !            76:        register struct ip *oip = mtod(n, struct ip *), *nip;
        !            77:        register unsigned oiplen = oip->ip_hl << 2;
        !            78:        register struct icmp *icp;
        !            79:        register struct mbuf *m;
        !            80:        unsigned icmplen;
        !            81: 
        !            82: #ifdef ICMPPRINTFS
        !            83:        if (icmpprintfs)
        !            84:                printf("icmp_error(%x, %d, %d)\n", oip, type, code);
        !            85: #endif
        !            86:        if (type != ICMP_REDIRECT)
        !            87:                icmpstat.icps_error++;
        !            88:        /*
        !            89:         * Don't send error if not the first fragment of message.
        !            90:         * Don't error if the old packet protocol was ICMP
        !            91:         * error message, only known informational types.
        !            92:         */
        !            93:        if (oip->ip_off &~ (IP_MF|IP_DF))
        !            94:                goto freeit;
        !            95:        if (oip->ip_p == IPPROTO_ICMP && type != ICMP_REDIRECT &&
        !            96:          n->m_len >= oiplen + ICMP_MINLEN &&
        !            97:          !ICMP_INFOTYPE(((struct icmp *)((caddr_t)oip + oiplen))->icmp_type)) {
        !            98:                icmpstat.icps_oldicmp++;
        !            99:                goto freeit;
        !           100:        }
        !           101: 
        !           102:        /*
        !           103:         * First, formulate icmp message
        !           104:         */
        !           105:        m = m_gethdr(M_DONTWAIT, MT_HEADER);
        !           106:        if (m == NULL)
        !           107:                goto freeit;
        !           108:        icmplen = oiplen + min(8, oip->ip_len);
        !           109:        m->m_len = icmplen + ICMP_MINLEN;
        !           110:        MH_ALIGN(m, m->m_len);
        !           111:        icp = mtod(m, struct icmp *);
        !           112:        if ((u_int)type > ICMP_MAXTYPE)
        !           113:                panic("icmp_error");
        !           114:        icmpstat.icps_outhist[type]++;
        !           115:        icp->icmp_type = type;
        !           116:        if (type == ICMP_REDIRECT)
        !           117:                icp->icmp_gwaddr = dest;
        !           118:        else
        !           119:                icp->icmp_void = 0;
        !           120:        if (type == ICMP_PARAMPROB) {
        !           121:                icp->icmp_pptr = code;
        !           122:                code = 0;
        !           123:        }
        !           124:        icp->icmp_code = code;
        !           125:        bcopy((caddr_t)oip, (caddr_t)&icp->icmp_ip, icmplen);
        !           126:        nip = &icp->icmp_ip;
        !           127:        nip->ip_len = htons((u_short)(nip->ip_len + oiplen));
        !           128: 
        !           129:        /*
        !           130:         * Now, copy old ip header (without options)
        !           131:         * in front of icmp message.
        !           132:         */
        !           133:        if (m->m_data - sizeof(struct ip) < m->m_pktdat)
        !           134:                panic("icmp len");
        !           135:        m->m_data -= sizeof(struct ip);
        !           136:        m->m_len += sizeof(struct ip);
        !           137:        m->m_pkthdr.len = m->m_len;
        !           138:        m->m_pkthdr.rcvif = n->m_pkthdr.rcvif;
        !           139:        nip = mtod(m, struct ip *);
        !           140:        bcopy((caddr_t)oip, (caddr_t)nip, oiplen);
        !           141:        nip->ip_len = m->m_len;
        !           142:        nip->ip_hl = sizeof(struct ip) >> 2;
        !           143:        nip->ip_p = IPPROTO_ICMP;
        !           144:        icmp_reflect(m);
        !           145: 
        !           146: freeit:
        !           147:        m_freem(n);
        !           148: }
        !           149: 
        !           150: static struct sockproto icmproto = { AF_INET, IPPROTO_ICMP };
        !           151: static struct sockaddr_in icmpsrc = { sizeof (struct sockaddr_in), AF_INET };
        !           152: static struct sockaddr_in icmpdst = { sizeof (struct sockaddr_in), AF_INET };
        !           153: static struct sockaddr_in icmpgw = { sizeof (struct sockaddr_in), AF_INET };
        !           154: struct sockaddr_in icmpmask = { 8, 0 };
        !           155: struct in_ifaddr *ifptoia();
        !           156: 
        !           157: /*
        !           158:  * Process a received ICMP message.
        !           159:  */
        !           160: icmp_input(m, hlen)
        !           161:        register struct mbuf *m;
        !           162:        int hlen;
        !           163: {
        !           164:        register struct icmp *icp;
        !           165:        register struct ip *ip = mtod(m, struct ip *);
        !           166:        int icmplen = ip->ip_len;
        !           167:        register int i;
        !           168:        struct in_ifaddr *ia;
        !           169:        int (*ctlfunc)(), code;
        !           170:        extern u_char ip_protox[];
        !           171:        extern struct in_addr in_makeaddr();
        !           172: 
        !           173:        /*
        !           174:         * Locate icmp structure in mbuf, and check
        !           175:         * that not corrupted and of at least minimum length.
        !           176:         */
        !           177: #ifdef ICMPPRINTFS
        !           178:        if (icmpprintfs)
        !           179:                printf("icmp_input from %x, len %d\n", ip->ip_src, icmplen);
        !           180: #endif
        !           181:        if (icmplen < ICMP_MINLEN) {
        !           182:                icmpstat.icps_tooshort++;
        !           183:                goto freeit;
        !           184:        }
        !           185:        i = hlen + MIN(icmplen, ICMP_ADVLENMIN);
        !           186:        if (m->m_len < i && (m = m_pullup(m, i)) == 0)  {
        !           187:                icmpstat.icps_tooshort++;
        !           188:                return;
        !           189:        }
        !           190:        ip = mtod(m, struct ip *);
        !           191:        m->m_len -= hlen;
        !           192:        m->m_data += hlen;
        !           193:        icp = mtod(m, struct icmp *);
        !           194:        if (in_cksum(m, icmplen)) {
        !           195:                icmpstat.icps_checksum++;
        !           196:                goto freeit;
        !           197:        }
        !           198:        m->m_len += hlen;
        !           199:        m->m_data -= hlen;
        !           200: 
        !           201: #ifdef ICMPPRINTFS
        !           202:        /*
        !           203:         * Message type specific processing.
        !           204:         */
        !           205:        if (icmpprintfs)
        !           206:                printf("icmp_input, type %d code %d\n", icp->icmp_type,
        !           207:                    icp->icmp_code);
        !           208: #endif
        !           209:        if (icp->icmp_type > ICMP_MAXTYPE)
        !           210:                goto raw;
        !           211:        icmpstat.icps_inhist[icp->icmp_type]++;
        !           212:        code = icp->icmp_code;
        !           213:        switch (icp->icmp_type) {
        !           214: 
        !           215:        case ICMP_UNREACH:
        !           216:                if (code > 5)
        !           217:                        goto badcode;
        !           218:                code += PRC_UNREACH_NET;
        !           219:                goto deliver;
        !           220: 
        !           221:        case ICMP_TIMXCEED:
        !           222:                if (code > 1)
        !           223:                        goto badcode;
        !           224:                code += PRC_TIMXCEED_INTRANS;
        !           225:                goto deliver;
        !           226: 
        !           227:        case ICMP_PARAMPROB:
        !           228:                if (code)
        !           229:                        goto badcode;
        !           230:                code = PRC_PARAMPROB;
        !           231:                goto deliver;
        !           232: 
        !           233:        case ICMP_SOURCEQUENCH:
        !           234:                if (code)
        !           235:                        goto badcode;
        !           236:                code = PRC_QUENCH;
        !           237:        deliver:
        !           238:                /*
        !           239:                 * Problem with datagram; advise higher level routines.
        !           240:                 */
        !           241:                if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp) ||
        !           242:                    icp->icmp_ip.ip_hl < (sizeof(struct ip) >> 2)) {
        !           243:                        icmpstat.icps_badlen++;
        !           244:                        goto freeit;
        !           245:                }
        !           246:                NTOHS(icp->icmp_ip.ip_len);
        !           247: #ifdef ICMPPRINTFS
        !           248:                if (icmpprintfs)
        !           249:                        printf("deliver to protocol %d\n", icp->icmp_ip.ip_p);
        !           250: #endif
        !           251:                icmpsrc.sin_addr = icp->icmp_ip.ip_dst;
        !           252:                if (ctlfunc = inetsw[ip_protox[icp->icmp_ip.ip_p]].pr_ctlinput)
        !           253:                        (*ctlfunc)(code, (struct sockaddr *)&icmpsrc,
        !           254:                            (caddr_t) &icp->icmp_ip);
        !           255:                break;
        !           256: 
        !           257:        badcode:
        !           258:                icmpstat.icps_badcode++;
        !           259:                break;
        !           260: 
        !           261:        case ICMP_ECHO:
        !           262:                icp->icmp_type = ICMP_ECHOREPLY;
        !           263:                goto reflect;
        !           264: 
        !           265:        case ICMP_TSTAMP:
        !           266:                if (icmplen < ICMP_TSLEN) {
        !           267:                        icmpstat.icps_badlen++;
        !           268:                        break;
        !           269:                }
        !           270:                icp->icmp_type = ICMP_TSTAMPREPLY;
        !           271:                icp->icmp_rtime = iptime();
        !           272:                icp->icmp_ttime = icp->icmp_rtime;      /* bogus, do later! */
        !           273:                goto reflect;
        !           274:                
        !           275:        case ICMP_IREQ:
        !           276: #define        satosin(sa)     ((struct sockaddr_in *)(sa))
        !           277:                if (in_netof(ip->ip_src) == 0 &&
        !           278:                    (ia = ifptoia(m->m_pkthdr.rcvif)))
        !           279:                        ip->ip_src = in_makeaddr(in_netof(IA_SIN(ia)->sin_addr),
        !           280:                            in_lnaof(ip->ip_src));
        !           281:                icp->icmp_type = ICMP_IREQREPLY;
        !           282:                goto reflect;
        !           283: 
        !           284:        case ICMP_MASKREQ:
        !           285:                if (icmplen < ICMP_MASKLEN ||
        !           286:                    (ia = ifptoia(m->m_pkthdr.rcvif)) == 0)
        !           287:                        break;
        !           288:                icp->icmp_type = ICMP_MASKREPLY;
        !           289:                icp->icmp_mask = ia->ia_sockmask.sin_addr.s_addr;
        !           290:                if (ip->ip_src.s_addr == 0) {
        !           291:                        if (ia->ia_ifp->if_flags & IFF_BROADCAST)
        !           292:                            ip->ip_src = satosin(&ia->ia_broadaddr)->sin_addr;
        !           293:                        else if (ia->ia_ifp->if_flags & IFF_POINTOPOINT)
        !           294:                            ip->ip_src = satosin(&ia->ia_dstaddr)->sin_addr;
        !           295:                }
        !           296: reflect:
        !           297:                ip->ip_len += hlen;     /* since ip_input deducts this */
        !           298:                icmpstat.icps_reflect++;
        !           299:                icmpstat.icps_outhist[icp->icmp_type]++;
        !           300:                icmp_reflect(m);
        !           301:                return;
        !           302: 
        !           303:        case ICMP_REDIRECT:
        !           304:                if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp)) {
        !           305:                        icmpstat.icps_badlen++;
        !           306:                        break;
        !           307:                }
        !           308:                /*
        !           309:                 * Short circuit routing redirects to force
        !           310:                 * immediate change in the kernel's routing
        !           311:                 * tables.  The message is also handed to anyone
        !           312:                 * listening on a raw socket (e.g. the routing
        !           313:                 * daemon for use in updating its tables).
        !           314:                 */
        !           315:                icmpgw.sin_addr = ip->ip_src;
        !           316:                icmpdst.sin_addr = icp->icmp_gwaddr;
        !           317: #ifdef ICMPPRINTFS
        !           318:                if (icmpprintfs)
        !           319:                        printf("redirect dst %x to %x\n", icp->icmp_ip.ip_dst,
        !           320:                                icp->icmp_gwaddr);
        !           321: #endif
        !           322:                if (code == ICMP_REDIRECT_NET || code == ICMP_REDIRECT_TOSNET) {
        !           323:                        u_long in_netof();
        !           324:                        icmpsrc.sin_addr =
        !           325:                         in_makeaddr(in_netof(icp->icmp_ip.ip_dst), INADDR_ANY);
        !           326:                        in_sockmaskof(icp->icmp_ip.ip_dst, &icmpmask);
        !           327:                        rtredirect((struct sockaddr *)&icmpsrc,
        !           328:                          (struct sockaddr *)&icmpdst,
        !           329:                          (struct sockaddr *)&icmpmask, RTF_GATEWAY,
        !           330:                          (struct sockaddr *)&icmpgw, (struct rtentry **)0);
        !           331:                        icmpsrc.sin_addr = icp->icmp_ip.ip_dst;
        !           332:                        pfctlinput(PRC_REDIRECT_NET,
        !           333:                          (struct sockaddr *)&icmpsrc);
        !           334:                } else {
        !           335:                        icmpsrc.sin_addr = icp->icmp_ip.ip_dst;
        !           336:                        rtredirect((struct sockaddr *)&icmpsrc,
        !           337:                          (struct sockaddr *)&icmpdst,
        !           338:                          (struct sockaddr *)0, RTF_GATEWAY | RTF_HOST,
        !           339:                          (struct sockaddr *)&icmpgw, (struct rtentry **)0);
        !           340:                        pfctlinput(PRC_REDIRECT_HOST,
        !           341:                          (struct sockaddr *)&icmpsrc);
        !           342:                }
        !           343:                break;
        !           344: 
        !           345:        /*
        !           346:         * No kernel processing for the following;
        !           347:         * just fall through to send to raw listener.
        !           348:         */
        !           349:        case ICMP_ECHOREPLY:
        !           350:        case ICMP_TSTAMPREPLY:
        !           351:        case ICMP_IREQREPLY:
        !           352:        case ICMP_MASKREPLY:
        !           353:        default:
        !           354:                break;
        !           355:        }
        !           356: 
        !           357: raw:
        !           358:        icmpsrc.sin_addr = ip->ip_src;
        !           359:        icmpdst.sin_addr = ip->ip_dst;
        !           360:        (void) raw_input(m, &icmproto, (struct sockaddr *)&icmpsrc,
        !           361:            (struct sockaddr *)&icmpdst);
        !           362:        return;
        !           363: 
        !           364: freeit:
        !           365:        m_freem(m);
        !           366: }
        !           367: 
        !           368: /*
        !           369:  * Reflect the ip packet back to the source
        !           370:  */
        !           371: icmp_reflect(m)
        !           372:        struct mbuf *m;
        !           373: {
        !           374:        register struct ip *ip = mtod(m, struct ip *);
        !           375:        register struct in_ifaddr *ia;
        !           376:        struct in_addr t;
        !           377:        struct mbuf *opts = 0, *ip_srcroute();
        !           378:        int optlen = (ip->ip_hl << 2) - sizeof(struct ip);
        !           379: 
        !           380:        t = ip->ip_dst;
        !           381:        ip->ip_dst = ip->ip_src;
        !           382:        /*
        !           383:         * If the incoming packet was addressed directly to us,
        !           384:         * use dst as the src for the reply.  Otherwise (broadcast
        !           385:         * or anonymous), use the address which corresponds
        !           386:         * to the incoming interface.
        !           387:         */
        !           388:        for (ia = in_ifaddr; ia; ia = ia->ia_next) {
        !           389:                if (t.s_addr == IA_SIN(ia)->sin_addr.s_addr)
        !           390:                        break;
        !           391:                if ((ia->ia_ifp->if_flags & IFF_BROADCAST) &&
        !           392:                    t.s_addr == satosin(&ia->ia_broadaddr)->sin_addr.s_addr)
        !           393:                        break;
        !           394:        }
        !           395:        if (ia == (struct in_ifaddr *)0)
        !           396:                ia = ifptoia(m->m_pkthdr.rcvif);
        !           397:        if (ia == (struct in_ifaddr *)0)
        !           398:                ia = in_ifaddr;
        !           399:        t = IA_SIN(ia)->sin_addr;
        !           400:        ip->ip_src = t;
        !           401:        ip->ip_ttl = MAXTTL;
        !           402: 
        !           403:        if (optlen > 0) {
        !           404:                register u_char *cp;
        !           405:                int opt, cnt;
        !           406:                u_int len;
        !           407: 
        !           408:                /*
        !           409:                 * Retrieve any source routing from the incoming packet;
        !           410:                 * add on any record-route or timestamp options.
        !           411:                 */
        !           412:                cp = (u_char *) (ip + 1);
        !           413:                if ((opts = ip_srcroute()) == 0 &&
        !           414:                    (opts = m_gethdr(M_DONTWAIT, MT_HEADER))) {
        !           415:                        opts->m_len = sizeof(struct in_addr);
        !           416:                        mtod(opts, struct in_addr *)->s_addr = 0;
        !           417:                }
        !           418:                if (opts) {
        !           419: #ifdef ICMPPRINTFS
        !           420:                    if (icmpprintfs)
        !           421:                            printf("icmp_reflect optlen %d rt %d => ",
        !           422:                                optlen, opts->m_len);
        !           423: #endif
        !           424:                    for (cnt = optlen; cnt > 0; cnt -= len, cp += len) {
        !           425:                            opt = cp[IPOPT_OPTVAL];
        !           426:                            if (opt == IPOPT_EOL)
        !           427:                                    break;
        !           428:                            if (opt == IPOPT_NOP)
        !           429:                                    len = 1;
        !           430:                            else {
        !           431:                                    len = cp[IPOPT_OLEN];
        !           432:                                    if (len <= 0 || len > cnt)
        !           433:                                            break;
        !           434:                            }
        !           435:                            /*
        !           436:                             * should check for overflow, but it "can't happen"
        !           437:                             */
        !           438:                            if (opt == IPOPT_RR || opt == IPOPT_TS) {
        !           439:                                    bcopy((caddr_t)cp,
        !           440:                                        mtod(opts, caddr_t) + opts->m_len, len);
        !           441:                                    opts->m_len += len;
        !           442:                            }
        !           443:                    }
        !           444:                    if (opts->m_len % 4 != 0) {
        !           445:                            *(mtod(opts, caddr_t) + opts->m_len) = IPOPT_EOL;
        !           446:                            opts->m_len++;
        !           447:                    }
        !           448: #ifdef ICMPPRINTFS
        !           449:                    if (icmpprintfs)
        !           450:                            printf("%d\n", opts->m_len);
        !           451: #endif
        !           452:                }
        !           453:                /*
        !           454:                 * Now strip out original options by copying rest of first
        !           455:                 * mbuf's data back, and adjust the IP length.
        !           456:                 */
        !           457:                ip->ip_len -= optlen;
        !           458:                ip->ip_hl = sizeof(struct ip) >> 2;
        !           459:                m->m_len -= optlen;
        !           460:                if (m->m_flags & M_PKTHDR)
        !           461:                        m->m_pkthdr.len -= optlen;
        !           462:                optlen += sizeof(struct ip);
        !           463:                bcopy((caddr_t)ip + optlen, (caddr_t)(ip + 1),
        !           464:                         (unsigned)(m->m_len - sizeof(struct ip)));
        !           465:        }
        !           466:        icmp_send(m, opts);
        !           467:        if (opts)
        !           468:                (void)m_free(opts);
        !           469: }
        !           470: 
        !           471: struct in_ifaddr *
        !           472: ifptoia(ifp)
        !           473:        struct ifnet *ifp;
        !           474: {
        !           475:        register struct in_ifaddr *ia;
        !           476: 
        !           477:        for (ia = in_ifaddr; ia; ia = ia->ia_next)
        !           478:                if (ia->ia_ifp == ifp)
        !           479:                        return (ia);
        !           480:        return ((struct in_ifaddr *)0);
        !           481: }
        !           482: 
        !           483: /*
        !           484:  * Send an icmp packet back to the ip level,
        !           485:  * after supplying a checksum.
        !           486:  */
        !           487: icmp_send(m, opts)
        !           488:        register struct mbuf *m;
        !           489:        struct mbuf *opts;
        !           490: {
        !           491:        register struct ip *ip = mtod(m, struct ip *);
        !           492:        register int hlen;
        !           493:        register struct icmp *icp;
        !           494: 
        !           495:        hlen = ip->ip_hl << 2;
        !           496:        m->m_data += hlen;
        !           497:        m->m_len -= hlen;
        !           498:        icp = mtod(m, struct icmp *);
        !           499:        icp->icmp_cksum = 0;
        !           500:        icp->icmp_cksum = in_cksum(m, ip->ip_len - hlen);
        !           501:        m->m_data -= hlen;
        !           502:        m->m_len += hlen;
        !           503: #ifdef ICMPPRINTFS
        !           504:        if (icmpprintfs)
        !           505:                printf("icmp_send dst %x src %x\n", ip->ip_dst, ip->ip_src);
        !           506: #endif
        !           507:        (void) ip_output(m, opts, (struct route *)0, 0);
        !           508: }
        !           509: 
        !           510: n_time
        !           511: iptime()
        !           512: {
        !           513:        struct timeval atv;
        !           514:        u_long t;
        !           515: 
        !           516:        microtime(&atv);
        !           517:        t = (atv.tv_sec % (24*60*60)) * 1000 + atv.tv_usec / 1000;
        !           518:        return (htonl(t));
        !           519: }

unix.superglobalmegacorp.com

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