[BUS] prevent disable operation from firing ref count ASSERT(). Clear hca field so...
[mirror/winof/.git] / etc / user / inet.c
1 /*\r
2  * Copyright (c) 2009 Intel Corp., Inc.\r
3  *\r
4  * This software is available to you under a choice of one of two\r
5  * licenses.  You may choose to be licensed under the terms of the GNU\r
6  * General Public License (GPL) Version 2, available from the file\r
7  * COPYING in the main directory of this source tree, or the\r
8  * OpenIB.org BSD license below:\r
9  *\r
10  *     Redistribution and use in source and binary forms, with or\r
11  *     without modification, are permitted provided that the following\r
12  *     conditions are met:\r
13  *\r
14  *      - Redistributions of source code must retain the above\r
15  *        copyright notice, this list of conditions and the following\r
16  *        disclaimer.\r
17  *\r
18  *      - Redistributions in binary form must reproduce the above\r
19  *        copyright notice, this list of conditions and the following\r
20  *        disclaimer in the documentation and/or other materials\r
21  *        provided with the distribution.\r
22  *\r
23  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
24  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
25  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
26  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
27  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
28  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
29  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
30  * SOFTWARE.\r
31  *\r
32  */\r
33 \r
34 #include <arpa/inet.h>\r
35 \r
36 static int inet_pton4(const char *src, struct in_addr *addr)\r
37 {\r
38         unsigned long ip;\r
39 \r
40         ip = inet_addr(src);\r
41         if (ip == INADDR_NONE)\r
42                 return 0;\r
43 \r
44         addr->S_un.S_addr = ip;\r
45         return 1;\r
46 }\r
47 \r
48 enum in6_addr_format_state\r
49 {\r
50         in6_fs_num,\r
51         in6_fs_colon,\r
52         in6_fs_0_colon,\r
53         in6_fs_0_num\r
54 };\r
55 \r
56 static int inet_check_groups(const char *src)\r
57 {\r
58         int i;\r
59         int digits = 0, groups = 0;\r
60         enum in6_addr_format_state state;\r
61 \r
62         if (src[0] == ':') {\r
63                 if (src[1] == ':') {\r
64                         i = 2;\r
65                         state = in6_fs_0_colon;\r
66                 } else {\r
67                         return -1;\r
68                 }\r
69         } else {\r
70                 i = 0;\r
71                 state = in6_fs_num;\r
72         }\r
73 \r
74         for (; src[i] != '\0'; i++) {\r
75                 if (src[i] == ':') {\r
76 \r
77                         switch (state) {\r
78                         case in6_fs_num:\r
79                                 state = in6_fs_colon;\r
80                                 break;\r
81                         case in6_fs_colon:\r
82                         case in6_fs_0_num:\r
83                                 state = in6_fs_0_colon;\r
84                                 break;\r
85                         default:\r
86                                 return -1;\r
87                         }\r
88                         digits = 0;\r
89 \r
90                 } else if (isxdigit(src[i]) && digits++ < 4) {\r
91 \r
92                         switch (state) {\r
93                         case in6_fs_colon:\r
94                                 state = in6_fs_num;\r
95                                 groups++;\r
96                                 break;\r
97                         case in6_fs_0_colon:\r
98                                 state = in6_fs_0_num;\r
99                                 groups++;\r
100                                 break;\r
101                         default:\r
102                                 break;\r
103                         }\r
104                 } else {\r
105                         return -1;\r
106                 }\r
107         }\r
108 \r
109         if (groups > 8 || state == in6_fs_colon)\r
110                 return -1;\r
111         \r
112         return groups;\r
113 }\r
114 \r
115 /*\r
116  * We don't handle the format x:x:x:x:x:x:d.d.d.d\r
117  */\r
118 static int inet_pton6(const char *src, struct in6_addr *addr)\r
119 {\r
120         const char *pos;\r
121         int i, skip;\r
122 \r
123         skip = 8 - inet_check_groups(src);\r
124         if (skip > 8)\r
125                 return -1;\r
126 \r
127         memset(addr, 0, sizeof(*addr));\r
128         if (src[0] == ':') {\r
129                 pos = src + 2;\r
130                 i = skip;\r
131         } else {\r
132                 pos = src;\r
133                 i = 0;\r
134         }\r
135 \r
136         for (; i < 8; i++) {\r
137                 addr->u.Word[i] = htons((u_short) strtoul(pos, (char **) &pos, 16));\r
138                 pos++;\r
139                 if (*pos == ':') {\r
140                         pos++;\r
141                         i += skip;\r
142                 }\r
143         }\r
144 \r
145         return 1;\r
146 }\r
147 \r
148 int inet_pton(int af, const char *src, void *dst)\r
149 {\r
150         switch (af) {\r
151         case AF_INET:\r
152                 return inet_pton4(src, dst);\r
153         case AF_INET6:\r
154                 return inet_pton6(src, dst);\r
155         default:\r
156                 return -1;\r
157         }\r
158 }\r