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.
6 * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
7 * Leland Stanford Junior University.
10 * icmp.c,v 3.8.4.2 1998/01/06 01:57:42 fenner Exp
16 static char rcsid[] = "@(#) $Id: \
17 icmp.c,v 3.8.4.2 1998/01/06 01:57:42 fenner Exp $";
20 static int icmp_socket;
22 static void icmp_handler __P((int, fd_set *));
23 static char * icmp_name __P((struct icmp *));
28 if ((icmp_socket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0)
29 log(LOG_ERR, errno, "ICMP socket");
31 register_input_handler(icmp_socket, icmp_handler);
34 log(LOG_DEBUG, 0, "registering icmp socket fd %d\n", icmp_socket);
38 icmp_handler(fd, rfds)
42 u_char icmp_buf[RECV_BUF_SIZE];
43 struct sockaddr_in from;
44 int fromlen, recvlen, iphdrlen, ipdatalen;
51 fromlen = sizeof(from);
52 recvlen = recvfrom(icmp_socket, icmp_buf, RECV_BUF_SIZE, 0,
53 (struct sockaddr *)&from, &fromlen);
56 log(LOG_WARNING, errno, "icmp_socket recvfrom");
59 ip = (struct ip *)icmp_buf;
60 iphdrlen = ip->ip_hl << 2;
61 #ifdef RAW_INPUT_IS_RAW
62 ipdatalen = ntohs(ip->ip_len) - iphdrlen;
64 ipdatalen = ip->ip_len;
66 if (iphdrlen + ipdatalen != recvlen) {
68 log(LOG_DEBUG, 0, "hdr %d data %d != rcv %d", iphdrlen, ipdatalen, recvlen);
69 /* Malformed ICMP, just return. */
72 if (ipdatalen < ICMP_MINLEN + sizeof(struct ip)) {
73 /* Not enough data for us to be interested in it. */
76 src = ip->ip_src.s_addr;
77 icmp = (struct icmp *)(icmp_buf + iphdrlen);
79 log(LOG_DEBUG, 0, "got ICMP type %d from %s",
80 icmp->icmp_type, inet_fmt(src, s1));
83 * have registry of ICMP listeners, by type, code and ICMP_ID
84 * (and maybe fields of the original packet too -- maybe need a
85 * generalized packet filter!) to allow ping and traceroute
86 * from the monitoring tool.
88 switch (icmp->icmp_type) {
91 /* Look at returned packet to see if it's us sending on a tunnel */
93 if (ip->ip_p != IPPROTO_IGMP && ip->ip_p != IPPROTO_IPIP)
95 for (v = uvifs, i = 0; i < numvifs; v++, i++) {
96 if (ip->ip_src.s_addr == v->uv_lcl_addr &&
97 ip->ip_dst.s_addr == v->uv_dst_addr) {
101 * I sent this packet on this vif.
103 n = ++v->uv_icmp_warn;
104 while (n && !(n & 1))
106 if (n == 1 && ((p = icmp_name(icmp)) != NULL))
107 log(LOG_WARNING, 0, "Received ICMP %s from %s %s %s on vif %d",
108 p, inet_fmt(src, s1), "for traffic sent to",
109 inet_fmt(ip->ip_dst.s_addr, s2),
120 * Return NULL for ICMP informational messages.
121 * Return string describing the error for ICMP errors.
127 static char retval[30];
129 switch (icmp->icmp_type) {
131 switch (icmp->icmp_code) {
132 case ICMP_UNREACH_NET:
133 return "network unreachable";
134 case ICMP_UNREACH_HOST:
135 return "host unreachable";
136 case ICMP_UNREACH_PROTOCOL:
137 return "protocol unreachable";
138 case ICMP_UNREACH_PORT:
139 return "port unreachable";
140 case ICMP_UNREACH_NEEDFRAG:
141 return "needs fragmentation";
142 case ICMP_UNREACH_SRCFAIL:
143 return "source route failed";
144 #ifndef ICMP_UNREACH_NET_UNKNOWN
145 #define ICMP_UNREACH_NET_UNKNOWN 6
147 case ICMP_UNREACH_NET_UNKNOWN:
148 return "network unknown";
149 #ifndef ICMP_UNREACH_HOST_UNKNOWN
150 #define ICMP_UNREACH_HOST_UNKNOWN 7
152 case ICMP_UNREACH_HOST_UNKNOWN:
153 return "host unknown";
154 #ifndef ICMP_UNREACH_ISOLATED
155 #define ICMP_UNREACH_ISOLATED 8
157 case ICMP_UNREACH_ISOLATED:
158 return "source host isolated";
159 #ifndef ICMP_UNREACH_NET_PROHIB
160 #define ICMP_UNREACH_NET_PROHIB 9
162 case ICMP_UNREACH_NET_PROHIB:
163 return "network access prohibited";
164 #ifndef ICMP_UNREACH_HOST_PROHIB
165 #define ICMP_UNREACH_HOST_PROHIB 10
167 case ICMP_UNREACH_HOST_PROHIB:
168 return "host access prohibited";
169 #ifndef ICMP_UNREACH_TOSNET
170 #define ICMP_UNREACH_TOSNET 11
172 case ICMP_UNREACH_TOSNET:
173 return "bad TOS for net";
174 #ifndef ICMP_UNREACH_TOSHOST
175 #define ICMP_UNREACH_TOSHOST 12
177 case ICMP_UNREACH_TOSHOST:
178 return "bad TOS for host";
179 #ifndef ICMP_UNREACH_FILTER_PROHIB
180 #define ICMP_UNREACH_FILTER_PROHIB 13
182 case ICMP_UNREACH_FILTER_PROHIB:
183 return "prohibited by filter";
184 #ifndef ICMP_UNREACH_HOST_PRECEDENCE
185 #define ICMP_UNREACH_HOST_PRECEDENCE 14
187 case ICMP_UNREACH_HOST_PRECEDENCE:
188 return "host precedence violation";
189 #ifndef ICMP_UNREACH_PRECEDENCE_CUTOFF
190 #define ICMP_UNREACH_PRECEDENCE_CUTOFF 15
192 case ICMP_UNREACH_PRECEDENCE_CUTOFF:
193 return "precedence cutoff";
195 sprintf(retval, "unreachable code %d", icmp->icmp_code);
198 case ICMP_SOURCEQUENCH:
199 return "source quench";
201 return NULL; /* XXX */
203 switch (icmp->icmp_code) {
204 case ICMP_TIMXCEED_INTRANS:
205 return "time exceeded in transit";
206 case ICMP_TIMXCEED_REASS:
207 return "time exceeded in reassembly";
209 sprintf(retval, "time exceeded code %d", icmp->icmp_code);
213 switch (icmp->icmp_code) {
214 #ifndef ICMP_PARAMPROB_OPTABSENT
215 #define ICMP_PARAMPROB_OPTABSENT 1
217 case ICMP_PARAMPROB_OPTABSENT:
218 return "required option absent";
220 sprintf(retval, "parameter problem code %d", icmp->icmp_code);