]> git.proxmox.com Git - mirror_edk2.git/blobdiff - StdLib/BsdSocketLib/inet_net_pton.c
Add Socket Libraries.
[mirror_edk2.git] / StdLib / BsdSocketLib / inet_net_pton.c
diff --git a/StdLib/BsdSocketLib/inet_net_pton.c b/StdLib/BsdSocketLib/inet_net_pton.c
new file mode 100644 (file)
index 0000000..4e4424a
--- /dev/null
@@ -0,0 +1,252 @@
+/*\r
+ * Copyright (c) 1996 by Internet Software Consortium.\r
+ *\r
+ * Permission to use, copy, modify, and distribute this software for any\r
+ * purpose with or without fee is hereby granted, provided that the above\r
+ * copyright notice and this permission notice appear in all copies.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS\r
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES\r
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE\r
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL\r
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR\r
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS\r
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS\r
+ * SOFTWARE.\r
+ */\r
+\r
+/*\r
+ * Portions copyright (c) 1999, 2000\r
+ * Intel Corporation.\r
+ * All rights reserved.\r
+ * \r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions\r
+ * are met:\r
+ * \r
+ * 1. Redistributions of source code must retain the above copyright\r
+ *    notice, this list of conditions and the following disclaimer.\r
+ * \r
+ * 2. Redistributions in binary form must reproduce the above copyright\r
+ *    notice, this list of conditions and the following disclaimer in the\r
+ *    documentation and/or other materials provided with the distribution.\r
+ * \r
+ * 3. All advertising materials mentioning features or use of this software\r
+ *    must display the following acknowledgement:\r
+ * \r
+ *    This product includes software developed by Intel Corporation and\r
+ *    its contributors.\r
+ * \r
+ * 4. Neither the name of Intel Corporation or its contributors may be\r
+ *    used to endorse or promote products derived from this software\r
+ *    without specific prior written permission.\r
+ * \r
+ * THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION AND CONTRIBUTORS ``AS IS''\r
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
+ * ARE DISCLAIMED.  IN NO EVENT SHALL INTEL CORPORATION OR CONTRIBUTORS BE\r
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF\r
+ * THE POSSIBILITY OF SUCH DAMAGE.\r
+ * \r
+ */\r
+\r
+#if defined(LIBC_SCCS) && !defined(lint)\r
+static const char orig_rcsid[] = "From Id: inet_net_pton.c,v 1.8 1996/11/21 10:28:12 vixie Exp $";\r
+static const char rcsid[] = "$Id: inet_net_pton.c,v 1.1.1.1 2003/11/19 01:51:29 kyu3 Exp $";\r
+#endif\r
+\r
+#include <sys/types.h>\r
+#include <sys/socket.h>\r
+#include <netinet/in.h>\r
+#include <arpa/inet.h>\r
+\r
+#include <assert.h>\r
+#include <ctype.h>\r
+#include <errno.h>\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <stdlib.h>\r
+\r
+#ifdef SPRINTF_CHAR\r
+# define SPRINTF(x) strlen(sprintf/**/x)\r
+#else\r
+# define SPRINTF(x) ((size_t)sprintf x)\r
+#endif\r
+\r
+static int     inet_net_pton_ipv4 (const char *src, u_char *dst,\r
+                                       size_t size);\r
+\r
+/*\r
+ * static int\r
+ * inet_net_pton(af, src, dst, size)\r
+ *     convert network number from presentation to network format.\r
+ *     accepts hex octets, hex strings, decimal octets, and /CIDR.\r
+ *     "size" is in bytes and describes "dst".\r
+ * return:\r
+ *     number of bits, either imputed classfully or specified with /CIDR,\r
+ *     or -1 if some failure occurred (check errno).  ENOENT means it was\r
+ *     not a valid network specification.\r
+ * author:\r
+ *     Paul Vixie (ISC), June 1996\r
+ */\r
+int\r
+inet_net_pton(\r
+       int af,\r
+       const char *src,\r
+       void *dst,\r
+       size_t size\r
+       )\r
+{\r
+       switch (af) {\r
+       case AF_INET:\r
+               return (inet_net_pton_ipv4(src, dst, size));\r
+       default:\r
+               errno = EAFNOSUPPORT;\r
+               return (-1);\r
+       }\r
+}\r
+\r
+/*\r
+ * static int\r
+ * inet_net_pton_ipv4(src, dst, size)\r
+ *     convert IPv4 network number from presentation to network format.\r
+ *     accepts hex octets, hex strings, decimal octets, and /CIDR.\r
+ *     "size" is in bytes and describes "dst".\r
+ * return:\r
+ *     number of bits, either imputed classfully or specified with /CIDR,\r
+ *     or -1 if some failure occurred (check errno).  ENOENT means it was\r
+ *     not an IPv4 network specification.\r
+ * note:\r
+ *     network byte order assumed.  this means 192.5.5.240/28 has\r
+ *     0x11110000 in its fourth octet.\r
+ * author:\r
+ *     Paul Vixie (ISC), June 1996\r
+ */\r
+static int\r
+inet_net_pton_ipv4(\r
+       const char *src,\r
+       u_char *dst,\r
+       size_t size\r
+       )\r
+{\r
+       static const char xdigits[] = "0123456789abcdef";\r
+       static const char digits[] = "0123456789";\r
+       int n;\r
+  int ch;\r
+  int tmp;\r
+  int dirty;\r
+  int bits;\r
+       const u_char *odst = dst;\r
+\r
+       ch = *src++;\r
+       if (ch == '0' && (src[0] == 'x' || src[0] == 'X')\r
+           && isascii(src[1]) && isxdigit(src[1])) {\r
+               /* Hexadecimal: Eat nybble string. */\r
+               if (size <= 0)\r
+                       goto emsgsize;\r
+               *dst = 0, dirty = 0;\r
+               src++;  /* skip x or X. */\r
+               while ((ch = *src++) != '\0' &&\r
+                      isascii(ch) && isxdigit(ch)) {\r
+                       if (isupper(ch))\r
+                               ch = tolower(ch);\r
+                       n = (int)(strchr(xdigits, ch) - xdigits);\r
+                       assert(n >= 0 && n <= 15);\r
+                       *dst |= n;\r
+                       if (!dirty++)\r
+                               *dst <<= 4;\r
+                       else if (size-- > 0)\r
+                               *++dst = 0, dirty = 0;\r
+                       else\r
+                               goto emsgsize;\r
+               }\r
+               if (dirty)\r
+                       size--;\r
+       } else if (isascii(ch) && isdigit(ch)) {\r
+               /* Decimal: eat dotted digit string. */\r
+               for (;;) {\r
+                       tmp = 0;\r
+                       do {\r
+                               n = (int)(strchr(digits, ch) - digits);\r
+                               assert(n >= 0 && n <= 9);\r
+                               tmp *= 10;\r
+                               tmp += n;\r
+                               if (tmp > 255)\r
+                                       goto enoent;\r
+                       } while ((ch = *src++) != '\0' &&\r
+                                isascii(ch) && isdigit(ch));\r
+                       if (size-- <= 0)\r
+                               goto emsgsize;\r
+                       *dst++ = (u_char) tmp;\r
+                       if (ch == '\0' || ch == '/')\r
+                               break;\r
+                       if (ch != '.')\r
+                               goto enoent;\r
+                       ch = *src++;\r
+                       if (!isascii(ch) || !isdigit(ch))\r
+                               goto enoent;\r
+               }\r
+       } else\r
+               goto enoent;\r
+\r
+       bits = -1;\r
+       if (ch == '/' && isascii(src[0]) && isdigit(src[0]) && dst > odst) {\r
+               /* CIDR width specifier.  Nothing can follow it. */\r
+               ch = *src++;    /* Skip over the /. */\r
+               bits = 0;\r
+               do {\r
+                       n = (int)(strchr(digits, ch) - digits);\r
+                       assert(n >= 0 && n <= 9);\r
+                       bits *= 10;\r
+                       bits += n;\r
+               } while ((ch = *src++) != '\0' && isascii(ch) && isdigit(ch));\r
+               if (ch != '\0')\r
+                       goto enoent;\r
+               if (bits > 32)\r
+                       goto emsgsize;\r
+       }\r
+\r
+       /* Firey death and destruction unless we prefetched EOS. */\r
+       if (ch != '\0')\r
+               goto enoent;\r
+\r
+       /* If nothing was written to the destination, we found no address. */\r
+       if (dst == odst)\r
+               goto enoent;\r
+       /* If no CIDR spec was given, infer width from net class. */\r
+       if (bits == -1) {\r
+               if (*odst >= 240)       /* Class E */\r
+                       bits = 32;\r
+               else if (*odst >= 224)  /* Class D */\r
+                       bits = 4;\r
+               else if (*odst >= 192)  /* Class C */\r
+                       bits = 24;\r
+               else if (*odst >= 128)  /* Class B */\r
+                       bits = 16;\r
+               else                    /* Class A */\r
+                       bits = 8;\r
+               /* If imputed mask is narrower than specified octets, widen. */\r
+               if (bits >= 8 && bits < ((dst - odst) * 8))\r
+                       bits = (int)(dst - odst) * 8;\r
+       }\r
+       /* Extend network to cover the actual mask. */\r
+       while (bits > ((dst - odst) * 8)) {\r
+               if (size-- <= 0)\r
+                       goto emsgsize;\r
+               *dst++ = '\0';\r
+       }\r
+       return (bits);\r
+\r
+ enoent:\r
+       errno = ENOENT;\r
+       return (-1);\r
+\r
+ emsgsize:\r
+       errno = EMSGSIZE;\r
+       return (-1);\r
+}\r