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.4 2004/03/15 18:10:28 dillon Exp $
16 static int icmp_socket
;
18 static void icmp_handler(int, fd_set
*);
19 static char * icmp_name(struct icmp
*);
24 if ((icmp_socket
= socket(AF_INET
, SOCK_RAW
, IPPROTO_ICMP
)) < 0)
25 dolog(LOG_ERR
, errno
, "ICMP socket");
27 register_input_handler(icmp_socket
, icmp_handler
);
30 dolog(LOG_DEBUG
, 0, "registering icmp socket fd %d\n", icmp_socket
);
34 icmp_handler(int fd
, fd_set
*rfds
)
36 u_char icmp_buf
[RECV_BUF_SIZE
];
37 struct sockaddr_in from
;
38 int fromlen
, recvlen
, iphdrlen
, ipdatalen
;
45 fromlen
= sizeof(from
);
46 recvlen
= recvfrom(icmp_socket
, icmp_buf
, RECV_BUF_SIZE
, 0,
47 (struct sockaddr
*)&from
, &fromlen
);
50 dolog(LOG_WARNING
, errno
, "icmp_socket recvfrom");
53 ip
= (struct ip
*)icmp_buf
;
54 iphdrlen
= ip
->ip_hl
<< 2;
55 #ifdef RAW_INPUT_IS_RAW
56 ipdatalen
= ntohs(ip
->ip_len
) - iphdrlen
;
58 ipdatalen
= ip
->ip_len
;
60 if (iphdrlen
+ ipdatalen
!= recvlen
) {
62 dolog(LOG_DEBUG
, 0, "hdr %d data %d != rcv %d", iphdrlen
, ipdatalen
, recvlen
);
63 /* Malformed ICMP, just return. */
66 if (ipdatalen
< ICMP_MINLEN
+ sizeof(struct ip
)) {
67 /* Not enough data for us to be interested in it. */
70 src
= ip
->ip_src
.s_addr
;
71 icmp
= (struct icmp
*)(icmp_buf
+ iphdrlen
);
73 dolog(LOG_DEBUG
, 0, "got ICMP type %d from %s",
74 icmp
->icmp_type
, inet_fmt(src
, s1
));
77 * have registry of ICMP listeners, by type, code and ICMP_ID
78 * (and maybe fields of the original packet too -- maybe need a
79 * generalized packet filter!) to allow ping and traceroute
80 * from the monitoring tool.
82 switch (icmp
->icmp_type
) {
85 /* Look at returned packet to see if it's us sending on a tunnel */
87 if (ip
->ip_p
!= IPPROTO_IGMP
&& ip
->ip_p
!= IPPROTO_IPIP
)
89 for (v
= uvifs
, i
= 0; i
< numvifs
; v
++, i
++) {
90 if (ip
->ip_src
.s_addr
== v
->uv_lcl_addr
&&
91 ip
->ip_dst
.s_addr
== v
->uv_dst_addr
) {
95 * I sent this packet on this vif.
97 n
= ++v
->uv_icmp_warn
;
100 if (n
== 1 && ((p
= icmp_name(icmp
)) != NULL
))
101 dolog(LOG_WARNING
, 0, "Received ICMP %s from %s %s %s on vif %d",
102 p
, inet_fmt(src
, s1
), "for traffic sent to",
103 inet_fmt(ip
->ip_dst
.s_addr
, s2
),
114 * Return NULL for ICMP informational messages.
115 * Return string describing the error for ICMP errors.
118 icmp_name(struct icmp
*icmp
)
120 static char retval
[30];
122 switch (icmp
->icmp_type
) {
124 switch (icmp
->icmp_code
) {
125 case ICMP_UNREACH_NET
:
126 return "network unreachable";
127 case ICMP_UNREACH_HOST
:
128 return "host unreachable";
129 case ICMP_UNREACH_PROTOCOL
:
130 return "protocol unreachable";
131 case ICMP_UNREACH_PORT
:
132 return "port unreachable";
133 case ICMP_UNREACH_NEEDFRAG
:
134 return "needs fragmentation";
135 case ICMP_UNREACH_SRCFAIL
:
136 return "source route failed";
137 #ifndef ICMP_UNREACH_NET_UNKNOWN
138 #define ICMP_UNREACH_NET_UNKNOWN 6
140 case ICMP_UNREACH_NET_UNKNOWN
:
141 return "network unknown";
142 #ifndef ICMP_UNREACH_HOST_UNKNOWN
143 #define ICMP_UNREACH_HOST_UNKNOWN 7
145 case ICMP_UNREACH_HOST_UNKNOWN
:
146 return "host unknown";
147 #ifndef ICMP_UNREACH_ISOLATED
148 #define ICMP_UNREACH_ISOLATED 8
150 case ICMP_UNREACH_ISOLATED
:
151 return "source host isolated";
152 #ifndef ICMP_UNREACH_NET_PROHIB
153 #define ICMP_UNREACH_NET_PROHIB 9
155 case ICMP_UNREACH_NET_PROHIB
:
156 return "network access prohibited";
157 #ifndef ICMP_UNREACH_HOST_PROHIB
158 #define ICMP_UNREACH_HOST_PROHIB 10
160 case ICMP_UNREACH_HOST_PROHIB
:
161 return "host access prohibited";
162 #ifndef ICMP_UNREACH_TOSNET
163 #define ICMP_UNREACH_TOSNET 11
165 case ICMP_UNREACH_TOSNET
:
166 return "bad TOS for net";
167 #ifndef ICMP_UNREACH_TOSHOST
168 #define ICMP_UNREACH_TOSHOST 12
170 case ICMP_UNREACH_TOSHOST
:
171 return "bad TOS for host";
172 #ifndef ICMP_UNREACH_FILTER_PROHIB
173 #define ICMP_UNREACH_FILTER_PROHIB 13
175 case ICMP_UNREACH_FILTER_PROHIB
:
176 return "prohibited by filter";
177 #ifndef ICMP_UNREACH_HOST_PRECEDENCE
178 #define ICMP_UNREACH_HOST_PRECEDENCE 14
180 case ICMP_UNREACH_HOST_PRECEDENCE
:
181 return "host precedence violation";
182 #ifndef ICMP_UNREACH_PRECEDENCE_CUTOFF
183 #define ICMP_UNREACH_PRECEDENCE_CUTOFF 15
185 case ICMP_UNREACH_PRECEDENCE_CUTOFF
:
186 return "precedence cutoff";
188 sprintf(retval
, "unreachable code %d", icmp
->icmp_code
);
191 case ICMP_SOURCEQUENCH
:
192 return "source quench";
194 return NULL
; /* XXX */
196 switch (icmp
->icmp_code
) {
197 case ICMP_TIMXCEED_INTRANS
:
198 return "time exceeded in transit";
199 case ICMP_TIMXCEED_REASS
:
200 return "time exceeded in reassembly";
202 sprintf(retval
, "time exceeded code %d", icmp
->icmp_code
);
206 switch (icmp
->icmp_code
) {
207 #ifndef ICMP_PARAMPROB_OPTABSENT
208 #define ICMP_PARAMPROB_OPTABSENT 1
210 case ICMP_PARAMPROB_OPTABSENT
:
211 return "required option absent";
213 sprintf(retval
, "parameter problem code %d", icmp
->icmp_code
);