Bug Summary

File:src/usr.sbin/bgpd/pfkey.c
Warning:line 466, column 25
The left operand of '!=' is a garbage value

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 pfkey.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/usr.sbin/bgpd/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.sbin/bgpd -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/bgpd/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/usr.sbin/bgpd/pfkey.c
1/* $OpenBSD: pfkey.c,v 1.61 2020/04/23 16:13:11 claudio Exp $ */
2
3/*
4 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
5 * Copyright (c) 2003, 2004 Markus Friedl <markus@openbsd.org>
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#include <sys/types.h>
21#include <sys/socket.h>
22#include <sys/uio.h>
23#include <net/pfkeyv2.h>
24#include <netinet/ip_ipsp.h>
25#include <netinet/in.h>
26#include <netinet/tcp.h>
27#include <ctype.h>
28#include <errno(*__errno()).h>
29#include <limits.h>
30#include <stdlib.h>
31#include <string.h>
32#include <unistd.h>
33
34#include "bgpd.h"
35#include "session.h"
36#include "log.h"
37
38extern struct bgpd_sysdep sysdep;
39
40#define PFKEY2_CHUNKsizeof(u_int64_t) sizeof(u_int64_t)
41#define ROUNDUP(x)(((x) + (sizeof(u_int64_t) - 1)) & ~(sizeof(u_int64_t) - 1
))
(((x) + (PFKEY2_CHUNKsizeof(u_int64_t) - 1)) & ~(PFKEY2_CHUNKsizeof(u_int64_t) - 1))
42#define IOV_CNT20 20
43
44static u_int32_t sadb_msg_seq = 0;
45static u_int32_t pid = 0; /* should pid_t but pfkey needs u_int32_t */
46static int pfkey_fd;
47
48int pfkey_reply(int, u_int32_t *);
49int pfkey_send(int, uint8_t, uint8_t, uint8_t,
50 struct bgpd_addr *, struct bgpd_addr *,
51 u_int32_t, uint8_t, int, char *, uint8_t, int, char *,
52 uint16_t, uint16_t);
53
54#define pfkey_flow(fd, satype, cmd, dir, from, to, sport, dport)pfkey_send(fd, satype, cmd, dir, from, to, 0, 0, 0, ((void *)
0), 0, 0, ((void *)0), sport, dport)
\
55 pfkey_send(fd, satype, cmd, dir, from, to, \
56 0, 0, 0, NULL((void *)0), 0, 0, NULL((void *)0), sport, dport)
57
58static struct bgpd_addr *
59pfkey_localaddr(struct peer *p)
60{
61 switch (p->conf.remote_addr.aid) {
62 case AID_INET1:
63 return &p->conf.local_addr_v4;
64 case AID_INET62:
65 return &p->conf.local_addr_v6;
66 }
67 fatalx("Unknown AID in pfkey_localaddr");
68}
69
70int
71pfkey_send(int sd, uint8_t satype, uint8_t mtype, uint8_t dir,
72 struct bgpd_addr *src, struct bgpd_addr *dst, u_int32_t spi,
73 uint8_t aalg, int alen, char *akey, uint8_t ealg, int elen, char *ekey,
74 uint16_t sport, uint16_t dport)
75{
76 struct sadb_msg smsg;
77 struct sadb_sa sa;
78 struct sadb_address sa_src, sa_dst, sa_peer, sa_smask, sa_dmask;
79 struct sadb_key sa_akey, sa_ekey;
80 struct sadb_spirange sa_spirange;
81 struct sadb_protocol sa_flowtype, sa_protocol;
82 struct iovec iov[IOV_CNT20];
83 ssize_t n;
84 int len = 0;
85 int iov_cnt;
86 struct sockaddr_storage ssrc, sdst, speer, smask, dmask;
87 struct sockaddr *saptr;
88 socklen_t salen;
89
90 if (!pid)
91 pid = getpid();
92
93 /* we need clean sockaddr... no ports set */
94 bzero(&ssrc, sizeof(ssrc));
95 bzero(&smask, sizeof(smask));
96 if ((saptr = addr2sa(src, 0, &salen))) {
97 memcpy(&ssrc, saptr, salen);
98 ssrc.ss_len = salen;
99 }
100 switch (src->aid) {
101 case AID_INET1:
102 memset(&((struct sockaddr_in *)&smask)->sin_addr, 0xff, 32/8);
103 break;
104 case AID_INET62:
105 memset(&((struct sockaddr_in6 *)&smask)->sin6_addr, 0xff,
106 128/8);
107 break;
108 case AID_UNSPEC0:
109 ssrc.ss_len = sizeof(struct sockaddr);
110 break;
111 default:
112 return (-1);
113 }
114 smask.ss_family = ssrc.ss_family;
115 smask.ss_len = ssrc.ss_len;
116
117 bzero(&sdst, sizeof(sdst));
118 bzero(&dmask, sizeof(dmask));
119 if ((saptr = addr2sa(dst, 0, &salen))) {
120 memcpy(&sdst, saptr, salen);
121 sdst.ss_len = salen;
122 }
123 switch (dst->aid) {
124 case AID_INET1:
125 memset(&((struct sockaddr_in *)&dmask)->sin_addr, 0xff, 32/8);
126 break;
127 case AID_INET62:
128 memset(&((struct sockaddr_in6 *)&dmask)->sin6_addr, 0xff,
129 128/8);
130 break;
131 case AID_UNSPEC0:
132 sdst.ss_len = sizeof(struct sockaddr);
133 break;
134 default:
135 return (-1);
136 }
137 dmask.ss_family = sdst.ss_family;
138 dmask.ss_len = sdst.ss_len;
139
140 bzero(&smsg, sizeof(smsg));
141 smsg.sadb_msg_version = PF_KEY_V22;
142 smsg.sadb_msg_seq = ++sadb_msg_seq;
143 smsg.sadb_msg_pid = pid;
144 smsg.sadb_msg_len = sizeof(smsg) / 8;
145 smsg.sadb_msg_type = mtype;
146 smsg.sadb_msg_satype = satype;
147
148 switch (mtype) {
149 case SADB_GETSPI1:
150 bzero(&sa_spirange, sizeof(sa_spirange));
151 sa_spirange.sadb_spirange_exttype = SADB_EXT_SPIRANGE16;
152 sa_spirange.sadb_spirange_len = sizeof(sa_spirange) / 8;
153 sa_spirange.sadb_spirange_min = 0x100;
154 sa_spirange.sadb_spirange_max = 0xffffffff;
155 sa_spirange.sadb_spirange_reserved = 0;
156 break;
157 case SADB_ADD3:
158 case SADB_UPDATE2:
159 case SADB_DELETE4:
160 bzero(&sa, sizeof(sa));
161 sa.sadb_sa_exttype = SADB_EXT_SA1;
162 sa.sadb_sa_len = sizeof(sa) / 8;
163 sa.sadb_sa_replay = 0;
164 sa.sadb_sa_spi = htonl(spi)(__uint32_t)(__builtin_constant_p(spi) ? (__uint32_t)(((__uint32_t
)(spi) & 0xff) << 24 | ((__uint32_t)(spi) & 0xff00
) << 8 | ((__uint32_t)(spi) & 0xff0000) >> 8 |
((__uint32_t)(spi) & 0xff000000) >> 24) : __swap32md
(spi))
;
165 sa.sadb_sa_state = SADB_SASTATE_MATURE1;
166 break;
167 case SADB_X_ADDFLOW12:
168 case SADB_X_DELFLOW13:
169 bzero(&sa_flowtype, sizeof(sa_flowtype));
170 sa_flowtype.sadb_protocol_exttype = SADB_X_EXT_FLOW_TYPE20;
171 sa_flowtype.sadb_protocol_len = sizeof(sa_flowtype) / 8;
172 sa_flowtype.sadb_protocol_direction = dir;
173 sa_flowtype.sadb_protocol_proto = SADB_X_FLOW_TYPE_REQUIRE3;
174
175 bzero(&sa_protocol, sizeof(sa_protocol));
176 sa_protocol.sadb_protocol_exttype = SADB_X_EXT_PROTOCOL19;
177 sa_protocol.sadb_protocol_len = sizeof(sa_protocol) / 8;
178 sa_protocol.sadb_protocol_direction = 0;
179 sa_protocol.sadb_protocol_proto = 6;
180 break;
181 }
182
183 bzero(&sa_src, sizeof(sa_src));
184 sa_src.sadb_address_exttype = SADB_EXT_ADDRESS_SRC5;
185 sa_src.sadb_address_len = (sizeof(sa_src) + ROUNDUP(ssrc.ss_len)(((ssrc.ss_len) + (sizeof(u_int64_t) - 1)) & ~(sizeof(u_int64_t
) - 1))
) / 8;
186
187 bzero(&sa_dst, sizeof(sa_dst));
188 sa_dst.sadb_address_exttype = SADB_EXT_ADDRESS_DST6;
189 sa_dst.sadb_address_len = (sizeof(sa_dst) + ROUNDUP(sdst.ss_len)(((sdst.ss_len) + (sizeof(u_int64_t) - 1)) & ~(sizeof(u_int64_t
) - 1))
) / 8;
190
191 sa.sadb_sa_auth = aalg;
192 sa.sadb_sa_encrypt = SADB_X_EALG_AES12; /* XXX */
193
194 switch (mtype) {
195 case SADB_ADD3:
196 case SADB_UPDATE2:
197 bzero(&sa_akey, sizeof(sa_akey));
198 sa_akey.sadb_key_exttype = SADB_EXT_KEY_AUTH8;
199 sa_akey.sadb_key_len = (sizeof(sa_akey) +
200 ((alen + 7) / 8) * 8) / 8;
201 sa_akey.sadb_key_bits = 8 * alen;
202
203 bzero(&sa_ekey, sizeof(sa_ekey));
204 sa_ekey.sadb_key_exttype = SADB_EXT_KEY_ENCRYPT9;
205 sa_ekey.sadb_key_len = (sizeof(sa_ekey) +
206 ((elen + 7) / 8) * 8) / 8;
207 sa_ekey.sadb_key_bits = 8 * elen;
208
209 break;
210 case SADB_X_ADDFLOW12:
211 case SADB_X_DELFLOW13:
212 /* sa_peer always points to the remote machine */
213 if (dir == IPSP_DIRECTION_IN0x1) {
214 speer = ssrc;
215 sa_peer = sa_src;
216 } else {
217 speer = sdst;
218 sa_peer = sa_dst;
219 }
220 sa_peer.sadb_address_exttype = SADB_EXT_ADDRESS_DST6;
221 sa_peer.sadb_address_len =
222 (sizeof(sa_peer) + ROUNDUP(speer.ss_len)(((speer.ss_len) + (sizeof(u_int64_t) - 1)) & ~(sizeof(u_int64_t
) - 1))
) / 8;
223
224 /* for addflow we also use src/dst as the flow destination */
225 sa_src.sadb_address_exttype = SADB_X_EXT_SRC_FLOW21;
226 sa_dst.sadb_address_exttype = SADB_X_EXT_DST_FLOW22;
227
228 bzero(&smask, sizeof(smask));
229 switch (src->aid) {
230 case AID_INET1:
231 smask.ss_len = sizeof(struct sockaddr_in);
232 smask.ss_family = AF_INET2;
233 memset(&((struct sockaddr_in *)&smask)->sin_addr,
234 0xff, 32/8);
235 if (sport) {
236 ((struct sockaddr_in *)&ssrc)->sin_port =
237 htons(sport)(__uint16_t)(__builtin_constant_p(sport) ? (__uint16_t)(((__uint16_t
)(sport) & 0xffU) << 8 | ((__uint16_t)(sport) &
0xff00U) >> 8) : __swap16md(sport))
;
238 ((struct sockaddr_in *)&smask)->sin_port =
239 htons(0xffff)(__uint16_t)(__builtin_constant_p(0xffff) ? (__uint16_t)(((__uint16_t
)(0xffff) & 0xffU) << 8 | ((__uint16_t)(0xffff) &
0xff00U) >> 8) : __swap16md(0xffff))
;
240 }
241 break;
242 case AID_INET62:
243 smask.ss_len = sizeof(struct sockaddr_in6);
244 smask.ss_family = AF_INET624;
245 memset(&((struct sockaddr_in6 *)&smask)->sin6_addr,
246 0xff, 128/8);
247 if (sport) {
248 ((struct sockaddr_in6 *)&ssrc)->sin6_port =
249 htons(sport)(__uint16_t)(__builtin_constant_p(sport) ? (__uint16_t)(((__uint16_t
)(sport) & 0xffU) << 8 | ((__uint16_t)(sport) &
0xff00U) >> 8) : __swap16md(sport))
;
250 ((struct sockaddr_in6 *)&smask)->sin6_port =
251 htons(0xffff)(__uint16_t)(__builtin_constant_p(0xffff) ? (__uint16_t)(((__uint16_t
)(0xffff) & 0xffU) << 8 | ((__uint16_t)(0xffff) &
0xff00U) >> 8) : __swap16md(0xffff))
;
252 }
253 break;
254 }
255 bzero(&dmask, sizeof(dmask));
256 switch (dst->aid) {
257 case AID_INET1:
258 dmask.ss_len = sizeof(struct sockaddr_in);
259 dmask.ss_family = AF_INET2;
260 memset(&((struct sockaddr_in *)&dmask)->sin_addr,
261 0xff, 32/8);
262 if (dport) {
263 ((struct sockaddr_in *)&sdst)->sin_port =
264 htons(dport)(__uint16_t)(__builtin_constant_p(dport) ? (__uint16_t)(((__uint16_t
)(dport) & 0xffU) << 8 | ((__uint16_t)(dport) &
0xff00U) >> 8) : __swap16md(dport))
;
265 ((struct sockaddr_in *)&dmask)->sin_port =
266 htons(0xffff)(__uint16_t)(__builtin_constant_p(0xffff) ? (__uint16_t)(((__uint16_t
)(0xffff) & 0xffU) << 8 | ((__uint16_t)(0xffff) &
0xff00U) >> 8) : __swap16md(0xffff))
;
267 }
268 break;
269 case AID_INET62:
270 dmask.ss_len = sizeof(struct sockaddr_in6);
271 dmask.ss_family = AF_INET624;
272 memset(&((struct sockaddr_in6 *)&dmask)->sin6_addr,
273 0xff, 128/8);
274 if (dport) {
275 ((struct sockaddr_in6 *)&sdst)->sin6_port =
276 htons(dport)(__uint16_t)(__builtin_constant_p(dport) ? (__uint16_t)(((__uint16_t
)(dport) & 0xffU) << 8 | ((__uint16_t)(dport) &
0xff00U) >> 8) : __swap16md(dport))
;
277 ((struct sockaddr_in6 *)&dmask)->sin6_port =
278 htons(0xffff)(__uint16_t)(__builtin_constant_p(0xffff) ? (__uint16_t)(((__uint16_t
)(0xffff) & 0xffU) << 8 | ((__uint16_t)(0xffff) &
0xff00U) >> 8) : __swap16md(0xffff))
;
279 }
280 break;
281 }
282
283 bzero(&sa_smask, sizeof(sa_smask));
284 sa_smask.sadb_address_exttype = SADB_X_EXT_SRC_MASK17;
285 sa_smask.sadb_address_len =
286 (sizeof(sa_smask) + ROUNDUP(smask.ss_len)(((smask.ss_len) + (sizeof(u_int64_t) - 1)) & ~(sizeof(u_int64_t
) - 1))
) / 8;
287
288 bzero(&sa_dmask, sizeof(sa_dmask));
289 sa_dmask.sadb_address_exttype = SADB_X_EXT_DST_MASK18;
290 sa_dmask.sadb_address_len =
291 (sizeof(sa_dmask) + ROUNDUP(dmask.ss_len)(((dmask.ss_len) + (sizeof(u_int64_t) - 1)) & ~(sizeof(u_int64_t
) - 1))
) / 8;
292 break;
293 }
294
295 iov_cnt = 0;
296
297 /* msghdr */
298 iov[iov_cnt].iov_base = &smsg;
299 iov[iov_cnt].iov_len = sizeof(smsg);
300 iov_cnt++;
301
302 switch (mtype) {
303 case SADB_ADD3:
304 case SADB_UPDATE2:
305 case SADB_DELETE4:
306 /* SA hdr */
307 iov[iov_cnt].iov_base = &sa;
308 iov[iov_cnt].iov_len = sizeof(sa);
309 smsg.sadb_msg_len += sa.sadb_sa_len;
310 iov_cnt++;
311 break;
312 case SADB_GETSPI1:
313 /* SPI range */
314 iov[iov_cnt].iov_base = &sa_spirange;
315 iov[iov_cnt].iov_len = sizeof(sa_spirange);
316 smsg.sadb_msg_len += sa_spirange.sadb_spirange_len;
317 iov_cnt++;
318 break;
319 case SADB_X_ADDFLOW12:
320 /* sa_peer always points to the remote machine */
321 iov[iov_cnt].iov_base = &sa_peer;
322 iov[iov_cnt].iov_len = sizeof(sa_peer);
323 iov_cnt++;
324 iov[iov_cnt].iov_base = &speer;
325 iov[iov_cnt].iov_len = ROUNDUP(speer.ss_len)(((speer.ss_len) + (sizeof(u_int64_t) - 1)) & ~(sizeof(u_int64_t
) - 1))
;
326 smsg.sadb_msg_len += sa_peer.sadb_address_len;
327 iov_cnt++;
328
329 /* FALLTHROUGH */
330 case SADB_X_DELFLOW13:
331 /* add flow type */
332 iov[iov_cnt].iov_base = &sa_flowtype;
333 iov[iov_cnt].iov_len = sizeof(sa_flowtype);
334 smsg.sadb_msg_len += sa_flowtype.sadb_protocol_len;
335 iov_cnt++;
336
337 /* add protocol */
338 iov[iov_cnt].iov_base = &sa_protocol;
339 iov[iov_cnt].iov_len = sizeof(sa_protocol);
340 smsg.sadb_msg_len += sa_protocol.sadb_protocol_len;
341 iov_cnt++;
342
343 /* add flow masks */
344 iov[iov_cnt].iov_base = &sa_smask;
345 iov[iov_cnt].iov_len = sizeof(sa_smask);
346 iov_cnt++;
347 iov[iov_cnt].iov_base = &smask;
348 iov[iov_cnt].iov_len = ROUNDUP(smask.ss_len)(((smask.ss_len) + (sizeof(u_int64_t) - 1)) & ~(sizeof(u_int64_t
) - 1))
;
349 smsg.sadb_msg_len += sa_smask.sadb_address_len;
350 iov_cnt++;
351
352 iov[iov_cnt].iov_base = &sa_dmask;
353 iov[iov_cnt].iov_len = sizeof(sa_dmask);
354 iov_cnt++;
355 iov[iov_cnt].iov_base = &dmask;
356 iov[iov_cnt].iov_len = ROUNDUP(dmask.ss_len)(((dmask.ss_len) + (sizeof(u_int64_t) - 1)) & ~(sizeof(u_int64_t
) - 1))
;
357 smsg.sadb_msg_len += sa_dmask.sadb_address_len;
358 iov_cnt++;
359 break;
360 }
361
362 /* dest addr */
363 iov[iov_cnt].iov_base = &sa_dst;
364 iov[iov_cnt].iov_len = sizeof(sa_dst);
365 iov_cnt++;
366 iov[iov_cnt].iov_base = &sdst;
367 iov[iov_cnt].iov_len = ROUNDUP(sdst.ss_len)(((sdst.ss_len) + (sizeof(u_int64_t) - 1)) & ~(sizeof(u_int64_t
) - 1))
;
368 smsg.sadb_msg_len += sa_dst.sadb_address_len;
369 iov_cnt++;
370
371 /* src addr */
372 iov[iov_cnt].iov_base = &sa_src;
373 iov[iov_cnt].iov_len = sizeof(sa_src);
374 iov_cnt++;
375 iov[iov_cnt].iov_base = &ssrc;
376 iov[iov_cnt].iov_len = ROUNDUP(ssrc.ss_len)(((ssrc.ss_len) + (sizeof(u_int64_t) - 1)) & ~(sizeof(u_int64_t
) - 1))
;
377 smsg.sadb_msg_len += sa_src.sadb_address_len;
378 iov_cnt++;
379
380 switch (mtype) {
381 case SADB_ADD3:
382 case SADB_UPDATE2:
383 if (alen) {
384 /* auth key */
385 iov[iov_cnt].iov_base = &sa_akey;
386 iov[iov_cnt].iov_len = sizeof(sa_akey);
387 iov_cnt++;
388 iov[iov_cnt].iov_base = akey;
389 iov[iov_cnt].iov_len = ((alen + 7) / 8) * 8;
390 smsg.sadb_msg_len += sa_akey.sadb_key_len;
391 iov_cnt++;
392 }
393 if (elen) {
394 /* encryption key */
395 iov[iov_cnt].iov_base = &sa_ekey;
396 iov[iov_cnt].iov_len = sizeof(sa_ekey);
397 iov_cnt++;
398 iov[iov_cnt].iov_base = ekey;
399 iov[iov_cnt].iov_len = ((elen + 7) / 8) * 8;
400 smsg.sadb_msg_len += sa_ekey.sadb_key_len;
401 iov_cnt++;
402 }
403 break;
404 }
405
406 len = smsg.sadb_msg_len * 8;
407 do {
408 n = writev(sd, iov, iov_cnt);
409 } while (n == -1 && (errno(*__errno()) == EAGAIN35 || errno(*__errno()) == EINTR4));
410
411 if (n == -1) {
412 log_warn("%s: writev (%d/%d)", __func__, iov_cnt, len);
413 return (-1);
414 }
415
416 return (0);
417}
418
419int
420pfkey_read(int sd, struct sadb_msg *h)
421{
422 struct sadb_msg hdr;
423
424 if (recv(sd, &hdr, sizeof(hdr), MSG_PEEK0x2) != sizeof(hdr)) {
7
Assuming the condition is true
8
Taking true branch
425 if (errno(*__errno()) == EAGAIN35 || errno(*__errno()) == EINTR4)
9
Assuming the condition is true
426 return (0);
10
Returning without writing to 'h->sadb_msg_errno'
11
Returning zero, which participates in a condition later
427 log_warn("pfkey peek");
428 return (-1);
429 }
430
431 /* XXX: Only one message can be outstanding. */
432 if (hdr.sadb_msg_seq == sadb_msg_seq &&
433 hdr.sadb_msg_pid == pid) {
434 if (h)
435 bcopy(&hdr, h, sizeof(hdr));
436 return (0);
437 }
438
439 /* not ours, discard */
440 if (read(sd, &hdr, sizeof(hdr)) == -1) {
441 if (errno(*__errno()) == EAGAIN35 || errno(*__errno()) == EINTR4)
442 return (0);
443 log_warn("pfkey read");
444 return (-1);
445 }
446
447 return (1);
448}
449
450int
451pfkey_reply(int sd, u_int32_t *spi)
452{
453 struct sadb_msg hdr, *msg;
454 struct sadb_ext *ext;
455 struct sadb_sa *sa;
456 u_int8_t *data;
457 ssize_t len;
458 int rv;
459
460 do {
14
Loop condition is false. Exiting loop
461 rv = pfkey_read(sd, &hdr);
6
Calling 'pfkey_read'
12
Returning from 'pfkey_read'
462 if (rv == -1)
13
Taking false branch
463 return (-1);
464 } while (rv);
465
466 if (hdr.sadb_msg_errno != 0) {
15
The left operand of '!=' is a garbage value
467 errno(*__errno()) = hdr.sadb_msg_errno;
468 if (errno(*__errno()) == ESRCH3)
469 return (0);
470 else {
471 log_warn("pfkey");
472 return (-1);
473 }
474 }
475 if ((data = reallocarray(NULL((void *)0), hdr.sadb_msg_len, PFKEY2_CHUNKsizeof(u_int64_t)))
476 == NULL((void *)0)) {
477 log_warn("pfkey malloc");
478 return (-1);
479 }
480 len = hdr.sadb_msg_len * PFKEY2_CHUNKsizeof(u_int64_t);
481 if (read(sd, data, len) != len) {
482 log_warn("pfkey read");
483 freezero(data, len);
484 return (-1);
485 }
486
487 if (hdr.sadb_msg_type == SADB_GETSPI1) {
488 if (spi == NULL((void *)0)) {
489 freezero(data, len);
490 return (0);
491 }
492
493 msg = (struct sadb_msg *)data;
494 for (ext = (struct sadb_ext *)(msg + 1);
495 (size_t)((u_int8_t *)ext - (u_int8_t *)msg) <
496 msg->sadb_msg_len * PFKEY2_CHUNKsizeof(u_int64_t);
497 ext = (struct sadb_ext *)((u_int8_t *)ext +
498 ext->sadb_ext_len * PFKEY2_CHUNKsizeof(u_int64_t))) {
499 if (ext->sadb_ext_type == SADB_EXT_SA1) {
500 sa = (struct sadb_sa *) ext;
501 *spi = ntohl(sa->sadb_sa_spi)(__uint32_t)(__builtin_constant_p(sa->sadb_sa_spi) ? (__uint32_t
)(((__uint32_t)(sa->sadb_sa_spi) & 0xff) << 24 |
((__uint32_t)(sa->sadb_sa_spi) & 0xff00) << 8 |
((__uint32_t)(sa->sadb_sa_spi) & 0xff0000) >> 8
| ((__uint32_t)(sa->sadb_sa_spi) & 0xff000000) >>
24) : __swap32md(sa->sadb_sa_spi))
;
502 break;
503 }
504 }
505 }
506 freezero(data, len);
507 return (0);
508}
509
510static int
511pfkey_sa_add(struct bgpd_addr *src, struct bgpd_addr *dst, u_int8_t keylen,
512 char *key, u_int32_t *spi)
513{
514 if (pfkey_send(pfkey_fd, SADB_X_SATYPE_TCPSIGNATURE8, SADB_GETSPI1, 0,
4
Taking false branch
515 src, dst, 0, 0, 0, NULL((void *)0), 0, 0, NULL((void *)0), 0, 0) == -1)
516 return (-1);
517 if (pfkey_reply(pfkey_fd, spi) == -1)
5
Calling 'pfkey_reply'
518 return (-1);
519 if (pfkey_send(pfkey_fd, SADB_X_SATYPE_TCPSIGNATURE8, SADB_UPDATE2, 0,
520 src, dst, *spi, 0, keylen, key, 0, 0, NULL((void *)0), 0, 0) == -1)
521 return (-1);
522 if (pfkey_reply(pfkey_fd, NULL((void *)0)) == -1)
523 return (-1);
524 return (0);
525}
526
527static int
528pfkey_sa_remove(struct bgpd_addr *src, struct bgpd_addr *dst, u_int32_t *spi)
529{
530 if (pfkey_send(pfkey_fd, SADB_X_SATYPE_TCPSIGNATURE8, SADB_DELETE4, 0,
531 src, dst, *spi, 0, 0, NULL((void *)0), 0, 0, NULL((void *)0), 0, 0) == -1)
532 return (-1);
533 if (pfkey_reply(pfkey_fd, NULL((void *)0)) == -1)
534 return (-1);
535 *spi = 0;
536 return (0);
537}
538
539static int
540pfkey_md5sig_establish(struct peer *p)
541{
542 u_int32_t spi_out = 0;
543 u_int32_t spi_in = 0;
544
545 if (pfkey_sa_add(pfkey_localaddr(p), &p->conf.remote_addr,
3
Calling 'pfkey_sa_add'
546 p->conf.auth.md5key_len, p->conf.auth.md5key,
547 &spi_out) == -1)
548 goto fail;
549
550 if (pfkey_sa_add(&p->conf.remote_addr, pfkey_localaddr(p),
551 p->conf.auth.md5key_len, p->conf.auth.md5key,
552 &spi_in) == -1)
553 goto fail;
554
555 /* cleanup old flow if one was present */
556 if (p->auth.established) {
557 if (pfkey_remove(p) == -1)
558 return (-1);
559 }
560
561 p->auth.established = 1;
562 p->auth.spi_out = spi_out;
563 p->auth.spi_in = spi_in;
564 return (0);
565
566fail:
567 log_peer_warn(&p->conf, "%s: failed to insert md5sig", __func__);
568 return (-1);
569}
570
571static int
572pfkey_md5sig_remove(struct peer *p)
573{
574 if (p->auth.spi_out)
575 if (pfkey_sa_remove(&p->auth.local_addr, &p->conf.remote_addr,
576 &p->auth.spi_out) == -1)
577 goto fail;
578 if (p->auth.spi_in)
579 if (pfkey_sa_remove(&p->conf.remote_addr, &p->auth.local_addr,
580 &p->auth.spi_in) == -1)
581 goto fail;
582
583 p->auth.established = 0;
584 p->auth.spi_out = 0;
585 p->auth.spi_in = 0;
586 return (0);
587
588fail:
589 log_peer_warn(&p->conf, "%s: failed to remove md5sig", __func__);
590 return (-1);
591}
592
593static int
594pfkey_ipsec_establish(struct peer *p)
595{
596 uint8_t satype = SADB_SATYPE_ESP2;
597 struct bgpd_addr *local_addr = pfkey_localaddr(p);
598
599 /* cleanup first, unlike in the TCP MD5 case */
600 if (p->auth.established) {
601 if (pfkey_remove(p) == -1)
602 return (-1);
603 }
604
605 switch (p->auth.method) {
606 case AUTH_IPSEC_IKE_ESP:
607 satype = SADB_SATYPE_ESP2;
608 break;
609 case AUTH_IPSEC_IKE_AH:
610 satype = SADB_SATYPE_AH1;
611 break;
612 case AUTH_IPSEC_MANUAL_ESP:
613 case AUTH_IPSEC_MANUAL_AH:
614 satype = p->auth.method == AUTH_IPSEC_MANUAL_ESP ?
615 SADB_SATYPE_ESP2 : SADB_SATYPE_AH1;
616 if (pfkey_send(pfkey_fd, satype, SADB_ADD3, 0,
617 local_addr, &p->conf.remote_addr,
618 p->conf.auth.spi_out,
619 p->conf.auth.auth_alg_out,
620 p->conf.auth.auth_keylen_out,
621 p->conf.auth.auth_key_out,
622 p->conf.auth.enc_alg_out,
623 p->conf.auth.enc_keylen_out,
624 p->conf.auth.enc_key_out,
625 0, 0) == -1)
626 goto fail_key;
627 if (pfkey_reply(pfkey_fd, NULL((void *)0)) == -1)
628 goto fail_key;
629 if (pfkey_send(pfkey_fd, satype, SADB_ADD3, 0,
630 &p->conf.remote_addr, local_addr,
631 p->conf.auth.spi_in,
632 p->conf.auth.auth_alg_in,
633 p->conf.auth.auth_keylen_in,
634 p->conf.auth.auth_key_in,
635 p->conf.auth.enc_alg_in,
636 p->conf.auth.enc_keylen_in,
637 p->conf.auth.enc_key_in,
638 0, 0) == -1)
639 goto fail_key;
640 if (pfkey_reply(pfkey_fd, NULL((void *)0)) == -1)
641 goto fail_key;
642 break;
643 default:
644 return (-1);
645 }
646
647 if (pfkey_flow(pfkey_fd, satype, SADB_X_ADDFLOW, IPSP_DIRECTION_OUT,pfkey_send(pfkey_fd, satype, 12, 0x2, local_addr, &p->
conf.remote_addr, 0, 0, 0, ((void *)0), 0, 0, ((void *)0), 0,
179)
648 local_addr, &p->conf.remote_addr, 0, BGP_PORT)pfkey_send(pfkey_fd, satype, 12, 0x2, local_addr, &p->
conf.remote_addr, 0, 0, 0, ((void *)0), 0, 0, ((void *)0), 0,
179)
== -1)
649 goto fail_flow;
650 if (pfkey_reply(pfkey_fd, NULL((void *)0)) == -1)
651 goto fail_flow;
652
653 if (pfkey_flow(pfkey_fd, satype, SADB_X_ADDFLOW, IPSP_DIRECTION_OUT,pfkey_send(pfkey_fd, satype, 12, 0x2, local_addr, &p->
conf.remote_addr, 0, 0, 0, ((void *)0), 0, 0, ((void *)0), 179
, 0)
654 local_addr, &p->conf.remote_addr, BGP_PORT, 0)pfkey_send(pfkey_fd, satype, 12, 0x2, local_addr, &p->
conf.remote_addr, 0, 0, 0, ((void *)0), 0, 0, ((void *)0), 179
, 0)
== -1)
655 goto fail_flow;
656 if (pfkey_reply(pfkey_fd, NULL((void *)0)) == -1)
657 goto fail_flow;
658
659 if (pfkey_flow(pfkey_fd, satype, SADB_X_ADDFLOW, IPSP_DIRECTION_IN,pfkey_send(pfkey_fd, satype, 12, 0x1, &p->conf.remote_addr
, local_addr, 0, 0, 0, ((void *)0), 0, 0, ((void *)0), 0, 179
)
660 &p->conf.remote_addr, local_addr, 0, BGP_PORT)pfkey_send(pfkey_fd, satype, 12, 0x1, &p->conf.remote_addr
, local_addr, 0, 0, 0, ((void *)0), 0, 0, ((void *)0), 0, 179
)
== -1)
661 goto fail_flow;
662 if (pfkey_reply(pfkey_fd, NULL((void *)0)) == -1)
663 goto fail_flow;
664
665 if (pfkey_flow(pfkey_fd, satype, SADB_X_ADDFLOW, IPSP_DIRECTION_IN,pfkey_send(pfkey_fd, satype, 12, 0x1, &p->conf.remote_addr
, local_addr, 0, 0, 0, ((void *)0), 0, 0, ((void *)0), 179, 0
)
666 &p->conf.remote_addr, local_addr, BGP_PORT, 0)pfkey_send(pfkey_fd, satype, 12, 0x1, &p->conf.remote_addr
, local_addr, 0, 0, 0, ((void *)0), 0, 0, ((void *)0), 179, 0
)
== -1)
667 goto fail_flow;
668 if (pfkey_reply(pfkey_fd, NULL((void *)0)) == -1)
669 goto fail_flow;
670
671 /* save SPI so that they can be removed later on */
672 p->auth.spi_in = p->conf.auth.spi_in;
673 p->auth.spi_out = p->conf.auth.spi_out;
674 p->auth.established = 1;
675 return (0);
676
677fail_key:
678 log_peer_warn(&p->conf, "%s: failed to insert ipsec key", __func__);
679 return (-1);
680fail_flow:
681 log_peer_warn(&p->conf, "%s: failed to insert flow", __func__);
682 return (-1);
683}
684
685static int
686pfkey_ipsec_remove(struct peer *p)
687{
688 uint8_t satype;
689
690 switch (p->auth.method) {
691 case AUTH_IPSEC_IKE_ESP:
692 satype = SADB_SATYPE_ESP2;
693 break;
694 case AUTH_IPSEC_IKE_AH:
695 satype = SADB_SATYPE_AH1;
696 break;
697 case AUTH_IPSEC_MANUAL_ESP:
698 case AUTH_IPSEC_MANUAL_AH:
699 satype = p->auth.method == AUTH_IPSEC_MANUAL_ESP ?
700 SADB_SATYPE_ESP2 : SADB_SATYPE_AH1;
701 if (pfkey_send(pfkey_fd, satype, SADB_DELETE4, 0,
702 &p->auth.local_addr, &p->conf.remote_addr,
703 p->auth.spi_out, 0, 0, NULL((void *)0), 0, 0, NULL((void *)0),
704 0, 0) == -1)
705 goto fail_key;
706 if (pfkey_reply(pfkey_fd, NULL((void *)0)) == -1)
707 goto fail_key;
708
709 if (pfkey_send(pfkey_fd, satype, SADB_DELETE4, 0,
710 &p->conf.remote_addr, &p->auth.local_addr,
711 p->auth.spi_in, 0, 0, NULL((void *)0), 0, 0, NULL((void *)0),
712 0, 0) == -1)
713 goto fail_key;
714 if (pfkey_reply(pfkey_fd, NULL((void *)0)) == -1)
715 goto fail_key;
716 break;
717 default:
718 return (-1);
719 }
720
721 if (pfkey_flow(pfkey_fd, satype, SADB_X_DELFLOW, IPSP_DIRECTION_OUT,pfkey_send(pfkey_fd, satype, 13, 0x2, &p->auth.local_addr
, &p->conf.remote_addr, 0, 0, 0, ((void *)0), 0, 0, ((
void *)0), 0, 179)
722 &p->auth.local_addr, &p->conf.remote_addr, 0, BGP_PORT)pfkey_send(pfkey_fd, satype, 13, 0x2, &p->auth.local_addr
, &p->conf.remote_addr, 0, 0, 0, ((void *)0), 0, 0, ((
void *)0), 0, 179)
== -1)
723 goto fail_flow;
724 if (pfkey_reply(pfkey_fd, NULL((void *)0)) == -1)
725 goto fail_flow;
726
727 if (pfkey_flow(pfkey_fd, satype, SADB_X_DELFLOW, IPSP_DIRECTION_OUT,pfkey_send(pfkey_fd, satype, 13, 0x2, &p->auth.local_addr
, &p->conf.remote_addr, 0, 0, 0, ((void *)0), 0, 0, ((
void *)0), 179, 0)
728 &p->auth.local_addr, &p->conf.remote_addr, BGP_PORT, 0)pfkey_send(pfkey_fd, satype, 13, 0x2, &p->auth.local_addr
, &p->conf.remote_addr, 0, 0, 0, ((void *)0), 0, 0, ((
void *)0), 179, 0)
== -1)
729 goto fail_flow;
730 if (pfkey_reply(pfkey_fd, NULL((void *)0)) == -1)
731 goto fail_flow;
732
733 if (pfkey_flow(pfkey_fd, satype, SADB_X_DELFLOW, IPSP_DIRECTION_IN,pfkey_send(pfkey_fd, satype, 13, 0x1, &p->conf.remote_addr
, &p->auth.local_addr, 0, 0, 0, ((void *)0), 0, 0, ((void
*)0), 0, 179)
734 &p->conf.remote_addr, &p->auth.local_addr, 0, BGP_PORT)pfkey_send(pfkey_fd, satype, 13, 0x1, &p->conf.remote_addr
, &p->auth.local_addr, 0, 0, 0, ((void *)0), 0, 0, ((void
*)0), 0, 179)
== -1)
735 goto fail_flow;
736 if (pfkey_reply(pfkey_fd, NULL((void *)0)) == -1)
737 goto fail_flow;
738
739 if (pfkey_flow(pfkey_fd, satype, SADB_X_DELFLOW, IPSP_DIRECTION_IN,pfkey_send(pfkey_fd, satype, 13, 0x1, &p->conf.remote_addr
, &p->auth.local_addr, 0, 0, 0, ((void *)0), 0, 0, ((void
*)0), 179, 0)
740 &p->conf.remote_addr, &p->auth.local_addr, BGP_PORT, 0)pfkey_send(pfkey_fd, satype, 13, 0x1, &p->conf.remote_addr
, &p->auth.local_addr, 0, 0, 0, ((void *)0), 0, 0, ((void
*)0), 179, 0)
== -1)
741 goto fail_flow;
742 if (pfkey_reply(pfkey_fd, NULL((void *)0)) == -1)
743 goto fail_flow;
744
745 p->auth.established = 0;
746 p->auth.spi_out = 0;
747 p->auth.spi_in = 0;
748 return (0);
749
750fail_key:
751 log_peer_warn(&p->conf, "%s: failed to remove ipsec key", __func__);
752 return (-1);
753fail_flow:
754 log_peer_warn(&p->conf, "%s: failed to remove flow", __func__);
755 return (-1);
756}
757
758int
759pfkey_establish(struct peer *p)
760{
761 int rv;
762
763 switch (p->conf.auth.method) {
1
Control jumps to 'case AUTH_MD5SIG:' at line 769
764 case AUTH_NONE:
765 rv = 0;
766 if (p->auth.established)
767 rv = pfkey_remove(p);
768 break;
769 case AUTH_MD5SIG:
770 rv = pfkey_md5sig_establish(p);
2
Calling 'pfkey_md5sig_establish'
771 break;
772 default:
773 rv = pfkey_ipsec_establish(p);
774 break;
775 }
776 /*
777 * make sure we keep copies of everything we need to
778 * remove SAs and flows later again, even if the
779 * info in p->conf changed due to reload.
780 * We need: SPIs, method, local_addr, remote_addr.
781 * remote_addr cannot change, so no copy, SPI are
782 * handled by the method specific functions.
783 */
784 memcpy(&p->auth.local_addr, pfkey_localaddr(p),
785 sizeof(p->auth.local_addr));
786 p->auth.method = p->conf.auth.method;
787
788 return (rv);
789}
790
791int
792pfkey_remove(struct peer *p)
793{
794 if (p->auth.established == 0)
795 return (0);
796
797 switch (p->auth.method) {
798 case AUTH_NONE:
799 return (0);
800 case AUTH_MD5SIG:
801 return (pfkey_md5sig_remove(p));
802 default:
803 return (pfkey_ipsec_remove(p));
804 }
805}
806
807int
808pfkey_init(void)
809{
810 if ((pfkey_fd = socket(PF_KEY30, SOCK_RAW3 | SOCK_CLOEXEC0x8000 | SOCK_NONBLOCK0x4000,
811 PF_KEY_V22)) == -1) {
812 if (errno(*__errno()) == EPROTONOSUPPORT43) {
813 log_warnx("PF_KEY not available, disabling ipsec");
814 return (-1);
815 } else
816 fatal("pfkey setup failed");
817 }
818 return (pfkey_fd);
819}
820
821/* verify that connection is using TCP MD5UM if required by config */
822int
823tcp_md5_check(int fd, struct peer *p)
824{
825 socklen_t len;
826 int opt;
827
828 if (p->conf.auth.method == AUTH_MD5SIG) {
829 if (sysdep.no_md5sig) {
830 log_peer_warnx(&p->conf,
831 "md5sig configured but not available");
832 return -1;
833 }
834 len = sizeof(opt);
835 if (getsockopt(fd, IPPROTO_TCP6, TCP_MD5SIG0x04,
836 &opt, &len) == -1)
837 fatal("getsockopt TCP_MD5SIG");
838 if (!opt) { /* non-md5'd connection! */
839 log_peer_warnx(&p->conf,
840 "connection attempt without md5 signature");
841 return -1;
842 }
843 }
844 return 0;
845}
846
847/* enable or set TCP MD5SIG on a new client connection */
848int
849tcp_md5_set(int fd, struct peer *p)
850{
851 int opt = 1;
852
853 if (p->conf.auth.method == AUTH_MD5SIG) {
854 if (sysdep.no_md5sig) {
855 log_peer_warnx(&p->conf,
856 "md5sig configured but not available");
857 return -1;
858 }
859 if (setsockopt(fd, IPPROTO_TCP6, TCP_MD5SIG0x04,
860 &opt, sizeof(opt)) == -1) {
861 log_peer_warn(&p->conf, "setsockopt md5sig");
862 return -1;
863 }
864 }
865 return 0;
866}
867
868/* enable or prepare a new listening socket for TCP MD5SIG usage */
869int
870tcp_md5_prep_listener(struct listen_addr *la, struct peer_head *p)
871{
872 int opt = 1;
873
874 if (setsockopt(la->fd, IPPROTO_TCP6, TCP_MD5SIG0x04,
875 &opt, sizeof(opt)) == -1) {
876 if (errno(*__errno()) == ENOPROTOOPT42) { /* system w/o md5sig */
877 log_warnx("md5sig not available, disabling");
878 sysdep.no_md5sig = 1;
879 return 0;
880 }
881 return -1;
882 }
883 return 0;
884}
885
886/* add md5 key to all listening sockets, dummy function for portable */
887void
888tcp_md5_add_listener(struct bgpd_config *conf, struct peer *p)
889{
890}
891
892/* delete md5 key form all listening sockets, dummy function for portable */
893void
894tcp_md5_del_listener(struct bgpd_config *conf, struct peer *p)
895{
896}