Annotation of embedaddon/mrouted/icmp.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * The mrouted program is covered by the license in the accompanying file
        !             3:  * named "LICENSE".  Use of the mrouted program represents acceptance of
        !             4:  * the terms and conditions listed in that file.
        !             5:  *
        !             6:  * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
        !             7:  * Leland Stanford Junior University.
        !             8:  */
        !             9: 
        !            10: #include "defs.h"
        !            11: 
        !            12: static int     icmp_socket;
        !            13: 
        !            14: static void    icmp_handler(int, fd_set *);
        !            15: static char *  icmp_name(struct icmp *);
        !            16: 
        !            17: void init_icmp(void)
        !            18: {
        !            19:     if ((icmp_socket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0)
        !            20:        logit(LOG_ERR, errno, "ICMP socket");
        !            21: 
        !            22:     register_input_handler(icmp_socket, icmp_handler);
        !            23: 
        !            24:     IF_DEBUG(DEBUG_ICMP)
        !            25:     logit(LOG_DEBUG, 0, "registering icmp socket fd %d\n", icmp_socket);
        !            26: }
        !            27: 
        !            28: static void icmp_handler(int fd, fd_set UNUSED *rfds)
        !            29: {
        !            30:     u_char icmp_buf[RECV_BUF_SIZE];
        !            31:     struct sockaddr_in from;
        !            32:     socklen_t fromlen;
        !            33:     ssize_t recvlen;
        !            34:     int iphdrlen, ipdatalen;
        !            35:     struct icmp *icmp;
        !            36:     struct ip *ip;
        !            37:     vifi_t i;
        !            38:     struct uvif *v;
        !            39:     u_int32 src;
        !            40: 
        !            41:     fromlen = sizeof(from);
        !            42:     recvlen = recvfrom(fd, icmp_buf, RECV_BUF_SIZE, 0,
        !            43:                            (struct sockaddr *)&from, &fromlen);
        !            44:     if (recvlen < 0) {
        !            45:        if (errno != EINTR)
        !            46:            logit(LOG_WARNING, errno, "icmp_socket recvfrom");
        !            47:        return;
        !            48:     }
        !            49:     ip = (struct ip *)icmp_buf;
        !            50:     iphdrlen = ip->ip_hl << 2;
        !            51:     ipdatalen = ntohs(ip->ip_len) - iphdrlen;
        !            52:     if (iphdrlen + ipdatalen != recvlen) {
        !            53:        IF_DEBUG(DEBUG_ICMP)
        !            54:        logit(LOG_DEBUG, 0, "hdr %d data %d != rcv %d", iphdrlen, ipdatalen, recvlen);
        !            55:        /* Malformed ICMP, just return. */
        !            56:        return;
        !            57:     }
        !            58:     if (ipdatalen < ICMP_MINLEN + (int)sizeof(struct ip)) {
        !            59:        /* Not enough data for us to be interested in it. */
        !            60:        return;
        !            61:     }
        !            62:     src = ip->ip_src.s_addr;
        !            63:     icmp = (struct icmp *)(icmp_buf + iphdrlen);
        !            64:     IF_DEBUG(DEBUG_ICMP)
        !            65:     logit(LOG_DEBUG, 0, "got ICMP type %d from %s",
        !            66:          icmp->icmp_type, inet_fmt(src, s1, sizeof(s1)));
        !            67:     /*
        !            68:      * Eventually:
        !            69:      * have registry of ICMP listeners, by type, code and ICMP_ID
        !            70:      * (and maybe fields of the original packet too -- maybe need a
        !            71:      * generalized packet filter!) to allow ping and traceroute
        !            72:      * from the monitoring tool.
        !            73:      */
        !            74:     switch (icmp->icmp_type) {
        !            75:        case ICMP_UNREACH:
        !            76:        case ICMP_TIMXCEED:
        !            77:            /* Look at returned packet to see if it's us sending on a tunnel */
        !            78:            ip = &icmp->icmp_ip;
        !            79:            if (ip->ip_p != IPPROTO_IGMP && ip->ip_p != IPPROTO_IPIP)
        !            80:                return;
        !            81:            for (v = uvifs, i = 0; i < numvifs; v++, i++) {
        !            82:                if (ip->ip_src.s_addr == v->uv_lcl_addr &&
        !            83:                    ip->ip_dst.s_addr == v->uv_dst_addr) {
        !            84:                    char *p;
        !            85:                    int n;
        !            86:                    /*
        !            87:                     * I sent this packet on this vif.
        !            88:                     */
        !            89:                    n = ++v->uv_icmp_warn;
        !            90:                    while (n && !(n & 1))
        !            91:                        n >>= 1;
        !            92:                    if (n == 1 && ((p = icmp_name(icmp)) != NULL))
        !            93:                        logit(LOG_WARNING, 0, "Received ICMP %s from %s %s %s on vif %d",
        !            94:                            p, inet_fmt(src, s1, sizeof(s1)), "for traffic sent to",
        !            95:                            inet_fmt(ip->ip_dst.s_addr, s2, sizeof(s2)),
        !            96:                            i);
        !            97: 
        !            98:                    break;
        !            99:                }
        !           100:            }
        !           101:            break;
        !           102:     }
        !           103: }
        !           104: 
        !           105: /*
        !           106:  * Return NULL for ICMP informational messages.
        !           107:  * Return string describing the error for ICMP errors.
        !           108:  */
        !           109: static char *icmp_name(struct icmp *icmp)
        !           110: {
        !           111:     static char retval[30];
        !           112: 
        !           113:     switch (icmp->icmp_type) {
        !           114:        case ICMP_UNREACH:
        !           115:            switch (icmp->icmp_code) {
        !           116:                case ICMP_UNREACH_NET:
        !           117:                    return "network unreachable";
        !           118:                case ICMP_UNREACH_HOST:
        !           119:                    return "host unreachable";
        !           120:                case ICMP_UNREACH_PROTOCOL:
        !           121:                    return "protocol unreachable";
        !           122:                case ICMP_UNREACH_PORT:
        !           123:                    return "port unreachable";
        !           124:                case ICMP_UNREACH_NEEDFRAG:
        !           125:                    return "needs fragmentation";
        !           126:                case ICMP_UNREACH_SRCFAIL:
        !           127:                    return "source route failed";
        !           128: #ifndef ICMP_UNREACH_NET_UNKNOWN
        !           129: #define ICMP_UNREACH_NET_UNKNOWN       6
        !           130: #endif
        !           131:                case ICMP_UNREACH_NET_UNKNOWN:
        !           132:                    return "network unknown";
        !           133: #ifndef ICMP_UNREACH_HOST_UNKNOWN
        !           134: #define ICMP_UNREACH_HOST_UNKNOWN      7
        !           135: #endif
        !           136:                case ICMP_UNREACH_HOST_UNKNOWN:
        !           137:                    return "host unknown";
        !           138: #ifndef ICMP_UNREACH_ISOLATED
        !           139: #define ICMP_UNREACH_ISOLATED          8
        !           140: #endif
        !           141:                case ICMP_UNREACH_ISOLATED:
        !           142:                    return "source host isolated";
        !           143: #ifndef ICMP_UNREACH_NET_PROHIB
        !           144: #define ICMP_UNREACH_NET_PROHIB                9
        !           145: #endif
        !           146:                case ICMP_UNREACH_NET_PROHIB:
        !           147:                    return "network access prohibited";
        !           148: #ifndef ICMP_UNREACH_HOST_PROHIB
        !           149: #define ICMP_UNREACH_HOST_PROHIB       10
        !           150: #endif
        !           151:                case ICMP_UNREACH_HOST_PROHIB:
        !           152:                    return "host access prohibited";
        !           153: #ifndef ICMP_UNREACH_TOSNET
        !           154: #define ICMP_UNREACH_TOSNET            11
        !           155: #endif
        !           156:                case ICMP_UNREACH_TOSNET:
        !           157:                    return "bad TOS for net";
        !           158: #ifndef ICMP_UNREACH_TOSHOST
        !           159: #define ICMP_UNREACH_TOSHOST           12
        !           160: #endif
        !           161:                case ICMP_UNREACH_TOSHOST:
        !           162:                    return "bad TOS for host";
        !           163: #ifndef ICMP_UNREACH_FILTER_PROHIB
        !           164: #define ICMP_UNREACH_FILTER_PROHIB     13
        !           165: #endif
        !           166:                case ICMP_UNREACH_FILTER_PROHIB:
        !           167:                    return "prohibited by filter";
        !           168: #ifndef ICMP_UNREACH_HOST_PRECEDENCE
        !           169: #define ICMP_UNREACH_HOST_PRECEDENCE   14
        !           170: #endif
        !           171:                case ICMP_UNREACH_HOST_PRECEDENCE:
        !           172:                    return "host precedence violation";
        !           173: #ifndef ICMP_UNREACH_PRECEDENCE_CUTOFF
        !           174: #define ICMP_UNREACH_PRECEDENCE_CUTOFF 15
        !           175: #endif
        !           176:                case ICMP_UNREACH_PRECEDENCE_CUTOFF:
        !           177:                    return "precedence cutoff";
        !           178:                default:
        !           179:                    snprintf(retval, sizeof(retval), "unreachable code %d", icmp->icmp_code);
        !           180:                    return retval;
        !           181:            }
        !           182:        case ICMP_SOURCEQUENCH:
        !           183:            return "source quench";
        !           184:        case ICMP_REDIRECT:
        !           185:            return NULL;        /* XXX */
        !           186:        case ICMP_TIMXCEED:
        !           187:            switch (icmp->icmp_code) {
        !           188:                case ICMP_TIMXCEED_INTRANS:
        !           189:                    return "time exceeded in transit";
        !           190:                case ICMP_TIMXCEED_REASS:
        !           191:                    return "time exceeded in reassembly";
        !           192:                default:
        !           193:                    snprintf(retval, sizeof(retval), "time exceeded code %d", icmp->icmp_code);
        !           194:                    return retval;
        !           195:            }
        !           196:        case ICMP_PARAMPROB:
        !           197:            switch (icmp->icmp_code) {
        !           198: #ifndef ICMP_PARAMPROB_OPTABSENT
        !           199: #define ICMP_PARAMPROB_OPTABSENT       1
        !           200: #endif
        !           201:                case ICMP_PARAMPROB_OPTABSENT:
        !           202:                    return "required option absent";
        !           203:                default:
        !           204:                    snprintf(retval, sizeof(retval), "parameter problem code %d", icmp->icmp_code);
        !           205:                    return retval;
        !           206:            }
        !           207:     }
        !           208:     return NULL;
        !           209: }
        !           210: 
        !           211: /**
        !           212:  * Local Variables:
        !           213:  *  version-control: t
        !           214:  *  indent-tabs-mode: t
        !           215:  *  c-file-style: "ellemtel"
        !           216:  *  c-basic-offset: 4
        !           217:  * End:
        !           218:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>