--- /dev/null
+/*\r
+ * Copyright (c) 2009 Intel Corp., Inc.\r
+ *\r
+ * This software is available to you under a choice of one of two\r
+ * licenses. You may choose to be licensed under the terms of the GNU\r
+ * General Public License (GPL) Version 2, available from the file\r
+ * COPYING in the main directory of this source tree, or the\r
+ * OpenIB.org BSD license below:\r
+ *\r
+ * Redistribution and use in source and binary forms, with or\r
+ * without modification, are permitted provided that the following\r
+ * conditions are met:\r
+ *\r
+ * - Redistributions of source code must retain the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer.\r
+ *\r
+ * - Redistributions in binary form must reproduce the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer in the documentation and/or other materials\r
+ * provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ */\r
+\r
+#include <arpa/inet.h>\r
+\r
+static int inet_pton4(const char *src, struct in_addr *addr)\r
+{\r
+ unsigned long ip;\r
+\r
+ ip = inet_addr(src);\r
+ if (ip == INADDR_NONE)\r
+ return 0;\r
+\r
+ addr->S_un.S_addr = ip;\r
+ return 1;\r
+}\r
+\r
+enum in6_addr_format_state\r
+{\r
+ in6_fs_num,\r
+ in6_fs_colon,\r
+ in6_fs_0_colon,\r
+ in6_fs_0_num\r
+};\r
+\r
+static int inet_check_groups(const char *src)\r
+{\r
+ int i;\r
+ int digits = 0, groups = 0;\r
+ enum in6_addr_format_state state;\r
+\r
+ if (src[0] == ':') {\r
+ if (src[1] == ':') {\r
+ i = 2;\r
+ state = in6_fs_0_colon;\r
+ } else {\r
+ return -1;\r
+ }\r
+ } else {\r
+ i = 0;\r
+ state = in6_fs_num;\r
+ }\r
+\r
+ for (; src[i] != '\0'; i++) {\r
+ if (src[i] == ':') {\r
+\r
+ switch (state) {\r
+ case in6_fs_num:\r
+ state = in6_fs_colon;\r
+ break;\r
+ case in6_fs_colon:\r
+ case in6_fs_0_num:\r
+ state = in6_fs_0_colon;\r
+ break;\r
+ default:\r
+ return -1;\r
+ }\r
+ digits = 0;\r
+\r
+ } else if (isxdigit(src[i]) && digits++ < 4) {\r
+\r
+ switch (state) {\r
+ case in6_fs_colon:\r
+ state = in6_fs_num;\r
+ groups++;\r
+ break;\r
+ case in6_fs_0_colon:\r
+ state = in6_fs_0_num;\r
+ groups++;\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+ } else {\r
+ return -1;\r
+ }\r
+ }\r
+\r
+ if (groups > 8 || state == in6_fs_colon)\r
+ return -1;\r
+ \r
+ return groups;\r
+}\r
+\r
+/*\r
+ * We don't handle the format x:x:x:x:x:x:d.d.d.d\r
+ */\r
+static int inet_pton6(const char *src, struct in6_addr *addr)\r
+{\r
+ const char *pos;\r
+ int i, skip;\r
+\r
+ skip = 8 - inet_check_groups(src);\r
+ if (skip > 8)\r
+ return -1;\r
+\r
+ memset(addr, 0, sizeof(*addr));\r
+ if (src[0] == ':') {\r
+ pos = src + 2;\r
+ i = skip;\r
+ } else {\r
+ pos = src;\r
+ i = 0;\r
+ }\r
+\r
+ for (; i < 8; i++) {\r
+ addr->u.Word[i] = htons((u_short) strtoul(pos, (char **) &pos, 16));\r
+ pos++;\r
+ if (*pos == ':') {\r
+ pos++;\r
+ i += skip;\r
+ }\r
+ }\r
+\r
+ return 1;\r
+}\r
+\r
+int inet_pton(int af, const char *src, void *dst)\r
+{\r
+ switch (af) {\r
+ case AF_INET:\r
+ return inet_pton4(src, dst);\r
+ case AF_INET6:\r
+ return inet_pton6(src, dst);\r
+ default:\r
+ return -1;\r
+ }\r
+}\r