(linenum→info "unix/slp.c:2238")

glibc/2.7/resolv/inet_net_pton.c

    1: /*
    2:  * Copyright (c) 1996,1999 by Internet Software Consortium.
    3:  *
    4:  * Permission to use, copy, modify, and distribute this software for any
    5:  * purpose with or without fee is hereby granted, provided that the above
    6:  * copyright notice and this permission notice appear in all copies.
    7:  *
    8:  * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
    9:  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
   10:  * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
   11:  * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
   12:  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
   13:  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
   14:  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
   15:  * SOFTWARE.
   16:  */
   17: 
   18: #if defined(LIBC_SCCS) && !defined(lint)
   19: static const char rcsid[] = "$BINDId: inet_net_pton.c,v 1.11 1999/01/08 19:23:44 vixie Exp $";
   20: #endif
   21: 
   22: #include <sys/types.h>
   23: #include <sys/socket.h>
   24: #include <netinet/in.h>
   25: #include <arpa/inet.h>
   26: 
   27: #include <assert.h>
   28: #include <ctype.h>
   29: #include <errno.h>
   30: #include <stdio.h>
   31: #include <string.h>
   32: #include <stdlib.h>
   33: 
   34: #ifdef SPRINTF_CHAR
   35: # define SPRINTF(x) strlen(sprintf/**/x)
   36: #else
   37: # define SPRINTF(x) ((size_t)sprintf x)
   38: #endif
   39: 
   40: static int      inet_net_pton_ipv4 (const char *src, u_char *dst,
   41:                                     size_t size) __THROW;
   42: 
   43: /*
   44:  * static int
   45:  * inet_net_pton(af, src, dst, size)
   46:  *      convert network number from presentation to network format.
   47:  *      accepts hex octets, hex strings, decimal octets, and /CIDR.
   48:  *      "size" is in bytes and describes "dst".
   49:  * return:
   50:  *      number of bits, either imputed classfully or specified with /CIDR,
   51:  *      or -1 if some failure occurred (check errno).  ENOENT means it was
   52:  *      not a valid network specification.
   53:  * author:
   54:  *      Paul Vixie (ISC), June 1996
   55:  */
   56: int
   57: inet_net_pton(af, src, dst, size)
   58:         int af;
   59:         const char *src;
   60:         void *dst;
   61:         size_t size;
   62: {
   63:         switch (af) {
   64:         case AF_INET:
   65:                 return (inet_net_pton_ipv4(src, dst, size));
   66:         default:
   67:                 __set_errno (EAFNOSUPPORT);
   68:                 return (-1);
   69:         }
   70: }
   71: 
   72: /*
   73:  * static int
   74:  * inet_net_pton_ipv4(src, dst, size)
   75:  *      convert IPv4 network number from presentation to network format.
   76:  *      accepts hex octets, hex strings, decimal octets, and /CIDR.
   77:  *      "size" is in bytes and describes "dst".
   78:  * return:
   79:  *      number of bits, either imputed classfully or specified with /CIDR,
   80:  *      or -1 if some failure occurred (check errno).  ENOENT means it was
   81:  *      not an IPv4 network specification.
   82:  * note:
   83:  *      network byte order assumed.  this means 192.5.5.240/28 has
   84:  *      0b11110000 in its fourth octet.
   85:  * author:
   86:  *      Paul Vixie (ISC), June 1996
   87:  */
   88: static int
   89: inet_net_pton_ipv4(src, dst, size)
   90:         const char *src;
   91:         u_char *dst;
   92:         size_t size;
   93: {
   94:         static const char xdigits[] = "0123456789abcdef";
   95:         int n, ch, tmp, dirty, bits;
   96:         const u_char *odst = dst;
   97: 
   98:         ch = *src++;
   99:         if (ch == '0' && (src[0] == 'x' || src[0] == 'X')
  100:             && isascii(src[1]) && isxdigit(src[1])) {
  101:                 /* Hexadecimal: Eat nybble string. */
  102:                 if (size <= 0)
  103:                         goto emsgsize;
  104:                 dirty = 0;
  105:                 tmp = 0;      /* To calm down gcc.  */
  106:                 src++;        /* skip x or X. */
  107:                 while (isxdigit((ch = *src++))) {
  108:                         ch = _tolower(ch);
  109:                         n = (const char *) __rawmemchr(xdigits, ch) - xdigits;
  110:                         assert(n >= 0 && n <= 15);
  111:                         if (dirty == 0)
  112:                                 tmp = n;
  113:                         else
  114:                                 tmp = (tmp << 4) | n;
  115:                         if (++dirty == 2) {
  116:                                 if (size-- <= 0)
  117:                                         goto emsgsize;
  118:                                 *dst++ = (u_char) tmp;
  119:                                 dirty = 0;
  120:                         }
  121:                 }
  122:                 if (dirty) {  /* Odd trailing nybble? */
  123:                         if (size-- <= 0)
  124:                                 goto emsgsize;
  125:                         *dst++ = (u_char) (tmp << 4);
  126:                 }
  127:         } else if (isascii(ch) && isdigit(ch)) {
  128:                 /* Decimal: eat dotted digit string. */
  129:                 for (;;) {
  130:                         tmp = 0;
  131:                         do {
  132:                                 n = ((const char *) __rawmemchr(xdigits, ch)
  133:                                      - xdigits);
  134:                                 assert(n >= 0 && n <= 9);
  135:                                 tmp *= 10;
  136:                                 tmp += n;
  137:                                 if (tmp > 255)
  138:                                         goto enoent;
  139:                         } while (isascii((ch = *src++)) && isdigit(ch));
  140:                         if (size-- <= 0)
  141:                                 goto emsgsize;
  142:                         *dst++ = (u_char) tmp;
  143:                         if (ch == '\0' || ch == '/')
  144:                                 break;
  145:                         if (ch != '.')
  146:                                 goto enoent;
  147:                         ch = *src++;
  148:                         if (!isascii(ch) || !isdigit(ch))
  149:                                 goto enoent;
  150:                 }
  151:         } else
  152:                 goto enoent;
  153: 
  154:         bits = -1;
  155:         if (ch == '/' && isascii(src[0]) && isdigit(src[0]) && dst > odst) {
  156:                 /* CIDR width specifier.  Nothing can follow it. */
  157:                 ch = *src++;  /* Skip over the /. */
  158:                 bits = 0;
  159:                 do {
  160:                         n = (const char *) __rawmemchr(xdigits, ch) - xdigits;
  161:                         assert(n >= 0 && n <= 9);
  162:                         bits *= 10;
  163:                         bits += n;
  164:                 } while (isascii((ch = *src++)) && isdigit(ch));
  165:                 if (ch != '\0')
  166:                         goto enoent;
  167:                 if (bits > 32)
  168:                         goto emsgsize;
  169:         }
  170: 
  171:         /* Firey death and destruction unless we prefetched EOS. */
  172:         if (ch != '\0')
  173:                 goto enoent;
  174: 
  175:         /* If nothing was written to the destination, we found no address. */
  176:         if (dst == odst)
  177:                 goto enoent;
  178:         /* If no CIDR spec was given, infer width from net class. */
  179:         if (bits == -1) {
  180:                 if (*odst >= 240)     /* Class E */
  181:                         bits = 32;
  182:                 else if (*odst >= 224)        /* Class D */
  183:                         bits = 4;
  184:                 else if (*odst >= 192)        /* Class C */
  185:                         bits = 24;
  186:                 else if (*odst >= 128)        /* Class B */
  187:                         bits = 16;
  188:                 else                  /* Class A */
  189:                         bits = 8;
  190:                 /* If imputed mask is narrower than specified octets, widen. */
  191:                 if (bits >= 8 && bits < ((dst - odst) * 8))
  192:                         bits = (dst - odst) * 8;
  193:         }
  194:         /* Extend network to cover the actual mask. */
  195:         while (bits > ((dst - odst) * 8)) {
  196:                 if (size-- <= 0)
  197:                         goto emsgsize;
  198:                 *dst++ = '\0';
  199:         }
  200:         return (bits);
  201: 
  202:  enoent:
  203:         __set_errno (ENOENT);
  204:         return (-1);
  205: 
  206:  emsgsize:
  207:         __set_errno (EMSGSIZE);
  208:         return (-1);
  209: }
Syntax (Markdown)