util.c revision 1.3 1 /* $NetBSD: util.c,v 1.3 2008/05/07 18:17:42 dyoung Exp $ */
2
3 /*-
4 * Copyright (c)2008 David Young. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28 #include <ctype.h>
29 #include <err.h>
30 #include <errno.h>
31 #include <stddef.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <unistd.h>
36
37 #include <sys/socket.h>
38 #include <netinet/in.h> /* XXX */
39
40 #include "util.h"
41
42 int
43 getsock(int naf)
44 {
45 static int oaf = -1, s;
46
47 if (oaf == naf || (oaf != -1 && naf == AF_UNSPEC))
48 return s;
49
50 if (oaf != -1)
51 close(s);
52
53 if (naf == AF_UNSPEC)
54 naf = AF_INET;
55
56 s = socket(naf, SOCK_DGRAM, 0);
57 if (s == -1)
58 oaf = -1;
59 else
60 oaf = naf;
61 return s;
62 }
63
64 const char *
65 get_string(const char *val, const char *sep, u_int8_t *buf, int *lenp)
66 {
67 int len;
68 bool hexstr;
69 u_int8_t *p;
70
71 len = *lenp;
72 p = buf;
73 hexstr = (val[0] == '0' && tolower((u_char)val[1]) == 'x');
74 if (hexstr)
75 val += 2;
76 for (;;) {
77 if (*val == '\0')
78 break;
79 if (sep != NULL && strchr(sep, *val) != NULL) {
80 val++;
81 break;
82 }
83 if (hexstr) {
84 if (!isxdigit((u_char)val[0]) ||
85 !isxdigit((u_char)val[1])) {
86 warnx("bad hexadecimal digits");
87 return NULL;
88 }
89 }
90 if (p > buf + len) {
91 if (hexstr)
92 warnx("hexadecimal digits too long");
93 else
94 warnx("strings too long");
95 return NULL;
96 }
97 if (hexstr) {
98 #define tohex(x) (isdigit(x) ? (x) - '0' : tolower(x) - 'a' + 10)
99 *p++ = (tohex((u_char)val[0]) << 4) |
100 tohex((u_char)val[1]);
101 #undef tohex
102 val += 2;
103 } else
104 *p++ = *val++;
105 }
106 len = p - buf;
107 if (len < *lenp)
108 memset(p, 0, *lenp - len);
109 *lenp = len;
110 return val;
111 }
112
113 void
114 print_string(const u_int8_t *buf, int len)
115 {
116 int i;
117 bool hasspc;
118
119 i = 0;
120 hasspc = false;
121 if (len < 2 || buf[0] != '0' || tolower(buf[1]) != 'x') {
122 for (; i < len; i++) {
123 if (!isprint(buf[i]))
124 break;
125 if (isspace(buf[i]))
126 hasspc = true;
127 }
128 }
129 if (i == len) {
130 if (hasspc || len == 0)
131 printf("\"%.*s\"", len, buf);
132 else
133 printf("%.*s", len, buf);
134 } else {
135 printf("0x");
136 for (i = 0; i < len; i++)
137 printf("%02x", buf[i]);
138 }
139 }
140
141 struct paddr_prefix *
142 prefixlen_to_mask(int af, int plen)
143 {
144 union {
145 struct sockaddr sa;
146 struct sockaddr_in sin;
147 struct sockaddr_in6 sin6;
148 } u;
149 struct paddr_prefix *pfx;
150 size_t addrlen;
151 uint8_t *addr;
152 int nbit;
153
154 memset(&u, 0, sizeof(u));
155
156 switch (af) {
157 case AF_INET:
158 addrlen = sizeof(u.sin.sin_addr);
159 addr = (uint8_t *)&u.sin.sin_addr;
160 u.sa.sa_len = sizeof(u.sin);
161 break;
162 case AF_INET6:
163 addrlen = sizeof(u.sin6.sin6_addr);
164 addr = (uint8_t *)&u.sin6.sin6_addr;
165 u.sa.sa_len = sizeof(u.sin6);
166 break;
167 default:
168 errno = EINVAL;
169 return NULL;
170 }
171 u.sa.sa_family = af;
172
173 if (plen < 0 || plen > addrlen * NBBY) {
174 errno = EINVAL;
175 return NULL;
176 }
177
178 if (plen == 0)
179 plen = addrlen * NBBY;
180
181 memset(addr, 0xff, (plen + NBBY - 1) / NBBY);
182
183 nbit = plen % NBBY;
184 if (nbit != 0)
185 addr[plen / NBBY] &= ~((uint8_t)0xff >> nbit);
186 pfx = malloc(offsetof(struct paddr_prefix, pfx_addr) + u.sa.sa_len);
187 if (pfx == NULL)
188 return NULL;
189 pfx->pfx_len = plen;
190 memcpy(&pfx->pfx_addr, &u.sa, u.sa.sa_len);
191
192 return pfx;
193 }
194