Add inet_pton and inet_ntop

This commit is contained in:
iabdalkader 2014-07-05 03:36:04 +02:00
parent 545c29763e
commit 7826c14c05
4 changed files with 419 additions and 0 deletions

View File

@ -0,0 +1,4 @@
#ifndef __INET_NTOP_H
#define __INET_NTOP_H
char *inet_ntop(int af, const void *addr, char *buf, size_t size);
#endif /* __INET_NTOP_H */

View File

@ -0,0 +1,4 @@
#ifndef __INET_PTON_H
#define __INET_PTON_H
int inet_pton(int, const char *, void *);
#endif /* __INET_PTON_H */

195
src/cc3k/src/inet_ntop.c Normal file
View File

@ -0,0 +1,195 @@
/*
* Copyright (C) 1996-2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* 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 INTERNET SOFTWARE CONSORTIUM
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
* INTERNET SOFTWARE CONSORTIUM 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.
*/
#include <std.h>
#include <string.h>
#include "cc3000_common.h"
#include "socket.h"
#include "inet_ntop.h"
#define IN6ADDRSZ 16
#define INADDRSZ 4
#define INT16SZ 2
#define ENOSPC (28)
#define EAFNOSUPPORT (106)
#define SET_ERRNO(err) (errno=-err)
/*
* Format an IPv4 address, more or less like inet_ntoa().
*
* Returns `dst' (as a const)
* Note:
* - uses no statics
* - takes a unsigned char* not an in_addr as input
*/
static char *inet_ntop4 (const unsigned char *src, char *dst, size_t size)
{
size_t len;
char tmp[sizeof "255.255.255.255"];
tmp[0] = '\0';
(void)snprintf(tmp, sizeof(tmp), "%d.%d.%d.%d",
((int)((unsigned char)src[0])) & 0xff,
((int)((unsigned char)src[1])) & 0xff,
((int)((unsigned char)src[2])) & 0xff,
((int)((unsigned char)src[3])) & 0xff);
len = strlen(tmp);
if(len == 0 || len >= size)
{
SET_ERRNO(ENOSPC);
return (NULL);
}
strcpy(dst, tmp);
return dst;
}
#ifdef ENABLE_IPV6
/*
* Convert IPv6 binary address into presentation (printable) format.
*/
static char *inet_ntop6 (const unsigned char *src, char *dst, size_t size)
{
/*
* Note that int32_t and int16_t need only be "at least" large enough
* to contain a value of the specified size. On some systems, like
* Crays, there is no such thing as an integer variable with 16 bits.
* Keep this in mind if you think this function should have been coded
* to use pointer overlays. All the world's not a VAX.
*/
char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
char *tp;
struct {
long base;
long len;
} best, cur;
unsigned long words[IN6ADDRSZ / INT16SZ];
int i;
/* Preprocess:
* Copy the input (bytewise) array into a wordwise array.
* Find the longest run of 0x00's in src[] for :: shorthanding.
*/
memset(words, '\0', sizeof(words));
for (i = 0; i < IN6ADDRSZ; i++)
words[i/2] |= (src[i] << ((1 - (i % 2)) << 3));
best.base = -1;
cur.base = -1;
best.len = 0;
cur.len = 0;
for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
{
if(words[i] == 0)
{
if(cur.base == -1)
cur.base = i, cur.len = 1;
else
cur.len++;
}
else if(cur.base != -1)
{
if(best.base == -1 || cur.len > best.len)
best = cur;
cur.base = -1;
}
}
if((cur.base != -1) && (best.base == -1 || cur.len > best.len))
best = cur;
if(best.base != -1 && best.len < 2)
best.base = -1;
/* Format the result.
*/
tp = tmp;
for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
{
/* Are we inside the best run of 0x00's?
*/
if(best.base != -1 && i >= best.base && i < (best.base + best.len))
{
if(i == best.base)
*tp++ = ':';
continue;
}
/* Are we following an initial run of 0x00s or any real hex?
*/
if(i != 0)
*tp++ = ':';
/* Is this address an encapsulated IPv4?
*/
if(i == 6 && best.base == 0 &&
(best.len == 6 || (best.len == 5 && words[5] == 0xffff)))
{
if(!inet_ntop4(src+12, tp, sizeof(tmp) - (tp - tmp)))
{
SET_ERRNO(ENOSPC);
return (NULL);
}
tp += strlen(tp);
break;
}
tp += snprintf(tp, 5, "%lx", words[i]);
}
/* Was it a trailing run of 0x00's?
*/
if(best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ))
*tp++ = ':';
*tp++ = '\0';
/* Check for overflow, copy, and we're done.
*/
if((size_t)(tp - tmp) > size)
{
SET_ERRNO(ENOSPC);
return (NULL);
}
strcpy(dst, tmp);
return dst;
}
#endif /* ENABLE_IPV6 */
/*
* Convert a network format address to presentation format.
*
* Returns pointer to presentation format address (`buf').
* Returns NULL on error and errno set with the specific
* error, EAFNOSUPPORT or ENOSPC.
*
* On Windows we store the error in the thread errno, not
* in the winsock error code. This is to avoid loosing the
* actual last winsock error. So use macro ERRNO to fetch the
* errno this funtion sets when returning NULL, not SOCKERRNO.
*/
char *inet_ntop(int af, const void *src, char *buf, size_t size)
{
switch (af) {
case AF_INET:
return inet_ntop4((const unsigned char*)src, buf, size);
#ifdef ENABLE_IPV6
case AF_INET6:
return inet_ntop6((const unsigned char*)src, buf, size);
#endif
default:
SET_ERRNO(EAFNOSUPPORT);
return NULL;
}
}

