File: | programs/pluto/iface_udp.c |
Warning: | line 504, column 3 Value stored to 'sizeof_buffer' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* udp packet processing, for libreswan |
2 | * |
3 | * Copyright (C) 1997 Angelos D. Keromytis. |
4 | * Copyright (C) 1998-2002, 2013,2016 D. Hugh Redelmeier <hugh@mimosa.com> |
5 | * Copyright (C) 2003-2008 Michael C Richardson <mcr@xelerance.com> |
6 | * Copyright (C) 2003-2010 Paul Wouters <paul@xelerance.com> |
7 | * Copyright (C) 2008-2009 David McCullough <david_mccullough@securecomputing.com> |
8 | * Copyright (C) 2009 Avesh Agarwal <avagarwa@redhat.com> |
9 | * Copyright (C) 2010 Tuomo Soini <tis@foobar.fi> |
10 | * Copyright (C) 2012-2017 Paul Wouters <pwouters@redhat.com> |
11 | * Copyright (C) 2013 Wolfgang Nothdurft <wolfgang@linogate.de> |
12 | * Copyright (C) 2016-2019 Andrew Cagney <cagney@gnu.org> |
13 | * Copyright (C) 2017 D. Hugh Redelmeier <hugh@mimosa.com> |
14 | * |
15 | * This program is free software; you can redistribute it and/or modify it |
16 | * under the terms of the GNU General Public License as published by the |
17 | * Free Software Foundation; either version 2 of the License, or (at your |
18 | * option) any later version. See <https://www.gnu.org/licenses/gpl2.txt>. |
19 | * |
20 | * This program is distributed in the hope that it will be useful, but |
21 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
22 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
23 | * for more details. |
24 | */ |
25 | |
26 | #include <sys/types.h> |
27 | #include <sys/socket.h> /* MSG_ERRQUEUE if defined */ |
28 | #include <netinet/udp.h> |
29 | #include <errno(*__errno_location ()).h> |
30 | #include <fcntl.h> |
31 | #include <unistd.h> |
32 | |
33 | #ifdef MSG_ERRQUEUEMSG_ERRQUEUE |
34 | # include <netinet/in.h> /* for IP_RECVERR */ |
35 | # include <linux1/errqueue.h> |
36 | # include <poll.h> |
37 | #endif |
38 | |
39 | #include "ip_address.h" |
40 | |
41 | #include "defs.h" |
42 | #include "kernel.h" |
43 | #include "server.h" /* for pluto_sock_bufsize */ |
44 | #include "iface.h" |
45 | #include "demux.h" |
46 | #include "state_db.h" /* for state_by_ike_spis() */ |
47 | #include "log.h" |
48 | #include "ip_info.h" |
49 | #include "ip_sockaddr.h" |
50 | #include "nat_traversal.h" /* for nat_traversal_enabled which seems like a broken idea */ |
51 | |
52 | static int bind_udp_socket(const struct iface_dev *ifd, ip_port port, |
53 | struct logger *logger) |
54 | { |
55 | const struct ip_info *type = address_type(&ifd->id_address); |
56 | int fd = socket(type->af, SOCK_DGRAMSOCK_DGRAM, IPPROTO_UDPIPPROTO_UDP); |
57 | if (fd < 0) { |
58 | log_errno(logger, errno, "socket() in %s()", __func__){ int e_ = (*__errno_location ()); log_error(logger, e_, "socket() in %s()" , __func__); }; |
59 | return -1; |
60 | } |
61 | |
62 | int fcntl_flags; |
63 | static const int on = true1; /* by-reference parameter; constant, we hope */ |
64 | |
65 | /* Set socket Nonblocking */ |
66 | if ((fcntl_flags = fcntl(fd, F_GETFL3)) >= 0) { |
67 | if (!(fcntl_flags & O_NONBLOCK04000)) { |
68 | fcntl_flags |= O_NONBLOCK04000; |
69 | if (fcntl(fd, F_SETFL4, fcntl_flags) == -1) { |
70 | log_errno(logger, errno, "fcntl(,, O_NONBLOCK) in create_socket()"){ int e_ = (*__errno_location ()); log_error(logger, e_, "fcntl(,, O_NONBLOCK) in create_socket()" ); }; |
71 | } |
72 | } |
73 | } |
74 | |
75 | if (fcntl(fd, F_SETFD2, FD_CLOEXEC1) == -1) { |
76 | log_errno(logger, errno, "fcntl(,, FD_CLOEXEC) in create_socket()"){ int e_ = (*__errno_location ()); log_error(logger, e_, "fcntl(,, FD_CLOEXEC) in create_socket()" ); }; |
77 | close(fd); |
78 | return -1; |
79 | } |
80 | |
81 | if (setsockopt(fd, SOL_SOCKET1, SO_REUSEADDR2, |
82 | (const void *)&on, sizeof(on)) < 0) { |
83 | log_errno(logger, errno, "setsockopt SO_REUSEADDR in create_socket()"){ int e_ = (*__errno_location ()); log_error(logger, e_, "setsockopt SO_REUSEADDR in create_socket()" ); }; |
84 | close(fd); |
85 | return -1; |
86 | } |
87 | |
88 | #ifdef SO_PRIORITY12 |
89 | static const int so_prio = 6; /* rumored maximum priority, might be 7 on linux? */ |
90 | if (setsockopt(fd, SOL_SOCKET1, SO_PRIORITY12, |
91 | (const void *)&so_prio, sizeof(so_prio)) < 0) { |
92 | log_errno(logger, errno, "setsockopt(SO_PRIORITY) in create_udp_socket()"){ int e_ = (*__errno_location ()); log_error(logger, e_, "setsockopt(SO_PRIORITY) in create_udp_socket()" ); }; |
93 | /* non-fatal */ |
94 | } |
95 | #endif |
96 | |
97 | if (pluto_sock_bufsize != IKE_BUF_AUTO0) { |
98 | #if defined(linux1) |
99 | /* |
100 | * Override system maximum |
101 | * Requires CAP_NET_ADMIN |
102 | */ |
103 | int so_rcv = SO_RCVBUFFORCE33; |
104 | int so_snd = SO_SNDBUFFORCE32; |
105 | #else |
106 | int so_rcv = SO_RCVBUF8; |
107 | int so_snd = SO_SNDBUF7; |
108 | #endif |
109 | if (setsockopt(fd, SOL_SOCKET1, so_rcv, |
110 | (const void *)&pluto_sock_bufsize, sizeof(pluto_sock_bufsize)) < 0) { |
111 | log_errno(logger, errno, "setsockopt(SO_RCVBUFFORCE) in create_udp_socket()"){ int e_ = (*__errno_location ()); log_error(logger, e_, "setsockopt(SO_RCVBUFFORCE) in create_udp_socket()" ); }; |
112 | } |
113 | if (setsockopt(fd, SOL_SOCKET1, so_snd, |
114 | (const void *)&pluto_sock_bufsize, sizeof(pluto_sock_bufsize)) < 0) { |
115 | log_errno(logger, errno, "setsockopt(SO_SNDBUFFORCE) in create_udp_socket()"){ int e_ = (*__errno_location ()); log_error(logger, e_, "setsockopt(SO_SNDBUFFORCE) in create_udp_socket()" ); }; |
116 | } |
117 | } |
118 | |
119 | /* To improve error reporting. See ip(7). */ |
120 | #ifdef MSG_ERRQUEUEMSG_ERRQUEUE |
121 | if (pluto_sock_errqueue) { |
122 | if (setsockopt(fd, SOL_IP0, IP_RECVERR11, (const void *)&on, sizeof(on)) < 0) { |
123 | log_errno(logger, errno, "setsockopt IP_RECVERR in create_socket()"){ int e_ = (*__errno_location ()); log_error(logger, e_, "setsockopt IP_RECVERR in create_socket()" ); }; |
124 | close(fd); |
125 | return -1; |
126 | } |
127 | dbg("MSG_ERRQUEUE enabled on fd %d", fd){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("MSG_ERRQUEUE enabled on fd %d", fd); } }; |
128 | } |
129 | #endif |
130 | |
131 | /* With IPv6, there is no fragmentation after |
132 | * it leaves our interface. PMTU discovery |
133 | * is mandatory but doesn't work well with IKE (why?). |
134 | * So we must set the IPV6_USE_MIN_MTU option. |
135 | * See draft-ietf-ipngwg-rfc2292bis-01.txt 11.1 |
136 | */ |
137 | #ifdef IPV6_USE_MIN_MTU /* YUCK: not always defined */ |
138 | if (type == &ipv6_info && |
139 | setsockopt(fd, SOL_SOCKET1, IPV6_USE_MIN_MTU, |
140 | (const void *)&on, sizeof(on)) < 0) { |
141 | log_errno(logger, errno, "setsockopt IPV6_USE_MIN_MTU in create_udp_socket()"){ int e_ = (*__errno_location ()); log_error(logger, e_, "setsockopt IPV6_USE_MIN_MTU in create_udp_socket()" ); }; |
142 | close(fd); |
143 | return -1; |
144 | } |
145 | #endif |
146 | |
147 | /* |
148 | * NETKEY requires us to poke an IPsec policy hole that allows |
149 | * IKE packets. This installs one IPsec policy per socket |
150 | * but this function is called for each: IPv4 port 500 and |
151 | * 4500 IPv6 port 500 |
152 | */ |
153 | if (kernel_ops->poke_ipsec_policy_hole != NULL((void*)0) && |
154 | !kernel_ops->poke_ipsec_policy_hole(ifd, fd, logger)) { |
155 | close(fd); |
156 | return -1; |
157 | } |
158 | |
159 | /* |
160 | * ??? does anyone care about the value of port of ifp->addr? |
161 | * Old code seemed to assume that it should be reset to pluto_port. |
162 | * But only on successful bind. Seems wrong or unnecessary. |
163 | */ |
164 | ip_endpoint if_endpoint = endpoint_from_address_protocol_port(ifd->id_address, |
165 | &ip_protocol_udpip_protocols[IPPROTO_UDP], |
166 | port); |
167 | ip_sockaddr if_sa = sockaddr_from_endpoint(if_endpoint); |
168 | if (bind(fd, &if_sa.sa.sa, if_sa.len) < 0) { |
169 | endpoint_buf b; |
170 | log_errno(logger, errno, "bind() for %s %s in process_raw_ifaces()",{ int e_ = (*__errno_location ()); log_error(logger, e_, "bind() for %s %s in process_raw_ifaces()" , ifd->id_rname, str_endpoint(&if_endpoint, &b)); } |
171 | ifd->id_rname, str_endpoint(&if_endpoint, &b)){ int e_ = (*__errno_location ()); log_error(logger, e_, "bind() for %s %s in process_raw_ifaces()" , ifd->id_rname, str_endpoint(&if_endpoint, &b)); }; |
172 | close(fd); |
173 | return -1; |
174 | } |
175 | |
176 | /* poke a hole for IKE messages in the IPsec layer */ |
177 | if (kernel_ops->exceptsocket != NULL((void*)0)) { |
178 | if (!kernel_ops->exceptsocket(fd, AF_INET2, logger)) { |
179 | close(fd); |
180 | return -1; |
181 | } |
182 | } |
183 | |
184 | return fd; |
185 | } |
186 | |
187 | static bool_Bool nat_traversal_espinudp(int sk, struct iface_dev *ifd, |
188 | struct logger *logger) |
189 | { |
190 | const char *fam = address_type(&ifd->id_address)->ip_name; |
191 | dbg("NAT-Traversal: Trying sockopt style NAT-T"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("NAT-Traversal: Trying sockopt style NAT-T"); } }; |
192 | |
193 | /* |
194 | * The SOL (aka socket level) is really the the protocol |
195 | * number which, for UDP, is always 17. Linux provides a |
196 | * SOL_* macro, the others don't. |
197 | */ |
198 | #if defined(SOL_UDP17) |
199 | const int sol_udp = SOL_UDP17; |
200 | #elif defined(IPPROTO_UDPIPPROTO_UDP) |
201 | const int sol_udp = IPPROTO_UDPIPPROTO_UDP; |
202 | #endif |
203 | |
204 | /* |
205 | * Was UDP_ESPINUDP (aka 100). Linux/NetBSD have the value |
206 | * 100, FreeBSD has the value 1. |
207 | */ |
208 | const int sol_name = UDP_ENCAP100; |
209 | |
210 | /* |
211 | * Was ESPINUDP_WITH_NON_ESP (aka 2) defined in "libreswan.h" |
212 | * which smells like something intended for the old KLIPS |
213 | * module. <netinet/udp.h> defines the below across linux and |
214 | * *BSD. |
215 | */ |
216 | const int sol_value = UDP_ENCAP_ESPINUDP2; |
217 | |
218 | int r = setsockopt(sk, sol_udp, sol_name, &sol_value, sizeof(sol_value)); |
219 | if (r == -1) { |
220 | dbg("NAT-Traversal: ESPINUDP(%d) setup failed for sockopt style NAT-T family %s (errno=%d)",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("NAT-Traversal: ESPINUDP(%d) setup failed for sockopt style NAT-T family %s (errno=%d)" , sol_value, fam, (*__errno_location ())); } } |
221 | sol_value, fam, errno){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("NAT-Traversal: ESPINUDP(%d) setup failed for sockopt style NAT-T family %s (errno=%d)" , sol_value, fam, (*__errno_location ())); } }; |
222 | /* all methods failed to detect NAT-T support */ |
223 | llog(RC_LOG_SERIOUS, logger, |
224 | "NAT-Traversal: ESPINUDP for this kernel not supported or not found for family %s; NAT-traversal is turned OFF", fam); |
225 | nat_traversal_enabled = false0; |
226 | return false0; |
227 | } |
228 | |
229 | dbg("NAT-Traversal: ESPINUDP(%d) setup succeeded for sockopt style NAT-T family %s",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("NAT-Traversal: ESPINUDP(%d) setup succeeded for sockopt style NAT-T family %s" , sol_value, fam); } } |
230 | sol_value, fam){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("NAT-Traversal: ESPINUDP(%d) setup succeeded for sockopt style NAT-T family %s" , sol_value, fam); } }; |
231 | return true1; |
232 | } |
233 | |
234 | #ifdef MSG_ERRQUEUEMSG_ERRQUEUE |
235 | static bool_Bool check_msg_errqueue(const struct iface_endpoint *ifp, |
236 | short interest, const char *func, |
237 | struct logger *logger); |
238 | #endif |
239 | |
240 | static enum iface_read_status udp_read_packet(struct iface_endpoint *ifp, |
241 | struct iface_packet *packet, |
242 | struct logger *logger) |
243 | { |
244 | #ifdef MSG_ERRQUEUEMSG_ERRQUEUE |
245 | /* |
246 | * Even though select(2) says that there is a message, it |
247 | * might only be a MSG_ERRQUEUE message. At least sometimes |
248 | * that leads to a hanging recvfrom. To avoid what appears to |
249 | * be a kernel bug, check_msg_errqueue uses poll(2) and tells |
250 | * us if there is anything for us to read. |
251 | * |
252 | * This is early enough that teardown isn't required: |
253 | * just return on failure. |
254 | */ |
255 | if (pluto_sock_errqueue) { |
256 | threadtime_t errqueue_start = threadtime_start(); |
257 | bool_Bool errqueue_ok = check_msg_errqueue(ifp, POLLIN0x001, __func__, |
258 | packet->logger); |
259 | threadtime_stop(&errqueue_start, SOS_NOBODY0, |
260 | "%s() calling check_incoming_msg_errqueue()", __func__); |
261 | if (!errqueue_ok) { |
262 | return IFACE_READ_IGNORE; /* no normal message to read */ |
263 | } |
264 | } |
265 | #endif |
266 | |
267 | /* |
268 | * COVERITY reports an overflow because FROM.LEN (aka |
269 | * sizeof(FROM.SA)) > sizeof(from.sa.sa). That's the point. |
270 | * The FROM.SA union is big enough to hold sockaddr, |
271 | * sockaddr_in and sockaddr_in6. |
272 | */ |
273 | ip_sockaddr from = { |
274 | .len = sizeof(from.sa), |
275 | }; |
276 | packet->len = recvfrom(ifp->fd, packet->ptr, packet->len, /*flags*/ 0, |
277 | &from.sa.sa, &from.len); |
278 | int packet_errno = errno(*__errno_location ()); /* save!!! */ |
279 | |
280 | /* |
281 | * Try to decode the from address. |
282 | * |
283 | * If that fails report some sense of error and then always |
284 | * give up. |
285 | */ |
286 | ip_address sender_udp_address; |
287 | ip_port sender_udp_port; |
288 | const char *from_ugh = sockaddr_to_address_port(from, &sender_udp_address, &sender_udp_port); |
289 | if (from_ugh != NULL((void*)0)) { |
290 | if (packet->len >= 0) { |
291 | /* technically it worked, but returned value was useless */ |
292 | llog(RC_LOG, packet->logger, |
293 | "recvfrom on %s returned malformed source sockaddr: %s", |
294 | ifp->ip_dev->id_rname, from_ugh); |
295 | } else if (from.len == sizeof(from) && |
296 | all_zero((const void *)&from, sizeof(from)) && |
297 | packet_errno == ECONNREFUSED111) { |
298 | /* |
299 | * Tone down scary message for vague event: We |
300 | * get "connection refused" in response to |
301 | * some datagram we sent, but we cannot tell |
302 | * which one. |
303 | */ |
304 | llog(RC_LOG, packet->logger, |
305 | "recvfrom on %s failed; some IKE message we sent has been rejected with ECONNREFUSED (kernel supplied no details)", |
306 | ifp->ip_dev->id_rname); |
307 | } else { |
308 | /* if from==0, this prints "unspecified", not "undisclosed", oops */ |
309 | llog_errno(RC_LOG, packet->logger, packet_errno, |
310 | "recvfrom on %s failed; cannot decode source sockaddr in rejection: %s"/*: */, |
311 | ifp->ip_dev->id_rname, from_ugh); |
312 | } |
313 | return IFACE_READ_IGNORE; |
314 | } |
315 | |
316 | packet->sender = endpoint_from_address_protocol_port(sender_udp_address, |
317 | &ip_protocol_udpip_protocols[IPPROTO_UDP], |
318 | sender_udp_port); |
319 | |
320 | |
321 | /* |
322 | * Managed to decode the from address; switch to a "from" |
323 | * logger so that it be used as log context prefix. |
324 | */ |
325 | struct logger from_logger = logger_from(logger, &packet->sender); |
326 | logger = &from_logger; |
327 | |
328 | if (packet->len < 0) { |
329 | llog_errno(RC_LOG, logger, packet_errno, |
330 | "recvfrom on %s failed"/*: */, ifp->ip_dev->id_rname); |
331 | return IFACE_READ_IGNORE; |
332 | } |
333 | |
334 | if (ifp->esp_encapsulation_enabled) { |
335 | uint32_t non_esp; |
336 | |
337 | if (packet->len < (int)sizeof(uint32_t)) { |
338 | llog(RC_LOG, logger, "too small packet (%zd)", |
339 | packet->len); |
340 | return IFACE_READ_IGNORE; |
341 | } |
342 | memcpy(&non_esp, packet->ptr, sizeof(uint32_t)); |
343 | if (non_esp != 0) { |
344 | llog(RC_LOG, logger, "has no Non-ESP marker"); |
345 | return IFACE_READ_IGNORE; |
346 | } |
347 | packet->ptr += sizeof(uint32_t); |
348 | packet->len -= sizeof(uint32_t); |
349 | } |
350 | |
351 | /* We think that in 2013 Feb, Apple iOS Racoon |
352 | * sometimes generates an extra useless buggy confusing |
353 | * Non ESP Marker |
354 | */ |
355 | { |
356 | static const uint8_t non_ESP_marker[NON_ESP_MARKER_SIZE4] = |
357 | { 0x00, }; |
358 | if (ifp->esp_encapsulation_enabled && |
359 | packet->len >= NON_ESP_MARKER_SIZE4 && |
360 | memeq(packet->ptr, non_ESP_marker,(memcmp((packet->ptr), (non_ESP_marker), (4)) == 0) |
361 | NON_ESP_MARKER_SIZE)(memcmp((packet->ptr), (non_ESP_marker), (4)) == 0)) { |
362 | llog(RC_LOG, logger, |
363 | "mangled with potential spurious non-esp marker"); |
364 | return IFACE_READ_IGNORE; |
365 | } |
366 | } |
367 | |
368 | if (packet->len == 1 && packet->ptr[0] == 0xff) { |
369 | /** |
370 | * NAT-T Keep-alive packets should be discarded by kernel ESPinUDP |
371 | * layer. But bogus keep-alive packets (sent with a non-esp marker) |
372 | * can reach this point. Complain and discard them. |
373 | * Possibly too if the NAT mapping vanished on the initiator NAT gw ? |
374 | */ |
375 | endpoint_buf eb; |
376 | dbg("NAT-T keep-alive (bogus ?) should not reach this point. Ignored. Sender: %s",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("NAT-T keep-alive (bogus ?) should not reach this point. Ignored. Sender: %s" , str_endpoint(&packet->sender, &eb)); } } |
377 | str_endpoint(&packet->sender, &eb)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("NAT-T keep-alive (bogus ?) should not reach this point. Ignored. Sender: %s" , str_endpoint(&packet->sender, &eb)); } }; /* sensitive? */ |
378 | return IFACE_READ_IGNORE; |
379 | } |
380 | |
381 | return IFACE_READ_OK; |
382 | } |
383 | |
384 | static ssize_t udp_write_packet(const struct iface_endpoint *ifp, |
385 | const void *ptr, size_t len, |
386 | const ip_endpoint *remote_endpoint, |
387 | struct logger *logger /*possibly*/UNUSED__attribute__ ((unused))) |
388 | { |
389 | #ifdef MSG_ERRQUEUEMSG_ERRQUEUE |
390 | if (pluto_sock_errqueue) { |
391 | check_msg_errqueue(ifp, POLLOUT0x004, __func__, logger); |
392 | } |
393 | #endif |
394 | |
395 | ip_sockaddr remote_sa = sockaddr_from_endpoint(*remote_endpoint); |
396 | return sendto(ifp->fd, ptr, len, 0, &remote_sa.sa.sa, remote_sa.len); |
397 | }; |
398 | |
399 | static void udp_listen(struct iface_endpoint *ifp, |
400 | struct logger *unused_logger UNUSED__attribute__ ((unused))) |
401 | { |
402 | if (ifp->udp_message_listener == NULL((void*)0)) { |
403 | attach_fd_read_sensor(&ifp->udp_message_listener, ifp->fd, |
404 | process_iface_packet, ifp); |
405 | } |
406 | } |
407 | |
408 | static int udp_bind_iface_endpoint(struct iface_dev *ifd, ip_port port, |
409 | bool_Bool esp_encapsulation_enabled, |
410 | struct logger *logger) |
411 | { |
412 | int fd = bind_udp_socket(ifd, port, logger); |
413 | if (fd < 0) { |
414 | return -1; |
415 | } |
416 | if (esp_encapsulation_enabled && |
417 | !nat_traversal_espinudp(fd, ifd, logger)) { |
418 | dbg("nat-traversal failed"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("nat-traversal failed"); } }; |
419 | } |
420 | return fd; |
421 | } |
422 | |
423 | static void udp_cleanup(struct iface_endpoint *ifp) |
424 | { |
425 | event_free(ifp->udp_message_listener); |
426 | ifp->udp_message_listener = NULL((void*)0); |
427 | } |
428 | |
429 | const struct iface_io udp_iface_io = { |
430 | .send_keepalive = true1, |
431 | .protocol = &ip_protocol_udpip_protocols[IPPROTO_UDP], |
432 | .read_packet = udp_read_packet, |
433 | .write_packet = udp_write_packet, |
434 | .listen = udp_listen, |
435 | .bind_iface_endpoint = udp_bind_iface_endpoint, |
436 | .cleanup = udp_cleanup, |
437 | }; |
438 | |
439 | #ifdef MSG_ERRQUEUEMSG_ERRQUEUE |
440 | |
441 | /* Process any message on the MSG_ERRQUEUE |
442 | * |
443 | * This information is generated because of the IP_RECVERR socket option. |
444 | * The API is sparsely documented, and may be LINUX-only, and only on |
445 | * fairly recent versions at that (hence the conditional compilation). |
446 | * |
447 | * - ip(7) describes IP_RECVERR |
448 | * - recvmsg(2) describes MSG_ERRQUEUE |
449 | * - readv(2) describes iovec |
450 | * - cmsg(3) describes how to process auxiliary messages |
451 | * |
452 | * ??? we should link this message with one we've sent |
453 | * so that the diagnostic can refer to that negotiation. |
454 | * |
455 | * ??? how long can the message be? |
456 | * |
457 | * ??? poll(2) has a very incomplete description of the POLL* events. |
458 | * We assume that POLLIN, POLLOUT, and POLLERR are all we need to deal with |
459 | * and that POLLERR will be on iff there is a MSG_ERRQUEUE message. |
460 | * |
461 | * We have to code around a couple of surprises: |
462 | * |
463 | * - Select can say that a socket is ready to read from, and |
464 | * yet a read will hang. It turns out that a message available on the |
465 | * MSG_ERRQUEUE will cause select to say something is pending, but |
466 | * a normal read will hang. poll(2) can tell when a MSG_ERRQUEUE |
467 | * message is pending. |
468 | * |
469 | * This is dealt with by calling check_msg_errqueue after select has |
470 | * indicated that there is something to read, but before the read is |
471 | * performed. check_msg_errqueue will return "true" if there is |
472 | * something left to read. |
473 | * |
474 | * - A write to a socket may fail because there is a pending MSG_ERRQUEUE |
475 | * message, without there being anything wrong with the write. This |
476 | * makes for confusing diagnostics. |
477 | * |
478 | * To avoid this, we call check_msg_errqueue before a write. True, |
479 | * there is a race condition (a MSG_ERRQUEUE message might arrive |
480 | * between the check and the write), but we should eliminate many |
481 | * of the problematic events. To narrow the window, the poll(2) |
482 | * will await until an event happens (in the case or a write, |
483 | * POLLOUT; this should be benign for POLLIN). |
484 | */ |
485 | |
486 | static struct state *find_likely_sender(size_t packet_len, uint8_t *buffer, |
487 | size_t sizeof_buffer) |
488 | { |
489 | if (packet_len > sizeof_buffer) { |
490 | /* |
491 | * When the message is too big it is truncated. But |
492 | * what about the returned packet length? Force |
493 | * truncation. |
494 | */ |
495 | dbg("MSG_ERRQUEUE packet longer than %zu bytes; truncated", sizeof_buffer){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("MSG_ERRQUEUE packet longer than %zu bytes; truncated" , sizeof_buffer); } }; |
496 | packet_len = sizeof_buffer; |
497 | } |
498 | |
499 | static const uint8_t non_ESP_marker[NON_ESP_MARKER_SIZE4] = { 0x00, }; |
500 | if (packet_len >= sizeof(non_ESP_marker) && |
501 | memeq(buffer, non_ESP_marker, sizeof(non_ESP_marker))(memcmp((buffer), (non_ESP_marker), (sizeof(non_ESP_marker))) == 0)) { |
502 | buffer += sizeof(non_ESP_marker); |
503 | packet_len -= sizeof(non_ESP_marker); |
504 | sizeof_buffer -= sizeof(non_ESP_marker); |
Value stored to 'sizeof_buffer' is never read | |
505 | dbg("MSG_ERRQUEUE packet has leading ESP:0 marker - discarded"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("MSG_ERRQUEUE packet has leading ESP:0 marker - discarded" ); } }; |
506 | } |
507 | |
508 | if (packet_len < sizeof(struct isakmp_hdr)) { |
509 | dbg("MSG_ERRQUEUE packet is smaller than an IKE header"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("MSG_ERRQUEUE packet is smaller than an IKE header" ); } }; |
510 | return NULL((void*)0); |
511 | } |
512 | |
513 | struct pbs_inpacket_byte_stream packet_pbs; |
514 | init_pbs(&packet_pbs, buffer, packet_len, __func__); |
515 | struct isakmp_hdr hdr; |
516 | diag_t d = pbs_in_struct(&packet_pbs, &raw_isakmp_hdr_desc, |
517 | &hdr, sizeof(hdr), NULL((void*)0)); |
518 | if (d != NULL((void*)0)) { |
519 | /* |
520 | * XXX: Only thing interesting is that there was an |
521 | * error, toss the message. |
522 | */ |
523 | pfree_diag(&d); |
524 | return NULL((void*)0); |
525 | } |
526 | |
527 | enum ike_version ike_version = hdr_ike_version(&hdr); |
528 | struct state *st; |
529 | switch (ike_version) { |
530 | case IKEv1: |
531 | /* might work? */ |
532 | st = state_by_ike_spis(ike_version, |
533 | NULL((void*)0)/*ignore-clonedfrom*/, |
534 | NULL((void*)0)/*ignore-v1_msgid*/, |
535 | NULL((void*)0)/*ignore-role*/, |
536 | &hdr.isa_ike_spis, |
537 | NULL((void*)0), NULL((void*)0), |
538 | __func__); |
539 | break; |
540 | case IKEv2: |
541 | { |
542 | /* |
543 | * Since this end sent the message mapping IKE_I is |
544 | * straight forward. |
545 | */ |
546 | enum sa_role ike_role = (hdr.isa_flags & ISAKMP_FLAGS_v2_IKE_I(1<<ISAKMP_FLAGS_v2_IKE_I_IX)) ? SA_INITIATOR : SA_RESPONDER; |
547 | so_serial_t clonedfrom = SOS_NOBODY0; |
548 | st = state_by_ike_spis(ike_version, |
549 | &clonedfrom/*IKE*/, |
550 | NULL((void*)0)/*ignore-v1_msgid*/, |
551 | &ike_role, |
552 | &hdr.isa_ike_spis, |
553 | NULL((void*)0), NULL((void*)0), |
554 | __func__); |
555 | break; |
556 | } |
557 | default: |
558 | dbg("MSG_ERRQUEUE packet IKE header version unknown"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("MSG_ERRQUEUE packet IKE header version unknown" ); } }; |
559 | return NULL((void*)0); |
560 | } |
561 | if (st == NULL((void*)0)) { |
562 | dbg("MSG_ERRQUEUE packet has no matching %s SA",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("MSG_ERRQUEUE packet has no matching %s SA", enum_name (&ike_version_names, ike_version)); } } |
563 | enum_name(&ike_version_names, ike_version)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("MSG_ERRQUEUE packet has no matching %s SA", enum_name (&ike_version_names, ike_version)); } }; |
564 | return NULL((void*)0); |
565 | } |
566 | |
567 | dbg("MSG_ERRQUEUE packet matches %s SA #%lu",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("MSG_ERRQUEUE packet matches %s SA #%lu", enum_name (&ike_version_names, ike_version), st->st_serialno); } } |
568 | enum_name(&ike_version_names, ike_version),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("MSG_ERRQUEUE packet matches %s SA #%lu", enum_name (&ike_version_names, ike_version), st->st_serialno); } } |
569 | st->st_serialno){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("MSG_ERRQUEUE packet matches %s SA #%lu", enum_name (&ike_version_names, ike_version), st->st_serialno); } }; |
570 | return st; |
571 | } |
572 | |
573 | static bool_Bool check_msg_errqueue(const struct iface_endpoint *ifp, short interest, |
574 | const char *before, |
575 | struct logger *logger) |
576 | { |
577 | struct pollfd pfd; |
578 | int again_count = 0; |
579 | |
580 | pfd.fd = ifp->fd; |
581 | pfd.events = interest | POLLPRI0x002 | POLLOUT0x004; |
582 | |
583 | while (/*clear .revents*/ pfd.revents = 0, |
584 | /*poll .revents*/ poll(&pfd, 1, -1) > 0 && |
585 | /*test .revents*/ (pfd.revents & POLLERR0x008)) { |
586 | |
587 | /* |
588 | * A single IOV (I/O Vector) pointing at a buffer for |
589 | * storing the message fragment. |
590 | * |
591 | * It needs to be large enough to fit the IKE header + |
592 | * leading ESP:0 prefix so that the IKE SPIs and flags |
593 | * can be extracted and used to find the sender of the |
594 | * message. |
595 | * |
596 | * Give it double that. |
597 | */ |
598 | uint8_t buffer[sizeof(struct isakmp_hdr) * 2]; |
599 | struct iovec eiov[1] = { |
600 | { |
601 | .iov_base = buffer, /* see readv(2) */ |
602 | .iov_len = sizeof(buffer), |
603 | }, |
604 | }; |
605 | |
606 | union { |
607 | /* force alignment (not documented as necessary) */ |
608 | struct cmsghdr ecms; |
609 | |
610 | /* how much space is enough? */ |
611 | unsigned char space[256]; |
612 | } ecms_buf; |
613 | |
614 | ip_sockaddr from = { 0, }; |
615 | struct msghdr emh = { |
616 | .msg_name = &from.sa, /* ??? filled in? */ |
617 | .msg_namelen = sizeof(from.sa), |
618 | .msg_iov = eiov, |
619 | .msg_iovlen = elemsof(eiov)(sizeof(eiov) / sizeof(*(eiov))), |
620 | .msg_control = &ecms_buf, |
621 | .msg_controllen = sizeof(ecms_buf), |
622 | .msg_flags = 0, |
623 | }; |
624 | |
625 | ssize_t packet_len = recvmsg(ifp->fd, &emh, MSG_ERRQUEUEMSG_ERRQUEUE); |
626 | |
627 | if (packet_len == -1) { |
628 | /* XXX: all paths either break. return, or continue */ |
629 | if (errno(*__errno_location ()) == EAGAIN11) { |
630 | /* 32 is picked from thin air */ |
631 | if (again_count == 32) { |
632 | llog(RC_LOG_SERIOUS, logger, |
633 | "recvmsg(,, MSG_ERRQUEUE): given up reading socket after 32 EAGAIN errors"); |
634 | return false0; |
635 | } |
636 | again_count++; |
637 | log_errno(logger, errno,{ int e_ = (*__errno_location ()); log_error(logger, e_, "recvmsg(,, MSG_ERRQUEUE) on %s failed (noticed before %s) (attempt %d)" , ifp->ip_dev->id_rname, before, again_count); } |
638 | "recvmsg(,, MSG_ERRQUEUE) on %s failed (noticed before %s) (attempt %d)",{ int e_ = (*__errno_location ()); log_error(logger, e_, "recvmsg(,, MSG_ERRQUEUE) on %s failed (noticed before %s) (attempt %d)" , ifp->ip_dev->id_rname, before, again_count); } |
639 | ifp->ip_dev->id_rname, before, again_count){ int e_ = (*__errno_location ()); log_error(logger, e_, "recvmsg(,, MSG_ERRQUEUE) on %s failed (noticed before %s) (attempt %d)" , ifp->ip_dev->id_rname, before, again_count); }; |
640 | continue; |
641 | } |
642 | log_errno(logger, errno,{ int e_ = (*__errno_location ()); log_error(logger, e_, "recvmsg(,, MSG_ERRQUEUE) on %s failed (noticed before %s)" , ifp->ip_dev->id_rname, before); } |
643 | "recvmsg(,, MSG_ERRQUEUE) on %s failed (noticed before %s)",{ int e_ = (*__errno_location ()); log_error(logger, e_, "recvmsg(,, MSG_ERRQUEUE) on %s failed (noticed before %s)" , ifp->ip_dev->id_rname, before); } |
644 | ifp->ip_dev->id_rname, before){ int e_ = (*__errno_location ()); log_error(logger, e_, "recvmsg(,, MSG_ERRQUEUE) on %s failed (noticed before %s)" , ifp->ip_dev->id_rname, before); }; |
645 | break; |
646 | } |
647 | passert(packet_len >= 0)({ _Bool assertion__ = packet_len >= 0; if (!assertion__) { where_t here = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/iface_udp.c", .line = 647, }; &here; }); const struct logger *logger_ = &failsafe_logger ; llog_passert(logger_, here, "%s", "packet_len >= 0"); } ( void) 1; }); |
648 | |
649 | /* |
650 | * Getting back a truncated IKE datagram isn't a big |
651 | * deal - find_likely_sender() only needs the header |
652 | * when figuring out which state sent the packet. |
653 | */ |
654 | if (DBGP(DBG_BASE)(cur_debugging & (((lset_t)1 << (DBG_BASE_IX)))) && (emh.msg_flags & MSG_TRUNCMSG_TRUNC)) { |
655 | DBG_log("recvmsg(,, MSG_ERRQUEUE) on %s returned a truncated (IKE) datagram (MSG_TRUNC)", |
656 | ifp->ip_dev->id_rname); |
657 | } |
658 | |
659 | if (DBGP(DBG_BASE)(cur_debugging & (((lset_t)1 << (DBG_BASE_IX))))) { |
660 | if (packet_len > 0) { |
661 | DBG_log("rejected packet:"); |
662 | DBG_dump(NULL((void*)0), buffer, packet_len); |
663 | } |
664 | DBG_log("control:"); |
665 | DBG_dump(NULL((void*)0), emh.msg_control, |
666 | emh.msg_controllen); |
667 | } |
668 | |
669 | struct state *sender = find_likely_sender((size_t) packet_len, |
670 | buffer, sizeof(buffer)); |
671 | |
672 | /* ??? Andi Kleen <ak@suse.de> and misc documentation |
673 | * suggests that name will have the original destination |
674 | * of the packet. We seem to see msg_namelen == 0. |
675 | * Andi says that this is a kernel bug and has fixed it. |
676 | * Perhaps in 2.2.18/2.4.0. |
677 | */ |
678 | passert(emh.msg_name == &from.sa)({ _Bool assertion__ = emh.msg_name == &from.sa; if (!assertion__ ) { where_t here = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/iface_udp.c", .line = 678 , }; &here; }); const struct logger *logger_ = &failsafe_logger ; llog_passert(logger_, here, "%s", "emh.msg_name == &from.sa" ); } (void) 1; }); |
679 | if (DBGP(DBG_BASE)(cur_debugging & (((lset_t)1 << (DBG_BASE_IX))))) { |
680 | DBG_log("name:"); |
681 | DBG_dump(NULL((void*)0), emh.msg_name, emh.msg_namelen); |
682 | } |
683 | |
684 | const struct ip_info *afi = aftoinfo(from.sa.sa.sa_family); |
685 | /* usual case :-( */ |
686 | char fromstr[sizeof(" for message to ?") + sizeof(endpoint_buf)] = ""; |
687 | if (afi != NULL((void*)0) && emh.msg_namelen == afi->sockaddr_size) { |
688 | ip_address sender_udp_address; |
689 | ip_port sender_udp_port; |
690 | if (sockaddr_to_address_port(from, &sender_udp_address, &sender_udp_port) == NULL((void*)0)) { |
691 | /* this is a udp socket so presumably the endpoint is udp */ |
692 | endpoint_buf ab; |
693 | ip_endpoint endpoint = endpoint_from_address_protocol_port(sender_udp_address, |
694 | &ip_protocol_udpip_protocols[IPPROTO_UDP], |
695 | sender_udp_port); |
696 | snprintf(fromstr, sizeof(fromstr), |
697 | " for message to %s", |
698 | str_endpoint_sensitive(&endpoint, &ab)); |
699 | } |
700 | } |
701 | |
702 | for (struct cmsghdr *cm = CMSG_FIRSTHDR(&emh)((size_t) (&emh)->msg_controllen >= sizeof (struct cmsghdr ) ? (struct cmsghdr *) (&emh)->msg_control : (struct cmsghdr *) 0); cm != NULL((void*)0); cm = CMSG_NXTHDR(&emh, cm)__cmsg_nxthdr (&emh, cm)) { |
703 | if (cm->cmsg_level == SOL_IP0 && |
704 | cm->cmsg_type == IP_RECVERR11) { |
705 | /* ip(7) and recvmsg(2) specify: |
706 | * ee_origin is SO_EE_ORIGIN_ICMP for ICMP |
707 | * or SO_EE_ORIGIN_LOCAL for locally generated errors. |
708 | * ee_type and ee_code are from the ICMP header. |
709 | * ee_info is the discovered MTU for EMSGSIZE errors |
710 | * ee_data is not used. |
711 | * |
712 | * ??? recvmsg(2) says "SOCK_EE_OFFENDER" but |
713 | * means "SO_EE_OFFENDER". The OFFENDER is really |
714 | * the router that complained. As such, the port |
715 | * is meaningless. |
716 | */ |
717 | |
718 | /* ??? cmsg(3) claims that CMSG_DATA returns |
719 | * void *, but RFC 2292 and /usr/include/bits/socket.h |
720 | * say unsigned char *. The manual is being fixed. |
721 | */ |
722 | struct sock_extended_err *ee = |
723 | (void *)CMSG_DATA(cm)((cm)->__cmsg_data); |
724 | const char *offstr = "unspecified"; |
725 | char offstrspace[INET6_ADDRSTRLEN46]; |
726 | char orname[50]; |
727 | |
728 | if (cm->cmsg_len > |
729 | CMSG_LEN(sizeof(struct sock_extended_err))((((sizeof (struct cmsghdr)) + sizeof (size_t) - 1) & (size_t ) ~(sizeof (size_t) - 1)) + (sizeof(struct sock_extended_err) ))) |
730 | { |
731 | const struct sockaddr *offender = |
732 | SO_EE_OFFENDER(ee)((struct sockaddr*)((ee)+1)); |
733 | |
734 | switch (offender->sa_family) { |
735 | case AF_INET2: |
736 | offstr = inet_ntop( |
737 | offender->sa_family, |
738 | &((const |
739 | struct sockaddr_in *) |
740 | offender)->sin_addr, |
741 | offstrspace, |
742 | sizeof(offstrspace)); |
743 | break; |
744 | case AF_INET610: |
745 | offstr = inet_ntop( |
746 | offender->sa_family, |
747 | &((const |
748 | struct sockaddr_in6 |
749 | *)offender)->sin6_addr, |
750 | offstrspace, |
751 | sizeof(offstrspace)); |
752 | break; |
753 | default: |
754 | offstr = "unknown"; |
755 | break; |
756 | } |
757 | } |
758 | |
759 | switch (ee->ee_origin) { |
760 | case SO_EE_ORIGIN_NONE0: |
761 | snprintf(orname, sizeof(orname), |
762 | "none"); |
763 | break; |
764 | case SO_EE_ORIGIN_LOCAL1: |
765 | snprintf(orname, sizeof(orname), |
766 | "local"); |
767 | break; |
768 | case SO_EE_ORIGIN_ICMP2: |
769 | snprintf(orname, sizeof(orname), |
770 | "ICMP type %d code %d (not authenticated)", |
771 | ee->ee_type, ee->ee_code); |
772 | break; |
773 | case SO_EE_ORIGIN_ICMP63: |
774 | snprintf(orname, sizeof(orname), |
775 | "ICMP6 type %d code %d (not authenticated)", |
776 | ee->ee_type, ee->ee_code); |
777 | break; |
778 | default: |
779 | snprintf(orname, sizeof(orname), |
780 | "invalid origin %u", |
781 | ee->ee_origin); |
782 | break; |
783 | } |
784 | |
785 | enum stream log_to; |
786 | if (packet_len == 1 && buffer[0] == 0xff && |
787 | (cur_debugging & DBG_BASE((lset_t)1 << (DBG_BASE_IX))) == 0) { |
788 | /* |
789 | * don't log NAT-T keepalive related errors unless NATT debug is |
790 | * enabled |
791 | */ |
792 | log_to = NO_STREAM; |
793 | } else if (sender != NULL((void*)0) && sender->st_connection != NULL((void*)0) && |
794 | LDISJOINT(sender->st_connection->policy, POLICY_OPPORTUNISTIC)(((sender->st_connection->policy) & (((lset_t)1 << (POLICY_OPPORTUNISTIC_IX)))) == ((lset_t)0))) { |
795 | /* |
796 | * The sender is known and |
797 | * this isn't an opportunistic |
798 | * connection, so log. |
799 | * |
800 | * XXX: originally this path |
801 | * was taken unconditionally |
802 | * but with opportunistic that |
803 | * got too verbose. Is there |
804 | * a global opportunistic |
805 | * disabled test so that |
806 | * behaviour can be restored? |
807 | * |
808 | * HACK: So that the logging |
809 | * system doesn't accidentally |
810 | * include a prefix for the |
811 | * wrong state et.al., switch |
812 | * out everything but SENDER. |
813 | * Better would be to make the |
814 | * state/connection an |
815 | * explicit parameter to the |
816 | * logging system? |
817 | */ |
818 | log_to = ALL_STREAMS; |
819 | } else if (DBGP(DBG_BASE)(cur_debugging & (((lset_t)1 << (DBG_BASE_IX))))) { |
820 | /* |
821 | * Since this output is forced |
822 | * using DBGP, report the |
823 | * error using debug-log. |
824 | * |
825 | * A NULL SENDER here doesn't |
826 | * matter - it just gets |
827 | * ignored. |
828 | */ |
829 | log_to = DEBUG_STREAM; |
830 | } else { |
831 | log_to = NO_STREAM; |
832 | } |
833 | if (log_to != NO_STREAM) { |
834 | endpoint_buf epb; |
835 | llog(log_to, (sender != NULL((void*)0) ? sender->st_logger : logger), |
836 | "ERROR: asynchronous network error report on %s (%s)%s, complainant %s: %s [errno %" PRIu32"u" ", origin %s]", |
837 | ifp->ip_dev->id_rname, |
838 | str_endpoint(&ifp->local_endpoint, &epb), |
839 | fromstr, |
840 | offstr, |
841 | strerror(ee->ee_errno), |
842 | ee->ee_errno, orname); |
843 | } |
844 | } else if (cm->cmsg_level == SOL_IP0 && |
845 | cm->cmsg_type == IP_PKTINFO8) { |
846 | /* do nothing */ |
847 | } else { |
848 | /* .cmsg_len is a kernel_size_t(!), |
849 | * but the value certainly ought to |
850 | * fit in a size_t. |
851 | */ |
852 | llog(RC_LOG, logger, |
853 | "unknown cmsg: level %d, type %d, len %zu", |
854 | cm->cmsg_level, cm->cmsg_type, |
855 | cm->cmsg_len); |
856 | } |
857 | } |
858 | } |
859 | return (pfd.revents & interest) != 0; |
860 | } |
861 | |
862 | #endif /* MSG_ERRQUEUE */ |