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