enhanced nwad functions

This commit is contained in:
2012-07-02 14:21:40 +00:00
parent c60ca301c4
commit a62984d47a
12 changed files with 583 additions and 247 deletions

View File

@ -24,121 +24,83 @@
#include <qse/cmn/fmt.h>
#include "mem.h"
#if 0
int qse_mbstonwad (const qse_mchar_t* str, qse_nwad_t* nwad)
#if defined(HAVE_NET_IF_H)
#include <net/if.h>
#include <qse/cmn/mbwc.h>
#if !defined(IF_NAMESIZE)
# define IF_NAMESIZE 63
#endif
#if defined(HAVE_IF_NAMETOINDEX)
static QSE_INLINE unsigned int mbsn_to_ifindex (const qse_mchar_t* ptr, qse_size_t len)
{
const qse_mchar_t* p;
qse_mcstr_t tmp;
qse_nwad_t tmpad;
QSE_MEMSET (&tmpad, 0, QSE_SIZEOF(tmpad));
p = str;
if (*p == QSE_MT('['))
qse_mchar_t tmp[IF_NAMESIZE + 1];
if (qse_mbsxncpy (tmp, QSE_COUNTOF(tmp), ptr, len) < len)
{
/* IPv6 address */
tmp.ptr = ++p; /* skip [ and remember the position */
while (*p != QSE_MT('\0') && *p != QSE_MT('%') && *p != QSE_MT(']')) p++;
if (*p == QSE_MT('\0')) return -1;
tmp.len = p - tmp.ptr;
if (*p == QSE_MT('%'))
{
/* handle scope id */
qse_uint32_t x;
p++; /* skip % */
if (!(*p >= QSE_MT('0') && *p <= QSE_MT('9'))) return -1;
tmpad.u.in6.scope = 0;
do
{
x = tmpad.u.in6.scope * 10 + (*p - QSE_MT('0'));
if (x < tmpad.u.in6.scope) return -1; /* overflow */
tmpad.u.in6.scope = x;
p++;
}
while (*p >= QSE_MT('0') && *p <= QSE_MT('9'));
if (*p != QSE_MT(']')) return -1;
}
p++; /* skip ] */
if (qse_mbsntoipad6 (tmp.ptr, tmp.len, &tmpad.u.in6.addr) <= -1) return -1;
tmpad.type = QSE_NWAD_IN6;
/* name too long */
return 0;
}
else
{
/* host name or IPv4 address */
tmp.ptr = p;
while (*p != QSE_MT('\0') && *p != QSE_MT(':')) p++;
tmp.len = p - tmp.ptr;
return if_nametoindex (tmp);
}
if (qse_mbsntoipad4 (tmp.ptr, tmp.len, &tmpad.u.in4.addr) <= -1)
{
/* check if it is an IPv6 address not enclosed in [].
* the port number can't be specified in this format. */
static QSE_INLINE unsigned int wcsn_to_ifindex (const qse_wchar_t* ptr, qse_size_t len)
{
qse_mchar_t tmp[IF_NAMESIZE + 1];
qse_size_t wl, ml;
while (*p != QSE_MT('\0') && *p != QSE_MT('%')) p++;
tmp.len = p - tmp.ptr;
wl = len; ml = QSE_COUNTOF(tmp) - 1;
if (qse_wcsntombsn (ptr, &wl, tmp, &ml) <= -1) return 0;
tmp[ml] = QSE_MT('\0');
return if_nametoindex (tmp);
}
#else
staitc QSE_INLINE unsigned int mbsn_to_ifindex (const qse_mchar_t* ptr, qse_size_t len)
{
return 0U;
}
staitc QSE_INLINE unsigned int wcsn_to_ifindex (const qse_wchar_t* ptr, qse_size_t len)
{
return 0U;
}
#endif
if (qse_mbsntoipad6 (tmp.ptr, tmp.len, &tmpad.u.in6.addr) <= -1)
return -1;
#if defined(HAVE_IF_INDEXTONAME)
static QSE_INLINE int ifindex_to_mbsn (unsigned int index, qse_mchar_t* buf, qse_size_t len)
{
qse_mchar_t tmp[IF_NAMESIZE + 1];
if (if_indextoname (index, tmp) == QSE_NULL) return 0;
return qse_mbsxcpy (buf, len, tmp);
}
if (*p == QSE_MT('%'))
{
/* handle scope id */
qse_uint32_t x;
static QSE_INLINE int ifindex_to_wcsn (unsigned int index, qse_wchar_t* buf, qse_size_t len)
{
qse_mchar_t tmp[IF_NAMESIZE + 1];
qse_size_t ml, wl;
int x;
p++; /* skip % */
if (!(*p >= QSE_MT('0') && *p <= QSE_MT('9'))) return -1;
tmpad.u.in6.scope = 0;
do
{
x = tmpad.u.in6.scope * 10 + (*p - QSE_MT('0'));
if (x < tmpad.u.in6.scope) return -1; /* overflow */
tmpad.u.in6.scope = x;
p++;
}
while (*p >= QSE_MT('0') && *p <= QSE_MT('9'));
}
if (if_indextoname (index, tmp) == QSE_NULL) return 0;
wl = len;
x = qse_mbstowcs (tmp, &ml, buf, &wl);
if (x == -2 && wl > 1) buf[wl - 1] = QSE_WT('\0');
else if (x != 0) return 0;
return wl;
}
if (*p != QSE_MT('\0')) return -1;
tmpad.type = QSE_NWAD_IN6;
goto done;
}
tmpad.type = QSE_NWAD_IN4;
}
if (*p == QSE_MT(':'))
{
/* port number */
qse_uint32_t port = 0;
p++; /* skip : */
for (tmp.ptr = p; *p >= QSE_MT('0') && *p <= QSE_MT('9'); p++)
port = port * 10 + (*p - QSE_MT('0'));
tmp.len = p - tmp.ptr;
if (tmp.len <= 0 || tmp.len >= 6 ||
port > QSE_TYPE_MAX(qse_uint16_t)) return -1;
if (tmpad.type == QSE_NWAD_IN4)
tmpad.u.in4.port = qse_hton16 (port);
else
tmpad.u.in6.port = qse_hton16 (port);
}
done:
if (nwad) *nwad = tmpad;
#else
static QSE_INLINE int ifindex_to_mbsn (unsigned int index, qse_mchar_t* buf, qse_size_t len)
{
return 0;
}
static QSE_INLINE int ifindex_to_wcsn (unsigned int index, qse_wchar_t* buf, qse_size_t len)
{
return 0;
}
#endif
#endif
int qse_mbstonwad (const qse_mchar_t* str, qse_nwad_t* nwad)
{
return qse_mbsntonwad (str, qse_mbslen(str), nwad);
@ -174,16 +136,33 @@ int qse_mbsntonwad (const qse_mchar_t* str, qse_size_t len, qse_nwad_t* nwad)
p++; /* skip % */
if (!(p < end && *p >= QSE_MT('0') && *p <= QSE_MT('9'))) return -1;
tmpad.u.in6.scope = 0;
do
if (p >= end)
{
x = tmpad.u.in6.scope * 10 + (*p - QSE_MT('0'));
if (x < tmpad.u.in6.scope) return -1; /* overflow */
tmpad.u.in6.scope = x;
p++;
/* premature end */
return -1;
}
if (*p >= QSE_MT('0') && *p <= QSE_MT('9'))
{
/* numeric scope id */
tmpad.u.in6.scope = 0;
do
{
x = tmpad.u.in6.scope * 10 + (*p - QSE_MT('0'));
if (x < tmpad.u.in6.scope) return -1; /* overflow */
tmpad.u.in6.scope = x;
p++;
}
while (p < end && *p >= QSE_MT('0') && *p <= QSE_MT('9'));
}
else
{
/* interface name as a scope id? */
const qse_mchar_t* stmp = p;
do p++; while (p < end && *p != QSE_MT(']'));
tmpad.u.in6.scope = mbsn_to_ifindex (stmp, p - stmp);
if (tmpad.u.in6.scope <= 0) return -1;
}
while (p < end && *p >= QSE_MT('0') && *p <= QSE_MT('9'));
if (p >= end || *p != QSE_MT(']')) return -1;
}
@ -218,16 +197,34 @@ int qse_mbsntonwad (const qse_mchar_t* str, qse_size_t len, qse_nwad_t* nwad)
qse_uint32_t x;
p++; /* skip % */
if (!(p < end && *p >= QSE_MT('0') && *p <= QSE_MT('9'))) return -1;
tmpad.u.in6.scope = 0;
do
if (p >= end)
{
x = tmpad.u.in6.scope * 10 + (*p - QSE_MT('0'));
if (x < tmpad.u.in6.scope) return -1; /* overflow */
tmpad.u.in6.scope = x;
p++;
/* premature end */
return -1;
}
if (*p >= QSE_MT('0') && *p <= QSE_MT('9'))
{
/* numeric scope id */
tmpad.u.in6.scope = 0;
do
{
x = tmpad.u.in6.scope * 10 + (*p - QSE_MT('0'));
if (x < tmpad.u.in6.scope) return -1; /* overflow */
tmpad.u.in6.scope = x;
p++;
}
while (p < end && *p >= QSE_MT('0') && *p <= QSE_MT('9'));
}
else
{
/* interface name as a scope id? */
const qse_mchar_t* stmp = p;
do p++; while (p < end);
tmpad.u.in6.scope = mbsn_to_ifindex (stmp, p - stmp);
if (tmpad.u.in6.scope <= 0) return -1;
}
while (p < end && *p >= QSE_MT('0') && *p <= QSE_MT('9'));
}
if (p < end) return -1;
@ -303,16 +300,33 @@ int qse_wcsntonwad (const qse_wchar_t* str, qse_size_t len, qse_nwad_t* nwad)
p++; /* skip % */
if (!(p < end && *p >= QSE_WT('0') && *p <= QSE_WT('9'))) return -1;
tmpad.u.in6.scope = 0;
do
if (p >= end)
{
x = tmpad.u.in6.scope * 10 + (*p - QSE_WT('0'));
if (x < tmpad.u.in6.scope) return -1; /* overflow */
tmpad.u.in6.scope = x;
p++;
/* premature end */
return -1;
}
if (*p >= QSE_WT('0') && *p <= QSE_WT('9'))
{
/* numeric scope id */
tmpad.u.in6.scope = 0;
do
{
x = tmpad.u.in6.scope * 10 + (*p - QSE_WT('0'));
if (x < tmpad.u.in6.scope) return -1; /* overflow */
tmpad.u.in6.scope = x;
p++;
}
while (p < end && *p >= QSE_WT('0') && *p <= QSE_WT('9'));
}
else
{
/* interface name as a scope id? */
const qse_wchar_t* stmp = p;
do p++; while (p < end && *p != QSE_WT(']'));
tmpad.u.in6.scope = wcsn_to_ifindex (stmp, p - stmp);
if (tmpad.u.in6.scope <= 0) return -1;
}
while (p < end && *p >= QSE_WT('0') && *p <= QSE_WT('9'));
if (p >= end || *p != QSE_WT(']')) return -1;
}
@ -347,16 +361,34 @@ int qse_wcsntonwad (const qse_wchar_t* str, qse_size_t len, qse_nwad_t* nwad)
qse_uint32_t x;
p++; /* skip % */
if (!(p < end && *p >= QSE_WT('0') && *p <= QSE_WT('9'))) return -1;
tmpad.u.in6.scope = 0;
do
if (p >= end)
{
x = tmpad.u.in6.scope * 10 + (*p - QSE_WT('0'));
if (x < tmpad.u.in6.scope) return -1; /* overflow */
tmpad.u.in6.scope = x;
p++;
/* premature end */
return -1;
}
if (*p >= QSE_WT('0') && *p <= QSE_WT('9'))
{
/* numeric scope id */
tmpad.u.in6.scope = 0;
do
{
x = tmpad.u.in6.scope * 10 + (*p - QSE_WT('0'));
if (x < tmpad.u.in6.scope) return -1; /* overflow */
tmpad.u.in6.scope = x;
p++;
}
while (p < end && *p >= QSE_WT('0') && *p <= QSE_WT('9'));
}
else
{
/* interface name as a scope id? */
const qse_wchar_t* stmp = p;
do p++; while (p < end);
tmpad.u.in6.scope = wcsn_to_ifindex (stmp, p - stmp);
if (tmpad.u.in6.scope <= 0) return -1;
}
while (p < end && *p >= QSE_WT('0') && *p <= QSE_WT('9'));
}
if (p < end) return -1;
@ -446,18 +478,27 @@ qse_size_t qse_nwadtombs (
if (flags & QSE_NWADTOMBS_ADDR)
{
if (xlen + 1 >= len) goto done;
xlen += qse_ipad6tombs (&nwad->u.in6.addr, &buf[xlen], len - xlen);
if (nwad->u.in6.scope != 0)
{
int tmp;
if (xlen + 1 >= len) goto done;
buf[xlen++] = QSE_MT('%');
if (xlen + 1 >= len) goto done;
xlen += qse_fmtuintmaxtombs (
&buf[xlen], len - xlen,
nwad->u.in6.scope, 10, 0, QSE_MT('\0'), QSE_NULL);
tmp = ifindex_to_mbsn (nwad->u.in6.scope, &buf[xlen], len - xlen);
if (tmp <= 0)
{
xlen += qse_fmtuintmaxtombs (
&buf[xlen], len - xlen,
nwad->u.in6.scope, 10, 0, QSE_MT('\0'), QSE_NULL);
}
else xlen += tmp;
}
}
@ -547,13 +588,21 @@ qse_size_t qse_nwadtowcs (
if (nwad->u.in6.scope != 0)
{
int tmp;
if (xlen + 1 >= len) goto done;
buf[xlen++] = QSE_WT('%');
if (xlen + 1 >= len) goto done;
xlen += qse_fmtuintmaxtowcs (
&buf[xlen], len - xlen,
nwad->u.in6.scope, 10, 0, QSE_WT('\0'), QSE_NULL);
tmp = ifindex_to_wcsn (nwad->u.in6.scope, &buf[xlen], len - xlen);
if (tmp <= 0)
{
xlen += qse_fmtuintmaxtowcs (
&buf[xlen], len - xlen,
nwad->u.in6.scope, 10, 0, QSE_WT('\0'), QSE_NULL);
}
else xlen += tmp;
}
}

View File

@ -437,14 +437,18 @@ int qse_nwio_init (
return -1;
#else
#if defined(SOCK_CLOEXEC)
nwio->handle = socket (family, type | SOCK_CLOEXEC, 0);
#else
nwio->handle = socket (family, type, 0);
#endif
if (nwio->handle <= -1)
{
nwio->errnum = syserr_to_errnum (errno);
goto oops;
}
#if defined(FD_CLOEXEC)
#if !defined(SOCK_CLOEXEC) && defined(FD_CLOEXEC)
{
int tmp = fcntl (nwio->handle, F_GETFD);
if (tmp >= 0) fcntl (nwio->handle, F_SETFD, tmp | FD_CLOEXEC);