2020-02-16 13:59:41 +00:00
|
|
|
/*
|
2020-02-20 15:35:16 +00:00
|
|
|
Copyright (c) 2016-2020 Chung, Hyung-Hwan. All rights reserved.
|
2020-02-16 13:59:41 +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.
|
|
|
|
*/
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
#include <hio-skad.h>
|
|
|
|
#include <hio-nwif.h>
|
|
|
|
#include <hio-fmt.h>
|
|
|
|
#include "hio-prv.h"
|
2020-02-16 13:59:41 +00:00
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#if defined(HAVE_NETINET_IN_H)
|
|
|
|
# include <netinet/in.h>
|
|
|
|
#endif
|
|
|
|
#if defined(HAVE_SYS_UN_H)
|
|
|
|
# include <sys/un.h>
|
|
|
|
#endif
|
|
|
|
#if defined(HAVE_NETPACKET_PACKET_H)
|
|
|
|
# include <netpacket/packet.h>
|
|
|
|
#endif
|
|
|
|
#if defined(HAVE_NET_IF_DL_H)
|
|
|
|
# include <net/if_dl.h>
|
|
|
|
#endif
|
|
|
|
|
2021-08-17 07:00:22 +00:00
|
|
|
struct sockaddr_extra_t
|
|
|
|
{
|
|
|
|
hio_uint16_t chan;
|
|
|
|
};
|
|
|
|
typedef struct sockaddr_extra_t sockaddr_extra_t;
|
|
|
|
|
2021-08-09 08:24:21 +00:00
|
|
|
#if (HIO_SIZEOF_STRUCT_SOCKADDR_IN > 0)
|
|
|
|
/* dirty hack to secure more space at the end of the actual socket address.
|
|
|
|
* the extra fiels must be transparent to unaware parties.
|
|
|
|
* if you add/delete extra fields or change the size of existing fields,
|
|
|
|
* you must update the corresponding checks in configure.ac.
|
|
|
|
*
|
|
|
|
* extra fields:
|
|
|
|
* chan - used as a stream number for SCTP PACKETSEQ sockets.
|
2021-08-17 07:00:22 +00:00
|
|
|
* use hio_skad_get_chan() and hio_skad_set_chan() for safe access.
|
2021-08-09 08:24:21 +00:00
|
|
|
*/
|
|
|
|
struct sockaddr_in_x
|
|
|
|
{
|
|
|
|
struct sockaddr_in a;
|
2021-08-17 07:00:22 +00:00
|
|
|
sockaddr_extra_t x;
|
2021-08-09 08:24:21 +00:00
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if (HIO_SIZEOF_STRUCT_SOCKADDR_IN6 > 0)
|
|
|
|
struct sockaddr_in6_x
|
|
|
|
{
|
|
|
|
struct sockaddr_in6 a;
|
2021-08-17 07:00:22 +00:00
|
|
|
sockaddr_extra_t x;
|
2021-08-09 08:24:21 +00:00
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
union hio_skad_alt_t
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
|
|
|
struct sockaddr sa;
|
2021-07-22 07:30:20 +00:00
|
|
|
#if (HIO_SIZEOF_STRUCT_SOCKADDR_IN > 0)
|
2021-08-09 08:24:21 +00:00
|
|
|
struct sockaddr_in_x in4;
|
2020-02-16 13:59:41 +00:00
|
|
|
#endif
|
2021-07-22 07:30:20 +00:00
|
|
|
#if (HIO_SIZEOF_STRUCT_SOCKADDR_IN6 > 0)
|
2021-08-09 08:24:21 +00:00
|
|
|
struct sockaddr_in6_x in6;
|
2020-02-16 13:59:41 +00:00
|
|
|
#endif
|
2021-07-22 07:30:20 +00:00
|
|
|
#if (HIO_SIZEOF_STRUCT_SOCKADDR_LL > 0)
|
2020-02-16 13:59:41 +00:00
|
|
|
struct sockaddr_ll ll;
|
|
|
|
#endif
|
2021-07-22 07:30:20 +00:00
|
|
|
#if (HIO_SIZEOF_STRUCT_SOCKADDR_DL > 0)
|
2020-02-20 06:00:53 +00:00
|
|
|
struct sockaddr_dl dl;
|
|
|
|
#endif
|
2021-07-22 07:30:20 +00:00
|
|
|
#if (HIO_SIZEOF_STRUCT_SOCKADDR_UN > 0)
|
2020-02-16 13:59:41 +00:00
|
|
|
struct sockaddr_un un;
|
|
|
|
#endif
|
|
|
|
};
|
2021-07-22 07:30:20 +00:00
|
|
|
typedef union hio_skad_alt_t hio_skad_alt_t;
|
2020-02-16 13:59:41 +00:00
|
|
|
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
static int uchars_to_ipv4 (const hio_uch_t* str, hio_oow_t len, struct in_addr* inaddr)
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
const hio_uch_t* end;
|
2020-02-16 13:59:41 +00:00
|
|
|
int dots = 0, digits = 0;
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_uint32_t acc = 0, addr = 0;
|
|
|
|
hio_uch_t c;
|
2020-02-19 14:59:06 +00:00
|
|
|
|
|
|
|
end = str + len;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
if (str >= end)
|
|
|
|
{
|
|
|
|
if (dots < 3 || digits == 0) return -1;
|
|
|
|
addr = (addr << 8) | acc;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
c = *str++;
|
|
|
|
|
|
|
|
if (c >= '0' && c <= '9')
|
|
|
|
{
|
|
|
|
if (digits > 0 && acc == 0) return -1;
|
|
|
|
acc = acc * 10 + (c - '0');
|
|
|
|
if (acc > 255) return -1;
|
|
|
|
digits++;
|
|
|
|
}
|
|
|
|
else if (c == '.')
|
|
|
|
{
|
|
|
|
if (dots >= 3 || digits == 0) return -1;
|
|
|
|
addr = (addr << 8) | acc;
|
|
|
|
dots++; acc = 0; digits = 0;
|
|
|
|
}
|
|
|
|
else return -1;
|
|
|
|
}
|
|
|
|
while (1);
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
inaddr->s_addr = hio_hton32(addr);
|
2020-02-19 14:59:06 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
static int bchars_to_ipv4 (const hio_bch_t* str, hio_oow_t len, struct in_addr* inaddr)
|
2020-02-19 14:59:06 +00:00
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
const hio_bch_t* end;
|
2020-02-19 14:59:06 +00:00
|
|
|
int dots = 0, digits = 0;
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_uint32_t acc = 0, addr = 0;
|
|
|
|
hio_bch_t c;
|
2020-02-16 13:59:41 +00:00
|
|
|
|
|
|
|
end = str + len;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
if (str >= end)
|
|
|
|
{
|
|
|
|
if (dots < 3 || digits == 0) return -1;
|
|
|
|
addr = (addr << 8) | acc;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
c = *str++;
|
|
|
|
|
|
|
|
if (c >= '0' && c <= '9')
|
|
|
|
{
|
|
|
|
if (digits > 0 && acc == 0) return -1;
|
|
|
|
acc = acc * 10 + (c - '0');
|
|
|
|
if (acc > 255) return -1;
|
|
|
|
digits++;
|
|
|
|
}
|
|
|
|
else if (c == '.')
|
|
|
|
{
|
|
|
|
if (dots >= 3 || digits == 0) return -1;
|
|
|
|
addr = (addr << 8) | acc;
|
|
|
|
dots++; acc = 0; digits = 0;
|
|
|
|
}
|
|
|
|
else return -1;
|
|
|
|
}
|
|
|
|
while (1);
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
inaddr->s_addr = hio_hton32(addr);
|
2020-02-16 13:59:41 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
#if (HIO_SIZEOF_STRUCT_SOCKADDR_IN6 > 0)
|
|
|
|
static int uchars_to_ipv6 (const hio_uch_t* src, hio_oow_t len, struct in6_addr* inaddr)
|
2020-02-19 14:59:06 +00:00
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_uint8_t* tp, * endp, * colonp;
|
|
|
|
const hio_uch_t* curtok;
|
|
|
|
hio_uch_t ch;
|
2020-02-19 14:59:06 +00:00
|
|
|
int saw_xdigit;
|
|
|
|
unsigned int val;
|
2021-07-22 07:30:20 +00:00
|
|
|
const hio_uch_t* src_end;
|
2020-02-19 14:59:06 +00:00
|
|
|
|
|
|
|
src_end = src + len;
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
HIO_MEMSET (inaddr, 0, HIO_SIZEOF(*inaddr));
|
2020-02-19 14:59:06 +00:00
|
|
|
tp = &inaddr->s6_addr[0];
|
2021-07-22 07:30:20 +00:00
|
|
|
endp = &inaddr->s6_addr[HIO_COUNTOF(inaddr->s6_addr)];
|
|
|
|
colonp = HIO_NULL;
|
2020-02-19 14:59:06 +00:00
|
|
|
|
|
|
|
/* Leading :: requires some special handling. */
|
|
|
|
if (src < src_end && *src == ':')
|
|
|
|
{
|
|
|
|
src++;
|
|
|
|
if (src >= src_end || *src != ':') return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
curtok = src;
|
|
|
|
saw_xdigit = 0;
|
|
|
|
val = 0;
|
|
|
|
|
|
|
|
while (src < src_end)
|
|
|
|
{
|
|
|
|
int v1;
|
|
|
|
|
|
|
|
ch = *src++;
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
v1 = HIO_XDIGIT_TO_NUM(ch);
|
2020-02-19 14:59:06 +00:00
|
|
|
if (v1 >= 0)
|
|
|
|
{
|
|
|
|
val <<= 4;
|
|
|
|
val |= v1;
|
|
|
|
if (val > 0xffff) return -1;
|
|
|
|
saw_xdigit = 1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ch == ':')
|
|
|
|
{
|
|
|
|
curtok = src;
|
|
|
|
if (!saw_xdigit)
|
|
|
|
{
|
|
|
|
if (colonp) return -1;
|
|
|
|
colonp = tp;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (src >= src_end)
|
|
|
|
{
|
|
|
|
/* a colon can't be the last character */
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
*tp++ = (hio_uint8_t)(val >> 8) & 0xff;
|
|
|
|
*tp++ = (hio_uint8_t)val & 0xff;
|
2020-02-19 14:59:06 +00:00
|
|
|
saw_xdigit = 0;
|
|
|
|
val = 0;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
if (ch == '.' && ((tp + HIO_SIZEOF(struct in_addr)) <= endp) &&
|
2020-02-19 14:59:06 +00:00
|
|
|
uchars_to_ipv4(curtok, src_end - curtok, (struct in_addr*)tp) == 0)
|
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
tp += HIO_SIZEOF(struct in_addr*);
|
2020-02-19 14:59:06 +00:00
|
|
|
saw_xdigit = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (saw_xdigit)
|
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
if (tp + HIO_SIZEOF(hio_uint16_t) > endp) return -1;
|
|
|
|
*tp++ = (hio_uint8_t)(val >> 8) & 0xff;
|
|
|
|
*tp++ = (hio_uint8_t)val & 0xff;
|
2020-02-19 14:59:06 +00:00
|
|
|
}
|
2021-07-22 07:30:20 +00:00
|
|
|
if (colonp != HIO_NULL)
|
2020-02-19 14:59:06 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Since some memmove()'s erroneously fail to handle
|
|
|
|
* overlapping regions, we'll do the shift by hand.
|
|
|
|
*/
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_oow_t n = tp - colonp;
|
|
|
|
hio_oow_t i;
|
2020-02-19 14:59:06 +00:00
|
|
|
|
|
|
|
for (i = 1; i <= n; i++)
|
|
|
|
{
|
|
|
|
endp[-i] = colonp[n - i];
|
|
|
|
colonp[n - i] = 0;
|
|
|
|
}
|
|
|
|
tp = endp;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tp != endp) return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
static int bchars_to_ipv6 (const hio_bch_t* src, hio_oow_t len, struct in6_addr* inaddr)
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_uint8_t* tp, * endp, * colonp;
|
|
|
|
const hio_bch_t* curtok;
|
|
|
|
hio_bch_t ch;
|
2020-02-16 13:59:41 +00:00
|
|
|
int saw_xdigit;
|
|
|
|
unsigned int val;
|
2021-07-22 07:30:20 +00:00
|
|
|
const hio_bch_t* src_end;
|
2020-02-16 13:59:41 +00:00
|
|
|
|
|
|
|
src_end = src + len;
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
HIO_MEMSET (inaddr, 0, HIO_SIZEOF(*inaddr));
|
2020-02-16 13:59:41 +00:00
|
|
|
tp = &inaddr->s6_addr[0];
|
2021-07-22 07:30:20 +00:00
|
|
|
endp = &inaddr->s6_addr[HIO_COUNTOF(inaddr->s6_addr)];
|
|
|
|
colonp = HIO_NULL;
|
2020-02-16 13:59:41 +00:00
|
|
|
|
|
|
|
/* Leading :: requires some special handling. */
|
|
|
|
if (src < src_end && *src == ':')
|
|
|
|
{
|
|
|
|
src++;
|
|
|
|
if (src >= src_end || *src != ':') return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
curtok = src;
|
|
|
|
saw_xdigit = 0;
|
|
|
|
val = 0;
|
|
|
|
|
|
|
|
while (src < src_end)
|
|
|
|
{
|
|
|
|
int v1;
|
|
|
|
|
|
|
|
ch = *src++;
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
v1 = HIO_XDIGIT_TO_NUM(ch);
|
2020-02-16 13:59:41 +00:00
|
|
|
if (v1 >= 0)
|
|
|
|
{
|
|
|
|
val <<= 4;
|
|
|
|
val |= v1;
|
|
|
|
if (val > 0xffff) return -1;
|
|
|
|
saw_xdigit = 1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ch == ':')
|
|
|
|
{
|
|
|
|
curtok = src;
|
|
|
|
if (!saw_xdigit)
|
|
|
|
{
|
|
|
|
if (colonp) return -1;
|
|
|
|
colonp = tp;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (src >= src_end)
|
|
|
|
{
|
|
|
|
/* a colon can't be the last character */
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
*tp++ = (hio_uint8_t)(val >> 8) & 0xff;
|
|
|
|
*tp++ = (hio_uint8_t)val & 0xff;
|
2020-02-16 13:59:41 +00:00
|
|
|
saw_xdigit = 0;
|
|
|
|
val = 0;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
if (ch == '.' && ((tp + HIO_SIZEOF(struct in_addr)) <= endp) &&
|
2020-02-19 14:59:06 +00:00
|
|
|
bchars_to_ipv4(curtok, src_end - curtok, (struct in_addr*)tp) == 0)
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
tp += HIO_SIZEOF(struct in_addr*);
|
2020-02-16 13:59:41 +00:00
|
|
|
saw_xdigit = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (saw_xdigit)
|
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
if (tp + HIO_SIZEOF(hio_uint16_t) > endp) return -1;
|
|
|
|
*tp++ = (hio_uint8_t)(val >> 8) & 0xff;
|
|
|
|
*tp++ = (hio_uint8_t)val & 0xff;
|
2020-02-16 13:59:41 +00:00
|
|
|
}
|
2021-07-22 07:30:20 +00:00
|
|
|
if (colonp != HIO_NULL)
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Since some memmove()'s erroneously fail to handle
|
|
|
|
* overlapping regions, we'll do the shift by hand.
|
|
|
|
*/
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_oow_t n = tp - colonp;
|
|
|
|
hio_oow_t i;
|
2020-02-16 13:59:41 +00:00
|
|
|
|
|
|
|
for (i = 1; i <= n; i++)
|
|
|
|
{
|
|
|
|
endp[-i] = colonp[n - i];
|
|
|
|
colonp[n - i] = 0;
|
|
|
|
}
|
|
|
|
tp = endp;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tp != endp) return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2020-02-19 14:59:06 +00:00
|
|
|
/* ---------------------------------------------------------- */
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
int hio_ucharstoskad (hio_t* hio, const hio_uch_t* str, hio_oow_t len, hio_skad_t* _skad)
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_skad_alt_t* skad = (hio_skad_alt_t*)_skad;
|
|
|
|
const hio_uch_t* p;
|
|
|
|
const hio_uch_t* end;
|
|
|
|
hio_ucs_t tmp;
|
2020-02-16 13:59:41 +00:00
|
|
|
|
|
|
|
p = str;
|
|
|
|
end = str + len;
|
|
|
|
|
|
|
|
if (p >= end)
|
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_seterrbfmt (hio, HIO_EINVAL, "blank address");
|
2020-02-16 13:59:41 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
/* use HIO_SIZEOF(*_skad) instead of HIO_SIZEOF(*skad) in case they are different */
|
|
|
|
HIO_MEMSET (skad, 0, HIO_SIZEOF(*_skad));
|
2020-02-16 13:59:41 +00:00
|
|
|
|
2021-08-06 03:23:48 +00:00
|
|
|
if (p[0] == '<' && p[1] == 'q' && p[2] == 'x' && p[3] == '>' && p[4] == '\0')
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
2021-08-06 03:23:48 +00:00
|
|
|
/* this is HIO specific. the rest isn't important */
|
|
|
|
skad->sa.sa_family = HIO_AF_QX;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*p == '@')
|
|
|
|
{
|
|
|
|
#if defined(AF_UNIX) && (HIO_SIZEOF_STRUCT_SOCKADDR_UN > 0)
|
|
|
|
/* @aaa, @/tmp/aaa ... */
|
|
|
|
hio_oow_t srclen, dstlen;
|
2021-07-22 07:30:20 +00:00
|
|
|
dstlen = HIO_COUNTOF(skad->un.sun_path) - 1;
|
2021-08-06 03:23:48 +00:00
|
|
|
srclen = len - 1;
|
|
|
|
if (hio_convutobchars(hio, p + 1, &srclen, skad->un.sun_path, &dstlen) <= -1) return -1;
|
2020-02-16 13:59:41 +00:00
|
|
|
skad->un.sun_path[dstlen] = '\0';
|
|
|
|
skad->un.sun_family = AF_UNIX;
|
|
|
|
return 0;
|
2021-08-06 03:23:48 +00:00
|
|
|
#else
|
|
|
|
hio_seterrbfmt (hio, HIO_ENOIMPL, "unix address not supported");
|
|
|
|
return -1;
|
2020-02-16 13:59:41 +00:00
|
|
|
#endif
|
2021-08-06 03:23:48 +00:00
|
|
|
}
|
|
|
|
|
2020-02-16 13:59:41 +00:00
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
#if (HIO_SIZEOF_STRUCT_SOCKADDR_IN6 > 0)
|
2020-02-16 13:59:41 +00:00
|
|
|
if (*p == '[')
|
|
|
|
{
|
|
|
|
/* IPv6 address */
|
2021-07-22 07:30:20 +00:00
|
|
|
tmp.ptr = (hio_uch_t*)++p; /* skip [ and remember the position */
|
2020-02-16 13:59:41 +00:00
|
|
|
while (p < end && *p != '%' && *p != ']') p++;
|
|
|
|
|
|
|
|
if (p >= end) goto no_rbrack;
|
|
|
|
|
|
|
|
tmp.len = p - tmp.ptr;
|
|
|
|
if (*p == '%')
|
|
|
|
{
|
|
|
|
/* handle scope id */
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_uint32_t x;
|
2020-02-16 13:59:41 +00:00
|
|
|
|
|
|
|
p++; /* skip % */
|
|
|
|
|
|
|
|
if (p >= end)
|
|
|
|
{
|
|
|
|
/* premature end */
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_seterrbfmt (hio, HIO_EINVAL, "scope id blank");
|
2020-02-16 13:59:41 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*p >= '0' && *p <= '9')
|
|
|
|
{
|
|
|
|
/* numeric scope id */
|
2021-08-09 08:24:21 +00:00
|
|
|
skad->in6.a.sin6_scope_id = 0;
|
2020-02-16 13:59:41 +00:00
|
|
|
do
|
|
|
|
{
|
2021-08-09 08:24:21 +00:00
|
|
|
x = skad->in6.a.sin6_scope_id * 10 + (*p - '0');
|
|
|
|
if (x < skad->in6.a.sin6_scope_id)
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_seterrbfmt (hio, HIO_EINVAL, "scope id too large");
|
2020-02-16 13:59:41 +00:00
|
|
|
return -1; /* overflow */
|
|
|
|
}
|
2021-08-09 08:24:21 +00:00
|
|
|
skad->in6.a.sin6_scope_id = x;
|
2020-02-16 13:59:41 +00:00
|
|
|
p++;
|
|
|
|
}
|
|
|
|
while (p < end && *p >= '0' && *p <= '9');
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* interface name as a scope id? */
|
2021-07-22 07:30:20 +00:00
|
|
|
const hio_uch_t* stmp = p;
|
2020-02-16 13:59:41 +00:00
|
|
|
unsigned int index;
|
|
|
|
do p++; while (p < end && *p != ']');
|
2021-07-22 07:30:20 +00:00
|
|
|
if (hio_ucharstoifindex(hio, stmp, p - stmp, &index) <= -1) return -1;
|
2021-08-09 08:24:21 +00:00
|
|
|
skad->in6.a.sin6_scope_id = index;
|
2020-02-16 13:59:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (p >= end || *p != ']') goto no_rbrack;
|
|
|
|
}
|
|
|
|
p++; /* skip ] */
|
|
|
|
|
2021-08-09 08:24:21 +00:00
|
|
|
if (uchars_to_ipv6(tmp.ptr, tmp.len, &skad->in6.a.sin6_addr) <= -1) goto unrecog;
|
|
|
|
skad->in6.a.sin6_family = AF_INET6;
|
2020-02-16 13:59:41 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
#endif
|
|
|
|
/* IPv4 address */
|
2021-07-22 07:30:20 +00:00
|
|
|
tmp.ptr = (hio_uch_t*)p;
|
2020-02-16 13:59:41 +00:00
|
|
|
while (p < end && *p != ':') p++;
|
|
|
|
tmp.len = p - tmp.ptr;
|
|
|
|
|
2021-08-09 08:24:21 +00:00
|
|
|
if (uchars_to_ipv4(tmp.ptr, tmp.len, &skad->in4.a.sin_addr) <= -1)
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
#if (HIO_SIZEOF_STRUCT_SOCKADDR_IN6 > 0)
|
2020-02-16 13:59:41 +00:00
|
|
|
/* check if it is an IPv6 address not enclosed in [].
|
|
|
|
* the port number can't be specified in this format. */
|
|
|
|
if (p >= end || *p != ':')
|
|
|
|
{
|
|
|
|
/* without :, it can't be an ipv6 address */
|
|
|
|
goto unrecog;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (p < end && *p != '%') p++;
|
|
|
|
tmp.len = p - tmp.ptr;
|
|
|
|
|
2021-08-09 08:24:21 +00:00
|
|
|
if (uchars_to_ipv6(tmp.ptr, tmp.len, &skad->in6.a.sin6_addr) <= -1) goto unrecog;
|
2020-02-16 13:59:41 +00:00
|
|
|
|
|
|
|
if (p < end && *p == '%')
|
|
|
|
{
|
|
|
|
/* handle scope id */
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_uint32_t x;
|
2020-02-16 13:59:41 +00:00
|
|
|
|
|
|
|
p++; /* skip % */
|
|
|
|
|
|
|
|
if (p >= end)
|
|
|
|
{
|
|
|
|
/* premature end */
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_seterrbfmt (hio, HIO_EINVAL, "scope id blank");
|
2020-02-16 13:59:41 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*p >= '0' && *p <= '9')
|
|
|
|
{
|
|
|
|
/* numeric scope id */
|
2021-08-09 08:24:21 +00:00
|
|
|
skad->in6.a.sin6_scope_id = 0;
|
2020-02-16 13:59:41 +00:00
|
|
|
do
|
|
|
|
{
|
2021-08-09 08:24:21 +00:00
|
|
|
x = skad->in6.a.sin6_scope_id * 10 + (*p - '0');
|
|
|
|
if (x < skad->in6.a.sin6_scope_id)
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_seterrbfmt (hio, HIO_EINVAL, "scope id too large");
|
2020-02-16 13:59:41 +00:00
|
|
|
return -1; /* overflow */
|
|
|
|
}
|
2021-08-09 08:24:21 +00:00
|
|
|
skad->in6.a.sin6_scope_id = x;
|
2020-02-16 13:59:41 +00:00
|
|
|
p++;
|
|
|
|
}
|
|
|
|
while (p < end && *p >= '0' && *p <= '9');
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* interface name as a scope id? */
|
2021-07-22 07:30:20 +00:00
|
|
|
const hio_uch_t* stmp = p;
|
2020-02-16 13:59:41 +00:00
|
|
|
unsigned int index;
|
|
|
|
do p++; while (p < end);
|
2021-07-22 07:30:20 +00:00
|
|
|
if (hio_ucharstoifindex(hio, stmp, p - stmp, &index) <= -1) return -1;
|
2021-08-09 08:24:21 +00:00
|
|
|
skad->in6.a.sin6_scope_id = index;
|
2020-02-16 13:59:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (p < end) goto unrecog; /* some gargage after the end? */
|
|
|
|
|
2021-08-09 08:24:21 +00:00
|
|
|
skad->in6.a.sin6_family = AF_INET6;
|
2020-02-16 13:59:41 +00:00
|
|
|
return 0;
|
|
|
|
#else
|
|
|
|
goto unrecog;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2021-08-09 08:24:21 +00:00
|
|
|
skad->in4.a.sin_family = AF_INET;
|
2021-07-22 07:30:20 +00:00
|
|
|
#if (HIO_SIZEOF_STRUCT_SOCKADDR_IN6 > 0)
|
2020-02-16 13:59:41 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (p < end && *p == ':')
|
|
|
|
{
|
|
|
|
/* port number */
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_uint32_t port = 0;
|
2020-02-16 13:59:41 +00:00
|
|
|
|
|
|
|
p++; /* skip : */
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
tmp.ptr = (hio_uch_t*)p;
|
2020-02-19 14:59:06 +00:00
|
|
|
while (p < end && *p >= '0' && *p <= '9')
|
|
|
|
{
|
|
|
|
port = port * 10 + (*p - '0');
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
|
|
|
|
tmp.len = p - tmp.ptr;
|
|
|
|
if (tmp.len <= 0 || tmp.len >= 6 ||
|
2021-07-22 07:30:20 +00:00
|
|
|
port > HIO_TYPE_MAX(hio_uint16_t))
|
2020-02-19 14:59:06 +00:00
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_seterrbfmt (hio, HIO_EINVAL, "port number blank or too large");
|
2020-02-19 14:59:06 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
#if (HIO_SIZEOF_STRUCT_SOCKADDR_IN6 > 0)
|
2021-08-09 08:24:21 +00:00
|
|
|
if (skad->in4.a.sin_family == AF_INET)
|
|
|
|
skad->in4.a.sin_port = hio_hton16(port);
|
2020-02-19 14:59:06 +00:00
|
|
|
else
|
2021-08-09 08:24:21 +00:00
|
|
|
skad->in6.a.sin6_port = hio_hton16(port);
|
2020-02-19 14:59:06 +00:00
|
|
|
#else
|
2021-08-09 08:24:21 +00:00
|
|
|
skad->in4.a.sin_port = hio_hton16(port);
|
2020-02-19 14:59:06 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
unrecog:
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_seterrbfmt (hio, HIO_EINVAL, "unrecognized address");
|
2020-02-19 14:59:06 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
no_rbrack:
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_seterrbfmt (hio, HIO_EINVAL, "missing right bracket");
|
2020-02-19 14:59:06 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ---------------------------------------------------------- */
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
int hio_bcharstoskad (hio_t* hio, const hio_bch_t* str, hio_oow_t len, hio_skad_t* _skad)
|
2020-02-19 14:59:06 +00:00
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_skad_alt_t* skad = (hio_skad_alt_t*)_skad;
|
|
|
|
const hio_bch_t* p;
|
|
|
|
const hio_bch_t* end;
|
|
|
|
hio_bcs_t tmp;
|
2020-02-19 14:59:06 +00:00
|
|
|
|
|
|
|
p = str;
|
|
|
|
end = str + len;
|
|
|
|
|
|
|
|
if (p >= end)
|
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_seterrbfmt (hio, HIO_EINVAL, "blank address");
|
2020-02-19 14:59:06 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
/* use HIO_SIZEOF(*_skad) instead of HIO_SIZEOF(*skad) in case they are different */
|
|
|
|
HIO_MEMSET (skad, 0, HIO_SIZEOF(*_skad));
|
2020-02-19 14:59:06 +00:00
|
|
|
|
2021-08-06 03:23:48 +00:00
|
|
|
if (p[0] == '<' && p[1] == 'q' && p[2] == 'x' && p[3] == '>' && p[4] == '\0')
|
2020-02-19 14:59:06 +00:00
|
|
|
{
|
2021-08-06 03:23:48 +00:00
|
|
|
/* this is HIO specific. the rest isn't important */
|
|
|
|
skad->sa.sa_family = HIO_AF_QX;
|
2020-02-19 14:59:06 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2021-08-06 03:23:48 +00:00
|
|
|
|
|
|
|
if (*p == '@')
|
|
|
|
{
|
|
|
|
#if defined(AF_UNIX) && (HIO_SIZEOF_STRUCT_SOCKADDR_UN > 0)
|
|
|
|
/* @aaa, @/tmp/aaa ... */
|
|
|
|
hio_copy_bchars_to_bcstr (skad->un.sun_path, HIO_COUNTOF(skad->un.sun_path), str + 1, len - 1);
|
2021-08-18 06:34:50 +00:00
|
|
|
skad->un.sun_family = AF_UNIX;
|
2021-08-06 03:23:48 +00:00
|
|
|
return 0;
|
|
|
|
#else
|
|
|
|
hio_seterrbfmt (hio, HIO_ENOIMPL, "unix address not supported");
|
|
|
|
return -1;
|
2020-02-19 14:59:06 +00:00
|
|
|
#endif
|
2021-08-06 03:23:48 +00:00
|
|
|
}
|
2020-02-19 14:59:06 +00:00
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
#if (HIO_SIZEOF_STRUCT_SOCKADDR_IN6 > 0)
|
2020-02-19 14:59:06 +00:00
|
|
|
if (*p == '[')
|
|
|
|
{
|
|
|
|
/* IPv6 address */
|
2021-07-22 07:30:20 +00:00
|
|
|
tmp.ptr = (hio_bch_t*)++p; /* skip [ and remember the position */
|
2020-02-19 14:59:06 +00:00
|
|
|
while (p < end && *p != '%' && *p != ']') p++;
|
|
|
|
|
|
|
|
if (p >= end) goto no_rbrack;
|
|
|
|
|
|
|
|
tmp.len = p - tmp.ptr;
|
|
|
|
if (*p == '%')
|
|
|
|
{
|
|
|
|
/* handle scope id */
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_uint32_t x;
|
2020-02-19 14:59:06 +00:00
|
|
|
|
|
|
|
p++; /* skip % */
|
|
|
|
|
|
|
|
if (p >= end)
|
|
|
|
{
|
|
|
|
/* premature end */
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_seterrbfmt (hio, HIO_EINVAL, "scope id blank");
|
2020-02-19 14:59:06 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*p >= '0' && *p <= '9')
|
|
|
|
{
|
|
|
|
/* numeric scope id */
|
2021-08-09 08:24:21 +00:00
|
|
|
skad->in6.a.sin6_scope_id = 0;
|
2020-02-19 14:59:06 +00:00
|
|
|
do
|
|
|
|
{
|
2021-08-09 08:24:21 +00:00
|
|
|
x = skad->in6.a.sin6_scope_id * 10 + (*p - '0');
|
|
|
|
if (x < skad->in6.a.sin6_scope_id)
|
2020-02-19 14:59:06 +00:00
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_seterrbfmt (hio, HIO_EINVAL, "scope id too large");
|
2020-02-19 14:59:06 +00:00
|
|
|
return -1; /* overflow */
|
|
|
|
}
|
2021-08-09 08:24:21 +00:00
|
|
|
skad->in6.a.sin6_scope_id = x;
|
2020-02-19 14:59:06 +00:00
|
|
|
p++;
|
|
|
|
}
|
|
|
|
while (p < end && *p >= '0' && *p <= '9');
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* interface name as a scope id? */
|
2021-07-22 07:30:20 +00:00
|
|
|
const hio_bch_t* stmp = p;
|
2020-02-19 14:59:06 +00:00
|
|
|
unsigned int index;
|
|
|
|
do p++; while (p < end && *p != ']');
|
2021-07-22 07:30:20 +00:00
|
|
|
if (hio_bcharstoifindex(hio, stmp, p - stmp, &index) <= -1) return -1;
|
2021-08-09 08:24:21 +00:00
|
|
|
skad->in6.a.sin6_scope_id = index;
|
2020-02-19 14:59:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (p >= end || *p != ']') goto no_rbrack;
|
|
|
|
}
|
|
|
|
p++; /* skip ] */
|
|
|
|
|
2021-08-09 08:24:21 +00:00
|
|
|
if (bchars_to_ipv6(tmp.ptr, tmp.len, &skad->in6.a.sin6_addr) <= -1) goto unrecog;
|
|
|
|
skad->in6.a.sin6_family = AF_INET6;
|
2020-02-19 14:59:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
#endif
|
|
|
|
/* IPv4 address */
|
2021-07-22 07:30:20 +00:00
|
|
|
tmp.ptr = (hio_bch_t*)p;
|
2020-02-19 14:59:06 +00:00
|
|
|
while (p < end && *p != ':') p++;
|
|
|
|
tmp.len = p - tmp.ptr;
|
|
|
|
|
2021-08-09 08:24:21 +00:00
|
|
|
if (bchars_to_ipv4(tmp.ptr, tmp.len, &skad->in4.a.sin_addr) <= -1)
|
2020-02-19 14:59:06 +00:00
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
#if (HIO_SIZEOF_STRUCT_SOCKADDR_IN6 > 0)
|
2020-02-19 14:59:06 +00:00
|
|
|
/* check if it is an IPv6 address not enclosed in [].
|
|
|
|
* the port number can't be specified in this format. */
|
|
|
|
if (p >= end || *p != ':')
|
|
|
|
{
|
|
|
|
/* without :, it can't be an ipv6 address */
|
|
|
|
goto unrecog;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
while (p < end && *p != '%') p++;
|
|
|
|
tmp.len = p - tmp.ptr;
|
|
|
|
|
2021-08-09 08:24:21 +00:00
|
|
|
if (bchars_to_ipv6(tmp.ptr, tmp.len, &skad->in6.a.sin6_addr) <= -1) goto unrecog;
|
2020-02-19 14:59:06 +00:00
|
|
|
|
|
|
|
if (p < end && *p == '%')
|
|
|
|
{
|
|
|
|
/* handle scope id */
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_uint32_t x;
|
2020-02-19 14:59:06 +00:00
|
|
|
|
|
|
|
p++; /* skip % */
|
|
|
|
|
|
|
|
if (p >= end)
|
|
|
|
{
|
|
|
|
/* premature end */
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_seterrbfmt (hio, HIO_EINVAL, "scope id blank");
|
2020-02-19 14:59:06 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*p >= '0' && *p <= '9')
|
|
|
|
{
|
|
|
|
/* numeric scope id */
|
2021-08-09 08:24:21 +00:00
|
|
|
skad->in6.a.sin6_scope_id = 0;
|
2020-02-19 14:59:06 +00:00
|
|
|
do
|
|
|
|
{
|
2021-08-09 08:24:21 +00:00
|
|
|
x = skad->in6.a.sin6_scope_id * 10 + (*p - '0');
|
|
|
|
if (x < skad->in6.a.sin6_scope_id)
|
2020-02-19 14:59:06 +00:00
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_seterrbfmt (hio, HIO_EINVAL, "scope id too large");
|
2020-02-19 14:59:06 +00:00
|
|
|
return -1; /* overflow */
|
|
|
|
}
|
2021-08-09 08:24:21 +00:00
|
|
|
skad->in6.a.sin6_scope_id = x;
|
2020-02-19 14:59:06 +00:00
|
|
|
p++;
|
|
|
|
}
|
|
|
|
while (p < end && *p >= '0' && *p <= '9');
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* interface name as a scope id? */
|
2021-07-22 07:30:20 +00:00
|
|
|
const hio_bch_t* stmp = p;
|
2020-02-19 14:59:06 +00:00
|
|
|
unsigned int index;
|
|
|
|
do p++; while (p < end);
|
2021-07-22 07:30:20 +00:00
|
|
|
if (hio_bcharstoifindex(hio, stmp, p - stmp, &index) <= -1) return -1;
|
2021-08-09 08:24:21 +00:00
|
|
|
skad->in6.a.sin6_scope_id = index;
|
2020-02-19 14:59:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (p < end) goto unrecog; /* some gargage after the end? */
|
|
|
|
|
2021-08-09 08:24:21 +00:00
|
|
|
skad->in6.a.sin6_family = AF_INET6;
|
2020-02-19 14:59:06 +00:00
|
|
|
return 0;
|
|
|
|
#else
|
|
|
|
goto unrecog;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2021-08-09 08:24:21 +00:00
|
|
|
skad->in4.a.sin_family = AF_INET;
|
2021-07-22 07:30:20 +00:00
|
|
|
#if (HIO_SIZEOF_STRUCT_SOCKADDR_IN6 > 0)
|
2020-02-19 14:59:06 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (p < end && *p == ':')
|
|
|
|
{
|
|
|
|
/* port number */
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_uint32_t port = 0;
|
2020-02-19 14:59:06 +00:00
|
|
|
|
|
|
|
p++; /* skip : */
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
tmp.ptr = (hio_bch_t*)p;
|
2020-02-16 13:59:41 +00:00
|
|
|
while (p < end && *p >= '0' && *p <= '9')
|
|
|
|
{
|
|
|
|
port = port * 10 + (*p - '0');
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
|
|
|
|
tmp.len = p - tmp.ptr;
|
|
|
|
if (tmp.len <= 0 || tmp.len >= 6 ||
|
2021-07-22 07:30:20 +00:00
|
|
|
port > HIO_TYPE_MAX(hio_uint16_t))
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_seterrbfmt (hio, HIO_EINVAL, "port number blank or too large");
|
2020-02-16 13:59:41 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
#if (HIO_SIZEOF_STRUCT_SOCKADDR_IN6 > 0)
|
2021-08-09 08:24:21 +00:00
|
|
|
if (skad->in4.a.sin_family == AF_INET)
|
|
|
|
skad->in4.a.sin_port = hio_hton16(port);
|
2020-02-16 13:59:41 +00:00
|
|
|
else
|
2021-08-09 08:24:21 +00:00
|
|
|
skad->in6.a.sin6_port = hio_hton16(port);
|
2020-02-16 13:59:41 +00:00
|
|
|
#else
|
2021-08-09 08:24:21 +00:00
|
|
|
skad->in4.a.sin_port = hio_hton16(port);
|
2020-02-16 13:59:41 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
unrecog:
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_seterrbfmt (hio, HIO_EINVAL, "unrecognized address");
|
2020-02-16 13:59:41 +00:00
|
|
|
return -1;
|
2020-02-25 07:09:20 +00:00
|
|
|
|
2020-02-16 13:59:41 +00:00
|
|
|
no_rbrack:
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_seterrbfmt (hio, HIO_EINVAL, "missing right bracket");
|
2020-02-16 13:59:41 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ---------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
|
|
#define __BTOA(type_t,b,p,end) \
|
|
|
|
do { \
|
|
|
|
type_t* sp = p; \
|
|
|
|
do { \
|
|
|
|
if (p >= end) { \
|
|
|
|
if (p == sp) break; \
|
|
|
|
if (p - sp > 1) p[-2] = p[-1]; \
|
|
|
|
p[-1] = (b % 10) + '0'; \
|
|
|
|
} \
|
|
|
|
else *p++ = (b % 10) + '0'; \
|
|
|
|
b /= 10; \
|
|
|
|
} while (b > 0); \
|
|
|
|
if (p - sp > 1) { \
|
|
|
|
type_t t = sp[0]; \
|
|
|
|
sp[0] = p[-1]; \
|
|
|
|
p[-1] = t; \
|
|
|
|
} \
|
|
|
|
} while (0);
|
|
|
|
|
|
|
|
#define __ADDDOT(p, end) \
|
|
|
|
do { \
|
|
|
|
if (p >= end) break; \
|
|
|
|
*p++ = '.'; \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
/* ---------------------------------------------------------- */
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
static hio_oow_t ip4ad_to_ucstr (const struct in_addr* ipad, hio_uch_t* buf, hio_oow_t size)
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_uint8_t b;
|
|
|
|
hio_uch_t* p, * end;
|
|
|
|
hio_uint32_t ip;
|
2020-02-16 13:59:41 +00:00
|
|
|
|
|
|
|
if (size <= 0) return 0;
|
|
|
|
|
|
|
|
ip = ipad->s_addr;
|
|
|
|
|
|
|
|
p = buf;
|
|
|
|
end = buf + size - 1;
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
#if defined(HIO_ENDIAN_BIG)
|
|
|
|
b = (ip >> 24) & 0xFF; __BTOA (hio_uch_t, b, p, end); __ADDDOT (p, end);
|
|
|
|
b = (ip >> 16) & 0xFF; __BTOA (hio_uch_t, b, p, end); __ADDDOT (p, end);
|
|
|
|
b = (ip >> 8) & 0xFF; __BTOA (hio_uch_t, b, p, end); __ADDDOT (p, end);
|
|
|
|
b = (ip >> 0) & 0xFF; __BTOA (hio_uch_t, b, p, end);
|
|
|
|
#elif defined(HIO_ENDIAN_LITTLE)
|
|
|
|
b = (ip >> 0) & 0xFF; __BTOA (hio_uch_t, b, p, end); __ADDDOT (p, end);
|
|
|
|
b = (ip >> 8) & 0xFF; __BTOA (hio_uch_t, b, p, end); __ADDDOT (p, end);
|
|
|
|
b = (ip >> 16) & 0xFF; __BTOA (hio_uch_t, b, p, end); __ADDDOT (p, end);
|
|
|
|
b = (ip >> 24) & 0xFF; __BTOA (hio_uch_t, b, p, end);
|
2020-02-16 13:59:41 +00:00
|
|
|
#else
|
|
|
|
# error Unknown Endian
|
|
|
|
#endif
|
|
|
|
|
|
|
|
*p = '\0';
|
|
|
|
return p - buf;
|
|
|
|
}
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
static hio_oow_t ip6ad_to_ucstr (const struct in6_addr* ipad, hio_uch_t* buf, hio_oow_t size)
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
#define IP6AD_NWORDS (HIO_SIZEOF(ipad->s6_addr) / HIO_SIZEOF(hio_uint16_t))
|
2020-02-16 13:59:41 +00:00
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_uch_t tmp[HIO_COUNTOF("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")], *tp;
|
2020-02-16 13:59:41 +00:00
|
|
|
struct { int base, len; } best, cur;
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_uint16_t words[IP6AD_NWORDS];
|
2020-02-16 13:59:41 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
if (size <= 0) return 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Preprocess:
|
|
|
|
* Copy the input (bytewise) array into a wordwise array.
|
|
|
|
* Find the longest run of 0x00's in src[] for :: shorthanding.
|
|
|
|
*/
|
2021-07-22 07:30:20 +00:00
|
|
|
HIO_MEMSET (words, 0, HIO_SIZEOF(words));
|
|
|
|
for (i = 0; i < HIO_SIZEOF(ipad->s6_addr); i++)
|
2020-02-16 13:59:41 +00:00
|
|
|
words[i / 2] |= (ipad->s6_addr[i] << ((1 - (i % 2)) << 3));
|
|
|
|
best.base = -1;
|
|
|
|
best.len = 0;
|
|
|
|
cur.base = -1;
|
|
|
|
cur.len = 0;
|
|
|
|
|
2021-07-22 03:23:07 +00:00
|
|
|
for (i = 0; i < IP6AD_NWORDS; i++)
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
if (best.base == -1 || cur.len > best.len) best = cur;
|
|
|
|
}
|
|
|
|
if (best.base != -1 && best.len < 2) best.base = -1;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Format the result.
|
|
|
|
*/
|
|
|
|
tp = tmp;
|
2021-07-22 03:23:07 +00:00
|
|
|
for (i = 0; i < IP6AD_NWORDS; i++)
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
|
|
|
/* 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? ipv4-compatible or ipv4-mapped */
|
|
|
|
if (i == 6 && best.base == 0 && (best.len == 6 || (best.len == 5 && words[5] == 0xffff)))
|
|
|
|
{
|
|
|
|
struct in_addr ip4ad;
|
2021-07-22 07:30:20 +00:00
|
|
|
HIO_MEMCPY (&ip4ad.s_addr, ipad->s6_addr + 12, HIO_SIZEOF(ip4ad.s_addr));
|
|
|
|
tp += ip4ad_to_ucstr(&ip4ad, tp, HIO_COUNTOF(tmp) - (tp - tmp));
|
2020-02-16 13:59:41 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
tp += hio_fmt_uintmax_to_ucstr(tp, HIO_COUNTOF(tmp) - (tp - tmp), words[i], 16, 0, '\0', HIO_NULL);
|
2020-02-16 13:59:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Was it a trailing run of 0x00's? */
|
2021-07-22 03:23:07 +00:00
|
|
|
if (best.base != -1 && (best.base + best.len) == IP6AD_NWORDS) *tp++ = ':';
|
2020-02-16 13:59:41 +00:00
|
|
|
*tp++ = '\0';
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
return hio_copy_ucstr(buf, size, tmp);
|
2020-02-16 13:59:41 +00:00
|
|
|
|
2021-07-22 03:23:07 +00:00
|
|
|
#undef IP6AD_NWORDS
|
2020-02-16 13:59:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_oow_t hio_skadtoucstr (hio_t* hio, const hio_skad_t* _skad, hio_uch_t* buf, hio_oow_t len, int flags)
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
const hio_skad_alt_t* skad = (const hio_skad_alt_t*)_skad;
|
|
|
|
hio_oow_t xlen = 0;
|
2020-02-16 13:59:41 +00:00
|
|
|
|
|
|
|
/* unsupported types will result in an empty string */
|
|
|
|
|
2021-08-17 07:00:22 +00:00
|
|
|
switch (hio_skad_get_family(_skad))
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
case HIO_AF_INET:
|
2021-08-06 03:23:48 +00:00
|
|
|
if (flags & HIO_SKAD_TO_UCSTR_ADDR)
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
|
|
|
if (xlen + 1 >= len) goto done;
|
2021-08-09 08:24:21 +00:00
|
|
|
xlen += ip4ad_to_ucstr(&skad->in4.a.sin_addr, buf, len);
|
2020-02-16 13:59:41 +00:00
|
|
|
}
|
|
|
|
|
2021-08-06 03:23:48 +00:00
|
|
|
if (flags & HIO_SKAD_TO_UCSTR_PORT)
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
2021-08-09 08:24:21 +00:00
|
|
|
if (!(flags & HIO_SKAD_TO_UCSTR_ADDR) || skad->in4.a.sin_port != 0)
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
2021-08-06 03:23:48 +00:00
|
|
|
if (flags & HIO_SKAD_TO_UCSTR_ADDR)
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
|
|
|
if (xlen + 1 >= len) goto done;
|
|
|
|
buf[xlen++] = ':';
|
|
|
|
}
|
|
|
|
|
|
|
|
if (xlen + 1 >= len) goto done;
|
2021-08-09 08:24:21 +00:00
|
|
|
xlen += hio_fmt_uintmax_to_ucstr(&buf[xlen], len - xlen, hio_ntoh16(skad->in4.a.sin_port), 10, 0, '\0', HIO_NULL);
|
2020-02-16 13:59:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
case HIO_AF_INET6:
|
2021-08-06 03:23:48 +00:00
|
|
|
if (flags & HIO_SKAD_TO_UCSTR_PORT)
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
2021-08-09 08:24:21 +00:00
|
|
|
if (!(flags & HIO_SKAD_TO_UCSTR_ADDR) || skad->in6.a.sin6_port != 0)
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
2021-08-06 03:23:48 +00:00
|
|
|
if (flags & HIO_SKAD_TO_UCSTR_ADDR)
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
|
|
|
if (xlen + 1 >= len) goto done;
|
|
|
|
buf[xlen++] = '[';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-06 03:23:48 +00:00
|
|
|
if (flags & HIO_SKAD_TO_UCSTR_ADDR)
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
|
|
|
if (xlen + 1 >= len) goto done;
|
2021-08-09 08:24:21 +00:00
|
|
|
xlen += ip6ad_to_ucstr(&skad->in6.a.sin6_addr, &buf[xlen], len - xlen);
|
2020-02-16 13:59:41 +00:00
|
|
|
|
2021-08-09 08:24:21 +00:00
|
|
|
if (skad->in6.a.sin6_scope_id != 0)
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
|
|
|
int tmp;
|
|
|
|
|
|
|
|
if (xlen + 1 >= len) goto done;
|
|
|
|
buf[xlen++] = '%';
|
|
|
|
|
|
|
|
if (xlen + 1 >= len) goto done;
|
|
|
|
|
2021-08-09 08:24:21 +00:00
|
|
|
tmp = hio_ifindextoucstr(hio, skad->in6.a.sin6_scope_id, &buf[xlen], len - xlen);
|
2020-02-16 13:59:41 +00:00
|
|
|
if (tmp <= -1)
|
|
|
|
{
|
2021-08-09 08:24:21 +00:00
|
|
|
xlen += hio_fmt_uintmax_to_ucstr(&buf[xlen], len - xlen, skad->in6.a.sin6_scope_id, 10, 0, '\0', HIO_NULL);
|
2020-02-16 13:59:41 +00:00
|
|
|
}
|
|
|
|
else xlen += tmp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-06 03:23:48 +00:00
|
|
|
if (flags & HIO_SKAD_TO_UCSTR_PORT)
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
2021-08-09 08:24:21 +00:00
|
|
|
if (!(flags & HIO_SKAD_TO_UCSTR_ADDR) || skad->in6.a.sin6_port != 0)
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
2021-08-06 03:23:48 +00:00
|
|
|
if (flags & HIO_SKAD_TO_UCSTR_ADDR)
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
|
|
|
if (xlen + 1 >= len) goto done;
|
|
|
|
buf[xlen++] = ']';
|
|
|
|
|
|
|
|
if (xlen + 1 >= len) goto done;
|
|
|
|
buf[xlen++] = ':';
|
|
|
|
}
|
|
|
|
|
|
|
|
if (xlen + 1 >= len) goto done;
|
2021-08-09 08:24:21 +00:00
|
|
|
xlen += hio_fmt_uintmax_to_ucstr(&buf[xlen], len - xlen, hio_ntoh16(skad->in6.a.sin6_port), 10, 0, '\0', HIO_NULL);
|
2020-02-16 13:59:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
case HIO_AF_UNIX:
|
2021-08-06 03:23:48 +00:00
|
|
|
if (flags & HIO_SKAD_TO_UCSTR_ADDR)
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
|
|
|
if (xlen + 1 >= len) goto done;
|
|
|
|
buf[xlen++] = '@';
|
|
|
|
|
|
|
|
if (xlen + 1 >= len) goto done;
|
|
|
|
else
|
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_oow_t mbslen, wcslen = len - xlen;
|
|
|
|
hio_convbtoucstr (hio, skad->un.sun_path, &mbslen, &buf[xlen], &wcslen, 1);
|
2020-02-16 13:59:41 +00:00
|
|
|
/* i don't care about conversion errors */
|
|
|
|
xlen += wcslen;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-06 03:23:48 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case HIO_AF_QX:
|
|
|
|
if (flags & HIO_SKAD_TO_UCSTR_ADDR)
|
|
|
|
{
|
|
|
|
if (xlen + 1 >= len) goto done;
|
|
|
|
buf[xlen++] = '<';
|
|
|
|
if (xlen + 1 >= len) goto done;
|
|
|
|
buf[xlen++] = 'q';
|
|
|
|
if (xlen + 1 >= len) goto done;
|
|
|
|
buf[xlen++] = 'x';
|
|
|
|
if (xlen + 1 >= len) goto done;
|
|
|
|
buf[xlen++] = '>';
|
|
|
|
}
|
|
|
|
|
2020-02-16 13:59:41 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
done:
|
|
|
|
if (xlen < len) buf[xlen] = '\0';
|
|
|
|
return xlen;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ---------------------------------------------------------- */
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
static hio_oow_t ip4ad_to_bcstr (const struct in_addr* ipad, hio_bch_t* buf, hio_oow_t size)
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_uint8_t b;
|
|
|
|
hio_bch_t* p, * end;
|
|
|
|
hio_uint32_t ip;
|
2020-02-16 13:59:41 +00:00
|
|
|
|
|
|
|
if (size <= 0) return 0;
|
|
|
|
|
|
|
|
ip = ipad->s_addr;
|
|
|
|
|
|
|
|
p = buf;
|
|
|
|
end = buf + size - 1;
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
#if defined(HIO_ENDIAN_BIG)
|
|
|
|
b = (ip >> 24) & 0xFF; __BTOA (hio_bch_t, b, p, end); __ADDDOT (p, end);
|
|
|
|
b = (ip >> 16) & 0xFF; __BTOA (hio_bch_t, b, p, end); __ADDDOT (p, end);
|
|
|
|
b = (ip >> 8) & 0xFF; __BTOA (hio_bch_t, b, p, end); __ADDDOT (p, end);
|
|
|
|
b = (ip >> 0) & 0xFF; __BTOA (hio_bch_t, b, p, end);
|
|
|
|
#elif defined(HIO_ENDIAN_LITTLE)
|
|
|
|
b = (ip >> 0) & 0xFF; __BTOA (hio_bch_t, b, p, end); __ADDDOT (p, end);
|
|
|
|
b = (ip >> 8) & 0xFF; __BTOA (hio_bch_t, b, p, end); __ADDDOT (p, end);
|
|
|
|
b = (ip >> 16) & 0xFF; __BTOA (hio_bch_t, b, p, end); __ADDDOT (p, end);
|
|
|
|
b = (ip >> 24) & 0xFF; __BTOA (hio_bch_t, b, p, end);
|
2020-02-16 13:59:41 +00:00
|
|
|
#else
|
|
|
|
# error Unknown Endian
|
|
|
|
#endif
|
|
|
|
|
|
|
|
*p = '\0';
|
|
|
|
return p - buf;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
static hio_oow_t ip6ad_to_bcstr (const struct in6_addr* ipad, hio_bch_t* buf, hio_oow_t size)
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
#define IP6AD_NWORDS (HIO_SIZEOF(ipad->s6_addr) / HIO_SIZEOF(hio_uint16_t))
|
2020-02-16 13:59:41 +00:00
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_bch_t tmp[HIO_COUNTOF("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")], *tp;
|
2020-02-16 13:59:41 +00:00
|
|
|
struct { int base, len; } best, cur;
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_uint16_t words[IP6AD_NWORDS];
|
2020-02-16 13:59:41 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
if (size <= 0) return 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Preprocess:
|
|
|
|
* Copy the input (bytewise) array into a wordwise array.
|
|
|
|
* Find the longest run of 0x00's in src[] for :: shorthanding.
|
|
|
|
*/
|
2021-07-22 07:30:20 +00:00
|
|
|
HIO_MEMSET (words, 0, HIO_SIZEOF(words));
|
|
|
|
for (i = 0; i < HIO_SIZEOF(ipad->s6_addr); i++)
|
2020-02-16 13:59:41 +00:00
|
|
|
words[i / 2] |= (ipad->s6_addr[i] << ((1 - (i % 2)) << 3));
|
|
|
|
best.base = -1;
|
|
|
|
best.len = 0;
|
|
|
|
cur.base = -1;
|
|
|
|
cur.len = 0;
|
|
|
|
|
2021-07-22 03:23:07 +00:00
|
|
|
for (i = 0; i < IP6AD_NWORDS; i++)
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
if (best.base == -1 || cur.len > best.len) best = cur;
|
|
|
|
}
|
|
|
|
if (best.base != -1 && best.len < 2) best.base = -1;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Format the result.
|
|
|
|
*/
|
|
|
|
tp = tmp;
|
2021-07-22 03:23:07 +00:00
|
|
|
for (i = 0; i < IP6AD_NWORDS; i++)
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
|
|
|
/* 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? ipv4-compatible or ipv4-mapped */
|
|
|
|
if (i == 6 && best.base == 0 && (best.len == 6 || (best.len == 5 && words[5] == 0xffff)))
|
|
|
|
{
|
|
|
|
struct in_addr ip4ad;
|
2021-07-22 07:30:20 +00:00
|
|
|
HIO_MEMCPY (&ip4ad.s_addr, ipad->s6_addr + 12, HIO_SIZEOF(ip4ad.s_addr));
|
|
|
|
tp += ip4ad_to_bcstr(&ip4ad, tp, HIO_COUNTOF(tmp) - (tp - tmp));
|
2020-02-16 13:59:41 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
tp += hio_fmt_uintmax_to_bcstr(tp, HIO_COUNTOF(tmp) - (tp - tmp), words[i], 16, 0, '\0', HIO_NULL);
|
2020-02-16 13:59:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Was it a trailing run of 0x00's? */
|
2021-07-22 03:23:07 +00:00
|
|
|
if (best.base != -1 && (best.base + best.len) == IP6AD_NWORDS) *tp++ = ':';
|
2020-02-16 13:59:41 +00:00
|
|
|
*tp++ = '\0';
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
return hio_copy_bcstr(buf, size, tmp);
|
2020-02-16 13:59:41 +00:00
|
|
|
|
2021-07-22 03:23:07 +00:00
|
|
|
#undef IP6AD_NWORDS
|
2020-02-16 13:59:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_oow_t hio_skadtobcstr (hio_t* hio, const hio_skad_t* _skad, hio_bch_t* buf, hio_oow_t len, int flags)
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
const hio_skad_alt_t* skad = (const hio_skad_alt_t*)_skad;
|
|
|
|
hio_oow_t xlen = 0;
|
2020-02-16 13:59:41 +00:00
|
|
|
|
|
|
|
/* unsupported types will result in an empty string */
|
|
|
|
|
2021-08-17 07:00:22 +00:00
|
|
|
switch (hio_skad_get_family(_skad))
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
case HIO_AF_INET:
|
|
|
|
if (flags & HIO_SKAD_TO_BCSTR_ADDR)
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
|
|
|
if (xlen + 1 >= len) goto done;
|
2021-08-09 08:24:21 +00:00
|
|
|
xlen += ip4ad_to_bcstr(&skad->in4.a.sin_addr, buf, len);
|
2020-02-16 13:59:41 +00:00
|
|
|
}
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
if (flags & HIO_SKAD_TO_BCSTR_PORT)
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
2021-08-09 08:24:21 +00:00
|
|
|
if (!(flags & HIO_SKAD_TO_BCSTR_ADDR) || skad->in4.a.sin_port != 0)
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
if (flags & HIO_SKAD_TO_BCSTR_ADDR)
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
|
|
|
if (xlen + 1 >= len) goto done;
|
|
|
|
buf[xlen++] = ':';
|
|
|
|
}
|
|
|
|
|
|
|
|
if (xlen + 1 >= len) goto done;
|
2021-08-09 08:24:21 +00:00
|
|
|
xlen += hio_fmt_uintmax_to_bcstr(&buf[xlen], len - xlen, hio_ntoh16(skad->in4.a.sin_port), 10, 0, '\0', HIO_NULL);
|
2020-02-16 13:59:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
case HIO_AF_INET6:
|
|
|
|
if (flags & HIO_SKAD_TO_BCSTR_PORT)
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
2021-08-09 08:24:21 +00:00
|
|
|
if (!(flags & HIO_SKAD_TO_BCSTR_ADDR) || skad->in6.a.sin6_port != 0)
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
if (flags & HIO_SKAD_TO_BCSTR_ADDR)
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
|
|
|
if (xlen + 1 >= len) goto done;
|
|
|
|
buf[xlen++] = '[';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
if (flags & HIO_SKAD_TO_BCSTR_ADDR)
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
if (xlen + 1 >= len) goto done;
|
2021-08-09 08:24:21 +00:00
|
|
|
xlen += ip6ad_to_bcstr(&skad->in6.a.sin6_addr, &buf[xlen], len - xlen);
|
2020-02-16 13:59:41 +00:00
|
|
|
|
2021-08-09 08:24:21 +00:00
|
|
|
if (skad->in6.a.sin6_scope_id != 0)
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
|
|
|
int tmp;
|
|
|
|
|
|
|
|
if (xlen + 1 >= len) goto done;
|
|
|
|
buf[xlen++] = '%';
|
|
|
|
|
|
|
|
if (xlen + 1 >= len) goto done;
|
|
|
|
|
2021-08-09 08:24:21 +00:00
|
|
|
tmp = hio_ifindextobcstr(hio, skad->in6.a.sin6_scope_id, &buf[xlen], len - xlen);
|
2020-02-16 13:59:41 +00:00
|
|
|
if (tmp <= -1)
|
|
|
|
{
|
2021-08-09 08:24:21 +00:00
|
|
|
xlen += hio_fmt_uintmax_to_bcstr(&buf[xlen], len - xlen, skad->in6.a.sin6_scope_id, 10, 0, '\0', HIO_NULL);
|
2020-02-16 13:59:41 +00:00
|
|
|
}
|
|
|
|
else xlen += tmp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
if (flags & HIO_SKAD_TO_BCSTR_PORT)
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
2021-08-09 08:24:21 +00:00
|
|
|
if (!(flags & HIO_SKAD_TO_BCSTR_ADDR) || skad->in6.a.sin6_port != 0)
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
if (flags & HIO_SKAD_TO_BCSTR_ADDR)
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
|
|
|
if (xlen + 1 >= len) goto done;
|
|
|
|
buf[xlen++] = ']';
|
|
|
|
|
|
|
|
if (xlen + 1 >= len) goto done;
|
|
|
|
buf[xlen++] = ':';
|
|
|
|
}
|
|
|
|
|
|
|
|
if (xlen + 1 >= len) goto done;
|
2021-08-09 08:24:21 +00:00
|
|
|
xlen += hio_fmt_uintmax_to_bcstr(&buf[xlen], len - xlen, hio_ntoh16(skad->in6.a.sin6_port), 10, 0, '\0', HIO_NULL);
|
2020-02-16 13:59:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
case HIO_AF_UNIX:
|
|
|
|
if (flags & HIO_SKAD_TO_BCSTR_ADDR)
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
|
|
|
if (xlen + 1 >= len) goto done;
|
|
|
|
buf[xlen++] = '@';
|
|
|
|
|
|
|
|
if (xlen + 1 >= len) goto done;
|
2021-07-22 07:30:20 +00:00
|
|
|
xlen += hio_copy_bcstr(&buf[xlen], len - xlen, skad->un.sun_path);
|
2020-02-16 13:59:41 +00:00
|
|
|
}
|
|
|
|
|
2021-08-06 03:23:48 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case HIO_AF_QX:
|
|
|
|
if (flags & HIO_SKAD_TO_BCSTR_ADDR)
|
|
|
|
{
|
|
|
|
if (xlen + 1 >= len) goto done;
|
|
|
|
buf[xlen++] = '<';
|
|
|
|
if (xlen + 1 >= len) goto done;
|
|
|
|
buf[xlen++] = 'q';
|
|
|
|
if (xlen + 1 >= len) goto done;
|
|
|
|
buf[xlen++] = 'x';
|
|
|
|
if (xlen + 1 >= len) goto done;
|
|
|
|
buf[xlen++] = '>';
|
|
|
|
}
|
|
|
|
|
2020-02-16 13:59:41 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
done:
|
|
|
|
if (xlen < len) buf[xlen] = '\0';
|
|
|
|
return xlen;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
2021-08-17 07:00:22 +00:00
|
|
|
int hio_skad_get_family (const hio_skad_t* _skad)
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
const hio_skad_alt_t* skad = (const hio_skad_alt_t*)_skad;
|
|
|
|
/*HIO_STATIC_ASSERT (HIO_SIZEOF(*_skad) >= HIO_SIZEOF(*skad));*/
|
2020-02-16 13:59:41 +00:00
|
|
|
return skad->sa.sa_family;
|
|
|
|
}
|
|
|
|
|
2021-08-17 07:00:22 +00:00
|
|
|
int hio_skad_get_size (const hio_skad_t* _skad)
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
2021-08-17 07:00:22 +00:00
|
|
|
/* this excludes the size of additiona fields(e.g. chan)
|
|
|
|
* the fields are not part of the core socket address */
|
2021-08-09 08:24:21 +00:00
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
const hio_skad_alt_t* skad = (const hio_skad_alt_t*)_skad;
|
|
|
|
/*HIO_STATIC_ASSERT (HIO_SIZEOF(*_skad) >= HIO_SIZEOF(*skad));*/
|
2020-02-16 13:59:41 +00:00
|
|
|
|
|
|
|
switch (skad->sa.sa_family)
|
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
#if defined(AF_INET) && (HIO_SIZEOF_STRUCT_SOCKADDR_IN > 0)
|
|
|
|
case AF_INET: return HIO_SIZEOF(struct sockaddr_in);
|
2020-02-16 13:59:41 +00:00
|
|
|
#endif
|
2021-07-22 07:30:20 +00:00
|
|
|
#if defined(AF_INET6) && (HIO_SIZEOF_STRUCT_SOCKADDR_IN6 > 0)
|
|
|
|
case AF_INET6: return HIO_SIZEOF(struct sockaddr_in6);
|
2020-02-16 13:59:41 +00:00
|
|
|
#endif
|
2021-07-22 07:30:20 +00:00
|
|
|
#if defined(AF_PACKET) && (HIO_SIZEOF_STRUCT_SOCKADDR_LL > 0)
|
|
|
|
case AF_PACKET: return HIO_SIZEOF(struct sockaddr_ll);
|
2020-02-16 13:59:41 +00:00
|
|
|
#endif
|
2021-07-22 07:30:20 +00:00
|
|
|
#if defined(AF_LINK) && (HIO_SIZEOF_STRUCT_SOCKADDR_DL > 0)
|
|
|
|
case AF_LINK: return HIO_SIZEOF(struct sockaddr_dl);
|
2020-02-20 06:00:53 +00:00
|
|
|
#endif
|
2021-07-22 07:30:20 +00:00
|
|
|
#if defined(AF_UNIX) && (HIO_SIZEOF_STRUCT_SOCKADDR_UN > 0)
|
|
|
|
case AF_UNIX: return HIO_SIZEOF(struct sockaddr_un);
|
2020-02-16 13:59:41 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-08-17 07:00:22 +00:00
|
|
|
int hio_skad_get_port (const hio_skad_t* _skad)
|
2020-02-20 06:00:53 +00:00
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
const hio_skad_alt_t* skad = (const hio_skad_alt_t*)_skad;
|
2020-02-20 06:00:53 +00:00
|
|
|
|
|
|
|
switch (skad->sa.sa_family)
|
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
#if defined(AF_INET) && (HIO_SIZEOF_STRUCT_SOCKADDR_IN > 0)
|
2021-08-09 08:24:21 +00:00
|
|
|
case AF_INET: return hio_ntoh16(skad->in4.a.sin_port);
|
2020-02-20 06:00:53 +00:00
|
|
|
#endif
|
2021-07-22 07:30:20 +00:00
|
|
|
#if defined(AF_INET6) && (HIO_SIZEOF_STRUCT_SOCKADDR_IN6 > 0)
|
2021-08-09 08:24:21 +00:00
|
|
|
case AF_INET6: return hio_ntoh16(skad->in6.a.sin6_port);
|
2020-02-20 06:00:53 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-08-17 07:00:22 +00:00
|
|
|
int hio_skad_get_ifindex (const hio_skad_t* _skad)
|
2020-02-20 06:00:53 +00:00
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
const hio_skad_alt_t* skad = (const hio_skad_alt_t*)_skad;
|
2020-02-20 06:00:53 +00:00
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
#if defined(AF_PACKET) && (HIO_SIZEOF_STRUCT_SOCKADDR_LL > 0)
|
2021-08-09 08:24:21 +00:00
|
|
|
if (skad->sa.sa_family == AF_PACKET) return skad->ll.sll_ifindex;
|
2020-02-20 06:00:53 +00:00
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
#elif defined(AF_LINK) && (HIO_SIZEOF_STRUCT_SOCKADDR_DL > 0)
|
2021-08-09 08:24:21 +00:00
|
|
|
if (skad->sa.sa_family == AF_LINK) return skad->dl.sdl_index;
|
2020-02-20 06:00:53 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-08-17 07:00:22 +00:00
|
|
|
int hio_skad_get_scope_id (const hio_skad_t* _skad)
|
2021-08-09 08:24:21 +00:00
|
|
|
{
|
|
|
|
const hio_skad_alt_t* skad = (const hio_skad_alt_t*)_skad;
|
|
|
|
|
|
|
|
#if defined(AF_INET6) && (HIO_SIZEOF_STRUCT_SOCKADDR_IN6 > 0)
|
|
|
|
if (skad->sa.sa_family == AF_INET6) return skad->in6.a.sin6_scope_id;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void hio_skad_set_scope_id (hio_skad_t* _skad, int scope_id)
|
|
|
|
{
|
|
|
|
hio_skad_alt_t* skad = (hio_skad_alt_t*)_skad;
|
|
|
|
|
|
|
|
#if defined(AF_INET6) && (HIO_SIZEOF_STRUCT_SOCKADDR_IN6 > 0)
|
|
|
|
if (skad->sa.sa_family == AF_INET6) skad->in6.a.sin6_scope_id = scope_id;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2021-08-17 07:00:22 +00:00
|
|
|
hio_uint16_t hio_skad_get_chan (const hio_skad_t* _skad)
|
2021-08-09 08:24:21 +00:00
|
|
|
{
|
|
|
|
const hio_skad_alt_t* skad = (const hio_skad_alt_t*)_skad;
|
|
|
|
|
|
|
|
switch (skad->sa.sa_family)
|
|
|
|
{
|
|
|
|
#if defined(AF_INET) && (HIO_SIZEOF_STRUCT_SOCKADDR_IN > 0)
|
2021-08-17 07:00:22 +00:00
|
|
|
case AF_INET: return skad->in4.x.chan;
|
2021-08-09 08:24:21 +00:00
|
|
|
#endif
|
|
|
|
#if defined(AF_INET6) && (HIO_SIZEOF_STRUCT_SOCKADDR_IN6 > 0)
|
2021-08-17 07:00:22 +00:00
|
|
|
case AF_INET6: return skad->in6.x.chan;
|
2021-08-09 08:24:21 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void hio_skad_set_chan (hio_skad_t* _skad, hio_uint16_t chan)
|
|
|
|
{
|
|
|
|
hio_skad_alt_t* skad = (hio_skad_alt_t*)_skad;
|
|
|
|
|
|
|
|
switch (skad->sa.sa_family)
|
|
|
|
{
|
|
|
|
#if defined(AF_INET) && (HIO_SIZEOF_STRUCT_SOCKADDR_IN > 0)
|
2021-08-17 07:00:22 +00:00
|
|
|
case AF_INET: skad->in4.x.chan = chan; break;
|
2021-08-09 08:24:21 +00:00
|
|
|
#endif
|
|
|
|
#if defined(AF_INET6) && (HIO_SIZEOF_STRUCT_SOCKADDR_IN6 > 0)
|
2021-08-17 07:00:22 +00:00
|
|
|
case AF_INET6: skad->in6.x.chan = chan; break;
|
2021-08-09 08:24:21 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
2020-02-20 06:00:53 +00:00
|
|
|
|
2021-08-17 07:00:22 +00:00
|
|
|
hio_oow_t hio_skad_get_ipad_bytes (hio_skad_t* _skad, void* buf, hio_oow_t len)
|
|
|
|
{
|
|
|
|
hio_skad_alt_t* skad = (hio_skad_alt_t*)_skad;
|
|
|
|
hio_oow_t outlen = 0;
|
|
|
|
|
|
|
|
switch (skad->sa.sa_family)
|
|
|
|
{
|
|
|
|
#if defined(AF_INET) && (HIO_SIZEOF_STRUCT_SOCKADDR_IN > 0)
|
|
|
|
case AF_INET:
|
|
|
|
outlen = len < HIO_SIZEOF(skad->in4.a.sin_addr)? len: HIO_SIZEOF(skad->in4.a.sin_addr);
|
|
|
|
HIO_MEMCPY (buf, &skad->in4.a.sin_addr, outlen);
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#if defined(AF_INET6) && (HIO_SIZEOF_STRUCT_SOCKADDR_IN6 > 0)
|
|
|
|
case AF_INET6:
|
|
|
|
outlen = len < HIO_SIZEOF(skad->in6.a.sin6_addr)? len: HIO_SIZEOF(skad->in6.a.sin6_addr);
|
|
|
|
HIO_MEMCPY (buf, &skad->in6.a.sin6_addr, outlen);
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
return outlen;
|
|
|
|
}
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
void hio_skad_init_for_ip4 (hio_skad_t* skad, hio_uint16_t port, hio_ip4ad_t* ip4ad)
|
2020-02-20 06:00:53 +00:00
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
#if (HIO_SIZEOF_STRUCT_SOCKADDR_IN > 0)
|
2020-02-20 06:00:53 +00:00
|
|
|
struct sockaddr_in* sin = (struct sockaddr_in*)skad;
|
2021-07-22 07:30:20 +00:00
|
|
|
HIO_MEMSET (sin, 0, HIO_SIZEOF(*sin));
|
2020-02-20 06:00:53 +00:00
|
|
|
sin->sin_family = AF_INET;
|
2021-07-22 07:30:20 +00:00
|
|
|
sin->sin_port = hio_hton16(port);
|
|
|
|
if (ip4ad) HIO_MEMCPY (&sin->sin_addr, ip4ad->v, HIO_IP4AD_LEN);
|
2020-02-21 09:42:10 +00:00
|
|
|
#endif
|
2020-02-20 06:00:53 +00:00
|
|
|
}
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
void hio_skad_init_for_ip6 (hio_skad_t* skad, hio_uint16_t port, hio_ip6ad_t* ip6ad, int scope_id)
|
2020-02-20 06:00:53 +00:00
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
#if (HIO_SIZEOF_STRUCT_SOCKADDR_IN6 > 0)
|
2020-02-20 06:00:53 +00:00
|
|
|
struct sockaddr_in6* sin = (struct sockaddr_in6*)skad;
|
2021-07-22 07:30:20 +00:00
|
|
|
HIO_MEMSET (sin, 0, HIO_SIZEOF(*sin));
|
2020-04-28 02:44:13 +00:00
|
|
|
sin->sin6_family = AF_INET6;
|
2021-07-22 07:30:20 +00:00
|
|
|
sin->sin6_port = hio_hton16(port);
|
2020-02-20 06:00:53 +00:00
|
|
|
sin->sin6_scope_id = scope_id;
|
2021-07-22 07:30:20 +00:00
|
|
|
if (ip6ad) HIO_MEMCPY (&sin->sin6_addr, ip6ad->v, HIO_IP6AD_LEN);
|
2020-02-21 09:42:10 +00:00
|
|
|
#endif
|
2020-02-20 06:00:53 +00:00
|
|
|
}
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
void hio_skad_init_for_ip_with_bytes (hio_skad_t* skad, hio_uint16_t port, const hio_uint8_t* bytes, hio_oow_t len)
|
2020-04-28 02:44:13 +00:00
|
|
|
{
|
|
|
|
switch (len)
|
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
#if (HIO_SIZEOF_STRUCT_SOCKADDR_IN > 0)
|
|
|
|
case HIO_IP4AD_LEN:
|
2020-04-28 02:44:13 +00:00
|
|
|
{
|
|
|
|
struct sockaddr_in* sin = (struct sockaddr_in*)skad;
|
2021-07-22 07:30:20 +00:00
|
|
|
HIO_MEMSET (sin, 0, HIO_SIZEOF(*sin));
|
2020-04-28 02:44:13 +00:00
|
|
|
sin->sin_family = AF_INET;
|
2021-07-22 07:30:20 +00:00
|
|
|
sin->sin_port = hio_hton16(port);
|
|
|
|
HIO_MEMCPY (&sin->sin_addr, bytes, len);
|
2020-04-28 02:44:13 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
#endif
|
2021-07-22 07:30:20 +00:00
|
|
|
#if (HIO_SIZEOF_STRUCT_SOCKADDR_IN6 > 0)
|
|
|
|
case HIO_IP6AD_LEN:
|
2020-04-28 02:44:13 +00:00
|
|
|
{
|
|
|
|
struct sockaddr_in6* sin = (struct sockaddr_in6*)skad;
|
2021-07-22 07:30:20 +00:00
|
|
|
HIO_MEMSET (sin, 0, HIO_SIZEOF(*sin));
|
2020-04-28 02:44:13 +00:00
|
|
|
sin->sin6_family = AF_INET6;
|
2021-07-22 07:30:20 +00:00
|
|
|
sin->sin6_port = hio_hton16(port);
|
|
|
|
HIO_MEMCPY (&sin->sin6_addr, bytes, len);
|
2020-04-28 02:44:13 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
void hio_skad_init_for_eth (hio_skad_t* skad, int ifindex, hio_ethad_t* ethad)
|
2020-02-20 06:00:53 +00:00
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
#if defined(AF_PACKET) && (HIO_SIZEOF_STRUCT_SOCKADDR_LL > 0)
|
2020-02-20 06:00:53 +00:00
|
|
|
struct sockaddr_ll* sll = (struct sockaddr_ll*)skad;
|
2021-07-22 07:30:20 +00:00
|
|
|
HIO_MEMSET (sll, 0, HIO_SIZEOF(*sll));
|
2020-02-20 06:00:53 +00:00
|
|
|
sll->sll_family = AF_PACKET;
|
|
|
|
sll->sll_ifindex = ifindex;
|
2021-07-22 03:23:07 +00:00
|
|
|
if (ethad)
|
2020-02-20 06:00:53 +00:00
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
sll->sll_halen = HIO_ETHAD_LEN;
|
|
|
|
HIO_MEMCPY (sll->sll_addr, ethad, HIO_ETHAD_LEN);
|
2020-02-20 06:00:53 +00:00
|
|
|
}
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
#elif defined(AF_LINK) && (HIO_SIZEOF_STRUCT_SOCKADDR_DL > 0)
|
2020-02-20 06:00:53 +00:00
|
|
|
struct sockaddr_dl* sll = (struct sockaddr_dl*)skad;
|
2021-07-22 07:30:20 +00:00
|
|
|
HIO_MEMSET (sll, 0, HIO_SIZEOF(*sll));
|
2020-02-20 06:00:53 +00:00
|
|
|
sll->sdl_family = AF_LINK;
|
|
|
|
sll->sdl_index = ifindex;
|
2021-07-22 03:23:07 +00:00
|
|
|
if (ethad)
|
2020-02-20 06:00:53 +00:00
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
sll->sdl_alen = HIO_ETHAD_LEN;
|
|
|
|
HIO_MEMCPY (sll->sdl_data, ethad, HIO_ETHAD_LEN);
|
2020-02-20 06:00:53 +00:00
|
|
|
}
|
|
|
|
#else
|
|
|
|
# error UNSUPPORTED DATALINK SOCKET ADDRESS
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2021-08-06 03:23:48 +00:00
|
|
|
void hio_skad_init_for_qx (hio_skad_t* _skad)
|
|
|
|
{
|
|
|
|
hio_skad_alt_t* skad = (hio_skad_alt_t*)_skad;
|
|
|
|
HIO_MEMSET (skad, 0, HIO_SIZEOF(*_skad));
|
|
|
|
skad->sa.sa_family = HIO_AF_QX;
|
|
|
|
}
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
void hio_clear_skad (hio_skad_t* _skad)
|
2020-02-16 13:59:41 +00:00
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_skad_alt_t* skad = (hio_skad_alt_t*)_skad;
|
|
|
|
/*HIO_STATIC_ASSERT (HIO_SIZEOF(*_skad) >= HIO_SIZEOF(*skad));*/
|
|
|
|
/* use HIO_SIZEOF(*_skad) instead of HIO_SIZEOF(*skad) in case they are different */
|
|
|
|
HIO_MEMSET (skad, 0, HIO_SIZEOF(*_skad));
|
|
|
|
skad->sa.sa_family = HIO_AF_UNSPEC;
|
2020-02-16 13:59:41 +00:00
|
|
|
}
|
2020-02-20 06:00:53 +00:00
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
int hio_equal_skads (const hio_skad_t* addr1, const hio_skad_t* addr2, int strict)
|
2020-02-20 06:00:53 +00:00
|
|
|
{
|
2020-02-20 10:07:12 +00:00
|
|
|
int f1;
|
|
|
|
|
2021-08-17 07:00:22 +00:00
|
|
|
if ((f1 = hio_skad_get_family(addr1)) != hio_skad_get_family(addr2) ||
|
|
|
|
hio_skad_get_size(addr1) != hio_skad_get_size(addr2)) return 0;
|
2020-02-20 10:07:12 +00:00
|
|
|
|
|
|
|
switch (f1)
|
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
#if defined(AF_INET) && (HIO_SIZEOF_STRUCT_SOCKADDR_IN > 0)
|
2020-02-20 10:07:12 +00:00
|
|
|
case AF_INET:
|
|
|
|
return ((struct sockaddr_in*)addr1)->sin_addr.s_addr == ((struct sockaddr_in*)addr2)->sin_addr.s_addr &&
|
|
|
|
((struct sockaddr_in*)addr1)->sin_port == ((struct sockaddr_in*)addr2)->sin_port;
|
2020-02-21 09:42:10 +00:00
|
|
|
#endif
|
2020-02-20 10:07:12 +00:00
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
#if defined(AF_INET6) && (HIO_SIZEOF_STRUCT_SOCKADDR_IN6 > 0)
|
2020-02-20 10:07:12 +00:00
|
|
|
case AF_INET6:
|
|
|
|
|
|
|
|
if (strict)
|
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
return HIO_MEMCMP(&((struct sockaddr_in6*)addr1)->sin6_addr, &((struct sockaddr_in6*)addr2)->sin6_addr, HIO_SIZEOF(((struct sockaddr_in6*)addr2)->sin6_addr)) == 0 &&
|
2020-02-20 10:07:12 +00:00
|
|
|
((struct sockaddr_in6*)addr1)->sin6_port == ((struct sockaddr_in6*)addr2)->sin6_port &&
|
|
|
|
((struct sockaddr_in6*)addr1)->sin6_scope_id == ((struct sockaddr_in6*)addr2)->sin6_scope_id;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-08-31 23:01:32 +00:00
|
|
|
/* don't care about scope id */
|
2021-07-22 07:30:20 +00:00
|
|
|
return HIO_MEMCMP(&((struct sockaddr_in6*)addr1)->sin6_addr, &((struct sockaddr_in6*)addr2)->sin6_addr, HIO_SIZEOF(((struct sockaddr_in6*)addr2)->sin6_addr)) == 0 &&
|
2020-02-20 10:07:12 +00:00
|
|
|
((struct sockaddr_in6*)addr1)->sin6_port == ((struct sockaddr_in6*)addr2)->sin6_port;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
#if defined(AF_UNIX) && (HIO_SIZEOF_STRUCT_SOCKADDR_UN > 0)
|
2020-02-20 10:07:12 +00:00
|
|
|
case AF_UNIX:
|
2021-07-22 07:30:20 +00:00
|
|
|
return hio_comp_bcstr(((struct sockaddr_un*)addr1)->sun_path, ((struct sockaddr_un*)addr2)->sun_path, 0) == 0;
|
2020-02-20 10:07:12 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
default:
|
2021-08-17 07:00:22 +00:00
|
|
|
return HIO_MEMCMP(addr1, addr2, hio_skad_get_size(addr1)) == 0;
|
2020-02-20 10:07:12 +00:00
|
|
|
}
|
2020-02-20 06:00:53 +00:00
|
|
|
}
|
2020-04-29 02:57:27 +00:00
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_oow_t hio_ipad_bytes_to_ucstr (const hio_uint8_t* iptr, hio_oow_t ilen, hio_uch_t* buf, hio_oow_t blen)
|
2020-04-29 02:57:27 +00:00
|
|
|
{
|
|
|
|
switch (ilen)
|
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
case HIO_IP4AD_LEN:
|
2020-04-29 02:57:27 +00:00
|
|
|
{
|
|
|
|
struct in_addr ip4ad;
|
2021-07-22 07:30:20 +00:00
|
|
|
HIO_MEMCPY (&ip4ad.s_addr, iptr, ilen);
|
2020-04-29 02:57:27 +00:00
|
|
|
return ip4ad_to_ucstr(&ip4ad, buf, blen);
|
|
|
|
}
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
case HIO_IP6AD_LEN:
|
2020-04-29 02:57:27 +00:00
|
|
|
{
|
|
|
|
struct in6_addr ip6ad;
|
2021-07-22 07:30:20 +00:00
|
|
|
HIO_MEMCPY (&ip6ad.s6_addr, iptr, ilen);
|
2020-04-29 02:57:27 +00:00
|
|
|
return ip6ad_to_ucstr(&ip6ad, buf, blen);
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
if (blen > 0) buf[blen] = '\0';
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_oow_t hio_ipad_bytes_to_bcstr (const hio_uint8_t* iptr, hio_oow_t ilen, hio_bch_t* buf, hio_oow_t blen)
|
2020-04-29 02:57:27 +00:00
|
|
|
{
|
|
|
|
switch (ilen)
|
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
case HIO_IP4AD_LEN:
|
2020-04-29 02:57:27 +00:00
|
|
|
{
|
|
|
|
struct in_addr ip4ad;
|
2021-07-22 07:30:20 +00:00
|
|
|
HIO_MEMCPY (&ip4ad.s_addr, iptr, ilen);
|
2020-04-29 02:57:27 +00:00
|
|
|
return ip4ad_to_bcstr(&ip4ad, buf, blen);
|
|
|
|
}
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
case HIO_IP6AD_LEN:
|
2020-04-29 02:57:27 +00:00
|
|
|
{
|
|
|
|
struct in6_addr ip6ad;
|
2021-07-22 07:30:20 +00:00
|
|
|
HIO_MEMCPY (&ip6ad.s6_addr, iptr, ilen);
|
2020-04-29 02:57:27 +00:00
|
|
|
return ip6ad_to_bcstr(&ip6ad, buf, blen);
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
if (blen > 0) buf[blen] = '\0';
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
2020-05-27 14:53:48 +00:00
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
int hio_uchars_to_ipad_bytes (const hio_uch_t* str, hio_oow_t slen, hio_uint8_t* buf, hio_oow_t blen)
|
2020-05-27 14:53:48 +00:00
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
if (blen >= HIO_IP6AD_LEN)
|
2020-05-27 14:53:48 +00:00
|
|
|
{
|
|
|
|
struct in6_addr i6;
|
|
|
|
if (uchars_to_ipv6(str, slen, &i6) <= -1) goto ipv4;
|
2021-07-22 07:30:20 +00:00
|
|
|
HIO_MEMCPY (buf, i6.s6_addr, 16);
|
|
|
|
return HIO_IP6AD_LEN;
|
2020-05-27 14:53:48 +00:00
|
|
|
}
|
2021-07-22 07:30:20 +00:00
|
|
|
else if (blen >= HIO_IP4AD_LEN)
|
2020-05-27 14:53:48 +00:00
|
|
|
{
|
|
|
|
struct in_addr i4;
|
|
|
|
ipv4:
|
|
|
|
if (uchars_to_ipv4(str, slen, &i4) <= -1) return -1;
|
2021-07-22 07:30:20 +00:00
|
|
|
HIO_MEMCPY (buf, &i4.s_addr, 4);
|
|
|
|
return HIO_IP4AD_LEN;
|
2020-05-27 14:53:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
int hio_bchars_to_ipad_bytes (const hio_bch_t* str, hio_oow_t slen, hio_uint8_t* buf, hio_oow_t blen)
|
2020-05-27 14:53:48 +00:00
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
if (blen >= HIO_IP6AD_LEN)
|
2020-05-27 14:53:48 +00:00
|
|
|
{
|
|
|
|
struct in6_addr i6;
|
|
|
|
if (bchars_to_ipv6(str, slen, &i6) <= -1) goto ipv4;
|
2021-07-22 07:30:20 +00:00
|
|
|
HIO_MEMCPY (buf, i6.s6_addr, 16);
|
|
|
|
return HIO_IP6AD_LEN;
|
2020-05-27 14:53:48 +00:00
|
|
|
}
|
2021-07-22 07:30:20 +00:00
|
|
|
else if (blen >= HIO_IP4AD_LEN)
|
2020-05-27 14:53:48 +00:00
|
|
|
{
|
|
|
|
struct in_addr i4;
|
|
|
|
ipv4:
|
|
|
|
if (bchars_to_ipv4(str, slen, &i4) <= -1) return -1;
|
2021-07-22 07:30:20 +00:00
|
|
|
HIO_MEMCPY (buf, &i4.s_addr, 4);
|
|
|
|
return HIO_IP4AD_LEN;
|
2020-05-27 14:53:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
2021-07-24 04:06:00 +00:00
|
|
|
|
|
|
|
int hio_ipad_bytes_is_v4_mapped (const hio_uint8_t* iptr, hio_oow_t ilen)
|
|
|
|
{
|
|
|
|
if (ilen != HIO_IP6AD_LEN) return 0;
|
|
|
|
|
|
|
|
return iptr[0] == 0x00 && iptr[1] == 0x00 &&
|
|
|
|
iptr[2] == 0x00 && iptr[3] == 0x00 &&
|
|
|
|
iptr[4] == 0x00 && iptr[5] == 0x00 &&
|
|
|
|
iptr[6] == 0x00 && iptr[7] == 0x00 &&
|
|
|
|
iptr[8] == 0x00 && iptr[9] == 0x00 &&
|
|
|
|
iptr[10] == 0xFF && iptr[11] == 0xFF;
|
|
|
|
}
|
|
|
|
|
|
|
|
int hio_ipad_bytes_is_loop_back (const hio_uint8_t* iptr, hio_oow_t ilen)
|
|
|
|
{
|
|
|
|
switch (ilen)
|
|
|
|
{
|
|
|
|
case HIO_IP4AD_LEN:
|
|
|
|
{
|
|
|
|
// 127.0.0.0/8
|
|
|
|
return iptr[0] == 0x7F;
|
|
|
|
}
|
|
|
|
|
|
|
|
case HIO_IP6AD_LEN:
|
|
|
|
{
|
|
|
|
hio_uint32_t* x = (hio_uint32_t*)iptr;
|
|
|
|
return (x[0] == 0 && x[1] == 0 && x[2] == 0 && x[3] == HIO_CONST_HTON32(1)) || /* TODO: is this alignment safe? */
|
|
|
|
(hio_ipad_bytes_is_v4_mapped(iptr, ilen) && (x[3] & HIO_CONST_HTON32(0xFF000000u)) == HIO_CONST_HTON32(0x7F000000u));
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int hio_ipad_bytes_is_link_local (const hio_uint8_t* iptr, hio_oow_t ilen)
|
|
|
|
{
|
|
|
|
switch (ilen)
|
|
|
|
{
|
|
|
|
case HIO_IP4AD_LEN:
|
|
|
|
{
|
|
|
|
// 169.254.0.0/16
|
|
|
|
return iptr[0] == 0xA9 && iptr[1] == 0xFE;
|
|
|
|
}
|
|
|
|
|
|
|
|
case HIO_IP6AD_LEN:
|
|
|
|
{
|
|
|
|
/* FE80::/10 */
|
|
|
|
return iptr[0] == 0xFE && (iptr[1] & 0xC0) == 0x80;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|