2012-02-13 14:43:50 +00:00
|
|
|
/*
|
|
|
|
* $Id$
|
|
|
|
*
|
2019-06-06 05:28:23 +00:00
|
|
|
Copyright (c) 2006-2019 Chung, Hyung-Hwan. All rights reserved.
|
2014-11-19 14:42:24 +00:00
|
|
|
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
|
|
modification, are permitted provided that the following conditions
|
|
|
|
are met:
|
|
|
|
1. Redistributions of source code must retain the above copyright
|
|
|
|
notice, this list of conditions and the following disclaimer.
|
|
|
|
2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
notice, this list of conditions and the following disclaimer in the
|
|
|
|
documentation and/or other materials provided with the distribution.
|
|
|
|
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
|
|
|
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
|
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
|
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
|
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
|
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
|
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
2012-02-13 14:43:50 +00:00
|
|
|
*/
|
|
|
|
|
2016-04-28 15:43:33 +00:00
|
|
|
#include <qse/si/nwad.h>
|
|
|
|
#include <qse/si/nwif.h>
|
|
|
|
|
2012-02-27 15:44:57 +00:00
|
|
|
#include <qse/cmn/hton.h>
|
|
|
|
#include <qse/cmn/str.h>
|
|
|
|
#include <qse/cmn/fmt.h>
|
2014-09-26 15:07:06 +00:00
|
|
|
#include <qse/cmn/mbwc.h>
|
2016-04-28 15:43:33 +00:00
|
|
|
|
2016-04-29 03:55:42 +00:00
|
|
|
#include "../cmn/mem-prv.h"
|
2012-02-27 15:44:57 +00:00
|
|
|
|
2018-10-31 08:19:59 +00:00
|
|
|
|
2020-09-06 18:17:32 +00:00
|
|
|
void qse_initnwadwithip4ad (qse_nwad_t* nwad, qse_uint16_t port, const qse_ip4ad_t* ipad)
|
2018-10-31 08:19:59 +00:00
|
|
|
{
|
|
|
|
QSE_MEMSET (nwad, 0, QSE_SIZEOF(*nwad));
|
|
|
|
nwad->type = QSE_NWAD_IN4;
|
|
|
|
nwad->u.in4.port = port;
|
|
|
|
nwad->u.in4.addr = *ipad;
|
|
|
|
};
|
|
|
|
|
|
|
|
void qse_initnwadwithip6ad (qse_nwad_t* nwad, qse_uint16_t port, const qse_ip6ad_t* ipad, qse_uint32_t scopeid)
|
|
|
|
{
|
|
|
|
QSE_MEMSET (nwad, 0, QSE_SIZEOF(*nwad));
|
|
|
|
nwad->type = QSE_NWAD_IN6;
|
|
|
|
nwad->u.in6.port = port;
|
|
|
|
nwad->u.in6.addr = *ipad;
|
|
|
|
nwad->u.in6.scope = scopeid;
|
|
|
|
}
|
|
|
|
|
2012-10-01 13:30:44 +00:00
|
|
|
int qse_nwadequal (const qse_nwad_t* x, const qse_nwad_t* y)
|
|
|
|
{
|
|
|
|
if (x->type != y->type) return 0;
|
|
|
|
|
|
|
|
switch (x->type)
|
|
|
|
{
|
|
|
|
case QSE_NWAD_IN4:
|
|
|
|
return (x->u.in4.port == y->u.in4.port &&
|
|
|
|
QSE_MEMCMP (&x->u.in4.addr, &y->u.in4.addr, QSE_SIZEOF(x->u.in4.addr)) == 0)? 1: 0;
|
|
|
|
|
|
|
|
case QSE_NWAD_IN6:
|
|
|
|
return (x->u.in6.port == y->u.in6.port &&
|
|
|
|
x->u.in6.scope == y->u.in6.scope &&
|
|
|
|
QSE_MEMCMP (&x->u.in6.addr, &y->u.in6.addr, QSE_SIZEOF(x->u.in6.addr)) == 0)? 1: 0;
|
|
|
|
|
2014-09-26 15:07:06 +00:00
|
|
|
case QSE_NWAD_LOCAL:
|
|
|
|
return qse_strcmp (x->u.local.path, y->u.local.path) == 0;
|
|
|
|
|
2012-10-01 13:30:44 +00:00
|
|
|
default:
|
|
|
|
/* can't compare */
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-19 14:32:38 +00:00
|
|
|
void qse_clearnwad (qse_nwad_t* nwad, qse_nwad_type_t type)
|
|
|
|
{
|
2014-07-23 16:07:43 +00:00
|
|
|
QSE_MEMSET (nwad, 0, QSE_SIZEOF(*nwad));
|
2012-11-19 14:32:38 +00:00
|
|
|
nwad->type = type;
|
|
|
|
}
|
|
|
|
|
2014-07-22 17:58:11 +00:00
|
|
|
void qse_setnwadport (qse_nwad_t* nwad, qse_uint16_t port)
|
|
|
|
{
|
|
|
|
switch (nwad->type)
|
|
|
|
{
|
|
|
|
case QSE_NWAD_IN4:
|
|
|
|
nwad->u.in4.port = port;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case QSE_NWAD_IN6:
|
2014-07-23 16:07:43 +00:00
|
|
|
nwad->u.in6.port = port;
|
2014-07-22 17:58:11 +00:00
|
|
|
break;
|
2014-09-26 15:07:06 +00:00
|
|
|
|
|
|
|
case QSE_NWAD_LOCAL:
|
|
|
|
/* no port for QSE_NWAD_LOCAL */
|
|
|
|
break;
|
2014-07-22 17:58:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-23 16:07:43 +00:00
|
|
|
qse_uint16_t qse_getnwadport (qse_nwad_t* nwad)
|
|
|
|
{
|
|
|
|
switch (nwad->type)
|
|
|
|
{
|
|
|
|
case QSE_NWAD_IN4:
|
|
|
|
return nwad->u.in4.port;
|
|
|
|
|
|
|
|
case QSE_NWAD_IN6:
|
|
|
|
return nwad->u.in6.port;
|
|
|
|
|
2014-09-26 15:07:06 +00:00
|
|
|
case QSE_NWAD_LOCAL:
|
2014-07-23 16:07:43 +00:00
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-06 18:17:32 +00:00
|
|
|
int qse_getnwadipsize (qse_nwad_t* nwad)
|
|
|
|
{
|
|
|
|
switch (nwad->type)
|
|
|
|
{
|
|
|
|
case QSE_NWAD_IN4:
|
|
|
|
return QSE_SIZEOF(qse_ip4ad_t);
|
|
|
|
|
|
|
|
case QSE_NWAD_IN6:
|
|
|
|
return QSE_SIZEOF(qse_ip6ad_t);
|
|
|
|
|
|
|
|
case QSE_NWAD_LOCAL:
|
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-02-27 15:44:57 +00:00
|
|
|
int qse_mbstonwad (const qse_mchar_t* str, qse_nwad_t* nwad)
|
|
|
|
{
|
|
|
|
return qse_mbsntonwad (str, qse_mbslen(str), nwad);
|
|
|
|
}
|
|
|
|
|
|
|
|
int qse_mbsntonwad (const qse_mchar_t* str, qse_size_t len, qse_nwad_t* nwad)
|
|
|
|
{
|
|
|
|
const qse_mchar_t* p;
|
|
|
|
const qse_mchar_t* end;
|
2014-07-08 14:30:42 +00:00
|
|
|
qse_mcstr_t tmp;
|
2012-02-27 15:44:57 +00:00
|
|
|
qse_nwad_t tmpad;
|
|
|
|
|
|
|
|
QSE_MEMSET (&tmpad, 0, QSE_SIZEOF(tmpad));
|
|
|
|
|
|
|
|
p = str;
|
|
|
|
end = str + len;
|
|
|
|
|
|
|
|
if (p >= end) return -1;
|
|
|
|
|
2020-09-14 17:49:29 +00:00
|
|
|
// with @, you can specify a relative path as well as an absolute path
|
|
|
|
if ((*p == '@' && len >= 2) || *p == '/')
|
2014-09-26 15:07:06 +00:00
|
|
|
{
|
2020-09-02 20:34:11 +00:00
|
|
|
/* the string begins with @. it's a local name excluding @.
|
|
|
|
* if it begins with /, it's also a local name */
|
2014-09-26 15:07:06 +00:00
|
|
|
#if defined(QSE_CHAR_IS_MCHAR)
|
2020-09-02 20:34:11 +00:00
|
|
|
qse_mbsxncpy (tmpad.u.local.path, QSE_COUNTOF(tmpad.u.local.path), p + (*p == '@'), len - (*p == '@'));
|
2014-09-26 15:07:06 +00:00
|
|
|
#else
|
2020-09-02 20:34:11 +00:00
|
|
|
qse_size_t mbslen = len - (*p == '@');
|
2014-09-26 15:07:06 +00:00
|
|
|
qse_size_t wcslen = QSE_COUNTOF(tmpad.u.local.path) - 1;
|
2020-09-02 20:34:11 +00:00
|
|
|
if (qse_mbsntowcsn(p + (*p == '@'), &mbslen, tmpad.u.local.path, &wcslen) <= -1) return -1;
|
2014-09-26 15:07:06 +00:00
|
|
|
tmpad.u.local.path[wcslen] = QSE_WT('\0');
|
|
|
|
#endif
|
|
|
|
|
|
|
|
tmpad.type = QSE_NWAD_LOCAL;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2012-02-27 15:44:57 +00:00
|
|
|
if (*p == QSE_MT('['))
|
|
|
|
{
|
|
|
|
/* IPv6 address */
|
|
|
|
tmp.ptr = ++p; /* skip [ and remember the position */
|
|
|
|
while (p < end && *p != QSE_MT('%') && *p != QSE_MT(']')) p++;
|
|
|
|
|
|
|
|
if (p >= end) return -1;
|
|
|
|
|
|
|
|
tmp.len = p - tmp.ptr;
|
|
|
|
if (*p == QSE_MT('%'))
|
|
|
|
{
|
|
|
|
/* handle scope id */
|
|
|
|
qse_uint32_t x;
|
|
|
|
|
|
|
|
p++; /* skip % */
|
|
|
|
|
2012-07-02 14:21:40 +00:00
|
|
|
if (p >= end)
|
|
|
|
{
|
|
|
|
/* 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
|
2012-02-27 15:44:57 +00:00
|
|
|
{
|
2012-07-02 14:21:40 +00:00
|
|
|
/* interface name as a scope id? */
|
|
|
|
const qse_mchar_t* stmp = p;
|
2012-11-18 15:19:51 +00:00
|
|
|
unsigned int index;
|
2012-07-02 14:21:40 +00:00
|
|
|
do p++; while (p < end && *p != QSE_MT(']'));
|
2012-11-18 15:19:51 +00:00
|
|
|
if (qse_nwifmbsntoindex (stmp, p - stmp, &index) <= -1) return -1;
|
|
|
|
tmpad.u.in6.scope = index;
|
2012-02-27 15:44:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (p >= end || *p != QSE_MT(']')) return -1;
|
|
|
|
}
|
|
|
|
p++; /* skip ] */
|
|
|
|
|
2012-11-18 15:19:51 +00:00
|
|
|
if (qse_mbsntoip6ad (tmp.ptr, tmp.len, &tmpad.u.in6.addr) <= -1) return -1;
|
2012-02-27 15:44:57 +00:00
|
|
|
tmpad.type = QSE_NWAD_IN6;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* host name or IPv4 address */
|
|
|
|
tmp.ptr = p;
|
|
|
|
while (p < end && *p != QSE_MT(':')) p++;
|
|
|
|
tmp.len = p - tmp.ptr;
|
|
|
|
|
2012-11-18 15:19:51 +00:00
|
|
|
if (qse_mbsntoip4ad (tmp.ptr, tmp.len, &tmpad.u.in4.addr) <= -1)
|
2012-02-27 15:44:57 +00:00
|
|
|
{
|
|
|
|
if (p >= end || *p != QSE_MT(':')) return -1;
|
|
|
|
|
|
|
|
/* check if it is an IPv6 address not enclosed in [].
|
|
|
|
* the port number can't be specified in this format. */
|
|
|
|
|
|
|
|
while (p < end && *p != QSE_MT('%')) p++;
|
|
|
|
tmp.len = p - tmp.ptr;
|
|
|
|
|
2012-11-18 15:19:51 +00:00
|
|
|
if (qse_mbsntoip6ad (tmp.ptr, tmp.len, &tmpad.u.in6.addr) <= -1)
|
2012-02-27 15:44:57 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (p < end && *p == QSE_MT('%'))
|
|
|
|
{
|
|
|
|
/* handle scope id */
|
|
|
|
qse_uint32_t x;
|
|
|
|
|
|
|
|
p++; /* skip % */
|
2012-07-02 14:21:40 +00:00
|
|
|
|
|
|
|
if (p >= end)
|
2012-02-27 15:44:57 +00:00
|
|
|
{
|
2012-07-02 14:21:40 +00:00
|
|
|
/* 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;
|
2012-11-18 15:19:51 +00:00
|
|
|
unsigned int index;
|
2012-07-02 14:21:40 +00:00
|
|
|
do p++; while (p < end);
|
2012-11-18 15:19:51 +00:00
|
|
|
if (qse_nwifmbsntoindex (stmp, p - stmp, &index) <= -1) return -1;
|
|
|
|
tmpad.u.in6.scope = index;
|
2012-02-27 15:44:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (p < end) return -1;
|
|
|
|
|
|
|
|
tmpad.type = QSE_NWAD_IN6;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
tmpad.type = QSE_NWAD_IN4;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (p < end && *p == QSE_MT(':'))
|
|
|
|
{
|
|
|
|
/* port number */
|
|
|
|
qse_uint32_t port = 0;
|
|
|
|
|
|
|
|
p++; /* skip : */
|
|
|
|
|
|
|
|
tmp.ptr = p;
|
|
|
|
while (p < end && *p >= QSE_MT('0') && *p <= QSE_MT('9'))
|
|
|
|
{
|
|
|
|
port = port * 10 + (*p - QSE_MT('0'));
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int qse_wcstonwad (const qse_wchar_t* str, qse_nwad_t* nwad)
|
|
|
|
{
|
|
|
|
return qse_wcsntonwad (str, qse_wcslen(str), nwad);
|
|
|
|
}
|
|
|
|
|
|
|
|
int qse_wcsntonwad (const qse_wchar_t* str, qse_size_t len, qse_nwad_t* nwad)
|
|
|
|
{
|
|
|
|
const qse_wchar_t* p;
|
|
|
|
const qse_wchar_t* end;
|
2014-07-08 14:30:42 +00:00
|
|
|
qse_wcstr_t tmp;
|
2012-02-27 15:44:57 +00:00
|
|
|
qse_nwad_t tmpad;
|
|
|
|
|
|
|
|
QSE_MEMSET (&tmpad, 0, QSE_SIZEOF(tmpad));
|
|
|
|
|
|
|
|
p = str;
|
|
|
|
end = str + len;
|
|
|
|
|
|
|
|
if (p >= end) return -1;
|
|
|
|
|
2020-09-02 20:34:11 +00:00
|
|
|
if ((*p == '@' && len >= 2) || *p == '/') // with @, you can specify a relative path
|
2014-09-26 15:07:06 +00:00
|
|
|
{
|
2020-09-02 20:34:11 +00:00
|
|
|
/* the string begins with @. it's a local name excluding @.
|
|
|
|
* if it begins with /, it's also a local name */
|
2014-09-26 15:07:06 +00:00
|
|
|
#if defined(QSE_CHAR_IS_MCHAR)
|
2014-09-27 15:22:08 +00:00
|
|
|
qse_size_t wcslen = len - 1;
|
2020-09-02 20:34:11 +00:00
|
|
|
qse_size_t mbslen = QSE_COUNTOF(tmpad.u.local.path) - (*p == '@');
|
|
|
|
if (qse_wcsntombsn(p + (*p == '@'), &wcslen, tmpad.u.local.path, &mbslen) <= -1) return -1;
|
2014-09-26 15:07:06 +00:00
|
|
|
tmpad.u.local.path[mbslen] = QSE_MT('\0');
|
|
|
|
#else
|
2020-09-02 20:34:11 +00:00
|
|
|
qse_wcsxncpy (tmpad.u.local.path, QSE_COUNTOF(tmpad.u.local.path), p + (*p == '@'), len - (*p == '@'));
|
2014-09-26 15:07:06 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
tmpad.type = QSE_NWAD_LOCAL;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2012-02-27 15:44:57 +00:00
|
|
|
if (*p == QSE_WT('['))
|
|
|
|
{
|
|
|
|
/* IPv6 address */
|
|
|
|
tmp.ptr = ++p; /* skip [ and remember the position */
|
|
|
|
while (p < end && *p != QSE_WT('%') && *p != QSE_WT(']')) p++;
|
|
|
|
|
|
|
|
if (p >= end) return -1;
|
|
|
|
|
|
|
|
tmp.len = p - tmp.ptr;
|
|
|
|
if (*p == QSE_WT('%'))
|
|
|
|
{
|
|
|
|
/* handle scope id */
|
|
|
|
qse_uint32_t x;
|
|
|
|
|
|
|
|
p++; /* skip % */
|
|
|
|
|
2012-07-02 14:21:40 +00:00
|
|
|
if (p >= end)
|
2012-02-27 15:44:57 +00:00
|
|
|
{
|
2012-07-02 14:21:40 +00:00
|
|
|
/* 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;
|
2012-11-18 15:19:51 +00:00
|
|
|
unsigned int index;
|
2012-07-02 14:21:40 +00:00
|
|
|
do p++; while (p < end && *p != QSE_WT(']'));
|
2012-11-18 15:19:51 +00:00
|
|
|
if (qse_nwifwcsntoindex (stmp, p - stmp, &index) <= -1) return -1;
|
|
|
|
tmpad.u.in6.scope = index;
|
2012-02-27 15:44:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (p >= end || *p != QSE_WT(']')) return -1;
|
|
|
|
}
|
|
|
|
p++; /* skip ] */
|
|
|
|
|
2012-11-18 15:19:51 +00:00
|
|
|
if (qse_wcsntoip6ad (tmp.ptr, tmp.len, &tmpad.u.in6.addr) <= -1) return -1;
|
2012-02-27 15:44:57 +00:00
|
|
|
tmpad.type = QSE_NWAD_IN6;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* host name or IPv4 address */
|
|
|
|
tmp.ptr = p;
|
|
|
|
while (p < end && *p != QSE_WT(':')) p++;
|
|
|
|
tmp.len = p - tmp.ptr;
|
|
|
|
|
2012-11-18 15:19:51 +00:00
|
|
|
if (qse_wcsntoip4ad (tmp.ptr, tmp.len, &tmpad.u.in4.addr) <= -1)
|
2012-02-27 15:44:57 +00:00
|
|
|
{
|
|
|
|
if (p >= end || *p != QSE_WT(':')) return -1;
|
|
|
|
|
|
|
|
/* check if it is an IPv6 address not enclosed in [].
|
|
|
|
* the port number can't be specified in this format. */
|
|
|
|
|
|
|
|
while (p < end && *p != QSE_WT('%')) p++;
|
|
|
|
tmp.len = p - tmp.ptr;
|
|
|
|
|
2012-11-18 15:19:51 +00:00
|
|
|
if (qse_wcsntoip6ad (tmp.ptr, tmp.len, &tmpad.u.in6.addr) <= -1)
|
2012-02-27 15:44:57 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (p < end && *p == QSE_WT('%'))
|
|
|
|
{
|
|
|
|
/* handle scope id */
|
|
|
|
qse_uint32_t x;
|
|
|
|
|
|
|
|
p++; /* skip % */
|
2012-07-02 14:21:40 +00:00
|
|
|
|
|
|
|
if (p >= end)
|
2012-02-27 15:44:57 +00:00
|
|
|
{
|
2012-07-02 14:21:40 +00:00
|
|
|
/* 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;
|
2012-11-18 15:19:51 +00:00
|
|
|
unsigned int index;
|
2012-07-02 14:21:40 +00:00
|
|
|
do p++; while (p < end);
|
2012-11-18 15:19:51 +00:00
|
|
|
if (qse_nwifwcsntoindex (stmp, p - stmp, &index) <= -1) return -1;
|
|
|
|
tmpad.u.in6.scope = index;
|
2012-02-27 15:44:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (p < end) return -1;
|
|
|
|
|
|
|
|
tmpad.type = QSE_NWAD_IN6;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
tmpad.type = QSE_NWAD_IN4;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (p < end && *p == QSE_WT(':'))
|
|
|
|
{
|
|
|
|
/* port number */
|
|
|
|
qse_uint32_t port = 0;
|
|
|
|
|
|
|
|
p++; /* skip : */
|
|
|
|
|
|
|
|
tmp.ptr = p;
|
|
|
|
while (p < end && *p >= QSE_WT('0') && *p <= QSE_WT('9'))
|
|
|
|
{
|
|
|
|
port = port * 10 + (*p - QSE_WT('0'));
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-02-28 09:41:01 +00:00
|
|
|
qse_size_t qse_nwadtombs (
|
|
|
|
const qse_nwad_t* nwad, qse_mchar_t* buf, qse_size_t len, int flags)
|
2012-02-27 15:44:57 +00:00
|
|
|
{
|
|
|
|
qse_size_t xlen = 0;
|
|
|
|
|
2012-02-28 09:41:01 +00:00
|
|
|
/* unsupported types will result in an empty string */
|
|
|
|
|
2012-02-27 15:44:57 +00:00
|
|
|
switch (nwad->type)
|
|
|
|
{
|
|
|
|
case QSE_NWAD_IN4:
|
2012-02-28 09:41:01 +00:00
|
|
|
if (flags & QSE_NWADTOMBS_ADDR)
|
|
|
|
{
|
|
|
|
if (xlen + 1 >= len) goto done;
|
2012-11-18 15:19:51 +00:00
|
|
|
xlen += qse_ip4adtombs (&nwad->u.in4.addr, buf, len);
|
2012-02-28 09:41:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & QSE_NWADTOMBS_PORT)
|
2012-02-27 15:44:57 +00:00
|
|
|
{
|
2012-02-28 09:41:01 +00:00
|
|
|
if (!(flags & QSE_NWADTOMBS_ADDR) ||
|
|
|
|
nwad->u.in4.port != 0)
|
2012-02-27 15:44:57 +00:00
|
|
|
{
|
2012-02-28 09:41:01 +00:00
|
|
|
if (flags & QSE_NWADTOMBS_ADDR)
|
2012-02-27 15:44:57 +00:00
|
|
|
{
|
2012-02-28 09:41:01 +00:00
|
|
|
if (xlen + 1 >= len) goto done;
|
|
|
|
buf[xlen++] = QSE_MT(':');
|
2012-02-27 15:44:57 +00:00
|
|
|
}
|
2012-02-28 09:41:01 +00:00
|
|
|
|
|
|
|
if (xlen + 1 >= len) goto done;
|
|
|
|
xlen += qse_fmtuintmaxtombs (
|
|
|
|
&buf[xlen], len - xlen,
|
|
|
|
qse_ntoh16(nwad->u.in4.port),
|
|
|
|
10, 0, QSE_MT('\0'), QSE_NULL);
|
2012-02-27 15:44:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case QSE_NWAD_IN6:
|
2012-02-28 09:41:01 +00:00
|
|
|
if (flags & QSE_NWADTOMBS_PORT)
|
2012-02-27 15:44:57 +00:00
|
|
|
{
|
2012-02-28 09:41:01 +00:00
|
|
|
if (!(flags & QSE_NWADTOMBS_ADDR) ||
|
|
|
|
nwad->u.in6.port != 0)
|
|
|
|
{
|
2012-09-25 02:47:25 +00:00
|
|
|
if (flags & QSE_NWADTOMBS_ADDR)
|
|
|
|
{
|
|
|
|
if (xlen + 1 >= len) goto done;
|
|
|
|
buf[xlen++] = QSE_MT('[');
|
|
|
|
}
|
2012-02-28 09:41:01 +00:00
|
|
|
}
|
|
|
|
}
|
2012-02-27 15:44:57 +00:00
|
|
|
|
2012-02-28 09:41:01 +00:00
|
|
|
if (flags & QSE_NWADTOMBS_ADDR)
|
|
|
|
{
|
2012-07-02 14:21:40 +00:00
|
|
|
|
2012-02-28 09:41:01 +00:00
|
|
|
if (xlen + 1 >= len) goto done;
|
2012-11-18 15:19:51 +00:00
|
|
|
xlen += qse_ip6adtombs (&nwad->u.in6.addr, &buf[xlen], len - xlen);
|
2012-02-28 09:41:01 +00:00
|
|
|
|
|
|
|
if (nwad->u.in6.scope != 0)
|
2012-02-27 15:44:57 +00:00
|
|
|
{
|
2012-07-02 14:21:40 +00:00
|
|
|
int tmp;
|
|
|
|
|
2012-02-28 09:41:01 +00:00
|
|
|
if (xlen + 1 >= len) goto done;
|
|
|
|
buf[xlen++] = QSE_MT('%');
|
|
|
|
|
|
|
|
if (xlen + 1 >= len) goto done;
|
2012-07-02 14:21:40 +00:00
|
|
|
|
2012-09-25 02:47:25 +00:00
|
|
|
tmp = qse_nwifindextombs (nwad->u.in6.scope, &buf[xlen], len - xlen);
|
2012-11-16 16:46:49 +00:00
|
|
|
if (tmp <= -1)
|
2012-07-02 14:21:40 +00:00
|
|
|
{
|
|
|
|
xlen += qse_fmtuintmaxtombs (
|
|
|
|
&buf[xlen], len - xlen,
|
|
|
|
nwad->u.in6.scope, 10, 0, QSE_MT('\0'), QSE_NULL);
|
|
|
|
}
|
|
|
|
else xlen += tmp;
|
2012-02-28 09:41:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & QSE_NWADTOMBS_PORT)
|
|
|
|
{
|
|
|
|
if (!(flags & QSE_NWADTOMBS_ADDR) ||
|
|
|
|
nwad->u.in6.port != 0)
|
|
|
|
{
|
|
|
|
if (flags & QSE_NWADTOMBS_ADDR)
|
2012-02-27 15:44:57 +00:00
|
|
|
{
|
2012-09-25 02:47:25 +00:00
|
|
|
if (xlen + 1 >= len) goto done;
|
2014-09-26 15:07:06 +00:00
|
|
|
buf[xlen++] = QSE_MT(']');
|
2012-09-25 02:47:25 +00:00
|
|
|
|
2012-02-28 09:41:01 +00:00
|
|
|
if (xlen + 1 >= len) goto done;
|
|
|
|
buf[xlen++] = QSE_MT(':');
|
2012-02-27 15:44:57 +00:00
|
|
|
}
|
|
|
|
|
2012-02-28 09:41:01 +00:00
|
|
|
if (xlen + 1 >= len) goto done;
|
|
|
|
xlen += qse_fmtuintmaxtombs (
|
|
|
|
&buf[xlen], len - xlen,
|
|
|
|
qse_ntoh16(nwad->u.in6.port),
|
|
|
|
10, 0, QSE_MT('\0'), QSE_NULL);
|
|
|
|
}
|
2012-02-27 15:44:57 +00:00
|
|
|
}
|
2012-02-28 09:41:01 +00:00
|
|
|
|
2012-02-27 15:44:57 +00:00
|
|
|
break;
|
|
|
|
|
2014-09-26 15:07:06 +00:00
|
|
|
case QSE_NWAD_LOCAL:
|
|
|
|
if (flags & QSE_NWADTOMBS_ADDR)
|
|
|
|
{
|
2020-09-02 20:34:11 +00:00
|
|
|
if (nwad->u.local.path[0] != '/')
|
|
|
|
{
|
|
|
|
if (xlen + 1 >= len) goto done;
|
|
|
|
buf[xlen++] = '@';
|
|
|
|
}
|
2014-09-27 15:22:08 +00:00
|
|
|
|
2014-09-26 15:07:06 +00:00
|
|
|
#if defined(QSE_CHAR_IS_MCHAR)
|
2014-09-27 15:22:08 +00:00
|
|
|
if (xlen + 1 >= len) goto done;
|
2014-10-08 15:40:32 +00:00
|
|
|
xlen += qse_mbsxcpy (&buf[xlen], len - xlen, nwad->u.local.path);
|
2014-09-26 15:07:06 +00:00
|
|
|
#else
|
2014-09-27 15:22:08 +00:00
|
|
|
if (xlen + 1 >= len) goto done;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
qse_size_t wcslen, mbslen = len - xlen;
|
|
|
|
qse_wcstombs (nwad->u.local.path, &wcslen, &buf[xlen], &mbslen);
|
|
|
|
/* i don't care about conversion errors */
|
|
|
|
xlen += mbslen;
|
|
|
|
}
|
2014-09-26 15:07:06 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
2012-02-27 15:44:57 +00:00
|
|
|
}
|
|
|
|
|
2012-02-28 09:41:01 +00:00
|
|
|
done:
|
|
|
|
if (xlen < len) buf[xlen] = QSE_MT('\0');
|
2012-02-27 15:44:57 +00:00
|
|
|
return xlen;
|
|
|
|
}
|
|
|
|
|
2012-02-28 09:41:01 +00:00
|
|
|
|
|
|
|
qse_size_t qse_nwadtowcs (
|
|
|
|
const qse_nwad_t* nwad, qse_wchar_t* buf, qse_size_t len, int flags)
|
2012-02-27 15:44:57 +00:00
|
|
|
{
|
|
|
|
qse_size_t xlen = 0;
|
|
|
|
|
2012-02-28 09:41:01 +00:00
|
|
|
/* unsupported types will result in an empty string */
|
|
|
|
|
2012-02-27 15:44:57 +00:00
|
|
|
switch (nwad->type)
|
|
|
|
{
|
|
|
|
case QSE_NWAD_IN4:
|
2012-02-28 09:41:01 +00:00
|
|
|
if (flags & QSE_NWADTOWCS_ADDR)
|
|
|
|
{
|
|
|
|
if (xlen + 1 >= len) goto done;
|
2012-11-18 15:19:51 +00:00
|
|
|
xlen += qse_ip4adtowcs (&nwad->u.in4.addr, buf, len);
|
2012-02-28 09:41:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & QSE_NWADTOWCS_PORT)
|
2012-02-27 15:44:57 +00:00
|
|
|
{
|
2012-02-28 09:41:01 +00:00
|
|
|
if (!(flags & QSE_NWADTOMBS_ADDR) ||
|
|
|
|
nwad->u.in4.port != 0)
|
2012-02-27 15:44:57 +00:00
|
|
|
{
|
2012-02-28 09:41:01 +00:00
|
|
|
if (flags & QSE_NWADTOMBS_ADDR)
|
2012-02-27 15:44:57 +00:00
|
|
|
{
|
2012-02-28 09:41:01 +00:00
|
|
|
if (xlen + 1 >= len) goto done;
|
|
|
|
buf[xlen++] = QSE_WT(':');
|
2012-02-27 15:44:57 +00:00
|
|
|
}
|
2012-02-28 09:41:01 +00:00
|
|
|
|
|
|
|
if (xlen + 1 >= len) goto done;
|
|
|
|
xlen += qse_fmtuintmaxtowcs (
|
|
|
|
&buf[xlen], len - xlen,
|
|
|
|
qse_ntoh16(nwad->u.in4.port),
|
|
|
|
10, 0, QSE_WT('\0'), QSE_NULL);
|
2012-02-27 15:44:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case QSE_NWAD_IN6:
|
2012-02-28 09:41:01 +00:00
|
|
|
if (flags & QSE_NWADTOWCS_PORT)
|
2012-02-27 15:44:57 +00:00
|
|
|
{
|
2012-02-28 09:41:01 +00:00
|
|
|
if (!(flags & QSE_NWADTOMBS_ADDR) ||
|
|
|
|
nwad->u.in6.port != 0)
|
|
|
|
{
|
2012-09-25 02:47:25 +00:00
|
|
|
if (flags & QSE_NWADTOMBS_ADDR)
|
|
|
|
{
|
|
|
|
if (xlen + 1 >= len) goto done;
|
|
|
|
buf[xlen++] = QSE_WT('[');
|
|
|
|
}
|
2012-02-28 09:41:01 +00:00
|
|
|
}
|
|
|
|
}
|
2012-02-27 15:44:57 +00:00
|
|
|
|
2012-02-28 09:41:01 +00:00
|
|
|
if (flags & QSE_NWADTOWCS_ADDR)
|
|
|
|
{
|
|
|
|
if (xlen + 1 >= len) goto done;
|
2012-11-18 15:19:51 +00:00
|
|
|
xlen += qse_ip6adtowcs (&nwad->u.in6.addr, &buf[xlen], len - xlen);
|
2012-02-28 09:41:01 +00:00
|
|
|
|
|
|
|
if (nwad->u.in6.scope != 0)
|
2012-02-27 15:44:57 +00:00
|
|
|
{
|
2012-07-02 14:21:40 +00:00
|
|
|
int tmp;
|
|
|
|
|
2012-02-28 09:41:01 +00:00
|
|
|
if (xlen + 1 >= len) goto done;
|
|
|
|
buf[xlen++] = QSE_WT('%');
|
2012-02-27 15:44:57 +00:00
|
|
|
|
2012-02-28 09:41:01 +00:00
|
|
|
if (xlen + 1 >= len) goto done;
|
2012-07-02 14:21:40 +00:00
|
|
|
|
2012-09-25 02:47:25 +00:00
|
|
|
tmp = qse_nwifindextowcs (nwad->u.in6.scope, &buf[xlen], len - xlen);
|
2012-11-16 16:46:49 +00:00
|
|
|
if (tmp <= -1)
|
2012-07-02 14:21:40 +00:00
|
|
|
{
|
|
|
|
xlen += qse_fmtuintmaxtowcs (
|
|
|
|
&buf[xlen], len - xlen,
|
|
|
|
nwad->u.in6.scope, 10, 0, QSE_WT('\0'), QSE_NULL);
|
|
|
|
}
|
|
|
|
else xlen += tmp;
|
2012-02-28 09:41:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & QSE_NWADTOWCS_PORT)
|
|
|
|
{
|
|
|
|
if (!(flags & QSE_NWADTOMBS_ADDR) ||
|
|
|
|
nwad->u.in6.port != 0)
|
|
|
|
{
|
|
|
|
if (flags & QSE_NWADTOMBS_ADDR)
|
2012-02-27 15:44:57 +00:00
|
|
|
{
|
2012-09-25 02:47:25 +00:00
|
|
|
if (xlen + 1 >= len) goto done;
|
2014-09-25 15:27:08 +00:00
|
|
|
buf[xlen++] = QSE_WT(']');
|
2012-09-25 02:47:25 +00:00
|
|
|
|
2012-02-28 09:41:01 +00:00
|
|
|
if (xlen + 1 >= len) goto done;
|
|
|
|
buf[xlen++] = QSE_WT(':');
|
2012-02-27 15:44:57 +00:00
|
|
|
}
|
|
|
|
|
2012-02-28 09:41:01 +00:00
|
|
|
if (xlen + 1 >= len) goto done;
|
|
|
|
xlen += qse_fmtuintmaxtowcs (
|
|
|
|
&buf[xlen], len - xlen,
|
|
|
|
qse_ntoh16(nwad->u.in6.port),
|
|
|
|
10, 0, QSE_WT('\0'), QSE_NULL);
|
|
|
|
}
|
2012-02-27 15:44:57 +00:00
|
|
|
}
|
2012-02-28 09:41:01 +00:00
|
|
|
|
2012-02-27 15:44:57 +00:00
|
|
|
break;
|
|
|
|
|
2014-09-26 15:07:06 +00:00
|
|
|
case QSE_NWAD_LOCAL:
|
|
|
|
if (flags & QSE_NWADTOMBS_ADDR)
|
|
|
|
{
|
2020-09-02 20:34:11 +00:00
|
|
|
if (nwad->u.local.path[0] != '/')
|
|
|
|
{
|
|
|
|
if (xlen + 1 >= len) goto done;
|
|
|
|
buf[xlen++] = '@';
|
|
|
|
}
|
2014-09-27 15:22:08 +00:00
|
|
|
|
2014-09-26 15:07:06 +00:00
|
|
|
#if defined(QSE_CHAR_IS_MCHAR)
|
2014-09-27 15:22:08 +00:00
|
|
|
if (xlen + 1 >= len) goto done;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
qse_size_t wcslen = len - xlen, mbslen;
|
|
|
|
qse_mbstowcs (nwad->u.local.path, &mbslen, &buf[xlen], &wcslen);
|
|
|
|
/* i don't care about conversion errors */
|
|
|
|
xlen += wcslen;
|
|
|
|
}
|
2014-09-26 15:07:06 +00:00
|
|
|
#else
|
2014-09-27 15:22:08 +00:00
|
|
|
if (xlen + 1 >= len) goto done;
|
|
|
|
xlen += qse_wcsxcpy (&buf[xlen], len - xlen, nwad->u.local.path);
|
2014-09-26 15:07:06 +00:00
|
|
|
#endif
|
|
|
|
}
|
2012-02-27 15:44:57 +00:00
|
|
|
}
|
|
|
|
|
2012-02-28 09:41:01 +00:00
|
|
|
done:
|
2012-02-27 15:44:57 +00:00
|
|
|
if (xlen < len) buf[xlen] = QSE_WT('\0');
|
|
|
|
return xlen;
|
|
|
|
}
|
2012-02-28 09:41:01 +00:00
|
|
|
|