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

unix.superglobalmegacorp.com

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