Bug Summary

File:src/sbin/isakmpd/udp_encap.c
Warning:line 306, column 2
Value stored to 't' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name udp_encap.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sbin/isakmpd/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/sbin/isakmpd -I . -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/sbin/isakmpd/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/sbin/isakmpd/udp_encap.c
1/* $OpenBSD: udp_encap.c,v 1.23 2015/08/20 22:02:21 deraadt 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_SIZE65536 65536
57
58/* If a system doesn't have SO_REUSEPORT, SO_REUSEADDR will have to do. */
59#ifndef SO_REUSEPORT0x0200
60#define SO_REUSEPORT0x0200 SO_REUSEADDR0x0004
61#endif
62
63/* Reused, from udp.c */
64struct transport *udp_clone(struct transport *, struct sockaddr *);
65int udp_fd_set(struct transport *, fd_set *, int);
66int udp_fd_isset(struct transport *, fd_set *);
67void udp_get_dst(struct transport *, struct sockaddr **);
68void udp_get_src(struct transport *, struct sockaddr **);
69char *udp_decode_ids(struct transport *);
70void udp_remove(struct transport *);
71
72static struct transport *udp_encap_create(char *);
73static void udp_encap_report(struct transport *);
74static void udp_encap_handle_message(struct transport *);
75static struct transport *udp_encap_make(struct sockaddr *);
76static int udp_encap_send_message(struct message *,
77 struct transport *);
78
79static 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
96char *udp_encap_default_port = 0;
97
98void
99udp_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. */
105static struct transport *
106udp_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_DGRAM2, IPPROTO_UDP17);
122 if (s == -1) {
123 log_error("udp_encap_make: socket (%d, %d, %d)",
124 laddr->sa_family, SOCK_DGRAM2, IPPROTO_UDP17);
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_INET2:
135 if (((struct sockaddr_in *)laddr)->sin_addr.s_addr
136 == INADDR_ANY((u_int32_t)(0x00000000)))
137 wildcardaddress = 1;
138 break;
139 case AF_INET624:
140 if (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)laddr)->sin6_addr)((*(const u_int32_t *)(const void *)(&(&((struct sockaddr_in6
*)laddr)->sin6_addr)->__u6_addr.__u6_addr8[0]) == 0) &&
(*(const u_int32_t *)(const void *)(&(&((struct sockaddr_in6
*)laddr)->sin6_addr)->__u6_addr.__u6_addr8[4]) == 0) &&
(*(const u_int32_t *)(const void *)(&(&((struct sockaddr_in6
*)laddr)->sin6_addr)->__u6_addr.__u6_addr8[8]) == 0) &&
(*(const u_int32_t *)(const void *)(&(&((struct sockaddr_in6
*)laddr)->sin6_addr)->__u6_addr.__u6_addr8[12]) == 0))
)
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_SOCKET0xffff,
154 wildcardaddress ? SO_REUSEPORT0x0200 : SO_REUSEADDR0x0004,
155 (void *)&on, sizeof on) == -1) {
156 log_error("udp_encap_make: setsockopt (%d, %d, %d, %p, %lu)",
157 s, SOL_SOCKET0xffff,
158 wildcardaddress ? SO_REUSEPORT0x0200 : SO_REUSEADDR0x0004, &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)((t->src)->sa_len))) {
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: "log_debug (LOG_MISC, 20, "udp_encap_make: " "transport %p socket %d family %d"
, t, s, t->src->sa_family == 2 ? 4 : 6)
179 "transport %p socket %d family %d", t, s,log_debug (LOG_MISC, 20, "udp_encap_make: " "transport %p socket %d family %d"
, t, s, t->src->sa_family == 2 ? 4 : 6)
180 t->src->sa_family == AF_INET ? 4 : 6))log_debug (LOG_MISC, 20, "udp_encap_make: " "transport %p socket %d family %d"
, t, s, t->src->sa_family == 2 ? 4 : 6)
;
181 else {
182 LOG_DBG((LOG_MISC, 20, "udp_encap_make: "log_debug (LOG_MISC, 20, "udp_encap_make: " "transport %p socket %d ip %s port %d"
, t, s, tstr, (__uint16_t)(__builtin_constant_p(sockaddr_port
(t->src)) ? (__uint16_t)(((__uint16_t)(sockaddr_port(t->
src)) & 0xffU) << 8 | ((__uint16_t)(sockaddr_port(t
->src)) & 0xff00U) >> 8) : __swap16md(sockaddr_port
(t->src))))
183 "transport %p socket %d ip %s port %d", t, s,log_debug (LOG_MISC, 20, "udp_encap_make: " "transport %p socket %d ip %s port %d"
, t, s, tstr, (__uint16_t)(__builtin_constant_p(sockaddr_port
(t->src)) ? (__uint16_t)(((__uint16_t)(sockaddr_port(t->
src)) & 0xffU) << 8 | ((__uint16_t)(sockaddr_port(t
->src)) & 0xff00U) >> 8) : __swap16md(sockaddr_port
(t->src))))
184 tstr, ntohs(sockaddr_port(t->src))))log_debug (LOG_MISC, 20, "udp_encap_make: " "transport %p socket %d ip %s port %d"
, t, s, tstr, (__uint16_t)(__builtin_constant_p(sockaddr_port
(t->src)) ? (__uint16_t)(((__uint16_t)(sockaddr_port(t->
src)) & 0xffU) << 8 | ((__uint16_t)(sockaddr_port(t
->src)) & 0xff00U) >> 8) : __swap16md(sockaddr_port
(t->src))))
;
185 free(tstr);
186 }
187 transport_setup(&t->transport, 0);
188 t->transport.flags |= TRANSPORT_LISTEN1;
189 return &t->transport;
190
191err:
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 */
208struct transport *
209udp_encap_bind(const struct sockaddr *addr)
210{
211 struct sockaddr *src;
212
213 src = malloc(SA_LEN(addr)((addr)->sa_len));
214 if (!src)
215 return 0;
216
217 memcpy(src, addr, SA_LEN(addr)((addr)->sa_len));
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 */
225static struct transport *
226udp_encap_create(char *name)
227{
228 struct virtual_transport *v;
229 struct udp_transport *u;
230 struct transport *rv, *t;
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"4500";
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)((&addr_list->fields)->tqh_first);
275 addr_node; addr_node = TAILQ_NEXT(addr_node, link)((addr_node)->link.tqe_next))
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 t = (struct transport *)v;
Value stored to 't' is never read
307 rv = udp_clone(v->encap, dst);
308 if (rv)
309 rv->vtbl = &udp_encap_transport_vtbl;
310
311ret:
312 if (addr_list)
313 conf_free_list(addr_list);
314 free(dst);
315 return rv;
316}
317
318/* Report transport-method specifics of the T transport. */
319void
320udp_encap_report(struct transport *t)
321{
322 struct udp_transport *u = (struct udp_transport *)t;
323 char *src = NULL((void *)0), *dst = NULL((void *)0);
324 in_port_t sport, dport;
325
326 if (sockaddr2text(u->src, &src, 0))
327 return;
328 sport = sockaddr_port(u->src);
329
330 if (!u->dst || sockaddr2text(u->dst, &dst, 0))
331 dst = 0;
332 dport = dst ? sockaddr_port(u->dst) : 0;
333
334 LOG_DBG ((LOG_REPORT, 0, "udp_encap_report: fd %d src %s:%u dst %s:%u",log_debug (-2, 0, "udp_encap_report: fd %d src %s:%u dst %s:%u"
, u->s, src, (__uint16_t)(__builtin_constant_p(sport) ? (__uint16_t
)(((__uint16_t)(sport) & 0xffU) << 8 | ((__uint16_t
)(sport) & 0xff00U) >> 8) : __swap16md(sport)), dst
? dst : "*", (__uint16_t)(__builtin_constant_p(dport) ? (__uint16_t
)(((__uint16_t)(dport) & 0xffU) << 8 | ((__uint16_t
)(dport) & 0xff00U) >> 8) : __swap16md(dport)))
335 u->s, src, ntohs(sport), dst ? dst : "*", ntohs(dport)))log_debug (-2, 0, "udp_encap_report: fd %d src %s:%u dst %s:%u"
, u->s, src, (__uint16_t)(__builtin_constant_p(sport) ? (__uint16_t
)(((__uint16_t)(sport) & 0xffU) << 8 | ((__uint16_t
)(sport) & 0xff00U) >> 8) : __swap16md(sport)), dst
? dst : "*", (__uint16_t)(__builtin_constant_p(dport) ? (__uint16_t
)(((__uint16_t)(dport) & 0xffU) << 8 | ((__uint16_t
)(dport) & 0xff00U) >> 8) : __swap16md(dport)))
;
336
337 free(dst);
338 free(src);
339}
340
341/*
342 * A message has arrived on transport T's socket. If T is single-ended,
343 * clone it into a double-ended transport which we will use from now on.
344 * Package the message as we want it and continue processing in the message
345 * module.
346 */
347static void
348udp_encap_handle_message(struct transport *t)
349{
350 struct udp_transport *u = (struct udp_transport *)t;
351 struct sockaddr_storage from;
352 struct message *msg;
353 u_int32_t len = sizeof from;
354 ssize_t n;
355 u_int8_t buf[UDP_SIZE65536];
356
357 n = recvfrom(u->s, buf, UDP_SIZE65536, 0, (struct sockaddr *)&from, &len);
358 if (n == -1) {
359 log_error("recvfrom (%d, %p, %d, %d, %p, %p)", u->s, buf,
360 UDP_SIZE65536, 0, &from, &len);
361 return;
362 }
363
364 if (t->virtual == (struct transport *)virtual_get_default(AF_INET2) ||
365 t->virtual == (struct transport *)virtual_get_default(AF_INET624)) {
366 t->virtual->vtbl->reinit();
367
368 /*
369 * As we don't know the actual destination address of the
370 * packet, we can't really deal with it. So, just ignore it
371 * and hope we catch the retransmission.
372 */
373 return;
374 }
375
376 /*
377 * Make a specialized UDP transport structure out of the incoming
378 * transport and the address information we got from recvfrom(2).
379 */
380 t = t->virtual->vtbl->clone(t->virtual, (struct sockaddr *)&from);
381 if (!t)
382 return;
383
384 /* Check NULL-ESP marker. */
385 if (n < (ssize_t)sizeof(u_int32_t) || *(u_int32_t *)buf != 0) {
386 /* Should never happen. */
387 log_print("udp_encap_handle_message: "
388 "Null-ESP marker not NULL or short message");
389 return;
390 }
391
392 /* NAT-Keepalive messages should not be processed further. */
393 n -= sizeof(u_int32_t);
394 if (n == 1 && buf[sizeof(u_int32_t)] == 0xFF)
395 return;
396
397 msg = message_alloc(t, buf + sizeof (u_int32_t), n);
398 if (!msg) {
399 log_error("failed to allocate message structure, dropping "
400 "packet received on transport %p", u);
401 return;
402 }
403
404 msg->flags |= MSG_NATT0x20;
405
406 message_recv(msg);
407}
408
409/*
410 * Physically send the message MSG over its associated transport.
411 * Special: if 'msg' is NULL, send a NAT-T keepalive message.
412 */
413static int
414udp_encap_send_message(struct message *msg, struct transport *t)
415{
416 struct udp_transport *u = (struct udp_transport *)t;
417 struct msghdr m;
418 struct iovec *new_iov = 0, keepalive;
419 ssize_t n;
420 u_int32_t marker = 0; /* NULL-ESP Marker */
421
422 if (msg) {
423 /* Construct new iov array, prefixing NULL-ESP Marker. */
424 new_iov = calloc(msg->iovlen + 1, sizeof *new_iov);
425 if (!new_iov) {
426 log_error ("udp_encap_send_message: "
427 "calloc(%lu, %lu) failed",
428 (unsigned long)msg->iovlen + 1,
429 (unsigned long)sizeof *new_iov);
430 return -1;
431 }
432 new_iov[0].iov_base = &marker;
433 new_iov[0].iov_len = IPSEC_SPI_SIZE4;
434 memcpy (new_iov + 1, msg->iov, msg->iovlen * sizeof *new_iov);
435 } else {
436 marker = ~marker;
437 keepalive.iov_base = &marker;
438 keepalive.iov_len = 1;
439 }
440
441 /*
442 * Sending on connected sockets requires that no destination address is
443 * given, or else EISCONN will occur.
444 */
445 m.msg_name = (caddr_t)u->dst;
446 m.msg_namelen = SA_LEN(u->dst)((u->dst)->sa_len);
447 m.msg_iov = msg ? new_iov : &keepalive;
448 m.msg_iovlen = msg ? msg->iovlen + 1 : 1;
449 m.msg_control = 0;
450 m.msg_controllen = 0;
451 m.msg_flags = 0;
452 n = sendmsg (u->s, &m, 0);
453 if (msg)
454 free (new_iov);
455 if (n == -1) {
456 /* XXX We should check whether the address has gone away */
457 log_error ("sendmsg (%d, %p, %d)", u->s, &m, 0);
458 return -1;
459 }
460 return 0;
461}