]> git.lizzy.rs Git - plan9front.git/blob - sys/src/ape/lib/bsd/inet_pton.c
ape: Add mkstemp to /sys/src/ape/lib/ap/gen/mkfile
[plan9front.git] / sys / src / ape / lib / bsd / inet_pton.c
1 /* posix */
2 #include <sys/types.h>
3 #include <unistd.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <ctype.h>
7
8 /* bsd extensions */
9 #include <sys/uio.h>
10 #include <sys/socket.h>
11 #include <netinet/in.h>
12
13 #include <errno.h>
14
15 static int
16 ipcharok(int c)
17 {
18         return c == ':' || isascii(c) && isxdigit(c);
19 }
20
21 static int
22 delimchar(int c)
23 {
24         if(c == '\0')
25                 return 1;
26         if(c == ':' || isascii(c) && isalnum(c))
27                 return 0;
28         return 1;
29 }
30
31 int
32 inet_pton(int af, char *src, void *dst)
33 {
34         int i, v4 = 1, elipsis = 0;
35         unsigned char *to;
36         unsigned long x;
37         char *p, *op;
38
39         if(af == AF_INET)
40                 return inet_aton(src, (struct in_addr*)dst);
41
42         if(af != AF_INET6){
43                 errno = EAFNOSUPPORT;
44                 return -1;
45         }
46
47         to = ((struct in6_addr*)dst)->s6_addr;
48         memset(to, 0, 16);
49
50         p = src;
51         for(i = 0; i < 16 && ipcharok(*p); i+=2){
52                 op = p;
53                 x = strtoul(p, &p, 16);
54
55                 if(*p == '.' || (*p == 0 && i == 0)){   /* ends with v4? */
56                         struct in_addr in;
57
58                         if(i > 16-4 || inet_aton(op, &in) == 0)
59                                 return 0;               /* parse error */
60
61                         memmove(to+i, (unsigned char*)&in.s_addr, 4);
62                         i += 4;
63                         break;
64                 }
65                 if(x != (unsigned short)x || *p != ':' && !delimchar(*p))
66                         return 0;                       /* parse error */
67
68                 to[i] = x>>8;
69                 to[i+1] = x;
70                 if(*p == ':'){
71                         v4 = 0;
72                         if(*++p == ':'){        /* :: is elided zero short(s) */
73                                 if (elipsis)
74                                         return 0;       /* second :: */
75                                 elipsis = i+2;
76                                 p++;
77                         }
78                 } else if (p == op)             /* strtoul made no progress? */
79                         break;
80         }
81         if (p == src || !delimchar(*p))
82                 return 0;                               /* parse error */
83         if(i < 16){
84                 memmove(&to[elipsis+16-i], &to[elipsis], i-elipsis);
85                 memset(&to[elipsis], 0, 16-i);
86         }
87         if(v4)
88                 to[10] = to[11] = 0xff;
89         return 1;
90 }