Annotation of embedaddon/mrouted/icmp.c, revision 1.1.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>