xref: /openbsd/sbin/iked/util.c (revision ce50f388)
1 /*	$OpenBSD: util.c,v 1.45 2024/07/01 14:15:15 yasuoka Exp $	*/
2 
3 /*
4  * Copyright (c) 2010-2013 Reyk Floeter <reyk@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/types.h>
20 #include <sys/queue.h>
21 #include <sys/socket.h>
22 #include <sys/uio.h>
23 
24 #include <netdb.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <string.h>
29 #include <errno.h>
30 #include <limits.h>
31 #include <fcntl.h>
32 #include <ctype.h>
33 #include <event.h>
34 
35 #include "iked.h"
36 #include "ikev2.h"
37 
38 int
socket_af(struct sockaddr * sa,in_port_t port)39 socket_af(struct sockaddr *sa, in_port_t port)
40 {
41 	errno = 0;
42 	switch (sa->sa_family) {
43 	case AF_INET:
44 		((struct sockaddr_in *)sa)->sin_port = port;
45 		((struct sockaddr_in *)sa)->sin_len =
46 		    sizeof(struct sockaddr_in);
47 		break;
48 	case AF_INET6:
49 		((struct sockaddr_in6 *)sa)->sin6_port = port;
50 		((struct sockaddr_in6 *)sa)->sin6_len =
51 		    sizeof(struct sockaddr_in6);
52 		break;
53 	default:
54 		errno = EPFNOSUPPORT;
55 		return (-1);
56 	}
57 
58 	return (0);
59 }
60 
61 in_port_t
socket_getport(struct sockaddr * sa)62 socket_getport(struct sockaddr *sa)
63 {
64 	switch (sa->sa_family) {
65 	case AF_INET:
66 		return (ntohs(((struct sockaddr_in *)sa)->sin_port));
67 	case AF_INET6:
68 		return (ntohs(((struct sockaddr_in6 *)sa)->sin6_port));
69 	default:
70 		return (0);
71 	}
72 
73 	/* NOTREACHED */
74 	return (0);
75 }
76 
77 int
socket_setport(struct sockaddr * sa,in_port_t port)78 socket_setport(struct sockaddr *sa, in_port_t port)
79 {
80 	switch (sa->sa_family) {
81 	case AF_INET:
82 		((struct sockaddr_in *)sa)->sin_port = htons(port);
83 		break;
84 	case AF_INET6:
85 		((struct sockaddr_in6 *)sa)->sin6_port = htons(port);
86 		break;
87 	default:
88 		return (-1);
89 	}
90 	return (0);
91 }
92 
93 int
socket_getaddr(int s,struct sockaddr_storage * ss)94 socket_getaddr(int s, struct sockaddr_storage *ss)
95 {
96 	socklen_t sslen = sizeof(*ss);
97 
98 	return (getsockname(s, (struct sockaddr *)ss, &sslen));
99 }
100 
101 int
socket_bypass(int s,struct sockaddr * sa)102 socket_bypass(int s, struct sockaddr *sa)
103 {
104 	int	 v, *a;
105 	int	 a4[] = {
106 		    IPPROTO_IP,
107 		    IP_AUTH_LEVEL,
108 		    IP_ESP_TRANS_LEVEL,
109 		    IP_ESP_NETWORK_LEVEL,
110 #ifdef IPV6_IPCOMP_LEVEL
111 		    IP_IPCOMP_LEVEL
112 #endif
113 	};
114 	int	 a6[] = {
115 		    IPPROTO_IPV6,
116 		    IPV6_AUTH_LEVEL,
117 		    IPV6_ESP_TRANS_LEVEL,
118 		    IPV6_ESP_NETWORK_LEVEL,
119 #ifdef IPV6_IPCOMP_LEVEL
120 		    IPV6_IPCOMP_LEVEL
121 #endif
122 	};
123 
124 	switch (sa->sa_family) {
125 	case AF_INET:
126 		a = a4;
127 		break;
128 	case AF_INET6:
129 		a = a6;
130 		break;
131 	default:
132 		log_warn("%s: invalid address family", __func__);
133 		return (-1);
134 	}
135 
136 	v = IPSEC_LEVEL_BYPASS;
137 	if (setsockopt(s, a[0], a[1], &v, sizeof(v)) == -1) {
138 		log_warn("%s: AUTH_LEVEL", __func__);
139 		return (-1);
140 	}
141 	if (setsockopt(s, a[0], a[2], &v, sizeof(v)) == -1) {
142 		log_warn("%s: ESP_TRANS_LEVEL", __func__);
143 		return (-1);
144 	}
145 	if (setsockopt(s, a[0], a[3], &v, sizeof(v)) == -1) {
146 		log_warn("%s: ESP_NETWORK_LEVEL", __func__);
147 		return (-1);
148 	}
149 #ifdef IP_IPCOMP_LEVEL
150 	if (setsockopt(s, a[0], a[4], &v, sizeof(v)) == -1) {
151 		log_warn("%s: IPCOMP_LEVEL", __func__);
152 		return (-1);
153 	}
154 #endif
155 
156 	return (0);
157 }
158 
159 int
udp_bind(struct sockaddr * sa,in_port_t port)160 udp_bind(struct sockaddr *sa, in_port_t port)
161 {
162 	int	 s, val;
163 
164 	if (socket_af(sa, port) == -1) {
165 		log_warn("%s: failed to set UDP port", __func__);
166 		return (-1);
167 	}
168 
169 	if ((s = socket(sa->sa_family,
170 	    SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP)) == -1) {
171 		log_warn("%s: failed to get UDP socket", __func__);
172 		return (-1);
173 	}
174 
175 	/* Skip IPsec processing (don't encrypt) for IKE messages */
176 	if (socket_bypass(s, sa) == -1) {
177 		log_warn("%s: failed to bypass IPsec on IKE socket",
178 		    __func__);
179 		goto bad;
180 	}
181 
182 	val = 1;
183 	if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(int)) == -1) {
184 		log_warn("%s: failed to set reuseport", __func__);
185 		goto bad;
186 	}
187 	val = 1;
188 	if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(int)) == -1) {
189 		log_warn("%s: failed to set reuseaddr", __func__);
190 		goto bad;
191 	}
192 
193 	if (sa->sa_family == AF_INET) {
194 		val = 1;
195 		if (setsockopt(s, IPPROTO_IP, IP_RECVDSTADDR,
196 		    &val, sizeof(int)) == -1) {
197 			log_warn("%s: failed to set IPv4 packet info",
198 			    __func__);
199 			goto bad;
200 		}
201 	} else {
202 		val = 1;
203 		if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO,
204 		    &val, sizeof(int)) == -1) {
205 			log_warn("%s: failed to set IPv6 packet info",
206 			    __func__);
207 			goto bad;
208 		}
209 	}
210 
211 	if (bind(s, sa, sa->sa_len) == -1) {
212 		log_warn("%s: failed to bind UDP socket", __func__);
213 		goto bad;
214 	}
215 
216 	return (s);
217  bad:
218 	close(s);
219 	return (-1);
220 }
221 
222 int
sockaddr_cmp(struct sockaddr * a,struct sockaddr * b,int prefixlen)223 sockaddr_cmp(struct sockaddr *a, struct sockaddr *b, int prefixlen)
224 {
225 	struct sockaddr_in	*a4, *b4;
226 	struct sockaddr_in6	*a6, *b6;
227 	uint32_t		 av[4], bv[4], mv[4];
228 
229 	if (a->sa_family == AF_UNSPEC || b->sa_family == AF_UNSPEC)
230 		return (0);
231 	else if (a->sa_family > b->sa_family)
232 		return (1);
233 	else if (a->sa_family < b->sa_family)
234 		return (-1);
235 
236 	if (prefixlen == -1)
237 		memset(&mv, 0xff, sizeof(mv));
238 
239 	switch (a->sa_family) {
240 	case AF_INET:
241 		a4 = (struct sockaddr_in *)a;
242 		b4 = (struct sockaddr_in *)b;
243 
244 		av[0] = a4->sin_addr.s_addr;
245 		bv[0] = b4->sin_addr.s_addr;
246 		if (prefixlen != -1)
247 			mv[0] = prefixlen2mask(prefixlen);
248 
249 		if ((av[0] & mv[0]) > (bv[0] & mv[0]))
250 			return (1);
251 		if ((av[0] & mv[0]) < (bv[0] & mv[0]))
252 			return (-1);
253 		break;
254 	case AF_INET6:
255 		a6 = (struct sockaddr_in6 *)a;
256 		b6 = (struct sockaddr_in6 *)b;
257 
258 		memcpy(&av, &a6->sin6_addr.s6_addr, 16);
259 		memcpy(&bv, &b6->sin6_addr.s6_addr, 16);
260 		if (prefixlen != -1)
261 			prefixlen2mask6(prefixlen, mv);
262 
263 		if ((av[3] & mv[3]) > (bv[3] & mv[3]))
264 			return (1);
265 		if ((av[3] & mv[3]) < (bv[3] & mv[3]))
266 			return (-1);
267 		if ((av[2] & mv[2]) > (bv[2] & mv[2]))
268 			return (1);
269 		if ((av[2] & mv[2]) < (bv[2] & mv[2]))
270 			return (-1);
271 		if ((av[1] & mv[1]) > (bv[1] & mv[1]))
272 			return (1);
273 		if ((av[1] & mv[1]) < (bv[1] & mv[1]))
274 			return (-1);
275 		if ((av[0] & mv[0]) > (bv[0] & mv[0]))
276 			return (1);
277 		if ((av[0] & mv[0]) < (bv[0] & mv[0]))
278 			return (-1);
279 		break;
280 	}
281 
282 	return (0);
283 }
284 
285 ssize_t
sendtofrom(int s,void * buf,size_t len,int flags,struct sockaddr * to,socklen_t tolen,struct sockaddr * from,socklen_t fromlen)286 sendtofrom(int s, void *buf, size_t len, int flags, struct sockaddr *to,
287     socklen_t tolen, struct sockaddr *from, socklen_t fromlen)
288 {
289 	struct iovec		 iov;
290 	struct msghdr		 msg;
291 	struct cmsghdr		*cmsg;
292 	struct in6_pktinfo	*pkt6;
293 	struct sockaddr_in	*in;
294 	struct sockaddr_in6	*in6;
295 	union {
296 		struct cmsghdr	hdr;
297 		char		inbuf[CMSG_SPACE(sizeof(struct in_addr))];
298 		char		in6buf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
299 	} cmsgbuf;
300 
301 	bzero(&msg, sizeof(msg));
302 	bzero(&cmsgbuf, sizeof(cmsgbuf));
303 
304 	iov.iov_base = buf;
305 	iov.iov_len = len;
306 	msg.msg_iov = &iov;
307 	msg.msg_iovlen = 1;
308 	msg.msg_name = to;
309 	msg.msg_namelen = tolen;
310 	msg.msg_control = &cmsgbuf;
311 	msg.msg_controllen = sizeof(cmsgbuf);
312 
313 	cmsg = CMSG_FIRSTHDR(&msg);
314 	switch (to->sa_family) {
315 	case AF_INET:
316 		msg.msg_controllen = sizeof(cmsgbuf.inbuf);
317 		cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
318 		cmsg->cmsg_level = IPPROTO_IP;
319 		cmsg->cmsg_type = IP_SENDSRCADDR;
320 		in = (struct sockaddr_in *)from;
321 		memcpy(CMSG_DATA(cmsg), &in->sin_addr, sizeof(struct in_addr));
322 		break;
323 	case AF_INET6:
324 		msg.msg_controllen = sizeof(cmsgbuf.in6buf);
325 		cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
326 		cmsg->cmsg_level = IPPROTO_IPV6;
327 		cmsg->cmsg_type = IPV6_PKTINFO;
328 		in6 = (struct sockaddr_in6 *)from;
329 		pkt6 = (struct in6_pktinfo *)CMSG_DATA(cmsg);
330 		pkt6->ipi6_addr = in6->sin6_addr;
331 		break;
332 	}
333 
334 	return sendmsg(s, &msg, flags);
335 }
336 
337 ssize_t
recvfromto(int s,void * buf,size_t len,int flags,struct sockaddr * from,socklen_t * fromlen,struct sockaddr * to,socklen_t * tolen)338 recvfromto(int s, void *buf, size_t len, int flags, struct sockaddr *from,
339     socklen_t *fromlen, struct sockaddr *to, socklen_t *tolen)
340 {
341 	struct iovec		 iov;
342 	struct msghdr		 msg;
343 	struct cmsghdr		*cmsg;
344 	struct in6_pktinfo	*pkt6;
345 	struct sockaddr_in	*in;
346 	struct sockaddr_in6	*in6;
347 	ssize_t			 ret;
348 	union {
349 		struct cmsghdr hdr;
350 		char	buf[CMSG_SPACE(sizeof(struct sockaddr_storage))];
351 	} cmsgbuf;
352 
353 	bzero(&msg, sizeof(msg));
354 	bzero(&cmsgbuf.buf, sizeof(cmsgbuf.buf));
355 
356 	iov.iov_base = buf;
357 	iov.iov_len = len;
358 	msg.msg_iov = &iov;
359 	msg.msg_iovlen = 1;
360 	msg.msg_name = from;
361 	msg.msg_namelen = *fromlen;
362 	msg.msg_control = &cmsgbuf.buf;
363 	msg.msg_controllen = sizeof(cmsgbuf.buf);
364 
365 	if ((ret = recvmsg(s, &msg, flags)) == -1)
366 		return (-1);
367 
368 	*fromlen = from->sa_len;
369 
370 	if (getsockname(s, to, tolen) != 0)
371 		*tolen = 0;
372 
373 	for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
374 	    cmsg = CMSG_NXTHDR(&msg, cmsg)) {
375 		switch (from->sa_family) {
376 		case AF_INET:
377 			if (cmsg->cmsg_level == IPPROTO_IP &&
378 			    cmsg->cmsg_type == IP_RECVDSTADDR) {
379 				in = (struct sockaddr_in *)to;
380 				in->sin_family = AF_INET;
381 				in->sin_len = *tolen = sizeof(*in);
382 				memcpy(&in->sin_addr, CMSG_DATA(cmsg),
383 				    sizeof(struct in_addr));
384 			}
385 			break;
386 		case AF_INET6:
387 			if (cmsg->cmsg_level == IPPROTO_IPV6 &&
388 			    cmsg->cmsg_type == IPV6_PKTINFO) {
389 				in6 = (struct sockaddr_in6 *)to;
390 				in6->sin6_family = AF_INET6;
391 				in6->sin6_len = *tolen = sizeof(*in6);
392 				pkt6 = (struct in6_pktinfo *)CMSG_DATA(cmsg);
393 				memcpy(&in6->sin6_addr, &pkt6->ipi6_addr,
394 				    sizeof(struct in6_addr));
395 				if (IN6_IS_ADDR_LINKLOCAL(&in6->sin6_addr))
396 					in6->sin6_scope_id =
397 					    pkt6->ipi6_ifindex;
398 			}
399 			break;
400 		}
401 	}
402 
403 	return (ret);
404 }
405 
406 const char *
print_spi(uint64_t spi,int size)407 print_spi(uint64_t spi, int size)
408 {
409 	static char		 buf[IKED_CYCLE_BUFFERS][32];
410 	static int		 i = 0;
411 	char			*ptr;
412 
413 	ptr = buf[i];
414 
415 	switch (size) {
416 	case 2:
417 		snprintf(ptr, 32, "0x%04x", (uint16_t)spi);
418 		break;
419 	case 4:
420 		snprintf(ptr, 32, "0x%08x", (uint32_t)spi);
421 		break;
422 	case 8:
423 		snprintf(ptr, 32, "0x%016llx", spi);
424 		break;
425 	default:
426 		snprintf(ptr, 32, "%llu", spi);
427 		break;
428 	}
429 
430 	if (++i >= IKED_CYCLE_BUFFERS)
431 		i = 0;
432 
433 	return (ptr);
434 }
435 
436 const char *
print_map(unsigned int type,struct iked_constmap * map)437 print_map(unsigned int type, struct iked_constmap *map)
438 {
439 	unsigned int		 i;
440 	static char		 buf[IKED_CYCLE_BUFFERS][32];
441 	static int		 idx = 0;
442 	const char		*name = NULL;
443 
444 	if (idx >= IKED_CYCLE_BUFFERS)
445 		idx = 0;
446 	bzero(buf[idx], sizeof(buf[idx]));
447 
448 	for (i = 0; map[i].cm_name != NULL; i++) {
449 		if (map[i].cm_type == type)
450 			name = map[i].cm_name;
451 	}
452 
453 	if (name == NULL)
454 		snprintf(buf[idx], sizeof(buf[idx]), "<UNKNOWN:%u>", type);
455 	else
456 		strlcpy(buf[idx], name, sizeof(buf[idx]));
457 
458 	return (buf[idx++]);
459 }
460 
461 void
lc_idtype(char * str)462 lc_idtype(char *str)
463 {
464 	for (; *str != '\0' && *str != '/'; str++)
465 		*str = tolower((unsigned char)*str);
466 }
467 
468 void
print_hex(const uint8_t * buf,off_t offset,size_t length)469 print_hex(const uint8_t *buf, off_t offset, size_t length)
470 {
471 	unsigned int	 i;
472 
473 	if (log_getverbose() < 3 || !length)
474 		return;
475 
476 	for (i = 0; i < length; i++) {
477 		if (i && (i % 4) == 0) {
478 			if ((i % 32) == 0)
479 				print_debug("\n");
480 			else
481 				print_debug(" ");
482 		}
483 		print_debug("%02x", buf[offset + i]);
484 	}
485 	print_debug("\n");
486 }
487 
488 void
print_hexval(const uint8_t * buf,off_t offset,size_t length)489 print_hexval(const uint8_t *buf, off_t offset, size_t length)
490 {
491 	unsigned int	 i;
492 
493 	if (log_getverbose() < 2 || !length)
494 		return;
495 
496 	print_debug("0x");
497 	for (i = 0; i < length; i++)
498 		print_debug("%02x", buf[offset + i]);
499 	print_debug("\n");
500 }
501 
502 void
print_hexbuf(struct ibuf * ibuf)503 print_hexbuf(struct ibuf *ibuf)
504 {
505 	print_hex(ibuf_data(ibuf), 0, ibuf_size(ibuf));
506 }
507 
508 const char *
print_bits(unsigned short v,unsigned char * bits)509 print_bits(unsigned short v, unsigned char *bits)
510 {
511 	static char	 buf[IKED_CYCLE_BUFFERS][BUFSIZ];
512 	static int	 idx = 0;
513 	unsigned int	 i, any = 0, j = 0;
514 	unsigned char	 c;
515 
516 	if (!bits)
517 		return ("");
518 
519 	if (++idx >= IKED_CYCLE_BUFFERS)
520 		idx = 0;
521 
522 	bzero(buf[idx], sizeof(buf[idx]));
523 
524 	bits++;
525 	while ((i = *bits++)) {
526 		if (v & (1 << (i-1))) {
527 			if (any) {
528 				buf[idx][j++] = ',';
529 				if (j >= sizeof(buf[idx]))
530 					return (buf[idx]);
531 			}
532 			any = 1;
533 			for (; (c = *bits) > 32; bits++) {
534 				buf[idx][j++] = tolower((unsigned char)c);
535 				if (j >= sizeof(buf[idx]))
536 					return (buf[idx]);
537 			}
538 		} else
539 			for (; *bits > 32; bits++)
540 				;
541 	}
542 
543 	return (buf[idx]);
544 }
545 
546 uint8_t
mask2prefixlen(struct sockaddr * sa)547 mask2prefixlen(struct sockaddr *sa)
548 {
549 	struct sockaddr_in	*sa_in = (struct sockaddr_in *)sa;
550 	in_addr_t		 ina = sa_in->sin_addr.s_addr;
551 
552 	if (ina == 0)
553 		return (0);
554 	else
555 		return (33 - ffs(ntohl(ina)));
556 }
557 
558 uint8_t
mask2prefixlen6(struct sockaddr * sa)559 mask2prefixlen6(struct sockaddr *sa)
560 {
561 	struct sockaddr_in6	*sa_in6 = (struct sockaddr_in6 *)sa;
562 	uint8_t			*ap, *ep;
563 	unsigned int		 l = 0;
564 
565 	/*
566 	 * sin6_len is the size of the sockaddr so substract the offset of
567 	 * the possibly truncated sin6_addr struct.
568 	 */
569 	ap = (uint8_t *)&sa_in6->sin6_addr;
570 	ep = (uint8_t *)sa_in6 + sa_in6->sin6_len;
571 	for (; ap < ep; ap++) {
572 		/* this "beauty" is adopted from sbin/route/show.c ... */
573 		switch (*ap) {
574 		case 0xff:
575 			l += 8;
576 			break;
577 		case 0xfe:
578 			l += 7;
579 			goto done;
580 		case 0xfc:
581 			l += 6;
582 			goto done;
583 		case 0xf8:
584 			l += 5;
585 			goto done;
586 		case 0xf0:
587 			l += 4;
588 			goto done;
589 		case 0xe0:
590 			l += 3;
591 			goto done;
592 		case 0xc0:
593 			l += 2;
594 			goto done;
595 		case 0x80:
596 			l += 1;
597 			goto done;
598 		case 0x00:
599 			goto done;
600 		default:
601 			fatalx("non contiguous inet6 netmask");
602 		}
603 	}
604 
605 done:
606 	if (l > sizeof(struct in6_addr) * 8)
607 		fatalx("%s: prefixlen %d out of bound", __func__, l);
608 	return (l);
609 }
610 
611 uint32_t
prefixlen2mask(uint8_t prefixlen)612 prefixlen2mask(uint8_t prefixlen)
613 {
614 	if (prefixlen == 0)
615 		return (0);
616 
617 	if (prefixlen > 32)
618 		prefixlen = 32;
619 
620 	return (htonl(0xffffffff << (32 - prefixlen)));
621 }
622 
623 struct in6_addr *
prefixlen2mask6(uint8_t prefixlen,uint32_t * mask)624 prefixlen2mask6(uint8_t prefixlen, uint32_t *mask)
625 {
626 	static struct in6_addr  s6;
627 	int			i;
628 
629 	if (prefixlen > 128)
630 		prefixlen = 128;
631 
632 	bzero(&s6, sizeof(s6));
633 	for (i = 0; i < prefixlen / 8; i++)
634 		s6.s6_addr[i] = 0xff;
635 	i = prefixlen % 8;
636 	if (i)
637 		s6.s6_addr[prefixlen / 8] = 0xff00 >> i;
638 
639 	memcpy(mask, &s6, sizeof(s6));
640 
641 	return (&s6);
642 }
643 
644 const char *
print_addr(void * addr)645 print_addr(void *addr)
646 {
647 	static char	 sbuf[IKED_CYCLE_BUFFERS][NI_MAXHOST + 9];
648 	static int	 idx;
649 	struct sockaddr	*sa = addr;
650 	char		*buf, *hbuf;
651 	size_t		 len, hlen;
652 	char		 pbuf[7];
653 	in_port_t	 port;
654 
655 	hbuf = buf = sbuf[idx];
656 	hlen = len = sizeof(sbuf[idx]);
657 	if (++idx >= IKED_CYCLE_BUFFERS)
658 		idx = 0;
659 
660 	if (sa->sa_family == AF_UNSPEC) {
661 		strlcpy(buf, "any", len);
662 		return (buf);
663 	}
664 
665 	if ((port = socket_getport(sa)) != 0 && sa->sa_family == AF_INET6) {
666 		/* surround [] */
667 		*(hbuf++) = '[';
668 		hlen--;
669 	}
670 
671 	if (getnameinfo(sa, sa->sa_len,
672 	    hbuf, hlen, NULL, 0, NI_NUMERICHOST) != 0) {
673 		strlcpy(buf, "unknown", len);
674 		return (buf);
675 	}
676 
677 	if (port != 0) {
678 		if (sa->sa_family == AF_INET6)
679 			(void)strlcat(buf, "]", len);
680 		snprintf(pbuf, sizeof(pbuf), ":%d", port);
681 		(void)strlcat(buf, pbuf, len);
682 	}
683 
684 	return (buf);
685 }
686 
687 char *
get_string(uint8_t * ptr,size_t len)688 get_string(uint8_t *ptr, size_t len)
689 {
690 	size_t	 i;
691 
692 	for (i = 0; i < len; i++)
693 		if (!isprint(ptr[i]))
694 			break;
695 
696 	return strndup(ptr, i);
697 }
698 
699 const char *
print_proto(uint8_t proto)700 print_proto(uint8_t proto)
701 {
702 	struct protoent *p;
703 	static char	 buf[IKED_CYCLE_BUFFERS][BUFSIZ];
704 	static int	 idx = 0;
705 
706 	if (idx >= IKED_CYCLE_BUFFERS)
707 		idx = 0;
708 
709 	if ((p = getprotobynumber(proto)) != NULL)
710 		strlcpy(buf[idx], p->p_name, sizeof(buf[idx]));
711 	else
712 		snprintf(buf[idx], sizeof(buf[idx]), "%u", proto);
713 
714 	return (buf[idx++]);
715 }
716 
717 int
expand_string(char * label,size_t len,const char * srch,const char * repl)718 expand_string(char *label, size_t len, const char *srch, const char *repl)
719 {
720 	char *tmp;
721 	char *p, *q;
722 
723 	if ((tmp = calloc(1, len)) == NULL) {
724 		log_debug("%s: calloc", __func__);
725 		return (-1);
726 	}
727 	p = label;
728 	while ((q = strstr(p, srch)) != NULL) {
729 		*q = '\0';
730 		if ((strlcat(tmp, p, len) >= len) ||
731 		    (strlcat(tmp, repl, len) >= len)) {
732 			log_debug("%s: string too long", __func__);
733 			free(tmp);
734 			return (-1);
735 		}
736 		q += strlen(srch);
737 		p = q;
738 	}
739 	if (strlcat(tmp, p, len) >= len) {
740 		log_debug("%s: string too long", __func__);
741 		free(tmp);
742 		return (-1);
743 	}
744 	strlcpy(label, tmp, len);	/* always fits */
745 	free(tmp);
746 
747 	return (0);
748 }
749 
750 uint8_t *
string2unicode(const char * ascii,size_t * outlen)751 string2unicode(const char *ascii, size_t *outlen)
752 {
753 	uint8_t		*uc = NULL;
754 	size_t		 i, len = strlen(ascii);
755 
756 	if ((uc = calloc(1, (len * 2) + 2)) == NULL)
757 		return (NULL);
758 
759 	for (i = 0; i < len; i++) {
760 		/* XXX what about the byte order? */
761 		uc[i * 2] = ascii[i];
762 	}
763 	*outlen = len * 2;
764 
765 	return (uc);
766 }
767 
768 void
print_debug(const char * emsg,...)769 print_debug(const char *emsg, ...)
770 {
771 	va_list	 ap;
772 
773 	if (log_getverbose() > 2) {
774 		va_start(ap, emsg);
775 		vfprintf(stderr, emsg, ap);
776 		va_end(ap);
777 	}
778 }
779 
780 void
print_verbose(const char * emsg,...)781 print_verbose(const char *emsg, ...)
782 {
783 	va_list	 ap;
784 
785 	if (log_getverbose()) {
786 		va_start(ap, emsg);
787 		vfprintf(stderr, emsg, ap);
788 		va_end(ap);
789 	}
790 }
791