Annotation of 42BSD/sys/netinet/ip_icmp.c, revision 1.1

1.1     ! root        1: /*     ip_icmp.c       6.2     83/09/19        */
        !             2: 
        !             3: #include "../h/param.h"
        !             4: #include "../h/systm.h"
        !             5: #include "../h/mbuf.h"
        !             6: #include "../h/protosw.h"
        !             7: #include "../h/socket.h"
        !             8: #include "../h/time.h"
        !             9: #include "../h/kernel.h"
        !            10: 
        !            11: #include "../net/route.h"
        !            12: 
        !            13: #include "../netinet/in.h"
        !            14: #include "../netinet/in_systm.h"
        !            15: #include "../netinet/ip.h"
        !            16: #include "../netinet/ip_icmp.h"
        !            17: #include "../netinet/icmp_var.h"
        !            18: 
        !            19: #ifdef ICMPPRINTFS
        !            20: /*
        !            21:  * ICMP routines: error generation, receive packet processing, and
        !            22:  * routines to turnaround packets back to the originator, and
        !            23:  * host table maintenance routines.
        !            24:  */
        !            25: int    icmpprintfs = 0;
        !            26: #endif
        !            27: 
        !            28: /*
        !            29:  * Generate an error packet of type error
        !            30:  * in response to bad packet ip.
        !            31:  */
        !            32: icmp_error(oip, type, code)
        !            33:        struct ip *oip;
        !            34:        int type, code;
        !            35: {
        !            36:        register unsigned oiplen = oip->ip_hl << 2;
        !            37:        register struct icmp *icp;
        !            38:        struct mbuf *m;
        !            39:        struct ip *nip;
        !            40: 
        !            41: #ifdef ICMPPRINTFS
        !            42:        if (icmpprintfs)
        !            43:                printf("icmp_error(%x, %d, %d)\n", oip, type, code);
        !            44: #endif
        !            45:        icmpstat.icps_error++;
        !            46:        /*
        !            47:         * Make sure that the old IP packet had 8 bytes of data to return;
        !            48:         * if not, don't bother.  Also don't EVER error if the old
        !            49:         * packet protocol was ICMP.
        !            50:         */
        !            51:        if (oip->ip_len < 8) {
        !            52:                icmpstat.icps_oldshort++;
        !            53:                goto free;
        !            54:        }
        !            55:        if (oip->ip_p == IPPROTO_ICMP) {
        !            56:                icmpstat.icps_oldicmp++;
        !            57:                goto free;
        !            58:        }
        !            59: 
        !            60:        /*
        !            61:         * First, formulate icmp message
        !            62:         */
        !            63:        m = m_get(M_DONTWAIT, MT_HEADER);
        !            64:        if (m == NULL)
        !            65:                goto free;
        !            66:        m->m_len = oiplen + 8 + ICMP_MINLEN;
        !            67:        m->m_off = MMAXOFF - m->m_len;
        !            68:        icp = mtod(m, struct icmp *);
        !            69:        if ((u_int)type > ICMP_IREQREPLY)
        !            70:                panic("icmp_error");
        !            71:        icmpstat.icps_outhist[type]++;
        !            72:        icp->icmp_type = type;
        !            73:        icp->icmp_void = 0;
        !            74:        if (type == ICMP_PARAMPROB) {
        !            75:                icp->icmp_pptr = code;
        !            76:                code = 0;
        !            77:        }
        !            78:        icp->icmp_code = code;
        !            79:        bcopy((caddr_t)oip, (caddr_t)&icp->icmp_ip, oiplen + 8);
        !            80:        nip = &icp->icmp_ip;
        !            81:        nip->ip_len += oiplen;
        !            82:        nip->ip_len = htons((u_short)nip->ip_len);
        !            83: 
        !            84:        /*
        !            85:         * Now, copy old ip header in front of icmp
        !            86:         * message.  This allows us to reuse any source
        !            87:         * routing info present.
        !            88:         */
        !            89:        m->m_off -= oiplen;
        !            90:        nip = mtod(m, struct ip *);
        !            91:        bcopy((caddr_t)oip, (caddr_t)nip, oiplen);
        !            92:        nip->ip_len = m->m_len + oiplen;
        !            93:        nip->ip_p = IPPROTO_ICMP;
        !            94:        /* icmp_send adds ip header to m_off and m_len, so we deduct here */
        !            95:        m->m_off += oiplen;
        !            96:        icmp_reflect(nip);
        !            97: 
        !            98: free:
        !            99:        m_freem(dtom(oip));
        !           100: }
        !           101: 
        !           102: static struct sockproto icmproto = { AF_INET, IPPROTO_ICMP };
        !           103: static struct sockaddr_in icmpsrc = { AF_INET };
        !           104: static struct sockaddr_in icmpdst = { AF_INET };
        !           105: 
        !           106: /*
        !           107:  * Process a received ICMP message.
        !           108:  */
        !           109: icmp_input(m)
        !           110:        struct mbuf *m;
        !           111: {
        !           112:        register struct icmp *icp;
        !           113:        register struct ip *ip = mtod(m, struct ip *);
        !           114:        int icmplen = ip->ip_len, hlen = ip->ip_hl << 2;
        !           115:        int (*ctlfunc)(), code, i;
        !           116:        extern u_char ip_protox[];
        !           117: 
        !           118:        /*
        !           119:         * Locate icmp structure in mbuf, and check
        !           120:         * that not corrupted and of at least minimum length.
        !           121:         */
        !           122: #ifdef ICMPPRINTFS
        !           123:        if (icmpprintfs)
        !           124:                printf("icmp_input from %x, len %d\n", ip->ip_src, icmplen);
        !           125: #endif
        !           126:        if (icmplen < ICMP_MINLEN) {
        !           127:                icmpstat.icps_tooshort++;
        !           128:                goto free;
        !           129:        }
        !           130:        m->m_len -= hlen;
        !           131:        m->m_off += hlen;
        !           132:        /* need routine to make sure header is in this mbuf here */
        !           133:        icp = mtod(m, struct icmp *);
        !           134:        i = icp->icmp_cksum;
        !           135:        icp->icmp_cksum = 0;
        !           136:        if (i != in_cksum(m, icmplen)) {
        !           137:                icmpstat.icps_checksum++;
        !           138:                goto free;
        !           139:        }
        !           140: 
        !           141: #ifdef ICMPPRINTFS
        !           142:        /*
        !           143:         * Message type specific processing.
        !           144:         */
        !           145:        if (icmpprintfs)
        !           146:                printf("icmp_input, type %d code %d\n", icp->icmp_type,
        !           147:                    icp->icmp_code);
        !           148: #endif
        !           149:        if (icp->icmp_type > ICMP_IREQREPLY)
        !           150:                goto free;
        !           151:        icmpstat.icps_inhist[icp->icmp_type]++;
        !           152:        code = icp->icmp_code;
        !           153:        switch (icp->icmp_type) {
        !           154: 
        !           155:        case ICMP_UNREACH:
        !           156:                if (code > 5)
        !           157:                        goto badcode;
        !           158:                code += PRC_UNREACH_NET;
        !           159:                goto deliver;
        !           160: 
        !           161:        case ICMP_TIMXCEED:
        !           162:                if (code > 1)
        !           163:                        goto badcode;
        !           164:                code += PRC_TIMXCEED_INTRANS;
        !           165:                goto deliver;
        !           166: 
        !           167:        case ICMP_PARAMPROB:
        !           168:                if (code)
        !           169:                        goto badcode;
        !           170:                code = PRC_PARAMPROB;
        !           171:                goto deliver;
        !           172: 
        !           173:        case ICMP_SOURCEQUENCH:
        !           174:                if (code)
        !           175:                        goto badcode;
        !           176:                code = PRC_QUENCH;
        !           177:        deliver:
        !           178:                /*
        !           179:                 * Problem with datagram; advise higher level routines.
        !           180:                 */
        !           181:                icp->icmp_ip.ip_len = ntohs((u_short)icp->icmp_ip.ip_len);
        !           182:                if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp)) {
        !           183:                        icmpstat.icps_badlen++;
        !           184:                        goto free;
        !           185:                }
        !           186: #ifdef ICMPPRINTFS
        !           187:                if (icmpprintfs)
        !           188:                        printf("deliver to protocol %d\n", icp->icmp_ip.ip_p);
        !           189: #endif
        !           190:                if (ctlfunc = inetsw[ip_protox[icp->icmp_ip.ip_p]].pr_ctlinput)
        !           191:                        (*ctlfunc)(code, (caddr_t)icp);
        !           192:                goto free;
        !           193: 
        !           194:        badcode:
        !           195:                icmpstat.icps_badcode++;
        !           196:                goto free;
        !           197: 
        !           198:        case ICMP_ECHO:
        !           199:                icp->icmp_type = ICMP_ECHOREPLY;
        !           200:                goto reflect;
        !           201: 
        !           202:        case ICMP_TSTAMP:
        !           203:                if (icmplen < ICMP_TSLEN) {
        !           204:                        icmpstat.icps_badlen++;
        !           205:                        goto free;
        !           206:                }
        !           207:                icp->icmp_type = ICMP_TSTAMPREPLY;
        !           208:                icp->icmp_rtime = iptime();
        !           209:                icp->icmp_ttime = icp->icmp_rtime;      /* bogus, do later! */
        !           210:                goto reflect;
        !           211:                
        !           212:        case ICMP_IREQ:
        !           213: #ifdef notdef
        !           214:                /* fill in source address zero fields! */
        !           215:                goto reflect;
        !           216: #else
        !           217:                goto free;              /* not yet implemented: ignore */
        !           218: #endif
        !           219: 
        !           220:        case ICMP_REDIRECT:
        !           221:        case ICMP_ECHOREPLY:
        !           222:        case ICMP_TSTAMPREPLY:
        !           223:        case ICMP_IREQREPLY:
        !           224:                if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp)) {
        !           225:                        icmpstat.icps_badlen++;
        !           226:                        goto free;
        !           227:                }
        !           228:                /*
        !           229:                 * Short circuit routing redirects to force
        !           230:                 * immediate change in the kernel's routing
        !           231:                 * tables.  The message is also handed to anyone
        !           232:                 * listening on a raw socket (e.g. the routing
        !           233:                 * daemon for use in updating it's tables).
        !           234:                 */
        !           235:                if (icp->icmp_type == ICMP_REDIRECT) {
        !           236:                        icmpsrc.sin_addr = icp->icmp_ip.ip_dst;
        !           237:                        icmpdst.sin_addr = icp->icmp_gwaddr;
        !           238:                        rtredirect((struct sockaddr *)&icmpsrc,
        !           239:                          (struct sockaddr *)&icmpdst);
        !           240:                }
        !           241:                icmpsrc.sin_addr = ip->ip_src;
        !           242:                icmpdst.sin_addr = ip->ip_dst;
        !           243:                raw_input(dtom(icp), &icmproto, (struct sockaddr *)&icmpsrc,
        !           244:                  (struct sockaddr *)&icmpdst);
        !           245:                return;
        !           246: 
        !           247:        default:
        !           248:                goto free;
        !           249:        }
        !           250: reflect:
        !           251:        ip->ip_len += hlen;             /* since ip_input deducts this */
        !           252:        icmpstat.icps_reflect++;
        !           253:        icmp_reflect(ip);
        !           254:        return;
        !           255: free:
        !           256:        m_freem(dtom(ip));
        !           257: }
        !           258: 
        !           259: /*
        !           260:  * Reflect the ip packet back to the source
        !           261:  * TODO: rearrange ip source routing options.
        !           262:  */
        !           263: icmp_reflect(ip)
        !           264:        struct ip *ip;
        !           265: {
        !           266:        struct in_addr t;
        !           267: 
        !           268:        t = ip->ip_dst;
        !           269:        ip->ip_dst = ip->ip_src;
        !           270:        ip->ip_src = t;
        !           271:        icmp_send(ip);
        !           272: }
        !           273: 
        !           274: /*
        !           275:  * Send an icmp packet back to the ip level,
        !           276:  * after supplying a checksum.
        !           277:  */
        !           278: icmp_send(ip)
        !           279:        struct ip *ip;
        !           280: {
        !           281:        register int hlen;
        !           282:        register struct icmp *icp;
        !           283:        register struct mbuf *m;
        !           284: 
        !           285:        m = dtom(ip);
        !           286:        hlen = ip->ip_hl << 2;
        !           287:        icp = mtod(m, struct icmp *);
        !           288:        icp->icmp_cksum = 0;
        !           289:        icp->icmp_cksum = in_cksum(m, ip->ip_len - hlen);
        !           290:        m->m_off -= hlen;
        !           291:        m->m_len += hlen;
        !           292: #ifdef ICMPPRINTFS
        !           293:        if (icmpprintfs)
        !           294:                printf("icmp_send dst %x src %x\n", ip->ip_dst, ip->ip_src);
        !           295: #endif
        !           296:        (void) ip_output(m, (struct mbuf *)0, (struct route *)0, 0);
        !           297: }
        !           298: 
        !           299: n_time
        !           300: iptime()
        !           301: {
        !           302:        int s = spl6();
        !           303:        u_long t;
        !           304: 
        !           305:        t = (time.tv_sec % (24*60*60)) * 1000 + time.tv_usec / 1000;
        !           306:        splx(s);
        !           307:        return (htonl(t));
        !           308: }

unix.superglobalmegacorp.com

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