216
src/cc3k/src/inet_pton.c Normal file
View File

@ -0,0 +1,216 @@
/* This is from the BIND 4.9.4 release, modified to compile by itself */
/* Copyright (c) 1996 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* 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 INTERNET SOFTWARE CONSORTIUM DISCLAIMS
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
* CONSORTIUM 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.
*/
#include <string.h>
#include "cc3000_common.h"
#include "socket.h"
#include "inet_pton.h"
#define IN6ADDRSZ 16
#define INADDRSZ 4
#define INT16SZ 2
static int inet_pton4(const char *src, unsigned char *dst);
#ifdef ENABLE_IPV6
static int inet_pton6(const char *src, unsigned char *dst);
#endif
#define EAFNOSUPPORT (106)
#define SET_ERRNO(err) (errno=-err)
/* int
* inet_pton(af, src, dst)
* convert from presentation format (which usually means ASCII printable)
* to network format (which is usually some kind of binary format).
* return:
* 1 if the address was valid for the specified address family
* 0 if the address wasn't valid (`dst' is untouched in this case)
* -1 if some other error occurred (`dst' is untouched in this case, too)
* notice:
* On Windows we store the error in the thread errno, not
* in the winsock error code. This is to avoid loosing the
* actual last winsock error. So use macro ERRNO to fetch the
* errno this funtion sets when returning (-1), not SOCKERRNO.
* author:
* Paul Vixie, 1996.
*/
int inet_pton(int af, const char *src, void *dst)
{
switch (af) {
case AF_INET:
return (inet_pton4(src, (unsigned char *)dst));
#ifdef ENABLE_IPV6
case AF_INET6:
return (inet_pton6(src, (unsigned char *)dst));
#endif
default:
SET_ERRNO(EAFNOSUPPORT);
return (-1);
}
/* NOTREACHED */
}
/* int
* inet_pton4(src, dst)
* like inet_aton() but without all the hexadecimal and shorthand.
* return:
* 1 if `src' is a valid dotted quad, else 0.
* notice:
* does not touch `dst' unless it's returning 1.
* author:
* Paul Vixie, 1996.
*/
static int inet_pton4(const char *src, unsigned char *dst)
{
static const char digits[] = "0123456789";
int saw_digit, octets, ch;
unsigned char tmp[INADDRSZ], *tp;
saw_digit = 0;
octets = 0;
tp = tmp;
*tp = 0;
while((ch = *src++) != '\0') {
const char *pch;
if((pch = strchr(digits, ch)) != NULL) {
unsigned int val = *tp * 10 + (unsigned int)(pch - digits);
if(saw_digit && *tp == 0)
return (0);
if(val > 255)
return (0);
*tp = (unsigned char)val;
if(! saw_digit) {
if(++octets > 4)
return (0);
saw_digit = 1;
}
}
else if(ch == '.' && saw_digit) {
if(octets == 4)
return (0);
*++tp = 0;
saw_digit = 0;
}
else
return (0);
}
if(octets < 4)
return (0);
memcpy(dst, tmp, INADDRSZ);
return (1);
}
#ifdef ENABLE_IPV6
/* int
* inet_pton6(src, dst)
* convert presentation level address to network order binary form.
* return:
* 1 if `src' is a valid [RFC1884 2.2] address, else 0.
* notice:
* (1) does not touch `dst' unless it's returning 1.
* (2) :: in a full address is silently ignored.
* credit:
* inspired by Mark Andrews.
* author:
* Paul Vixie, 1996.
*/
static int inet_pton6(const char *src, unsigned char *dst)
{
static const char xdigits_l[] = "0123456789abcdef",
xdigits_u[] = "0123456789ABCDEF";
unsigned char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
const char *xdigits, *curtok;
int ch, saw_xdigit;
unsigned int val;
memset((tp = tmp), 0, IN6ADDRSZ);
endp = tp + IN6ADDRSZ;
colonp = NULL;
/* Leading :: requires some special handling. */
if(*src == ':')
if(*++src != ':')
return (0);
curtok = src;
saw_xdigit = 0;
val = 0;
while((ch = *src++) != '\0') {
const char *pch;
if((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
pch = strchr((xdigits = xdigits_u), ch);
if(pch != NULL) {
val <<= 4;
val |= (pch - xdigits);
if(++saw_xdigit > 4)
return (0);
continue;
}
if(ch == ':') {
curtok = src;
if(!saw_xdigit) {
if(colonp)
return (0);
colonp = tp;
continue;
}
if(tp + INT16SZ > endp)
return (0);
*tp++ = (unsigned char) (val >> 8) & 0xff;
*tp++ = (unsigned char) val & 0xff;
saw_xdigit = 0;
val = 0;
continue;
}
if(ch == '.' && ((tp + INADDRSZ) <= endp) &&
inet_pton4(curtok, tp) > 0) {
tp += INADDRSZ;
saw_xdigit = 0;
break; /* '\0' was seen by inet_pton4(). */
}
return (0);
}
if(saw_xdigit) {
if(tp + INT16SZ > endp)
return (0);
*tp++ = (unsigned char) (val >> 8) & 0xff;
*tp++ = (unsigned char) val & 0xff;
}
if(colonp != NULL) {
/*
* Since some memmove()'s erroneously fail to handle
* overlapping regions, we'll do the shift by hand.
*/
const long n = tp - colonp;
long i;
if(tp == endp)
return (0);
for (i = 1; i <= n; i++) {
endp[- i] = colonp[n - i];
colonp[n - i] = 0;
}
tp = endp;
}
if(tp != endp)
return (0);
memcpy(dst, tmp, IN6ADDRSZ);
return (1);
}
#endif /* ENABLE_IPV6 */