File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / mrouted / icmp.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 23:10:48 2012 UTC (12 years, 3 months ago) by misho
Branches: mrouted, MAIN
CVS tags: v3_9_6p0, v3_9_6, v3_9_5, HEAD
mrouted

    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>