/*
* Copyright (C) 2004, 2005, 2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1996, 1998, 1999, 2001, 2003 Internet Software Consortium.
*
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#endif
#include "port_before.h"
#include <isc/assertions.h>
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "port_after.h"
#ifdef SPRINTF_CHAR
#else
#endif
/*%
* static int
* inet_net_pton_ipv4(src, dst, size)
* convert IPv4 network number from presentation to network format.
* accepts hex octets, hex strings, decimal octets, and /CIDR.
* "size" is in bytes and describes "dst".
* return:
* number of bits, either imputed classfully or specified with /CIDR,
* or -1 if some failure occurred (check errno). ENOENT means it was
* not an IPv4 network specification.
* note:
* network byte order assumed. this means 192.5.5.240/28 has
* 0b11110000 in its fourth octet.
* author:
* Paul Vixie (ISC), June 1996
*/
static int
/* Hexadecimal: Eat nybble string. */
if (size <= 0U)
goto emsgsize;
dirty = 0;
src++; /*%< skip x or X. */
INSIST(n >= 0 && n <= 15);
if (dirty == 0)
tmp = n;
else
if (++dirty == 2) {
if (size-- <= 0U)
goto emsgsize;
dirty = 0;
}
}
if (dirty) { /*%< Odd trailing nybble? */
if (size-- <= 0U)
goto emsgsize;
}
/* Decimal: eat dotted digit string. */
for (;;) {
tmp = 0;
do {
INSIST(n >= 0 && n <= 9);
tmp *= 10;
tmp += n;
if (tmp > 255)
goto enoent;
if (size-- <= 0U)
goto emsgsize;
break;
if (ch != '.')
goto enoent;
goto enoent;
}
} else
goto enoent;
bits = -1;
/* CIDR width specifier. Nothing can follow it. */
bits = 0;
do {
INSIST(n >= 0 && n <= 9);
bits *= 10;
bits += n;
if (bits > 32)
goto enoent;
if (ch != '\0')
goto enoent;
}
/* Firey death and destruction unless we prefetched EOS. */
if (ch != '\0')
goto enoent;
/* If nothing was written to the destination, we found no address. */
goto enoent;
/* If no CIDR spec was given, infer width from net class. */
if (bits == -1) {
bits = 32;
bits = 8;
bits = 24;
bits = 16;
else /*%< Class A */
bits = 8;
/* If imputed mask is narrower than specified octets, widen. */
/*
* If there are no additional bits specified for a class D
* address adjust bits to 4.
*/
bits = 4;
}
/* Extend network to cover the actual mask. */
if (size-- <= 0U)
goto emsgsize;
*dst++ = '\0';
}
return (bits);
return (-1);
return (-1);
}
static int
int n;
int val;
char ch;
val = 0;
n = 0;
const char *pch;
if (n++ != 0 && val == 0) /*%< no leading zeros */
return (0);
val *= 10;
return (0);
continue;
}
return (0);
}
if (n == 0)
return (0);
return (1);
}
static int
int n;
char ch;
val = 0;
n = 0;
const char *pch;
if (n++ != 0 && val == 0) /*%< no leading zeros */
return (0);
val *= 10;
return (0);
continue;
}
return (0);
if (ch == '/')
val = 0;
n = 0;
continue;
}
return (0);
}
if (n == 0)
return (0);
return (0);
return (1);
}
static int
int digits;
int bits;
int words;
int ipv4;
/* Leading :: requires some special handling. */
if (*src == ':')
if (*++src != ':')
goto enoent;
saw_xdigit = 0;
val = 0;
digits = 0;
bits = -1;
ipv4 = 0;
const char *pch;
val <<= 4;
if (++digits > 4)
goto enoent;
saw_xdigit = 1;
continue;
}
if (ch == ':') {
if (!saw_xdigit) {
if (colonp)
goto enoent;
continue;
} else if (*src == '\0')
goto enoent;
return (0);
saw_xdigit = 0;
digits = 0;
val = 0;
continue;
}
tp += NS_INADDRSZ;
saw_xdigit = 0;
ipv4 = 1;
break; /*%< '\\0' was seen by inet_pton4(). */
}
break;
goto enoent;
}
if (saw_xdigit) {
goto enoent;
}
if (bits == -1)
bits = 128;
if (words < 2)
words = 2;
if (ipv4)
words = 8;
/*
* Since some memmove()'s erroneously fail to handle
* overlapping regions, we'll do the shift by hand.
*/
int i;
goto enoent;
for (i = 1; i <= n; i++) {
colonp[n - i] = 0;
}
}
goto enoent;
goto emsgsize;
return (bits);
return (-1);
return (-1);
}
/*%
* int
* inet_net_pton(af, src, dst, size)
* convert network number from presentation to network format.
* accepts hex octets, hex strings, decimal octets, and /CIDR.
* "size" is in bytes and describes "dst".
* return:
* number of bits, either imputed classfully or specified with /CIDR,
* or -1 if some failure occurred (check errno). ENOENT means it was
* not a valid network specification.
* author:
* Paul Vixie (ISC), June 1996
*/
int
switch (af) {
case AF_INET:
case AF_INET6:
default:
return (-1);
}
}
/*! \file */