#include <sys_defs.h>
#include <string.h>
#include <msg.h>
#include <mymalloc.h>
#include <inet_addr_list.h>
#include <inet_addr_local.h>
#include <inet_addr_host.h>
#include <stringops.h>
#include <myaddrinfo.h>
#include <sock_addr.h>
#include <inet_proto.h>
#include <mail_params.h>
#include <own_inet_addr.h>
static INET_ADDR_LIST saved_addr_list;
static INET_ADDR_LIST saved_mask_list;
static INET_ADDR_LIST saved_proxy_list;
static void own_inet_addr_init(INET_ADDR_LIST *addr_list,
INET_ADDR_LIST *mask_list)
{
INET_ADDR_LIST local_addrs;
INET_ADDR_LIST local_masks;
char *hosts;
char *host;
const char *sep = " \t,";
char *bufp;
int nvirtual;
int nlocal;
MAI_HOSTADDR_STR hostaddr;
struct sockaddr_storage *sa;
struct sockaddr_storage *ma;
inet_addr_list_init(addr_list);
inet_addr_list_init(mask_list);
if (inet_proto_info()->ai_family_list[0] == 0) {
if (msg_verbose)
msg_info("skipping %s setting - "
"all network protocols are disabled",
VAR_INET_INTERFACES);
return;
}
if (strcmp(var_inet_interfaces, INET_INTERFACES_ALL) == 0) {
if (inet_addr_local(addr_list, mask_list,
inet_proto_info()->ai_family_list) == 0)
msg_fatal("could not find any active network interfaces");
}
else if (strcmp(var_inet_interfaces, INET_INTERFACES_LOCAL) == 0) {
inet_addr_list_init(&local_addrs);
inet_addr_list_init(&local_masks);
if (inet_addr_local(&local_addrs, &local_masks,
inet_proto_info()->ai_family_list) == 0)
msg_fatal("could not find any active network interfaces");
for (sa = local_addrs.addrs, ma = local_masks.addrs;
sa < local_addrs.addrs + local_addrs.used; sa++, ma++) {
if (sock_addr_in_loopback(SOCK_ADDR_PTR(sa))) {
inet_addr_list_append(addr_list, SOCK_ADDR_PTR(sa));
inet_addr_list_append(mask_list, SOCK_ADDR_PTR(ma));
}
}
inet_addr_list_free(&local_addrs);
inet_addr_list_free(&local_masks);
}
else {
bufp = hosts = mystrdup(var_inet_interfaces);
while ((host = mystrtok(&bufp, sep)) != 0)
if (inet_addr_host(addr_list, host) == 0)
msg_fatal("config variable %s: host not found: %s",
VAR_INET_INTERFACES, host);
myfree(hosts);
inet_addr_list_uniq(addr_list);
inet_addr_list_init(&local_addrs);
inet_addr_list_init(&local_masks);
if (inet_addr_local(&local_addrs, &local_masks,
inet_proto_info()->ai_family_list) == 0)
msg_fatal("could not find any active network interfaces");
for (nvirtual = 0; nvirtual < addr_list->used; nvirtual++) {
for (nlocal = 0; ; nlocal++) {
if (nlocal >= local_addrs.used) {
SOCKADDR_TO_HOSTADDR(
SOCK_ADDR_PTR(addr_list->addrs + nvirtual),
SOCK_ADDR_LEN(addr_list->addrs + nvirtual),
&hostaddr, (MAI_SERVPORT_STR *) 0, 0);
msg_fatal("parameter %s: no local interface found for %s",
VAR_INET_INTERFACES, hostaddr.buf);
}
if (SOCK_ADDR_EQ_ADDR(addr_list->addrs + nvirtual,
local_addrs.addrs + nlocal)) {
inet_addr_list_append(mask_list,
SOCK_ADDR_PTR(local_masks.addrs + nlocal));
break;
}
}
}
inet_addr_list_free(&local_addrs);
inet_addr_list_free(&local_masks);
}
}
int own_inet_addr(struct sockaddr * addr)
{
int i;
if (saved_addr_list.used == 0)
own_inet_addr_init(&saved_addr_list, &saved_mask_list);
for (i = 0; i < saved_addr_list.used; i++)
if (SOCK_ADDR_EQ_ADDR(addr, saved_addr_list.addrs + i))
return (1);
return (0);
}
INET_ADDR_LIST *own_inet_addr_list(void)
{
if (saved_addr_list.used == 0)
own_inet_addr_init(&saved_addr_list, &saved_mask_list);
return (&saved_addr_list);
}
INET_ADDR_LIST *own_inet_mask_list(void)
{
if (saved_addr_list.used == 0)
own_inet_addr_init(&saved_addr_list, &saved_mask_list);
return (&saved_mask_list);
}
static void proxy_inet_addr_init(INET_ADDR_LIST *addr_list)
{
char *hosts;
char *host;
const char *sep = " \t,";
char *bufp;
inet_addr_list_init(addr_list);
bufp = hosts = mystrdup(var_proxy_interfaces);
while ((host = mystrtok(&bufp, sep)) != 0)
if (inet_addr_host(addr_list, host) == 0)
msg_fatal("config variable %s: host not found: %s",
VAR_PROXY_INTERFACES, host);
myfree(hosts);
inet_addr_list_uniq(addr_list);
}
int proxy_inet_addr(struct sockaddr * addr)
{
int i;
if (*var_proxy_interfaces == 0)
return (0);
if (saved_proxy_list.used == 0)
proxy_inet_addr_init(&saved_proxy_list);
for (i = 0; i < saved_proxy_list.used; i++)
if (SOCK_ADDR_EQ_ADDR(addr, saved_proxy_list.addrs + i))
return (1);
return (0);
}
INET_ADDR_LIST *proxy_inet_addr_list(void)
{
if (*var_proxy_interfaces != 0 && saved_proxy_list.used == 0)
proxy_inet_addr_init(&saved_proxy_list);
return (&saved_proxy_list);
}
#ifdef TEST
#include <inet_proto.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);
}
}
char *var_inet_interfaces;
int main(int argc, char **argv)
{
INET_PROTO_INFO *proto_info;
INET_ADDR_LIST *list;
if (argc != 3)
msg_fatal("usage: %s protocols interface_list (e.g. \"all all\")",
argv[0]);
msg_verbose = 10;
proto_info = inet_proto_init(argv[0], argv[1]);
var_inet_interfaces = argv[2];
list = own_inet_addr_list();
inet_addr_list_print(list);
return (0);
}
#endif