Main Page | File List | Globals

src/inet_pton.c

Go to the documentation of this file.
00001 /*
00002      This file is part of PlibC.
00003      (C) 2005 Nils Durner (and other contributing authors)
00004 
00005            This library is free software; you can redistribute it and/or
00006            modify it under the terms of the GNU Lesser General Public
00007            License as published by the Free Software Foundation; either
00008            version 2.1 of the License, or (at your option) any later version.
00009         
00010            This library is distributed in the hope that it will be useful,
00011            but WITHOUT ANY WARRANTY; without even the implied warranty of
00012            MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013            Lesser General Public License for more details.
00014         
00015            You should have received a copy of the GNU Lesser General Public
00016            License along with this library; if not, write to the Free Software
00017            Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 */
00019 
00026 /* Copyright (c) 1996 by Internet Software Consortium.
00027  *
00028  * Permission to use, copy, modify, and distribute this software for any
00029  * purpose with or without fee is hereby granted, provided that the above
00030  * copyright notice and this permission notice appear in all copies.
00031  *
00032  * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
00033  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
00034  * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
00035  * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
00036  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
00037  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
00038  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
00039  * SOFTWARE.
00040  */
00041 
00042 #include "plibc_private.h"
00043 
00044 #ifndef HAVE_INET_PTON
00045 
00046 #if HAVE_ARPA_NAMESER_H
00047 #include <arpa/nameser.h>
00048 #endif
00049 
00050   /*
00051    * Net-SNMP Win32 additions
00052    */
00053 #if HAVE_WINSOCK_H
00054 #include <winsock2.h>
00055 #include <errno.h>
00056 #include <stdio.h>
00057 #endif
00058 
00059 #ifndef EAFNOSUPPORT
00060 #define EAFNOSUPPORT            WSAEAFNOSUPPORT
00061 #endif
00062 
00063 #ifndef IN6ADDRSZ
00064 #define IN6ADDRSZ       16
00065 #endif
00066 
00067 #ifndef INT16SZ
00068 #define INT16SZ         2
00069 #endif
00070   /*
00071    * End of Net-SNMP Win32 additions
00072    */
00073 
00074 #ifndef INADDRSZ
00075 #define INADDRSZ        4
00076 #endif
00077 
00078 /*
00079  *  Don't even consider trying to compile this on a system where
00080  * sizeof(int) < 4.  sizeof(int) > 4 is fine; all the world's not a VAX.
00081  */
00082 
00083 int     inet_pton4(const char *src, u_char *dst, int pton);
00084 #if USE_IPV6
00085 int     inet_pton6(const char *src, u_char *dst);
00086 #endif
00087 
00088 /* int
00089  * inet_pton(af, src, dst)
00090  *      convert from presentation format (which usually means ASCII printable)
00091  *      to network format (which is usually some kind of binary format).
00092  * return:
00093  *      1 if the address was valid for the specified address family
00094  *      0 if the address wasn't valid (`dst' is untouched in this case)
00095  *      -1 if some other error occurred (`dst' is untouched in this case, too)
00096  * author:
00097  *      Paul Vixie, 1996.
00098  */
00099 int inet_pton(int af, const char *src, void *dst)
00100 {
00101 
00102         switch (af) {
00103         case AF_INET:
00104                 return (inet_pton4(src, dst, 1));
00105 #if USE_IPV6
00106         case AF_INET6:
00107                 return (inet_pton6(src, dst));
00108 #endif
00109         default:
00110                 errno = EAFNOSUPPORT;
00111                 return (-1);
00112         }
00113         /* NOTREACHED */
00114 }
00115 
00116 /* int
00117  * inet_pton4(src, dst, pton)
00118  *      when last arg is 0: inet_aton(). with hexadecimal, octal and shorthand.
00119  *      when last arg is 1: inet_pton(). decimal dotted-quad only.
00120  * return:
00121  *      1 if `src' is a valid input, else 0.
00122  * notice:
00123  *      does not touch `dst' unless it's returning 1.
00124  * author:
00125  *      Paul Vixie, 1996.
00126  */
00127 int     inet_pton4(const char *src, u_char *dst, int pton)
00128 {
00129         u_int val;
00130         u_int digit;
00131         int base, n;
00132         unsigned char c;
00133         u_int parts[4];
00134         register u_int *pp = parts;
00135 
00136         c = *src;
00137         for (;;) {
00138                 /*
00139                  * Collect number up to ``.''.
00140                  * Values are specified as for C:
00141                  * 0x=hex, 0=octal, isdigit=decimal.
00142                  */
00143                 if (!isdigit(c))
00144                         return (0);
00145                 val = 0; base = 10;
00146                 if (c == '0') {
00147                         c = *++src;
00148                         if (c == 'x' || c == 'X')
00149                                 base = 16, c = *++src;
00150                         else if (isdigit(c) && c != '9')
00151                                 base = 8;
00152                 }
00153                 /* inet_pton() takes decimal only */
00154                 if (pton && base != 10)
00155                         return (0);
00156                 for (;;) {
00157                         if (isdigit(c)) {
00158                                 digit = c - '0';
00159                                 if (digit >= base)
00160                                         break;
00161                                 val = (val * base) + digit;
00162                                 c = *++src;
00163                         } else if (base == 16 && isxdigit(c)) {
00164                                 digit = c + 10 - (islower(c) ? 'a' : 'A');
00165                                 if (digit >= 16)
00166                                         break;
00167                                 val = (val << 4) | digit;
00168                                 c = *++src;
00169                         } else
00170                                 break;
00171                 }
00172                 if (c == '.') {
00173                         /*
00174                          * Internet format:
00175                          *      a.b.c.d
00176                          *      a.b.c   (with c treated as 16 bits)
00177                          *      a.b     (with b treated as 24 bits)
00178                          *      a       (with a treated as 32 bits)
00179                          */
00180                         if (pp >= parts + 3)
00181                                 return (0);
00182                         *pp++ = val;
00183                         c = *++src;
00184                 } else
00185                         break;
00186         }
00187         /*
00188          * Check for trailing characters.
00189          */
00190         if (c != '\0' && !isspace(c))
00191                 return (0);
00192         /*
00193          * Concoct the address according to
00194          * the number of parts specified.
00195          */
00196         n = pp - parts + 1;
00197         /* inet_pton() takes dotted-quad only.  it does not take shorthand. */
00198         if (pton && n != 4)
00199                 return (0);
00200         switch (n) {
00201 
00202         case 0:
00203                 return (0);             /* initial nondigit */
00204 
00205         case 1:                         /* a -- 32 bits */
00206                 break;
00207 
00208         case 2:                         /* a.b -- 8.24 bits */
00209                 if (parts[0] > 0xff || val > 0xffffff)
00210                         return (0);
00211                 val |= parts[0] << 24;
00212                 break;
00213 
00214         case 3:                         /* a.b.c -- 8.8.16 bits */
00215                 if ((parts[0] | parts[1]) > 0xff || val > 0xffff)
00216                         return (0);
00217                 val |= (parts[0] << 24) | (parts[1] << 16);
00218                 break;
00219 
00220         case 4:                         /* a.b.c.d -- 8.8.8.8 bits */
00221                 if ((parts[0] | parts[1] | parts[2] | val) > 0xff)
00222                         return (0);
00223                 val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
00224                 break;
00225         }
00226         if (dst) {
00227                 val = htonl(val);
00228                 memcpy(dst, &val, INADDRSZ);
00229         }
00230         return (1);
00231 }
00232 
00233 #if USE_IPV6
00234 /* int
00235  * inet_pton6(src, dst)
00236  *      convert presentation level address to network order binary form.
00237  * return:
00238  *      1 if `src' is a valid [RFC1884 2.2] address, else 0.
00239  * notice:
00240  *      (1) does not touch `dst' unless it's returning 1.
00241  *      (2) :: in a full address is silently ignored.
00242  * credit:
00243  *      inspired by Mark Andrews.
00244  * author:
00245  *      Paul Vixie, 1996.
00246  */
00247 int inet_pton6(const char *src, u_char *dst)
00248 {
00249         static const char xdigits_l[] = "0123456789abcdef",
00250                           xdigits_u[] = "0123456789ABCDEF";
00251         u_char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
00252         const char *xdigits, *curtok;
00253         int ch, saw_xdigit;
00254         u_int val;
00255 
00256         memset((tp = tmp), '\0', IN6ADDRSZ);
00257         endp = tp + IN6ADDRSZ;
00258         colonp = NULL;
00259         /* Leading :: requires some special handling. */
00260         if (*src == ':')
00261                 if (*++src != ':')
00262                         return (0);
00263         curtok = src;
00264         saw_xdigit = 0;
00265         val = 0;
00266         while ((ch = *src++) != '\0') {
00267                 const char *pch;
00268 
00269                 if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
00270                         pch = strchr((xdigits = xdigits_u), ch);
00271                 if (pch != NULL) {
00272                         val <<= 4;
00273                         val |= (pch - xdigits);
00274                         if (val > 0xffff)
00275                                 return (0);
00276                         saw_xdigit = 1;
00277                         continue;
00278                 }
00279                 if (ch == ':') {
00280                         curtok = src;
00281                         if (!saw_xdigit) {
00282                                 if (colonp)
00283                                         return (0);
00284                                 colonp = tp;
00285                                 continue;
00286                         } else if (*src == '\0')
00287                                 return (0);
00288                         if (tp + INT16SZ > endp)
00289                                 return (0);
00290                         *tp++ = (u_char) (val >> 8) & 0xff;
00291                         *tp++ = (u_char) val & 0xff;
00292                         saw_xdigit = 0;
00293                         val = 0;
00294                         continue;
00295                 }
00296                 if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
00297                     inet_pton4(curtok, tp, 1) > 0) {
00298                         tp += INADDRSZ;
00299                         saw_xdigit = 0;
00300                         break;  /* '\0' was seen by inet_pton4(). */
00301                 }
00302                 return (0);
00303         }
00304         if (saw_xdigit) {
00305                 if (tp + INT16SZ > endp)
00306                         return (0);
00307                 *tp++ = (u_char) (val >> 8) & 0xff;
00308                 *tp++ = (u_char) val & 0xff;
00309         }
00310         if (colonp != NULL) {
00311                 /*
00312                  * Since some memmove()'s erroneously fail to handle
00313                  * overlapping regions, we'll do the shift by hand.
00314                  */
00315                 const int n = tp - colonp;
00316                 int i;
00317 
00318                 if (tp == endp)
00319                         return (0);
00320                 for (i = 1; i <= n; i++) {
00321                         endp[- i] = colonp[n - i];
00322                         colonp[n - i] = 0;
00323                 }
00324                 tp = endp;
00325         }
00326         if (tp != endp)
00327                 return (0);
00328         memcpy(dst, tmp, IN6ADDRSZ);
00329         return (1);
00330 }
00331 #endif
00332 
00333 #endif /* HAVE_INET_PTON */

Generated on Sun Sep 4 11:16:47 2005 for PlibC by  doxygen 1.4.2