1 /* $OpenBSD: udp_encap.c,v 1.24 2022/01/16 14:30:11 naddy Exp $ */
2
3 /*
4 * Copyright (c) 1998, 1999, 2001 Niklas Hallqvist. All rights reserved.
5 * Copyright (c) 2000 Angelos D. Keromytis. All rights reserved.
6 * Copyright (c) 2004 H�kan Olsson. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <sys/types.h>
30 #include <sys/ioctl.h>
31 #include <sys/socket.h>
32 #include <sys/sockio.h>
33 #include <net/if.h>
34 #include <netinet/in.h>
35 #include <arpa/inet.h>
36 #include <ctype.h>
37 #include <limits.h>
38 #include <netdb.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <unistd.h>
42
43 #include "conf.h"
44 #include "if.h"
45 #include "ipsec_doi.h"
46 #include "isakmp.h"
47 #include "log.h"
48 #include "message.h"
49 #include "monitor.h"
50 #include "transport.h"
51 #include "udp.h"
52 #include "udp_encap.h"
53 #include "util.h"
54 #include "virtual.h"
55
56 #define UDP_SIZE 65536
57
58 /* If a system doesn't have SO_REUSEPORT, SO_REUSEADDR will have to do. */
59 #ifndef SO_REUSEPORT
60 #define SO_REUSEPORT SO_REUSEADDR
61 #endif
62
63 /* Reused, from udp.c */
64 struct transport *udp_clone(struct transport *, struct sockaddr *);
65 int udp_fd_set(struct transport *, fd_set *, int);
66 int udp_fd_isset(struct transport *, fd_set *);
67 void udp_get_dst(struct transport *, struct sockaddr **);
68 void udp_get_src(struct transport *, struct sockaddr **);
69 char *udp_decode_ids(struct transport *);
70 void udp_remove(struct transport *);
71
72 static struct transport *udp_encap_create(char *);
73 static void udp_encap_report(struct transport *);
74 static void udp_encap_handle_message(struct transport *);
75 static struct transport *udp_encap_make(struct sockaddr *);
76 static int udp_encap_send_message(struct message *,
77 struct transport *);
78
79 static struct transport_vtbl udp_encap_transport_vtbl = {
80 { 0 }, "udp_encap",
81 udp_encap_create,
82 0,
83 udp_remove,
84 udp_encap_report,
85 udp_fd_set,
86 udp_fd_isset,
87 udp_encap_handle_message,
88 udp_encap_send_message,
89 udp_get_dst,
90 udp_get_src,
91 udp_decode_ids,
92 udp_clone,
93 0
94 };
95
96 char *udp_encap_default_port = 0;
97
98 void
udp_encap_init(void)99 udp_encap_init(void)
100 {
101 transport_method_add(&udp_encap_transport_vtbl);
102 }
103
104 /* Create a UDP transport structure bound to LADDR just for listening. */
105 static struct transport *
udp_encap_make(struct sockaddr * laddr)106 udp_encap_make(struct sockaddr *laddr)
107 {
108 struct udp_transport *t = 0;
109 int s, on, wildcardaddress = 0;
110 char *tstr;
111
112 t = calloc(1, sizeof *t);
113 if (!t) {
114 log_print("udp_encap_make: malloc(%lu) failed",
115 (unsigned long)sizeof *t);
116 free(laddr);
117 return 0;
118 }
119 t->src = laddr;
120
121 s = socket(laddr->sa_family, SOCK_DGRAM, IPPROTO_UDP);
122 if (s == -1) {
123 log_error("udp_encap_make: socket (%d, %d, %d)",
124 laddr->sa_family, SOCK_DGRAM, IPPROTO_UDP);
125 goto err;
126 }
127
128 /* Make sure we don't get our traffic encrypted. */
129 if (sysdep_cleartext(s, laddr->sa_family) == -1)
130 goto err;
131
132 /* Wildcard address ? */
133 switch (laddr->sa_family) {
134 case AF_INET:
135 if (((struct sockaddr_in *)laddr)->sin_addr.s_addr
136 == INADDR_ANY)
137 wildcardaddress = 1;
138 break;
139 case AF_INET6:
140 if (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)laddr)->sin6_addr))
141 wildcardaddress = 1;
142 break;
143 }
144
145 /*
146 * In order to have several bound specific address-port combinations
147 * with the same port SO_REUSEADDR is needed.
148 * If this is a wildcard socket and we are not listening there, but
149 * only sending from it make sure it is entirely reuseable with
150 * SO_REUSEPORT.
151 */
152 on = 1;
153 if (setsockopt(s, SOL_SOCKET,
154 wildcardaddress ? SO_REUSEPORT : SO_REUSEADDR,
155 (void *)&on, sizeof on) == -1) {
156 log_error("udp_encap_make: setsockopt (%d, %d, %d, %p, %lu)",
157 s, SOL_SOCKET,
158 wildcardaddress ? SO_REUSEPORT : SO_REUSEADDR, &on,
159 (unsigned long)sizeof on);
160 goto err;
161 }
162
163 t->transport.vtbl = &udp_encap_transport_vtbl;
164 if (monitor_bind(s, t->src, SA_LEN(t->src))) {
165 if (sockaddr2text(t->src, &tstr, 0))
166 log_error("udp_encap_make: bind (%d, %p, %lu)", s,
167 &t->src, (unsigned long)sizeof t->src);
168 else {
169 log_error("udp_encap_make: bind (%d, %s, %lu)", s,
170 tstr, (unsigned long)sizeof t->src);
171 free(tstr);
172 }
173 goto err;
174 }
175
176 t->s = s;
177 if (sockaddr2text(t->src, &tstr, 0))
178 LOG_DBG((LOG_MISC, 20, "udp_encap_make: "
179 "transport %p socket %d family %d", t, s,
180 t->src->sa_family == AF_INET ? 4 : 6));
181 else {
182 LOG_DBG((LOG_MISC, 20, "udp_encap_make: "
183 "transport %p socket %d ip %s port %d", t, s,
184 tstr, ntohs(sockaddr_port(t->src))));
185 free(tstr);
186 }
187 transport_setup(&t->transport, 0);
188 t->transport.flags |= TRANSPORT_LISTEN;
189 return &t->transport;
190
191 err:
192 if (s >= 0)
193 close (s);
194 if (t) {
195 /* Already closed. */
196 t->s = -1;
197 udp_remove(&t->transport);
198 }
199 return 0;
200 }
201
202 /*
203 * Initialize an object of the UDP transport class. Fill in the local
204 * IP address and port information and create a server socket bound to
205 * that specific port. Add the polymorphic transport structure to the
206 * system-wide pools of known ISAKMP transports.
207 */
208 struct transport *
udp_encap_bind(const struct sockaddr * addr)209 udp_encap_bind(const struct sockaddr *addr)
210 {
211 struct sockaddr *src;
212
213 src = malloc(SA_LEN(addr));
214 if (!src)
215 return 0;
216
217 memcpy(src, addr, SA_LEN(addr));
218 return udp_encap_make(src);
219 }
220
221 /*
222 * NAME is a section name found in the config database. Setup and return
223 * a transport useable to talk to the peer specified by that name.
224 */
225 static struct transport *
udp_encap_create(char * name)226 udp_encap_create(char *name)
227 {
228 struct virtual_transport *v;
229 struct udp_transport *u;
230 struct transport *rv;
231 struct sockaddr *dst, *addr;
232 struct conf_list *addr_list = 0;
233 struct conf_list_node *addr_node;
234 char *addr_str, *port_str;
235
236 port_str = conf_get_str(name, "Port"); /* XXX "Encap-port" ? */
237 if (!port_str)
238 port_str = udp_encap_default_port;
239 if (!port_str)
240 port_str = UDP_ENCAP_DEFAULT_PORT_STR;
241
242 addr_str = conf_get_str(name, "Address");
243 if (!addr_str) {
244 log_print("udp_encap_create: no address configured "
245 "for \"%s\"", name);
246 return 0;
247 }
248 if (text2sockaddr(addr_str, port_str, &dst, 0, 0)) {
249 log_print("udp_encap_create: address \"%s\" not understood",
250 addr_str);
251 return 0;
252 }
253
254 addr_str = conf_get_str(name, "Local-address");
255 if (!addr_str)
256 addr_list = conf_get_list("General", "Listen-on");
257 if (!addr_str && !addr_list) {
258 v = virtual_get_default(dst->sa_family);
259 u = (struct udp_transport *)v->encap;
260
261 if (!u) {
262 log_print("udp_encap_create: no default transport");
263 rv = 0;
264 goto ret;
265 } else {
266 rv = udp_clone((struct transport *)u, dst);
267 if (rv)
268 rv->vtbl = &udp_encap_transport_vtbl;
269 goto ret;
270 }
271 }
272
273 if (addr_list) {
274 for (addr_node = TAILQ_FIRST(&addr_list->fields);
275 addr_node; addr_node = TAILQ_NEXT(addr_node, link))
276 if (text2sockaddr(addr_node->field, port_str,
277 &addr, 0, 0) == 0) {
278 v = virtual_listen_lookup(addr);
279 free(addr);
280 if (v) {
281 addr_str = addr_node->field;
282 break;
283 }
284 }
285 if (!addr_str) {
286 log_print("udp_encap_create: "
287 "no matching listener found");
288 rv = 0;
289 goto ret;
290 }
291 }
292 if (text2sockaddr(addr_str, port_str, &addr, 0, 0)) {
293 log_print("udp_encap_create: "
294 "address \"%s\" not understood", addr_str);
295 rv = 0;
296 goto ret;
297 }
298 v = virtual_listen_lookup(addr);
299 free(addr);
300 if (!v) {
301 log_print("udp_encap_create: "
302 "%s:%s must exist as a listener too", addr_str, port_str);
303 rv = 0;
304 goto ret;
305 }
306 rv = udp_clone(v->encap, dst);
307 if (rv)
308 rv->vtbl = &udp_encap_transport_vtbl;
309
310 ret:
311 if (addr_list)
312 conf_free_list(addr_list);
313 free(dst);
314 return rv;
315 }
316
317 /* Report transport-method specifics of the T transport. */
318 void
udp_encap_report(struct transport * t)319 udp_encap_report(struct transport *t)
320 {
321 struct udp_transport *u = (struct udp_transport *)t;
322 char *src = NULL, *dst = NULL;
323 in_port_t sport, dport;
324
325 if (sockaddr2text(u->src, &src, 0))
326 return;
327 sport = sockaddr_port(u->src);
328
329 if (!u->dst || sockaddr2text(u->dst, &dst, 0))
330 dst = 0;
331 dport = dst ? sockaddr_port(u->dst) : 0;
332
333 LOG_DBG ((LOG_REPORT, 0, "udp_encap_report: fd %d src %s:%u dst %s:%u",
334 u->s, src, ntohs(sport), dst ? dst : "*", ntohs(dport)));
335
336 free(dst);
337 free(src);
338 }
339
340 /*
341 * A message has arrived on transport T's socket. If T is single-ended,
342 * clone it into a double-ended transport which we will use from now on.
343 * Package the message as we want it and continue processing in the message
344 * module.
345 */
346 static void
udp_encap_handle_message(struct transport * t)347 udp_encap_handle_message(struct transport *t)
348 {
349 struct udp_transport *u = (struct udp_transport *)t;
350 struct sockaddr_storage from;
351 struct message *msg;
352 u_int32_t len = sizeof from;
353 ssize_t n;
354 u_int8_t buf[UDP_SIZE];
355
356 n = recvfrom(u->s, buf, UDP_SIZE, 0, (struct sockaddr *)&from, &len);
357 if (n == -1) {
358 log_error("recvfrom (%d, %p, %d, %d, %p, %p)", u->s, buf,
359 UDP_SIZE, 0, &from, &len);
360 return;
361 }
362
363 if (t->virtual == (struct transport *)virtual_get_default(AF_INET) ||
364 t->virtual == (struct transport *)virtual_get_default(AF_INET6)) {
365 t->virtual->vtbl->reinit();
366
367 /*
368 * As we don't know the actual destination address of the
369 * packet, we can't really deal with it. So, just ignore it
370 * and hope we catch the retransmission.
371 */
372 return;
373 }
374
375 /*
376 * Make a specialized UDP transport structure out of the incoming
377 * transport and the address information we got from recvfrom(2).
378 */
379 t = t->virtual->vtbl->clone(t->virtual, (struct sockaddr *)&from);
380 if (!t)
381 return;
382
383 /* Check NULL-ESP marker. */
384 if (n < (ssize_t)sizeof(u_int32_t) || *(u_int32_t *)buf != 0) {
385 /* Should never happen. */
386 log_print("udp_encap_handle_message: "
387 "Null-ESP marker not NULL or short message");
388 return;
389 }
390
391 /* NAT-Keepalive messages should not be processed further. */
392 n -= sizeof(u_int32_t);
393 if (n == 1 && buf[sizeof(u_int32_t)] == 0xFF)
394 return;
395
396 msg = message_alloc(t, buf + sizeof (u_int32_t), n);
397 if (!msg) {
398 log_error("failed to allocate message structure, dropping "
399 "packet received on transport %p", u);
400 return;
401 }
402
403 msg->flags |= MSG_NATT;
404
405 message_recv(msg);
406 }
407
408 /*
409 * Physically send the message MSG over its associated transport.
410 * Special: if 'msg' is NULL, send a NAT-T keepalive message.
411 */
412 static int
udp_encap_send_message(struct message * msg,struct transport * t)413 udp_encap_send_message(struct message *msg, struct transport *t)
414 {
415 struct udp_transport *u = (struct udp_transport *)t;
416 struct msghdr m;
417 struct iovec *new_iov = 0, keepalive;
418 ssize_t n;
419 u_int32_t marker = 0; /* NULL-ESP Marker */
420
421 if (msg) {
422 /* Construct new iov array, prefixing NULL-ESP Marker. */
423 new_iov = calloc(msg->iovlen + 1, sizeof *new_iov);
424 if (!new_iov) {
425 log_error ("udp_encap_send_message: "
426 "calloc(%lu, %lu) failed",
427 (unsigned long)msg->iovlen + 1,
428 (unsigned long)sizeof *new_iov);
429 return -1;
430 }
431 new_iov[0].iov_base = ▮
432 new_iov[0].iov_len = IPSEC_SPI_SIZE;
433 memcpy (new_iov + 1, msg->iov, msg->iovlen * sizeof *new_iov);
434 } else {
435 marker = ~marker;
436 keepalive.iov_base = ▮
437 keepalive.iov_len = 1;
438 }
439
440 /*
441 * Sending on connected sockets requires that no destination address is
442 * given, or else EISCONN will occur.
443 */
444 m.msg_name = (caddr_t)u->dst;
445 m.msg_namelen = SA_LEN(u->dst);
446 m.msg_iov = msg ? new_iov : &keepalive;
447 m.msg_iovlen = msg ? msg->iovlen + 1 : 1;
448 m.msg_control = 0;
449 m.msg_controllen = 0;
450 m.msg_flags = 0;
451 n = sendmsg (u->s, &m, 0);
452 if (msg)
453 free (new_iov);
454 if (n == -1) {
455 /* XXX We should check whether the address has gone away */
456 log_error ("sendmsg (%d, %p, %d)", u->s, &m, 0);
457 return -1;
458 }
459 return 0;
460 }
461