diff options
author | eric <> | 2012-07-13 17:49:54 +0000 |
---|---|---|
committer | eric <> | 2012-07-13 17:49:54 +0000 |
commit | 9204e59073bcf27e1487ec4ac46e981902ddd904 (patch) | |
tree | c9d57f5a2812d08f0e504c69deb162dc89ae78a9 /src/regress/lib/libc/asr/bin/common.c | |
parent | 1cb24e474ab651a39f96d1b0c7582a081ea8c2b8 (diff) | |
download | openbsd-9204e59073bcf27e1487ec4ac46e981902ddd904.tar.gz openbsd-9204e59073bcf27e1487ec4ac46e981902ddd904.tar.bz2 openbsd-9204e59073bcf27e1487ec4ac46e981902ddd904.zip |
import regression suite for asr
Diffstat (limited to 'src/regress/lib/libc/asr/bin/common.c')
-rw-r--r-- | src/regress/lib/libc/asr/bin/common.c | 633 |
1 files changed, 633 insertions, 0 deletions
diff --git a/src/regress/lib/libc/asr/bin/common.c b/src/regress/lib/libc/asr/bin/common.c new file mode 100644 index 0000000000..4402d08373 --- /dev/null +++ b/src/regress/lib/libc/asr/bin/common.c | |||
@@ -0,0 +1,633 @@ | |||
1 | /* $OpenBSD: common.c,v 1.1.1.1 2012/07/13 17:49:53 eric Exp $ */ | ||
2 | /* | ||
3 | * Copyright (c) 2012 Eric Faurot <eric@openbsd.org> | ||
4 | * | ||
5 | * Permission to use, copy, modify, and distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | #include <sys/types.h> | ||
18 | #include <sys/socket.h> | ||
19 | #include <netinet/in.h> | ||
20 | #include <arpa/inet.h> | ||
21 | #include <arpa/nameser.h> | ||
22 | |||
23 | #include <err.h> | ||
24 | #include <errno.h> | ||
25 | #include <inttypes.h> | ||
26 | #include <netdb.h> | ||
27 | #include <resolv.h> | ||
28 | #include <stdio.h> | ||
29 | #include <string.h> | ||
30 | |||
31 | #include "common.h" | ||
32 | |||
33 | int long_err; | ||
34 | int gai_errno; | ||
35 | int rrset_errno; | ||
36 | |||
37 | |||
38 | char * | ||
39 | gethostarg(char *n) | ||
40 | { | ||
41 | if (n == NULL) | ||
42 | return (n); | ||
43 | if (!strcmp(n, "NULL")) | ||
44 | return (NULL); | ||
45 | if (!strcmp(n, "EMPTY")) | ||
46 | return (""); | ||
47 | return (n); | ||
48 | } | ||
49 | |||
50 | const char *rrsetstrerror(int); | ||
51 | char * print_addr(const struct sockaddr *, char *, size_t); | ||
52 | |||
53 | struct kv { int code; const char *name; }; | ||
54 | |||
55 | struct kv kv_family[] = { | ||
56 | { AF_UNIX, "unix" }, | ||
57 | { AF_INET, "inet" }, | ||
58 | { AF_INET6, "inet6" }, | ||
59 | { AF_IMPLINK, "implink" }, | ||
60 | { AF_BLUETOOTH, "bluetooth" }, | ||
61 | { 0, NULL, } | ||
62 | }; | ||
63 | struct kv kv_socktype[] = { | ||
64 | { SOCK_STREAM, "stream" }, | ||
65 | { SOCK_DGRAM, "dgram" }, | ||
66 | { SOCK_RAW, "raw" }, | ||
67 | { 0, NULL, } | ||
68 | }; | ||
69 | struct kv kv_protocol[] = { | ||
70 | { IPPROTO_UDP, "udp" }, | ||
71 | { IPPROTO_TCP, "tcp" }, | ||
72 | { 0, NULL, } | ||
73 | }; | ||
74 | |||
75 | static const char * | ||
76 | kv_lookup_name(struct kv *kv, int code) | ||
77 | { | ||
78 | while (kv->name) { | ||
79 | if (kv->code == code) | ||
80 | return (kv->name); | ||
81 | kv++; | ||
82 | } | ||
83 | return "???"; | ||
84 | } | ||
85 | |||
86 | struct keyval { | ||
87 | const char *key; | ||
88 | uint16_t value; | ||
89 | }; | ||
90 | |||
91 | static struct keyval kv_class[] = { | ||
92 | { "IN", C_IN }, | ||
93 | { "CHAOS", C_CHAOS }, | ||
94 | { "HS", C_HS }, | ||
95 | { "ANY", C_ANY }, | ||
96 | { NULL, 0 }, | ||
97 | }; | ||
98 | |||
99 | static struct keyval kv_type[] = { | ||
100 | { "A", T_A }, | ||
101 | { "NS", T_NS }, | ||
102 | { "MD", T_MD }, | ||
103 | { "MF", T_MF }, | ||
104 | { "CNAME", T_CNAME }, | ||
105 | { "SOA", T_SOA }, | ||
106 | { "MB", T_MB }, | ||
107 | { "MG", T_MG }, | ||
108 | { "MR", T_MR }, | ||
109 | { "NULL", T_NULL }, | ||
110 | { "WKS", T_WKS }, | ||
111 | { "PTR", T_PTR }, | ||
112 | { "HINFO", T_HINFO }, | ||
113 | { "MINFO", T_MINFO }, | ||
114 | { "MX", T_MX }, | ||
115 | { "TXT", T_TXT }, | ||
116 | |||
117 | { "AAAA", T_AAAA }, | ||
118 | |||
119 | { "AXFR", T_AXFR }, | ||
120 | { "MAILB", T_MAILB }, | ||
121 | { "MAILA", T_MAILA }, | ||
122 | { "ANY", T_ANY }, | ||
123 | { NULL, 0 }, | ||
124 | }; | ||
125 | |||
126 | static struct keyval kv_rcode[] = { | ||
127 | { "NOERROR", NOERROR }, | ||
128 | { "FORMERR", FORMERR }, | ||
129 | { "SERVFAIL", SERVFAIL }, | ||
130 | { "NXDOMAIN", NXDOMAIN }, | ||
131 | { "NOTIMP", NOTIMP }, | ||
132 | { "REFUSED", REFUSED }, | ||
133 | { NULL, 0 }, | ||
134 | }; | ||
135 | |||
136 | |||
137 | const char * | ||
138 | rcodetostr(uint16_t v) | ||
139 | { | ||
140 | static char buf[16]; | ||
141 | size_t i; | ||
142 | |||
143 | for(i = 0; kv_rcode[i].key; i++) | ||
144 | if (kv_rcode[i].value == v) | ||
145 | return (kv_rcode[i].key); | ||
146 | |||
147 | snprintf(buf, sizeof buf, "%"PRIu16"?", v); | ||
148 | |||
149 | return (buf); | ||
150 | } | ||
151 | |||
152 | const char * | ||
153 | typetostr(uint16_t v) | ||
154 | { | ||
155 | static char buf[16]; | ||
156 | size_t i; | ||
157 | |||
158 | for(i = 0; kv_type[i].key; i++) | ||
159 | if (kv_type[i].value == v) | ||
160 | return (kv_type[i].key); | ||
161 | |||
162 | snprintf(buf, sizeof buf, "%"PRIu16"?", v); | ||
163 | |||
164 | return (buf); | ||
165 | } | ||
166 | |||
167 | const char * | ||
168 | classtostr(uint16_t v) | ||
169 | { | ||
170 | static char buf[16]; | ||
171 | size_t i; | ||
172 | |||
173 | for(i = 0; kv_class[i].key; i++) | ||
174 | if (kv_class[i].value == v) | ||
175 | return (kv_class[i].key); | ||
176 | |||
177 | snprintf(buf, sizeof buf, "%"PRIu16"?", v); | ||
178 | |||
179 | return (buf); | ||
180 | } | ||
181 | |||
182 | uint16_t | ||
183 | strtotype(const char *name) | ||
184 | { | ||
185 | size_t i; | ||
186 | |||
187 | for(i = 0; kv_type[i].key; i++) | ||
188 | if (!strcmp(kv_type[i].key, name)) | ||
189 | return (kv_type[i].value); | ||
190 | |||
191 | return (0); | ||
192 | } | ||
193 | |||
194 | uint16_t | ||
195 | strtoclass(const char *name) | ||
196 | { | ||
197 | size_t i; | ||
198 | |||
199 | for(i = 0; kv_class[i].key; i++) | ||
200 | if (!strcmp(kv_class[i].key, name)) | ||
201 | return (kv_class[i].value); | ||
202 | |||
203 | return (0); | ||
204 | } | ||
205 | |||
206 | void | ||
207 | print_hostent(struct hostent *e) | ||
208 | { | ||
209 | char buf[256], **c; | ||
210 | |||
211 | printf("name = \"%s\"\n", e->h_name); | ||
212 | printf("aliases ="); | ||
213 | for(c = e->h_aliases; *c; c++) | ||
214 | printf(" \"%s\"", *c); | ||
215 | printf("\n"); | ||
216 | printf("addrtype = %i\n", e->h_addrtype); | ||
217 | printf("addrlength = %i\n", e->h_length); | ||
218 | printf("addr_list ="); | ||
219 | for(c = e->h_addr_list; *c; c++) { | ||
220 | printf(" %s", inet_ntop(e->h_addrtype, *c, buf, sizeof buf)); | ||
221 | } | ||
222 | printf("\n"); | ||
223 | } | ||
224 | |||
225 | void | ||
226 | print_netent(struct netent *e) | ||
227 | { | ||
228 | char buf[256], **c; | ||
229 | uint32_t addr; | ||
230 | |||
231 | /* network number are given in host order */ | ||
232 | addr = htonl(e->n_net); | ||
233 | |||
234 | printf("name = \"%s\"\n", e->n_name); | ||
235 | printf("aliases ="); | ||
236 | for (c = e->n_aliases; *c; c++) | ||
237 | printf(" \"%s\"", *c); | ||
238 | printf("\n"); | ||
239 | printf("addrtype = %i\n", e->n_addrtype); | ||
240 | printf("net = %s\n", inet_ntop(e->n_addrtype, &addr, buf, sizeof buf)); | ||
241 | } | ||
242 | |||
243 | void | ||
244 | print_addrinfo(struct addrinfo *ai) | ||
245 | { | ||
246 | char buf[256]; | ||
247 | |||
248 | printf("family=%s socktype=%s protocol=%s addr=%s canonname=%s\n", | ||
249 | kv_lookup_name(kv_family, ai->ai_family), | ||
250 | kv_lookup_name(kv_socktype, ai->ai_socktype), | ||
251 | kv_lookup_name(kv_protocol, ai->ai_protocol), | ||
252 | print_addr(ai->ai_addr, buf, sizeof buf), | ||
253 | ai->ai_canonname); | ||
254 | } | ||
255 | |||
256 | const char * | ||
257 | rrsetstrerror(int e) | ||
258 | { | ||
259 | switch (e) { | ||
260 | case 0: | ||
261 | return "OK"; | ||
262 | case ERRSET_NONAME: | ||
263 | return "ERRSET_NONAME"; | ||
264 | case ERRSET_NODATA: | ||
265 | return "ERRSET_NODATA"; | ||
266 | case ERRSET_NOMEMORY: | ||
267 | return "ERRSET_NOMEMORY"; | ||
268 | case ERRSET_INVAL: | ||
269 | return "ERRSET_INVAL"; | ||
270 | case ERRSET_FAIL: | ||
271 | return "ERRSET_FAIL"; | ||
272 | default: | ||
273 | return "???"; | ||
274 | } | ||
275 | } | ||
276 | |||
277 | void | ||
278 | print_rrsetinfo(struct rrsetinfo * rrset) | ||
279 | { | ||
280 | printf("rri_flags=%u\n", rrset->rri_flags); | ||
281 | printf("rri_rdclass=%u\n", rrset->rri_rdclass); | ||
282 | printf("rri_rdtype=%u\n", rrset->rri_rdtype); | ||
283 | printf("rri_ttl=%u\n", rrset->rri_ttl); | ||
284 | printf("rri_nrdatas=%u\n", rrset->rri_nrdatas); | ||
285 | printf("rri_nsigs=%u\n", rrset->rri_nsigs); | ||
286 | printf("rri_name=\"%s\"\n", rrset->rri_name); | ||
287 | } | ||
288 | |||
289 | void | ||
290 | print_errors(void) | ||
291 | { | ||
292 | switch (long_err) { | ||
293 | case 0: | ||
294 | return; | ||
295 | case 1: | ||
296 | printf(" => errno %i, h_errno %i", errno, h_errno); | ||
297 | printf(", rrset_errno %i", rrset_errno); | ||
298 | printf(", gai_errno %i", gai_errno); | ||
299 | printf ("\n"); | ||
300 | return; | ||
301 | default: | ||
302 | printf(" => errno %i: %s\n => h_errno %i: %s\n => rrset_errno %i: %s\n", | ||
303 | errno, errno ? strerror(errno) : "ok", | ||
304 | h_errno, h_errno ? hstrerror(h_errno) : "ok", | ||
305 | rrset_errno, rrset_errno ? rrsetstrerror(rrset_errno) : "ok"); | ||
306 | printf(" => gai_errno %i: %s\n", | ||
307 | gai_errno, gai_errno ? gai_strerror(gai_errno) : "ok"); | ||
308 | } | ||
309 | } | ||
310 | |||
311 | |||
312 | static char * | ||
313 | print_host(const struct sockaddr *sa, char *buf, size_t len) | ||
314 | { | ||
315 | switch (sa->sa_family) { | ||
316 | case AF_INET: | ||
317 | inet_ntop(AF_INET, &((struct sockaddr_in*)sa)->sin_addr, | ||
318 | buf, len); | ||
319 | break; | ||
320 | case AF_INET6: | ||
321 | inet_ntop(AF_INET6, &((struct sockaddr_in6*)sa)->sin6_addr, | ||
322 | buf, len); | ||
323 | break; | ||
324 | default: | ||
325 | buf[0] = '\0'; | ||
326 | } | ||
327 | return (buf); | ||
328 | } | ||
329 | |||
330 | |||
331 | char * | ||
332 | print_addr(const struct sockaddr *sa, char *buf, size_t len) | ||
333 | { | ||
334 | char h[256]; | ||
335 | |||
336 | print_host(sa, h, sizeof h); | ||
337 | |||
338 | switch (sa->sa_family) { | ||
339 | case AF_INET: | ||
340 | snprintf(buf, len, "%s:%i", h, | ||
341 | ntohs(((struct sockaddr_in*)(sa))->sin_port)); | ||
342 | break; | ||
343 | case AF_INET6: | ||
344 | snprintf(buf, len, "[%s]:%i", h, | ||
345 | ntohs(((struct sockaddr_in6*)(sa))->sin6_port)); | ||
346 | break; | ||
347 | default: | ||
348 | snprintf(buf, len, "?"); | ||
349 | break; | ||
350 | } | ||
351 | |||
352 | return (buf); | ||
353 | } | ||
354 | |||
355 | void | ||
356 | packed_init(struct packed *pack, char *data, size_t len) | ||
357 | { | ||
358 | pack->data = data; | ||
359 | pack->len = len; | ||
360 | pack->offset = 0; | ||
361 | pack->err = NULL; | ||
362 | } | ||
363 | |||
364 | |||
365 | static ssize_t | ||
366 | dname_expand(const unsigned char *data, size_t len, size_t offset, | ||
367 | size_t *newoffset, char *dst, size_t max) | ||
368 | { | ||
369 | size_t n, count, end, ptr, start; | ||
370 | ssize_t res; | ||
371 | |||
372 | if (offset >= len) | ||
373 | return (-1); | ||
374 | |||
375 | res = 0; | ||
376 | end = start = offset; | ||
377 | |||
378 | for(; (n = data[offset]); ) { | ||
379 | if ((n & 0xc0) == 0xc0) { | ||
380 | if (offset + 2 > len) | ||
381 | return (-1); | ||
382 | ptr = 256 * (n & ~0xc0) + data[offset + 1]; | ||
383 | if (ptr >= start) | ||
384 | return (-1); | ||
385 | if (end < offset + 2) | ||
386 | end = offset + 2; | ||
387 | offset = ptr; | ||
388 | continue; | ||
389 | } | ||
390 | if (offset + n + 1 > len) | ||
391 | return (-1); | ||
392 | |||
393 | |||
394 | /* copy n + at offset+1 */ | ||
395 | if (dst != NULL && max != 0) { | ||
396 | count = (max < n + 1) ? (max) : (n + 1); | ||
397 | memmove(dst, data + offset, count); | ||
398 | dst += count; | ||
399 | max -= count; | ||
400 | } | ||
401 | res += n + 1; | ||
402 | offset += n + 1; | ||
403 | if (end < offset) | ||
404 | end = offset; | ||
405 | } | ||
406 | if (end < offset + 1) | ||
407 | end = offset + 1; | ||
408 | |||
409 | if (dst != NULL && max != 0) | ||
410 | dst[0] = 0; | ||
411 | if (newoffset) | ||
412 | *newoffset = end; | ||
413 | return (res + 1); | ||
414 | } | ||
415 | |||
416 | static int | ||
417 | unpack_data(struct packed *p, void *data, size_t len) | ||
418 | { | ||
419 | if (p->err) | ||
420 | return (-1); | ||
421 | |||
422 | if (p->len - p->offset < len) { | ||
423 | p->err = "too short"; | ||
424 | return (-1); | ||
425 | } | ||
426 | |||
427 | memmove(data, p->data + p->offset, len); | ||
428 | p->offset += len; | ||
429 | |||
430 | return (0); | ||
431 | } | ||
432 | |||
433 | static int | ||
434 | unpack_u16(struct packed *p, uint16_t *u16) | ||
435 | { | ||
436 | if (unpack_data(p, u16, 2) == -1) | ||
437 | return (-1); | ||
438 | |||
439 | *u16 = ntohs(*u16); | ||
440 | |||
441 | return (0); | ||
442 | } | ||
443 | |||
444 | static int | ||
445 | unpack_u32(struct packed *p, uint32_t *u32) | ||
446 | { | ||
447 | if (unpack_data(p, u32, 4) == -1) | ||
448 | return (-1); | ||
449 | |||
450 | *u32 = ntohl(*u32); | ||
451 | |||
452 | return (0); | ||
453 | } | ||
454 | |||
455 | static int | ||
456 | unpack_inaddr(struct packed *p, struct in_addr *a) | ||
457 | { | ||
458 | return (unpack_data(p, a, 4)); | ||
459 | } | ||
460 | |||
461 | static int | ||
462 | unpack_in6addr(struct packed *p, struct in6_addr *a6) | ||
463 | { | ||
464 | return (unpack_data(p, a6, 16)); | ||
465 | } | ||
466 | |||
467 | static int | ||
468 | unpack_dname(struct packed *p, char *dst, size_t max) | ||
469 | { | ||
470 | ssize_t e; | ||
471 | |||
472 | if (p->err) | ||
473 | return (-1); | ||
474 | |||
475 | e = dname_expand(p->data, p->len, p->offset, &p->offset, dst, max); | ||
476 | if (e == -1) { | ||
477 | p->err = "bad domain name"; | ||
478 | return (-1); | ||
479 | } | ||
480 | if (e < 0 || e > MAXDNAME) { | ||
481 | p->err = "domain name too long"; | ||
482 | return (-1); | ||
483 | } | ||
484 | |||
485 | return (0); | ||
486 | } | ||
487 | |||
488 | int | ||
489 | unpack_header(struct packed *p, struct header *h) | ||
490 | { | ||
491 | if (unpack_data(p, h, HFIXEDSZ) == -1) | ||
492 | return (-1); | ||
493 | |||
494 | h->flags = ntohs(h->flags); | ||
495 | h->qdcount = ntohs(h->qdcount); | ||
496 | h->ancount = ntohs(h->ancount); | ||
497 | h->nscount = ntohs(h->nscount); | ||
498 | h->arcount = ntohs(h->arcount); | ||
499 | |||
500 | return (0); | ||
501 | } | ||
502 | |||
503 | int | ||
504 | unpack_query(struct packed *p, struct query *q) | ||
505 | { | ||
506 | unpack_dname(p, q->q_dname, sizeof(q->q_dname)); | ||
507 | unpack_u16(p, &q->q_type); | ||
508 | unpack_u16(p, &q->q_class); | ||
509 | |||
510 | return (p->err) ? (-1) : (0); | ||
511 | } | ||
512 | |||
513 | int | ||
514 | unpack_rr(struct packed *p, struct rr *rr) | ||
515 | { | ||
516 | uint16_t rdlen; | ||
517 | size_t save_offset; | ||
518 | |||
519 | unpack_dname(p, rr->rr_dname, sizeof(rr->rr_dname)); | ||
520 | unpack_u16(p, &rr->rr_type); | ||
521 | unpack_u16(p, &rr->rr_class); | ||
522 | unpack_u32(p, &rr->rr_ttl); | ||
523 | unpack_u16(p, &rdlen); | ||
524 | |||
525 | if (p->err) | ||
526 | return (-1); | ||
527 | |||
528 | if (p->len - p->offset < rdlen) { | ||
529 | p->err = "too short"; | ||
530 | return (-1); | ||
531 | } | ||
532 | |||
533 | save_offset = p->offset; | ||
534 | |||
535 | switch(rr->rr_type) { | ||
536 | |||
537 | case T_CNAME: | ||
538 | unpack_dname(p, rr->rr.cname.cname, sizeof(rr->rr.cname.cname)); | ||
539 | break; | ||
540 | |||
541 | case T_MX: | ||
542 | unpack_u16(p, &rr->rr.mx.preference); | ||
543 | unpack_dname(p, rr->rr.mx.exchange, sizeof(rr->rr.mx.exchange)); | ||
544 | break; | ||
545 | |||
546 | case T_NS: | ||
547 | unpack_dname(p, rr->rr.ns.nsname, sizeof(rr->rr.ns.nsname)); | ||
548 | break; | ||
549 | |||
550 | case T_PTR: | ||
551 | unpack_dname(p, rr->rr.ptr.ptrname, sizeof(rr->rr.ptr.ptrname)); | ||
552 | break; | ||
553 | |||
554 | case T_SOA: | ||
555 | unpack_dname(p, rr->rr.soa.mname, sizeof(rr->rr.soa.mname)); | ||
556 | unpack_dname(p, rr->rr.soa.rname, sizeof(rr->rr.soa.rname)); | ||
557 | unpack_u32(p, &rr->rr.soa.serial); | ||
558 | unpack_u32(p, &rr->rr.soa.refresh); | ||
559 | unpack_u32(p, &rr->rr.soa.retry); | ||
560 | unpack_u32(p, &rr->rr.soa.expire); | ||
561 | unpack_u32(p, &rr->rr.soa.minimum); | ||
562 | break; | ||
563 | |||
564 | case T_A: | ||
565 | if (rr->rr_class != C_IN) | ||
566 | goto other; | ||
567 | unpack_inaddr(p, &rr->rr.in_a.addr); | ||
568 | break; | ||
569 | |||
570 | case T_AAAA: | ||
571 | if (rr->rr_class != C_IN) | ||
572 | goto other; | ||
573 | unpack_in6addr(p, &rr->rr.in_aaaa.addr6); | ||
574 | break; | ||
575 | default: | ||
576 | other: | ||
577 | rr->rr.other.rdata = p->data + p->offset; | ||
578 | rr->rr.other.rdlen = rdlen; | ||
579 | p->offset += rdlen; | ||
580 | } | ||
581 | |||
582 | if (p->err) | ||
583 | return (-1); | ||
584 | |||
585 | /* make sure that the advertised rdlen is really ok */ | ||
586 | if (p->offset - save_offset != rdlen) | ||
587 | p->err = "bad dlen"; | ||
588 | |||
589 | return (p->err) ? (-1) : (0); | ||
590 | } | ||
591 | |||
592 | int | ||
593 | sockaddr_from_str(struct sockaddr *sa, int family, const char *str) | ||
594 | { | ||
595 | struct in_addr ina; | ||
596 | struct in6_addr in6a; | ||
597 | struct sockaddr_in *sin; | ||
598 | struct sockaddr_in6 *sin6; | ||
599 | |||
600 | switch (family) { | ||
601 | case PF_UNSPEC: | ||
602 | if (sockaddr_from_str(sa, PF_INET, str) == 0) | ||
603 | return (0); | ||
604 | return sockaddr_from_str(sa, PF_INET6, str); | ||
605 | |||
606 | case PF_INET: | ||
607 | if (inet_pton(PF_INET, str, &ina) != 1) | ||
608 | return (-1); | ||
609 | |||
610 | sin = (struct sockaddr_in *)sa; | ||
611 | memset(sin, 0, sizeof *sin); | ||
612 | sin->sin_len = sizeof(struct sockaddr_in); | ||
613 | sin->sin_family = PF_INET; | ||
614 | sin->sin_addr.s_addr = ina.s_addr; | ||
615 | return (0); | ||
616 | |||
617 | case PF_INET6: | ||
618 | if (inet_pton(PF_INET6, str, &in6a) != 1) | ||
619 | return (-1); | ||
620 | |||
621 | sin6 = (struct sockaddr_in6 *)sa; | ||
622 | memset(sin6, 0, sizeof *sin6); | ||
623 | sin6->sin6_len = sizeof(struct sockaddr_in6); | ||
624 | sin6->sin6_family = PF_INET6; | ||
625 | sin6->sin6_addr = in6a; | ||
626 | return (0); | ||
627 | |||
628 | default: | ||
629 | break; | ||
630 | } | ||
631 | |||
632 | return (-1); | ||
633 | } | ||