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>