Bug Summary

File:src/sbin/iked/vroute.c
Warning:line 613, column 3
Value stored to 'ptr' 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 vroute.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/iked/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/sbin/iked -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/sbin/iked/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/iked/vroute.c
1/* $OpenBSD: vroute.c,v 1.15 2021/12/01 16:42:13 deraadt Exp $ */
2
3/*
4 * Copyright (c) 2021 Tobias Heider <tobhe@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <sys/ioctl.h>
20
21#include <net/if.h>
22#include <net/route.h>
23#include <netinet/in.h>
24#include <netinet6/in6_var.h>
25#include <netinet6/nd6.h>
26
27#include <event.h>
28#include <err.h>
29#include <errno(*__errno()).h>
30#include <poll.h>
31#include <string.h>
32#include <strings.h>
33#include <unistd.h>
34#include <netdb.h>
35
36#include <iked.h>
37
38#define ROUTE_SOCKET_BUF_SIZE16384 16384
39#define IKED_VROUTE_PRIO6 6
40
41#define ROUNDUP(a)(a>0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long
))
(a>0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
42
43int vroute_setroute(struct iked *, uint8_t, struct sockaddr *, uint8_t,
44 struct sockaddr *, int);
45int vroute_doroute(struct iked *, int, int, int, uint8_t, struct sockaddr *,
46 struct sockaddr *, struct sockaddr *, int *);
47int vroute_doaddr(struct iked *, char *, struct sockaddr *, struct sockaddr *, int);
48int vroute_dodns(struct iked *, struct sockaddr *, int, unsigned int);
49void vroute_cleanup(struct iked *);
50void vroute_rtmsg_cb(int, short, void *);
51
52void vroute_insertaddr(struct iked *, int, struct sockaddr *, struct sockaddr *);
53void vroute_removeaddr(struct iked *, int, struct sockaddr *, struct sockaddr *);
54void vroute_insertdns(struct iked *, int, struct sockaddr *);
55void vroute_removedns(struct iked *, int, struct sockaddr *);
56void vroute_insertroute(struct iked *, int, struct sockaddr *, struct sockaddr *);
57void vroute_removeroute(struct iked *, int, struct sockaddr *, struct sockaddr *);
58
59struct vroute_addr {
60 int va_ifidx;
61 struct sockaddr_storage va_addr;
62 struct sockaddr_storage va_mask;
63 TAILQ_ENTRY(vroute_addr)struct { struct vroute_addr *tqe_next; struct vroute_addr **tqe_prev
; }
va_entry;
64};
65TAILQ_HEAD(vroute_addrs, vroute_addr)struct vroute_addrs { struct vroute_addr *tqh_first; struct vroute_addr
**tqh_last; }
;
66
67struct vroute_route {
68 int vr_rdomain;
69 int vr_flags;
70 struct sockaddr_storage vr_dest;
71 struct sockaddr_storage vr_mask;
72 TAILQ_ENTRY(vroute_route)struct { struct vroute_route *tqe_next; struct vroute_route *
*tqe_prev; }
vr_entry;
73};
74TAILQ_HEAD(vroute_routes, vroute_route)struct vroute_routes { struct vroute_route *tqh_first; struct
vroute_route **tqh_last; }
;
75
76struct vroute_dns {
77 struct sockaddr_storage vd_addr;
78 int vd_ifidx;
79};
80
81struct iked_vroute_sc {
82 struct vroute_addrs ivr_addrs;
83 struct vroute_routes ivr_routes;
84 struct vroute_dns *ivr_dns;
85 struct event ivr_routeev;
86 int ivr_iosock;
87 int ivr_iosock6;
88 int ivr_rtsock;
89 int ivr_rtseq;
90 pid_t ivr_pid;
91};
92
93struct vroute_msg {
94 struct rt_msghdr vm_rtm;
95 uint8_t vm_space[512];
96};
97
98int vroute_process(struct iked *, int msglen, struct vroute_msg *,
99 struct sockaddr *, struct sockaddr *, struct sockaddr *, int *);
100
101void
102vroute_rtmsg_cb(int fd, short events, void *arg)
103{
104 struct iked *env = (struct iked *) arg;
105 struct iked_vroute_sc *ivr = env->sc_vroute;
106 static uint8_t *buf;
107 struct rt_msghdr *rtm;
108 ssize_t n;
109
110 if (buf == NULL((void *)0)) {
111 buf = malloc(ROUTE_SOCKET_BUF_SIZE16384);
112 if (buf == NULL((void *)0))
113 fatal("malloc");
114 }
115 rtm = (struct rt_msghdr *)buf;
116 if ((n = read(fd, buf, ROUTE_SOCKET_BUF_SIZE16384)) == -1) {
117 if (errno(*__errno()) == EAGAIN35 || errno(*__errno()) == EINTR4)
118 return;
119 log_warn("%s: read error", __func__);
120 return;
121 }
122
123 if (n == 0)
124 fatal("routing socket closed");
125
126 if (n < (ssize_t)sizeof(rtm->rtm_msglen) || n < rtm->rtm_msglen) {
127 log_warnx("partial rtm of %zd in buffer", n);
128 return;
129 }
130
131 if (rtm->rtm_version != RTM_VERSION5)
132 return;
133
134 switch(rtm->rtm_type) {
135 case RTM_PROPOSAL0x13:
136 if (rtm->rtm_priority == RTP_PROPOSAL_SOLICIT62) {
137 log_debug("%s: got solicit", __func__);
138 vroute_dodns(env, (struct sockaddr *)&ivr->ivr_dns->vd_addr, 1,
139 ivr->ivr_dns->vd_ifidx);
140 }
141 break;
142 default:
143 log_debug("%s: unexpected RTM: %d", __func__, rtm->rtm_type);
144 break;
145 }
146}
147
148void
149vroute_init(struct iked *env)
150{
151 struct iked_vroute_sc *ivr;
152 int rtfilter;
153
154 ivr = calloc(1, sizeof(*ivr));
155 if (ivr == NULL((void *)0))
156 fatal("%s: calloc.", __func__);
157
158 if ((ivr->ivr_iosock = socket(AF_INET2, SOCK_DGRAM2, 0)) == -1)
159 fatal("%s: failed to create ioctl socket", __func__);
160
161 if ((ivr->ivr_iosock6 = socket(AF_INET624, SOCK_DGRAM2, 0)) == -1)
162 fatal("%s: failed to create ioctl socket", __func__);
163
164 if ((ivr->ivr_rtsock = socket(AF_ROUTE17, SOCK_RAW3, AF_UNSPEC0)) == -1)
165 fatal("%s: failed to create routing socket", __func__);
166
167 rtfilter = ROUTE_FILTER(RTM_GET)(1 << (0x4)) | ROUTE_FILTER(RTM_PROPOSAL)(1 << (0x13));
168 if (setsockopt(ivr->ivr_rtsock, AF_ROUTE17, ROUTE_MSGFILTER1, &rtfilter,
169 sizeof(rtfilter)) == -1)
170 fatal("%s: setsockopt(ROUTE_MSGFILTER)", __func__);
171
172 TAILQ_INIT(&ivr->ivr_addrs)do { (&ivr->ivr_addrs)->tqh_first = ((void *)0); (&
ivr->ivr_addrs)->tqh_last = &(&ivr->ivr_addrs
)->tqh_first; } while (0)
;
173 TAILQ_INIT(&ivr->ivr_routes)do { (&ivr->ivr_routes)->tqh_first = ((void *)0); (
&ivr->ivr_routes)->tqh_last = &(&ivr->ivr_routes
)->tqh_first; } while (0)
;
174
175 ivr->ivr_pid = getpid();
176
177 env->sc_vroute = ivr;
178
179 event_set(&ivr->ivr_routeev, ivr->ivr_rtsock, EV_READ0x02 | EV_PERSIST0x10,
180 vroute_rtmsg_cb, env);
181 event_add(&ivr->ivr_routeev, NULL((void *)0));
182}
183
184void
185vroute_cleanup(struct iked *env)
186{
187 char ifname[IF_NAMESIZE16];
188 struct iked_vroute_sc *ivr = env->sc_vroute;
189 struct vroute_addr *addr;
190 struct vroute_route *route;
191
192 while ((addr = TAILQ_FIRST(&ivr->ivr_addrs)((&ivr->ivr_addrs)->tqh_first))) {
193 if_indextoname(addr->va_ifidx, ifname);
194 vroute_doaddr(env, ifname,
195 (struct sockaddr *)&addr->va_addr,
196 (struct sockaddr *)&addr->va_mask, 0);
197 TAILQ_REMOVE(&ivr->ivr_addrs, addr, va_entry)do { if (((addr)->va_entry.tqe_next) != ((void *)0)) (addr
)->va_entry.tqe_next->va_entry.tqe_prev = (addr)->va_entry
.tqe_prev; else (&ivr->ivr_addrs)->tqh_last = (addr
)->va_entry.tqe_prev; *(addr)->va_entry.tqe_prev = (addr
)->va_entry.tqe_next; ; ; } while (0)
;
198 free(addr);
199 }
200
201 while ((route = TAILQ_FIRST(&ivr->ivr_routes)((&ivr->ivr_routes)->tqh_first))) {
202 vroute_doroute(env, RTF_UP0x1 | RTF_GATEWAY0x2 | RTF_STATIC0x800,
203 route->vr_flags, route->vr_rdomain, RTM_DELETE0x2,
204 (struct sockaddr *)&route->vr_dest,
205 (struct sockaddr *)&route->vr_mask,
206 NULL((void *)0), NULL((void *)0));
207 TAILQ_REMOVE(&ivr->ivr_routes, route, vr_entry)do { if (((route)->vr_entry.tqe_next) != ((void *)0)) (route
)->vr_entry.tqe_next->vr_entry.tqe_prev = (route)->vr_entry
.tqe_prev; else (&ivr->ivr_routes)->tqh_last = (route
)->vr_entry.tqe_prev; *(route)->vr_entry.tqe_prev = (route
)->vr_entry.tqe_next; ; ; } while (0)
;
208 free(route);
209 }
210
211 if (ivr->ivr_dns) {
212 vroute_dodns(env, (struct sockaddr *)&ivr->ivr_dns->vd_addr, 0,
213 ivr->ivr_dns->vd_ifidx);
214 free(ivr->ivr_dns);
215 }
216}
217
218int
219vroute_setaddr(struct iked *env, int add, struct sockaddr *addr,
220 int mask, unsigned int ifidx)
221{
222 struct iovec iov[4];
223 int iovcnt;
224 struct sockaddr_in mask4;
225 struct sockaddr_in6 mask6;
226
227 iovcnt = 0;
228 iov[0].iov_base = addr;
229 iov[0].iov_len = addr->sa_len;
230 iovcnt++;
231
232 switch(addr->sa_family) {
233 case AF_INET2:
234 bzero(&mask, sizeof(mask));
235 mask4.sin_addr.s_addr = prefixlen2mask(mask ? mask : 32);
236 mask4.sin_family = AF_INET2;
237 mask4.sin_len = sizeof(mask4);
238
239 iov[1].iov_base = &mask4;
240 iov[1].iov_len = sizeof(mask4);
241 iovcnt++;
242 break;
243 case AF_INET624:
244 bzero(&mask6, sizeof(mask6));
245 prefixlen2mask6(mask ? mask : 128,
246 (uint32_t *)&mask6.sin6_addr.s6_addr__u6_addr.__u6_addr8);
247 mask6.sin6_family = AF_INET624;
248 mask6.sin6_len = sizeof(mask6);
249 iov[1].iov_base = &mask6;
250 iov[1].iov_len = sizeof(mask6);
251 iovcnt++;
252 break;
253 default:
254 return -1;
255 }
256
257 iov[2].iov_base = &ifidx;
258 iov[2].iov_len = sizeof(ifidx);
259 iovcnt++;
260
261 return (proc_composev(&env->sc_ps, PROC_PARENT,
262 add ? IMSG_IF_ADDADDR : IMSG_IF_DELADDR, iov, iovcnt));
263}
264
265int
266vroute_getaddr(struct iked *env, struct imsg *imsg)
267{
268 char ifname[IF_NAMESIZE16];
269 struct sockaddr *addr, *mask;
270 uint8_t *ptr;
271 size_t left;
272 int af, add;
273 unsigned int ifidx;
274
275 ptr = imsg->data;
276 left = IMSG_DATA_SIZE(imsg)((imsg)->hdr.len - sizeof(struct imsg_hdr));
277
278 if (left < sizeof(*addr))
279 fatalx("bad length imsg received");
280
281 addr = (struct sockaddr *) ptr;
282 af = addr->sa_family;
283
284 if (left < addr->sa_len)
285 fatalx("bad length imsg received");
286 ptr += addr->sa_len;
287 left -= addr->sa_len;
288
289 if (left < sizeof(*mask))
290 fatalx("bad length imsg received");
291 mask = (struct sockaddr *) ptr;
292 if (mask->sa_family != af)
293 return (-1);
294
295 if (left < mask->sa_len)
296 fatalx("bad length imsg received");
297 ptr += mask->sa_len;
298 left -= mask->sa_len;
299
300 if (left != sizeof(ifidx))
301 fatalx("bad length imsg received");
302 memcpy(&ifidx, ptr, sizeof(ifidx));
303 ptr += sizeof(ifidx);
304 left -= sizeof(ifidx);
305
306 add = (imsg->hdr.type == IMSG_IF_ADDADDR);
307 /* Store address for cleanup */
308 if (add)
309 vroute_insertaddr(env, ifidx, addr, mask);
310 else
311 vroute_removeaddr(env, ifidx, addr, mask);
312
313 if_indextoname(ifidx, ifname);
314 return (vroute_doaddr(env, ifname, addr, mask, add));
315}
316
317int
318vroute_setdns(struct iked *env, int add, struct sockaddr *addr,
319 unsigned int ifidx)
320{
321 struct iovec iov[2];
322
323 iov[0].iov_base = addr;
324 iov[0].iov_len = addr->sa_len;
325
326 iov[1].iov_base = &ifidx;
327 iov[1].iov_len = sizeof(ifidx);
328
329 return (proc_composev(&env->sc_ps, PROC_PARENT,
330 add ? IMSG_VDNS_ADD: IMSG_VDNS_DEL, iov, 2));
331}
332
333int
334vroute_getdns(struct iked *env, struct imsg *imsg)
335{
336 struct iked_vroute_sc *ivr = env->sc_vroute;
337 struct sockaddr *dns;
338 uint8_t *ptr;
339 size_t left;
340 int add;
341 unsigned int ifidx;
342
343 ptr = imsg->data;
344 left = IMSG_DATA_SIZE(imsg)((imsg)->hdr.len - sizeof(struct imsg_hdr));
345
346 if (left < sizeof(*dns))
347 fatalx("bad length imsg received");
348
349 dns = (struct sockaddr *) ptr;
350 if (left < dns->sa_len)
351 fatalx("bad length imsg received");
352 ptr += dns->sa_len;
353 left -= dns->sa_len;
354
355 if (left != sizeof(ifidx))
356 fatalx("bad length imsg received");
357 memcpy(&ifidx, ptr, sizeof(ifidx));
358 ptr += sizeof(ifidx);
359 left -= sizeof(ifidx);
360
361 add = (imsg->hdr.type == IMSG_VDNS_ADD);
362 if (add) {
363 if (ivr->ivr_dns != NULL((void *)0))
364 return (0);
365 vroute_insertdns(env, ifidx, dns);
366 } else {
367 if (ivr->ivr_dns == NULL((void *)0))
368 return (0);
369 vroute_removedns(env, ifidx, dns);
370 }
371
372 return (vroute_dodns(env, dns, add, ifidx));
373}
374
375void
376vroute_insertroute(struct iked *env, int rdomain, struct sockaddr *dest,
377 struct sockaddr *mask)
378{
379 struct iked_vroute_sc *ivr = env->sc_vroute;
380 struct vroute_route *route;
381
382 route = calloc(1, sizeof(*route));
383 if (route == NULL((void *)0))
384 fatalx("%s: calloc.", __func__);
385
386 if (dest != NULL((void *)0)) {
387 route->vr_flags |= RTA_DST0x1;
388 memcpy(&route->vr_dest, dest, dest->sa_len);
389 }
390 if (mask != NULL((void *)0)) {
391 route->vr_flags |= RTA_NETMASK0x4;
392 memcpy(&route->vr_mask, mask, mask->sa_len);
393 }
394 route->vr_rdomain = rdomain;
395
396 TAILQ_INSERT_TAIL(&ivr->ivr_routes, route, vr_entry)do { (route)->vr_entry.tqe_next = ((void *)0); (route)->
vr_entry.tqe_prev = (&ivr->ivr_routes)->tqh_last; *
(&ivr->ivr_routes)->tqh_last = (route); (&ivr->
ivr_routes)->tqh_last = &(route)->vr_entry.tqe_next
; } while (0)
;
397}
398
399void
400vroute_removeroute(struct iked *env, int rdomain, struct sockaddr *dest,
401 struct sockaddr *mask)
402{
403 struct iked_vroute_sc *ivr = env->sc_vroute;
404 struct vroute_route *route, *troute;
405
406 TAILQ_FOREACH_SAFE(route, &ivr->ivr_routes, vr_entry, troute)for ((route) = ((&ivr->ivr_routes)->tqh_first); (route
) != ((void *)0) && ((troute) = ((route)->vr_entry
.tqe_next), 1); (route) = (troute))
{
407 if (sockaddr_cmp(dest, (struct sockaddr *)&route->vr_dest, -1))
408 continue;
409 if (mask && !(route->vr_flags & RTA_NETMASK0x4))
410 continue;
411 if (mask &&
412 sockaddr_cmp(mask, (struct sockaddr *)&route->vr_mask, -1))
413 continue;
414 if (rdomain != route->vr_rdomain)
415 continue;
416 TAILQ_REMOVE(&ivr->ivr_routes, route, vr_entry)do { if (((route)->vr_entry.tqe_next) != ((void *)0)) (route
)->vr_entry.tqe_next->vr_entry.tqe_prev = (route)->vr_entry
.tqe_prev; else (&ivr->ivr_routes)->tqh_last = (route
)->vr_entry.tqe_prev; *(route)->vr_entry.tqe_prev = (route
)->vr_entry.tqe_next; ; ; } while (0)
;
417 free(route);
418 }
419}
420
421void
422vroute_insertdns(struct iked *env, int ifidx, struct sockaddr *addr)
423{
424 struct iked_vroute_sc *ivr = env->sc_vroute;
425 struct vroute_dns *dns;
426
427 dns = calloc(1, sizeof(*dns));
428 if (dns == NULL((void *)0))
429 fatalx("%s: calloc.", __func__);
430
431 memcpy(&dns->vd_addr, addr, addr->sa_len);
432 dns->vd_ifidx = ifidx;
433
434 ivr->ivr_dns = dns;
435}
436
437void
438vroute_removedns(struct iked *env, int ifidx, struct sockaddr *addr)
439{
440 struct iked_vroute_sc *ivr = env->sc_vroute;
441
442 if (ifidx == ivr->ivr_dns->vd_ifidx &&
443 sockaddr_cmp(addr, (struct sockaddr *)
444 &ivr->ivr_dns->vd_addr, -1) == 0) {
445 free(ivr->ivr_dns);
446 ivr->ivr_dns = NULL((void *)0);
447 }
448}
449
450void
451vroute_insertaddr(struct iked *env, int ifidx, struct sockaddr *addr,
452 struct sockaddr *mask)
453{
454 struct iked_vroute_sc *ivr = env->sc_vroute;
455 struct vroute_addr *vaddr;
456
457 vaddr = calloc(1, sizeof(*vaddr));
458 if (vaddr == NULL((void *)0))
459 fatalx("%s: calloc.", __func__);
460
461 memcpy(&vaddr->va_addr, addr, addr->sa_len);
462 memcpy(&vaddr->va_mask, mask, mask->sa_len);
463 vaddr->va_ifidx = ifidx;
464
465 TAILQ_INSERT_TAIL(&ivr->ivr_addrs, vaddr, va_entry)do { (vaddr)->va_entry.tqe_next = ((void *)0); (vaddr)->
va_entry.tqe_prev = (&ivr->ivr_addrs)->tqh_last; *(
&ivr->ivr_addrs)->tqh_last = (vaddr); (&ivr->
ivr_addrs)->tqh_last = &(vaddr)->va_entry.tqe_next;
} while (0)
;
466}
467
468void
469vroute_removeaddr(struct iked *env, int ifidx, struct sockaddr *addr,
470 struct sockaddr *mask)
471{
472 struct iked_vroute_sc *ivr = env->sc_vroute;
473 struct vroute_addr *vaddr, *tvaddr;
474
475 TAILQ_FOREACH_SAFE(vaddr, &ivr->ivr_addrs, va_entry, tvaddr)for ((vaddr) = ((&ivr->ivr_addrs)->tqh_first); (vaddr
) != ((void *)0) && ((tvaddr) = ((vaddr)->va_entry
.tqe_next), 1); (vaddr) = (tvaddr))
{
476 if (sockaddr_cmp(addr, (struct sockaddr *)&vaddr->va_addr, -1))
477 continue;
478 if (sockaddr_cmp(mask, (struct sockaddr *)&vaddr->va_mask, -1))
479 continue;
480 if (ifidx != vaddr->va_ifidx)
481 continue;
482 TAILQ_REMOVE(&ivr->ivr_addrs, vaddr, va_entry)do { if (((vaddr)->va_entry.tqe_next) != ((void *)0)) (vaddr
)->va_entry.tqe_next->va_entry.tqe_prev = (vaddr)->va_entry
.tqe_prev; else (&ivr->ivr_addrs)->tqh_last = (vaddr
)->va_entry.tqe_prev; *(vaddr)->va_entry.tqe_prev = (vaddr
)->va_entry.tqe_next; ; ; } while (0)
;
483 free(vaddr);
484 }
485}
486
487int
488vroute_setaddroute(struct iked *env, uint8_t rdomain, struct sockaddr *dst,
489 uint8_t mask, struct sockaddr *ifa)
490{
491 return (vroute_setroute(env, rdomain, dst, mask, ifa,
492 IMSG_VROUTE_ADD));
493}
494
495int
496vroute_setcloneroute(struct iked *env, uint8_t rdomain, struct sockaddr *dst,
497 uint8_t mask, struct sockaddr *addr)
498{
499 return (vroute_setroute(env, rdomain, dst, mask, addr,
500 IMSG_VROUTE_CLONE));
501}
502
503int
504vroute_setdelroute(struct iked *env, uint8_t rdomain, struct sockaddr *dst,
505 uint8_t mask, struct sockaddr *addr)
506{
507 return (vroute_setroute(env, rdomain, dst, mask, addr,
508 IMSG_VROUTE_DEL));
509}
510
511int
512vroute_setroute(struct iked *env, uint8_t rdomain, struct sockaddr *dst,
513 uint8_t mask, struct sockaddr *addr, int type)
514{
515 struct sockaddr_storage sa;
516 struct sockaddr_in *in;
517 struct sockaddr_in6 *in6;
518 struct iovec iov[5];
519 int iovcnt = 0;
520 uint8_t af;
521
522 if (addr && dst->sa_family != addr->sa_family)
523 return (-1);
524 af = dst->sa_family;
525
526 iov[iovcnt].iov_base = &rdomain;
527 iov[iovcnt].iov_len = sizeof(rdomain);
528 iovcnt++;
529
530 iov[iovcnt].iov_base = dst;
531 iov[iovcnt].iov_len = dst->sa_len;
532 iovcnt++;
533
534 if (type != IMSG_VROUTE_CLONE && addr) {
535 bzero(&sa, sizeof(sa));
536 switch(af) {
537 case AF_INET2:
538 in = (struct sockaddr_in *)&sa;
539 in->sin_addr.s_addr = prefixlen2mask(mask);
540 in->sin_family = af;
541 in->sin_len = sizeof(*in);
542 iov[iovcnt].iov_base = in;
543 iov[iovcnt].iov_len = sizeof(*in);
544 iovcnt++;
545 break;
546 case AF_INET624:
547 in6 = (struct sockaddr_in6 *)&sa;
548 prefixlen2mask6(mask,
549 (uint32_t *)in6->sin6_addr.s6_addr__u6_addr.__u6_addr8);
550 in6->sin6_family = af;
551 in6->sin6_len = sizeof(*in6);
552 iov[iovcnt].iov_base = in6;
553 iov[iovcnt].iov_len = sizeof(*in6);
554 iovcnt++;
555 break;
556 }
557
558 iov[iovcnt].iov_base = addr;
559 iov[iovcnt].iov_len = addr->sa_len;
560 iovcnt++;
561 }
562
563 return (proc_composev(&env->sc_ps, PROC_PARENT, type, iov, iovcnt));
564}
565
566int
567vroute_getroute(struct iked *env, struct imsg *imsg)
568{
569 struct sockaddr *dest, *mask = NULL((void *)0), *gateway = NULL((void *)0);
570 uint8_t *ptr;
571 size_t left;
572 int addrs = 0;
573 int type, flags;
574 uint8_t rdomain;
575
576 ptr = (uint8_t *)imsg->data;
577 left = IMSG_DATA_SIZE(imsg)((imsg)->hdr.len - sizeof(struct imsg_hdr));
578
579 if (left < sizeof(rdomain))
580 return (-1);
581 rdomain = *ptr;
582 ptr += sizeof(rdomain);
583 left -= sizeof(rdomain);
584
585 if (left < sizeof(struct sockaddr))
586 return (-1);
587 dest = (struct sockaddr *)ptr;
588 if (left < dest->sa_len)
589 return (-1);
590 socket_setport(dest, 0);
591 ptr += dest->sa_len;
592 left -= dest->sa_len;
593 addrs |= RTA_DST0x1;
594
595 flags = RTF_UP0x1 | RTF_GATEWAY0x2 | RTF_STATIC0x800;
596 if (left != 0) {
597 if (left < sizeof(struct sockaddr))
598 return (-1);
599 mask = (struct sockaddr *)ptr;
600 if (left < mask->sa_len)
601 return (-1);
602 socket_setport(mask, 0);
603 ptr += mask->sa_len;
604 left -= mask->sa_len;
605 addrs |= RTA_NETMASK0x4;
606
607 if (left < sizeof(struct sockaddr))
608 return (-1);
609 gateway = (struct sockaddr *)ptr;
610 if (left < gateway->sa_len)
611 return (-1);
612 socket_setport(gateway, 0);
613 ptr += gateway->sa_len;
Value stored to 'ptr' is never read
614 left -= gateway->sa_len;
615 addrs |= RTA_GATEWAY0x2;
616 } else {
617 flags |= RTF_HOST0x4;
618 }
619
620 switch(imsg->hdr.type) {
621 case IMSG_VROUTE_ADD:
622 type = RTM_ADD0x1;
623 break;
624 case IMSG_VROUTE_DEL:
625 type = RTM_DELETE0x2;
626 break;
627 }
628
629 if (type == RTM_ADD0x1)
630 vroute_insertroute(env, rdomain, dest, mask);
631 else
632 vroute_removeroute(env, rdomain, dest, mask);
633 return (vroute_doroute(env, flags, addrs, rdomain, type,
634 dest, mask, gateway, NULL((void *)0)));
635}
636
637int
638vroute_getcloneroute(struct iked *env, struct imsg *imsg)
639{
640 struct sockaddr *dst;
641 struct sockaddr_storage dest;
642 struct sockaddr_storage mask;
643 struct sockaddr_storage addr;
644 uint8_t *ptr;
645 size_t left;
646 uint8_t rdomain;
647 int flags;
648 int addrs;
649 int need_gw;
650
651 ptr = (uint8_t *)imsg->data;
652 left = IMSG_DATA_SIZE(imsg)((imsg)->hdr.len - sizeof(struct imsg_hdr));
653
654 if (left < sizeof(rdomain))
655 return (-1);
656 rdomain = *ptr;
657 ptr += sizeof(rdomain);
658 left -= sizeof(rdomain);
659
660 bzero(&dest, sizeof(dest));
661 bzero(&mask, sizeof(mask));
662 bzero(&addr, sizeof(addr));
663
664 if (left < sizeof(struct sockaddr))
665 return (-1);
666 dst = (struct sockaddr *)ptr;
667 if (left < dst->sa_len)
668 return (-1);
669 memcpy(&dest, dst, dst->sa_len);
670 ptr += dst->sa_len;
671 left -= dst->sa_len;
672
673 /* Get route to peer */
674 flags = RTF_UP0x1 | RTF_HOST0x4 | RTF_STATIC0x800;
675 if (vroute_doroute(env, flags, RTA_DST0x1, rdomain, RTM_GET0x4,
676 (struct sockaddr *)&dest, (struct sockaddr *)&mask,
677 (struct sockaddr *)&addr, &need_gw))
678 return (-1);
679
680 if (need_gw)
681 flags |= RTF_GATEWAY0x2;
682
683 memcpy(&dest, dst, dst->sa_len);
684 socket_setport((struct sockaddr *)&dest, 0);
685 vroute_insertroute(env, rdomain, (struct sockaddr *)&dest, NULL((void *)0));
686
687 /* Set explicit route to peer with gateway addr*/
688 addrs = RTA_DST0x1 | RTA_GATEWAY0x2 | RTA_NETMASK0x4;
689 return (vroute_doroute(env, flags, addrs, rdomain, RTM_ADD0x1,
690 (struct sockaddr *)&dest, (struct sockaddr *)&mask,
691 (struct sockaddr *)&addr, NULL((void *)0)));
692}
693
694int
695vroute_dodns(struct iked *env, struct sockaddr *dns, int add,
696 unsigned int ifidx)
697{
698 struct vroute_msg m_rtmsg;
699 struct sockaddr_in *in;
700 struct sockaddr_in6 *in6;
701 struct sockaddr_rtdns rtdns;
702 struct iked_vroute_sc *ivr = env->sc_vroute;
703 struct iovec iov[3];
704 int i;
705 long pad = 0;
706 int iovcnt = 0, padlen;
707
708 bzero(&m_rtmsg, sizeof(m_rtmsg));
709#define rtm m_rtmsg.vm_rtm
710 rtm.rtm_version = RTM_VERSION5;
711 rtm.rtm_type = RTM_PROPOSAL0x13;
712 rtm.rtm_seq = ++ivr->ivr_rtseq;
713 rtm.rtm_priority = RTP_PROPOSAL_STATIC57;
714 rtm.rtm_flags = RTF_UP0x1;
715 rtm.rtm_addrs = RTA_DNS0x1000;
716 rtm.rtm_index = ifidx;
717
718 iov[iovcnt].iov_base = &rtm;
719 iov[iovcnt].iov_len = sizeof(rtm);
720 iovcnt++;
721
722 bzero(&rtdns, sizeof(rtdns));
723 rtdns.sr_family = dns->sa_family;
724 rtdns.sr_len = 2;
725 if (add) {
726 switch(dns->sa_family) {
727 case AF_INET2:
728 rtdns.sr_family = AF_INET2;
729 rtdns.sr_len += sizeof(struct in_addr);
730 in = (struct sockaddr_in *)dns;
731 memcpy(rtdns.sr_dns, &in->sin_addr, sizeof(struct in_addr));
732 break;
733 case AF_INET624:
734 rtdns.sr_family = AF_INET624;
735 rtdns.sr_len += sizeof(struct in6_addr);
736 in6 = (struct sockaddr_in6 *)dns;
737 memcpy(rtdns.sr_dns, &in6->sin6_addr, sizeof(struct in6_addr));
738 break;
739 default:
740 return (-1);
741 }
742 }
743 iov[iovcnt].iov_base = &rtdns;
744 iov[iovcnt++].iov_len = sizeof(rtdns);
745 padlen = ROUNDUP(sizeof(rtdns))(sizeof(rtdns)>0 ? (1 + (((sizeof(rtdns)) - 1) | (sizeof(long
) - 1))) : sizeof(long))
- sizeof(rtdns);
746 if (padlen > 0) {
747 iov[iovcnt].iov_base = &pad;
748 iov[iovcnt++].iov_len = padlen;
749 }
750
751 for (i = 0; i < iovcnt; i++)
752 rtm.rtm_msglen += iov[i].iov_len;
753#undef rtm
754
755 if (writev(ivr->ivr_rtsock, iov, iovcnt) == -1)
756 log_warn("failed to send route message");
757
758 return (0);
759}
760
761int
762vroute_doroute(struct iked *env, int flags, int addrs, int rdomain, uint8_t type,
763 struct sockaddr *dest, struct sockaddr *mask, struct sockaddr *addr, int *need_gw)
764{
765 struct vroute_msg m_rtmsg;
766 struct iovec iov[7];
767 struct iked_vroute_sc *ivr = env->sc_vroute;
768 ssize_t len;
769 int iovcnt = 0;
770 int i;
771 long pad = 0;
772 size_t padlen;
773
774 bzero(&m_rtmsg, sizeof(m_rtmsg));
775#define rtm m_rtmsg.vm_rtm
776 rtm.rtm_version = RTM_VERSION5;
777 rtm.rtm_tableid = rdomain;
778 rtm.rtm_type = type;
779 rtm.rtm_seq = ++ivr->ivr_rtseq;
780 if (type != RTM_GET0x4)
781 rtm.rtm_priority = IKED_VROUTE_PRIO6;
782 rtm.rtm_flags = flags;
783 rtm.rtm_addrs = addrs;
784
785 iov[iovcnt].iov_base = &rtm;
786 iov[iovcnt].iov_len = sizeof(rtm);
787 iovcnt++;
788
789 if (rtm.rtm_addrs & RTA_DST0x1) {
790 iov[iovcnt].iov_base = dest;
791 iov[iovcnt].iov_len = dest->sa_len;
792 iovcnt++;
793 padlen = ROUNDUP(dest->sa_len)(dest->sa_len>0 ? (1 + (((dest->sa_len) - 1) | (sizeof
(long) - 1))) : sizeof(long))
- dest->sa_len;
794 if (padlen > 0) {
795 iov[iovcnt].iov_base = &pad;
796 iov[iovcnt].iov_len = padlen;
797 iovcnt++;
798 }
799 }
800
801 if (rtm.rtm_addrs & RTA_GATEWAY0x2) {
802 iov[iovcnt].iov_base = addr;
803 iov[iovcnt].iov_len = addr->sa_len;
804 iovcnt++;
805 padlen = ROUNDUP(addr->sa_len)(addr->sa_len>0 ? (1 + (((addr->sa_len) - 1) | (sizeof
(long) - 1))) : sizeof(long))
- addr->sa_len;
806 if (padlen > 0) {
807 iov[iovcnt].iov_base = &pad;
808 iov[iovcnt].iov_len = padlen;
809 iovcnt++;
810 }
811 }
812
813 if (rtm.rtm_addrs & RTA_NETMASK0x4) {
814 iov[iovcnt].iov_base = mask;
815 iov[iovcnt].iov_len = mask->sa_len;
816 iovcnt++;
817 padlen = ROUNDUP(mask->sa_len)(mask->sa_len>0 ? (1 + (((mask->sa_len) - 1) | (sizeof
(long) - 1))) : sizeof(long))
- mask->sa_len;
818 if (padlen > 0) {
819 iov[iovcnt].iov_base = &pad;
820 iov[iovcnt].iov_len = padlen;
821 iovcnt++;
822 }
823 }
824
825 for (i = 0; i < iovcnt; i++)
826 rtm.rtm_msglen += iov[i].iov_len;
827
828 log_debug("%s: len: %u type: %s rdomain: %d flags %x (%s%s)"
829 " addrs %x (dst %s mask %s gw %s)", __func__, rtm.rtm_msglen,
830 type == RTM_ADD0x1 ? "RTM_ADD" : type == RTM_DELETE0x2 ? "RTM_DELETE" :
831 type == RTM_GET0x4 ? "RTM_GET" : "unknown", rdomain,
832 flags,
833 flags & RTF_HOST0x4 ? "H" : "",
834 flags & RTF_GATEWAY0x2 ? "G" : "",
835 addrs,
836 addrs & RTA_DST0x1 ? print_host(dest, NULL((void *)0), 0) : "<>",
837 addrs & RTA_NETMASK0x4 ? print_host(mask, NULL((void *)0), 0) : "<>",
838 addrs & RTA_GATEWAY0x2 ? print_host(addr, NULL((void *)0), 0) : "<>");
839
840 if (writev(ivr->ivr_rtsock, iov, iovcnt) == -1) {
841 if ((type == RTM_ADD0x1 && errno(*__errno()) != EEXIST17) ||
842 (type == RTM_DELETE0x2 && errno(*__errno()) != ESRCH3)) {
843 log_warn("%s: write %d", __func__, rtm.rtm_errno);
844 return (0);
845 }
846 }
847
848 if (type == RTM_GET0x4) {
849 do {
850 len = read(ivr->ivr_rtsock, &m_rtmsg, sizeof(m_rtmsg));
851 } while(len > 0 && (rtm.rtm_version != RTM_VERSION5 ||
852 rtm.rtm_seq != ivr->ivr_rtseq || rtm.rtm_pid != ivr->ivr_pid));
853 return (vroute_process(env, len, &m_rtmsg, dest, mask, addr, need_gw));
854 }
855#undef rtm
856
857 return (0);
858}
859
860int
861vroute_process(struct iked *env, int msglen, struct vroute_msg *m_rtmsg,
862 struct sockaddr *dest, struct sockaddr *mask, struct sockaddr *addr, int *need_gw)
863{
864 struct sockaddr *sa;
865 char *cp;
866 int i;
867
868#define rtm m_rtmsg->vm_rtm
869 if (rtm.rtm_version != RTM_VERSION5) {
870 warnx("routing message version %u not understood",
871 rtm.rtm_version);
872 return (-1);
873 }
874 if (rtm.rtm_msglen > msglen) {
875 warnx("message length mismatch, in packet %u, returned %d",
876 rtm.rtm_msglen, msglen);
877 return (-1);
878 }
879 if (rtm.rtm_errno) {
880 warnx("RTM_GET: %s (errno %d)",
881 strerror(rtm.rtm_errno), rtm.rtm_errno);
882 return (-1);
883 }
884 cp = m_rtmsg->vm_space;
885 *need_gw = rtm.rtm_flags & RTF_GATEWAY0x2;
886 if(rtm.rtm_addrs) {
887 for (i = 1; i; i <<= 1) {
888 if (i & rtm.rtm_addrs) {
889 sa = (struct sockaddr *)cp;
890 switch(i) {
891 case RTA_DST0x1:
892 memcpy(dest, cp, sa->sa_len);
893 break;
894 case RTA_NETMASK0x4:
895 memcpy(mask, cp, sa->sa_len);
896 break;
897 case RTA_GATEWAY0x2:
898 memcpy(addr, cp, sa->sa_len);
899 break;
900 }
901 cp += ROUNDUP(sa->sa_len)(sa->sa_len>0 ? (1 + (((sa->sa_len) - 1) | (sizeof(long
) - 1))) : sizeof(long))
;
902 }
903 }
904 }
905#undef rtm
906 return (0);
907}
908
909int
910vroute_doaddr(struct iked *env, char *ifname, struct sockaddr *addr,
911 struct sockaddr *mask, int add)
912{
913 struct iked_vroute_sc *ivr = env->sc_vroute;
914 struct ifaliasreq req;
915 struct in6_aliasreq req6;
916 unsigned long ioreq;
917 int af;
918
919 af = addr->sa_family;
920 switch (af) {
921 case AF_INET2:
922 bzero(&req, sizeof(req));
923 strncpy(req.ifra_name, ifname, sizeof(req.ifra_name));
924 memcpy(&req.ifra_addrifra_ifrau.ifrau_addr, addr, sizeof(req.ifra_addrifra_ifrau.ifrau_addr));
925 if (add)
926 memcpy(&req.ifra_mask, mask, sizeof(req.ifra_addrifra_ifrau.ifrau_addr));
927
928 log_debug("%s: %s inet %s netmask %s", __func__,
929 add ? "add" : "del",
930 print_host((struct sockaddr *)addr, NULL((void *)0), 0),
931 print_host((struct sockaddr *)mask, NULL((void *)0), 0));
932
933 ioreq = add ? SIOCAIFADDR((unsigned long)0x80000000 | ((sizeof(struct ifaliasreq) &
0x1fff) << 16) | ((('i')) << 8) | ((26)))
: SIOCDIFADDR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((25)))
;
934 if (ioctl(ivr->ivr_iosock, ioreq, &req) == -1) {
935 log_warn("%s: req: %lu", __func__, ioreq);
936 return (-1);
937 }
938 break;
939 case AF_INET624:
940 bzero(&req6, sizeof(req6));
941 strncpy(req6.ifra_name, ifname, sizeof(req6.ifra_name));
942 req6.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME0xffffffff;
943 req6.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME0xffffffff;
944
945 memcpy(&req6.ifra_addrifra_ifrau.ifrau_addr, addr, sizeof(req6.ifra_addrifra_ifrau.ifrau_addr));
946 if (add)
947 memcpy(&req6.ifra_prefixmask, mask,
948 sizeof(req6.ifra_prefixmask));
949
950 log_debug("%s: %s inet6 %s netmask %s", __func__,
951 add ? "add" : "del",
952 print_host((struct sockaddr *)addr, NULL((void *)0), 0),
953 print_host((struct sockaddr *)mask, NULL((void *)0), 0));
954
955 ioreq = add ? SIOCAIFADDR_IN6((unsigned long)0x80000000 | ((sizeof(struct in6_aliasreq) &
0x1fff) << 16) | ((('i')) << 8) | ((26)))
: SIOCDIFADDR_IN6((unsigned long)0x80000000 | ((sizeof(struct in6_ifreq) &
0x1fff) << 16) | ((('i')) << 8) | ((25)))
;
956 if (ioctl(ivr->ivr_iosock6, ioreq, &req6) == -1) {
957 log_warn("%s: req: %lu", __func__, ioreq);
958 return (-1);
959 }
960 break;
961 default:
962 return (-1);
963 }
964
965 return (0);
966}