"Fossies" - the Fresh Open Source Software Archive

Member "scanssh-2.1/inet_pton.c" (31 Mar 2004, 5222 Bytes) of package /linux/privat/old/scanssh-2.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /*  $OpenBSD: inet_pton.c,v 1.3 1999/12/08 09:31:15 itojun Exp $    */
    2 
    3 /* Copyright (c) 1996 by Internet Software Consortium.
    4  *
    5  * Permission to use, copy, modify, and distribute this software for any
    6  * purpose with or without fee is hereby granted, provided that the above
    7  * copyright notice and this permission notice appear in all copies.
    8  *
    9  * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
   10  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
   11  * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
   12  * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
   13  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
   14  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
   15  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
   16  * SOFTWARE.
   17  */
   18 
   19 #include <sys/param.h>
   20 #include <sys/types.h>
   21 #include <sys/socket.h>
   22 #include <netinet/in.h>
   23 #include <arpa/inet.h>
   24 #include <arpa/nameser.h>
   25 #include <string.h>
   26 #include <errno.h>
   27 
   28 #include "config.h"
   29 
   30 /*
   31  * WARNING: Don't even consider trying to compile this on a system where
   32  * sizeof(int) < 4.  sizeof(int) > 4 is fine; all the world's not a VAX.
   33  */
   34 
   35 static int  inet_pton4(const char *src, u_char *dst);
   36 static int  inet_pton6(const char *src, u_char *dst);
   37 
   38 /* int
   39  * inet_pton(af, src, dst)
   40  *  convert from presentation format (which usually means ASCII printable)
   41  *  to network format (which is usually some kind of binary format).
   42  * return:
   43  *  1 if the address was valid for the specified address family
   44  *  0 if the address wasn't valid (`dst' is untouched in this case)
   45  *  -1 if some other error occurred (`dst' is untouched in this case, too)
   46  * author:
   47  *  Paul Vixie, 1996.
   48  */
   49 int
   50 inet_pton(af, src, dst)
   51     int af;
   52     const char *src;
   53     void *dst;
   54 {
   55     switch (af) {
   56     case AF_INET:
   57         return (inet_pton4(src, dst));
   58 #ifdef AF_INET6
   59     case AF_INET6:
   60         return (inet_pton6(src, dst));
   61 #endif /* AF_INET6 */
   62     default:
   63         errno = EAFNOSUPPORT;
   64         return (-1);
   65     }
   66     /* NOTREACHED */
   67 }
   68 
   69 /* int
   70  * inet_pton4(src, dst)
   71  *  like inet_aton() but without all the hexadecimal and shorthand.
   72  * return:
   73  *  1 if `src' is a valid dotted quad, else 0.
   74  * notice:
   75  *  does not touch `dst' unless it's returning 1.
   76  * author:
   77  *  Paul Vixie, 1996.
   78  */
   79 static int
   80 inet_pton4(src, dst)
   81     const char *src;
   82     u_char *dst;
   83 {
   84     static const char digits[] = "0123456789";
   85     int saw_digit, octets, ch;
   86     u_char tmp[INADDRSZ], *tp;
   87 
   88     saw_digit = 0;
   89     octets = 0;
   90     *(tp = tmp) = 0;
   91     while ((ch = *src++) != '\0') {
   92         const char *pch;
   93 
   94         if ((pch = strchr(digits, ch)) != NULL) {
   95             u_int new = *tp * 10 + (pch - digits);
   96 
   97             if (new > 255)
   98                 return (0);
   99             if (! saw_digit) {
  100                 if (++octets > 4)
  101                     return (0);
  102                 saw_digit = 1;
  103             }
  104             *tp = new;
  105         } else if (ch == '.' && saw_digit) {
  106             if (octets == 4)
  107                 return (0);
  108             *++tp = 0;
  109             saw_digit = 0;
  110         } else
  111             return (0);
  112     }
  113     if (octets < 4)
  114         return (0);
  115 
  116     memcpy(dst, tmp, INADDRSZ);
  117     return (1);
  118 }
  119 
  120 #ifdef AF_INET6
  121 
  122 /* int
  123  * inet_pton6(src, dst)
  124  *  convert presentation level address to network order binary form.
  125  * return:
  126  *  1 if `src' is a valid [RFC1884 2.2] address, else 0.
  127  * notice:
  128  *  (1) does not touch `dst' unless it's returning 1.
  129  *  (2) :: in a full address is silently ignored.
  130  * credit:
  131  *  inspired by Mark Andrews.
  132  * author:
  133  *  Paul Vixie, 1996.
  134  */
  135 static int
  136 inet_pton6(src, dst)
  137     const char *src;
  138     u_char *dst;
  139 {
  140     static const char xdigits_l[] = "0123456789abcdef",
  141               xdigits_u[] = "0123456789ABCDEF";
  142     u_char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
  143     const char *xdigits, *curtok;
  144     int ch, saw_xdigit;
  145     u_int val;
  146 
  147     memset((tp = tmp), '\0', IN6ADDRSZ);
  148     endp = tp + IN6ADDRSZ;
  149     colonp = NULL;
  150     /* Leading :: requires some special handling. */
  151     if (*src == ':')
  152         if (*++src != ':')
  153             return (0);
  154     curtok = src;
  155     saw_xdigit = 0;
  156     val = 0;
  157     while ((ch = *src++) != '\0') {
  158         const char *pch;
  159 
  160         if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
  161             pch = strchr((xdigits = xdigits_u), ch);
  162         if (pch != NULL) {
  163             val <<= 4;
  164             val |= (pch - xdigits);
  165             if (val > 0xffff)
  166                 return (0);
  167             saw_xdigit = 1;
  168             continue;
  169         }
  170         if (ch == ':') {
  171             curtok = src;
  172             if (!saw_xdigit) {
  173                 if (colonp)
  174                     return (0);
  175                 colonp = tp;
  176                 continue;
  177             } else if (*src == '\0') {
  178                 return (0);
  179             }
  180             if (tp + INT16SZ > endp)
  181                 return (0);
  182             *tp++ = (u_char) (val >> 8) & 0xff;
  183             *tp++ = (u_char) val & 0xff;
  184             saw_xdigit = 0;
  185             val = 0;
  186             continue;
  187         }
  188         if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
  189             inet_pton4(curtok, tp) > 0) {
  190             tp += INADDRSZ;
  191             saw_xdigit = 0;
  192             break;  /* '\0' was seen by inet_pton4(). */
  193         }
  194         return (0);
  195     }
  196     if (saw_xdigit) {
  197         if (tp + INT16SZ > endp)
  198             return (0);
  199         *tp++ = (u_char) (val >> 8) & 0xff;
  200         *tp++ = (u_char) val & 0xff;
  201     }
  202     if (colonp != NULL) {
  203         /*
  204          * Since some memmove()'s erroneously fail to handle
  205          * overlapping regions, we'll do the shift by hand.
  206          */
  207         const int n = tp - colonp;
  208         int i;
  209 
  210         for (i = 1; i <= n; i++) {
  211             endp[- i] = colonp[n - i];
  212             colonp[n - i] = 0;
  213         }
  214         tp = endp;
  215     }
  216     if (tp != endp)
  217         return (0);
  218     memcpy(dst, tmp, IN6ADDRSZ);
  219     return (1);
  220 }
  221 #endif /* AF_INET6 */