util.c revision 1.1 1 #include <ctype.h>
2 #include <err.h>
3 #include <errno.h>
4 #include <stddef.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <unistd.h>
9
10 #include <sys/socket.h>
11 #include <netinet/in.h> /* XXX */
12
13 #include "util.h"
14
15 int
16 getsock(int naf)
17 {
18 static int oaf = -1, s;
19
20 if (oaf == naf || (oaf != -1 && naf == AF_UNSPEC))
21 return s;
22
23 if (oaf != -1)
24 close(s);
25
26 if (naf == AF_UNSPEC)
27 naf = AF_INET;
28
29 s = socket(naf, SOCK_DGRAM, 0);
30 if (s == -1)
31 oaf = -1;
32 else
33 oaf = naf;
34 return s;
35 }
36
37 const char *
38 get_string(const char *val, const char *sep, u_int8_t *buf, int *lenp)
39 {
40 int len;
41 bool hexstr;
42 u_int8_t *p;
43
44 len = *lenp;
45 p = buf;
46 hexstr = (val[0] == '0' && tolower((u_char)val[1]) == 'x');
47 if (hexstr)
48 val += 2;
49 for (;;) {
50 if (*val == '\0')
51 break;
52 if (sep != NULL && strchr(sep, *val) != NULL) {
53 val++;
54 break;
55 }
56 if (hexstr) {
57 if (!isxdigit((u_char)val[0]) ||
58 !isxdigit((u_char)val[1])) {
59 warnx("bad hexadecimal digits");
60 return NULL;
61 }
62 }
63 if (p > buf + len) {
64 if (hexstr)
65 warnx("hexadecimal digits too long");
66 else
67 warnx("strings too long");
68 return NULL;
69 }
70 if (hexstr) {
71 #define tohex(x) (isdigit(x) ? (x) - '0' : tolower(x) - 'a' + 10)
72 *p++ = (tohex((u_char)val[0]) << 4) |
73 tohex((u_char)val[1]);
74 #undef tohex
75 val += 2;
76 } else
77 *p++ = *val++;
78 }
79 len = p - buf;
80 if (len < *lenp)
81 memset(p, 0, *lenp - len);
82 *lenp = len;
83 return val;
84 }
85
86 void
87 print_string(const u_int8_t *buf, int len)
88 {
89 int i;
90 bool hasspc;
91
92 i = 0;
93 hasspc = false;
94 if (len < 2 || buf[0] != '0' || tolower(buf[1]) != 'x') {
95 for (; i < len; i++) {
96 if (!isprint(buf[i]))
97 break;
98 if (isspace(buf[i]))
99 hasspc = true;
100 }
101 }
102 if (i == len) {
103 if (hasspc || len == 0)
104 printf("\"%.*s\"", len, buf);
105 else
106 printf("%.*s", len, buf);
107 } else {
108 printf("0x");
109 for (i = 0; i < len; i++)
110 printf("%02x", buf[i]);
111 }
112 }
113
114 struct paddr_prefix *
115 prefixlen_to_mask(int af, int plen)
116 {
117 union {
118 struct sockaddr sa;
119 struct sockaddr_in sin;
120 struct sockaddr_in6 sin6;
121 } u;
122 struct paddr_prefix *pfx;
123 size_t addrlen;
124 uint8_t *addr;
125 int nbit;
126
127 memset(&u, 0, sizeof(u));
128
129 switch (af) {
130 case AF_INET:
131 addrlen = sizeof(u.sin.sin_addr);
132 addr = (uint8_t *)&u.sin.sin_addr;
133 u.sa.sa_len = sizeof(u.sin);
134 break;
135 case AF_INET6:
136 addrlen = sizeof(u.sin6.sin6_addr);
137 addr = (uint8_t *)&u.sin6.sin6_addr;
138 u.sa.sa_len = sizeof(u.sin6);
139 break;
140 default:
141 errno = EINVAL;
142 return NULL;
143 }
144 u.sa.sa_family = af;
145
146 if (plen < 0 || plen > addrlen * NBBY) {
147 errno = EINVAL;
148 return NULL;
149 }
150
151 memset(addr, 0xff, (plen + NBBY - 1) / NBBY);
152
153 nbit = plen % NBBY;
154 if (nbit != 0)
155 addr[plen / NBBY] &= ~((uint8_t)0xff >> nbit);
156 pfx = malloc(offsetof(struct paddr_prefix, pfx_addr) + u.sa.sa_len);
157 if (pfx == NULL)
158 return NULL;
159 pfx->pfx_len = plen;
160 memcpy(&pfx->pfx_addr, &u.sa, u.sa.sa_len);
161
162 return pfx;
163 }
164