#include <sys_defs.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <netdb.h>
#include <msg.h>
#include <mymalloc.h>
#include <myaddrinfo.h>
#include <sock_addr.h>
#include <inet_addr_list.h>
void inet_addr_list_init(INET_ADDR_LIST *list)
{
int init_size;
list->used = 0;
list->size = 0;
init_size = 2;
list->addrs = (struct sockaddr_storage *)
mymalloc(sizeof(*list->addrs) * init_size);
list->size = init_size;
}
void inet_addr_list_append(INET_ADDR_LIST *list,
struct sockaddr * addr)
{
const char *myname = "inet_addr_list_append";
MAI_HOSTADDR_STR hostaddr;
int new_size;
if (msg_verbose > 1) {
SOCKADDR_TO_HOSTADDR(addr, SOCK_ADDR_LEN(addr),
&hostaddr, (MAI_SERVPORT_STR *) 0, 0);
msg_info("%s: %s", myname, hostaddr.buf);
}
if (list->used >= list->size) {
new_size = list->size * 2;
list->addrs = (struct sockaddr_storage *)
myrealloc((char *) list->addrs, sizeof(*list->addrs) * new_size);
list->size = new_size;
}
memcpy(list->addrs + list->used++, addr, SOCK_ADDR_LEN(addr));
}
static int inet_addr_list_comp(const void *a, const void *b)
{
return (sock_addr_cmp_addr(SOCK_ADDR_PTR(a), SOCK_ADDR_PTR(b)));
}
void inet_addr_list_uniq(INET_ADDR_LIST *list)
{
int n;
int m;
qsort((void *) list->addrs, list->used,
sizeof(list->addrs[0]), inet_addr_list_comp);
for (m = n = 0; m < list->used; m++, n++) {
if (m != n)
list->addrs[n] = list->addrs[m];
while (m + 1 < list->used
&& inet_addr_list_comp((void *) &(list->addrs[n]),
(void *) &(list->addrs[m + 1])) == 0)
m += 1;
}
list->used = n;
}
#ifdef __APPLE_OS_X_SERVER__
void inet_addr_list_clean(INET_ADDR_LIST *list)
{
int n = 0;
while (n < list->used) {
if (list->addrs[n].ss_family == AF_INET6 &&
SOCK_ADDR_IN6_PTR(&list->addrs[n])->sin6_scope_id != 0) {
memmove(&list->addrs[n], &list->addrs[n + 1],
sizeof list->addrs[0] * (list->used - n - 1));
--list->used;
} else
++n;
}
}
#endif
void inet_addr_list_free(INET_ADDR_LIST *list)
{
myfree((char *) list->addrs);
}
#ifdef TEST
#include <inet_proto.h>
#include <inet_addr_host.h>
static void inet_addr_list_print(INET_ADDR_LIST *list)
{
MAI_HOSTADDR_STR hostaddr;
struct sockaddr_storage *sa;
for (sa = list->addrs; sa < list->addrs + list->used; sa++) {
SOCKADDR_TO_HOSTADDR(SOCK_ADDR_PTR(sa), SOCK_ADDR_LEN(sa),
&hostaddr, (MAI_SERVPORT_STR *) 0, 0);
msg_info("%s", hostaddr.buf);
}
}
int main(int argc, char **argv)
{
INET_ADDR_LIST list;
INET_PROTO_INFO *proto_info;
proto_info = inet_proto_init(argv[0], INET_PROTO_NAME_ALL);
inet_addr_list_init(&list);
while (--argc && *++argv)
if (inet_addr_host(&list, *argv) == 0)
msg_fatal("host not found: %s", *argv);
msg_info("list before sort/uniq");
inet_addr_list_print(&list);
inet_addr_list_uniq(&list);
msg_info("list after sort/uniq");
inet_addr_list_print(&list);
inet_addr_list_free(&list);
return (0);
}
#endif