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>