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 * @(#) $Id icmp.c,v 3.8.4.2 1998/01/06 01:57:42 fenner Exp $
11 * $DragonFly: src/usr.sbin/mrouted/icmp.c,v 1.2 2003/06/17 04:29:57 dillon Exp $
16 static int icmp_socket;
18 static void icmp_handler __P((int, fd_set *));
19 static char * icmp_name __P((struct icmp *));
24 if ((icmp_socket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0)
25 log(LOG_ERR, errno, "ICMP socket");
27 register_input_handler(icmp_socket, icmp_handler);
30 log(LOG_DEBUG, 0, "registering icmp socket fd %d\n", icmp_socket);
34 icmp_handler(fd, rfds)
38 u_char icmp_buf[RECV_BUF_SIZE];
39 struct sockaddr_in from;
40 int fromlen, recvlen, iphdrlen, ipdatalen;
47 fromlen = sizeof(from);
48 recvlen = recvfrom(icmp_socket, icmp_buf, RECV_BUF_SIZE, 0,
49 (struct sockaddr *)&from, &fromlen);
52 log(LOG_WARNING, errno, "icmp_socket recvfrom");
55 ip = (struct ip *)icmp_buf;
56 iphdrlen = ip->ip_hl << 2;
57 #ifdef RAW_INPUT_IS_RAW
58 ipdatalen = ntohs(ip->ip_len) - iphdrlen;
60 ipdatalen = ip->ip_len;
62 if (iphdrlen + ipdatalen != recvlen) {
64 log(LOG_DEBUG, 0, "hdr %d data %d != rcv %d", iphdrlen, ipdatalen, recvlen);
65 /* Malformed ICMP, just return. */
68 if (ipdatalen < ICMP_MINLEN + sizeof(struct ip)) {
69 /* Not enough data for us to be interested in it. */
72 src = ip->ip_src.s_addr;
73 icmp = (struct icmp *)(icmp_buf + iphdrlen);
75 log(LOG_DEBUG, 0, "got ICMP type %d from %s",
76 icmp->icmp_type, inet_fmt(src, s1));
79 * have registry of ICMP listeners, by type, code and ICMP_ID
80 * (and maybe fields of the original packet too -- maybe need a
81 * generalized packet filter!) to allow ping and traceroute
82 * from the monitoring tool.
84 switch (icmp->icmp_type) {
87 /* Look at returned packet to see if it's us sending on a tunnel */
89 if (ip->ip_p != IPPROTO_IGMP && ip->ip_p != IPPROTO_IPIP)
91 for (v = uvifs, i = 0; i < numvifs; v++, i++) {
92 if (ip->ip_src.s_addr == v->uv_lcl_addr &&
93 ip->ip_dst.s_addr == v->uv_dst_addr) {
97 * I sent this packet on this vif.
99 n = ++v->uv_icmp_warn;
100 while (n && !(n & 1))
102 if (n == 1 && ((p = icmp_name(icmp)) != NULL))
103 log(LOG_WARNING, 0, "Received ICMP %s from %s %s %s on vif %d",
104 p, inet_fmt(src, s1), "for traffic sent to",
105 inet_fmt(ip->ip_dst.s_addr, s2),
116 * Return NULL for ICMP informational messages.
117 * Return string describing the error for ICMP errors.
123 static char retval[30];
125 switch (icmp->icmp_type) {
127 switch (icmp->icmp_code) {
128 case ICMP_UNREACH_NET:
129 return "network unreachable";
130 case ICMP_UNREACH_HOST:
131 return "host unreachable";
132 case ICMP_UNREACH_PROTOCOL:
133 return "protocol unreachable";
134 case ICMP_UNREACH_PORT:
135 return "port unreachable";
136 case ICMP_UNREACH_NEEDFRAG:
137 return "needs fragmentation";
138 case ICMP_UNREACH_SRCFAIL:
139 return "source route failed";
140 #ifndef ICMP_UNREACH_NET_UNKNOWN
141 #define ICMP_UNREACH_NET_UNKNOWN 6
143 case ICMP_UNREACH_NET_UNKNOWN:
144 return "network unknown";
145 #ifndef ICMP_UNREACH_HOST_UNKNOWN
146 #define ICMP_UNREACH_HOST_UNKNOWN 7
148 case ICMP_UNREACH_HOST_UNKNOWN:
149 return "host unknown";
150 #ifndef ICMP_UNREACH_ISOLATED
151 #define ICMP_UNREACH_ISOLATED 8
153 case ICMP_UNREACH_ISOLATED:
154 return "source host isolated";
155 #ifndef ICMP_UNREACH_NET_PROHIB
156 #define ICMP_UNREACH_NET_PROHIB 9
158 case ICMP_UNREACH_NET_PROHIB:
159 return "network access prohibited";
160 #ifndef ICMP_UNREACH_HOST_PROHIB
161 #define ICMP_UNREACH_HOST_PROHIB 10
163 case ICMP_UNREACH_HOST_PROHIB:
164 return "host access prohibited";
165 #ifndef ICMP_UNREACH_TOSNET
166 #define ICMP_UNREACH_TOSNET 11
168 case ICMP_UNREACH_TOSNET:
169 return "bad TOS for net";
170 #ifndef ICMP_UNREACH_TOSHOST
171 #define ICMP_UNREACH_TOSHOST 12
173 case ICMP_UNREACH_TOSHOST:
174 return "bad TOS for host";
175 #ifndef ICMP_UNREACH_FILTER_PROHIB
176 #define ICMP_UNREACH_FILTER_PROHIB 13
178 case ICMP_UNREACH_FILTER_PROHIB:
179 return "prohibited by filter";
180 #ifndef ICMP_UNREACH_HOST_PRECEDENCE
181 #define ICMP_UNREACH_HOST_PRECEDENCE 14
183 case ICMP_UNREACH_HOST_PRECEDENCE:
184 return "host precedence violation";
185 #ifndef ICMP_UNREACH_PRECEDENCE_CUTOFF
186 #define ICMP_UNREACH_PRECEDENCE_CUTOFF 15
188 case ICMP_UNREACH_PRECEDENCE_CUTOFF:
189 return "precedence cutoff";
191 sprintf(retval, "unreachable code %d", icmp->icmp_code);
194 case ICMP_SOURCEQUENCH:
195 return "source quench";
197 return NULL; /* XXX */
199 switch (icmp->icmp_code) {
200 case ICMP_TIMXCEED_INTRANS:
201 return "time exceeded in transit";
202 case ICMP_TIMXCEED_REASS:
203 return "time exceeded in reassembly";
205 sprintf(retval, "time exceeded code %d", icmp->icmp_code);
209 switch (icmp->icmp_code) {
210 #ifndef ICMP_PARAMPROB_OPTABSENT
211 #define ICMP_PARAMPROB_OPTABSENT 1
213 case ICMP_PARAMPROB_OPTABSENT:
214 return "required option absent";
216 sprintf(retval, "parameter problem code %d", icmp->icmp_code);