tpws: more bind-linklocal modes

This commit is contained in:
bol-van
2021-03-08 22:33:21 +03:00
parent 4016534dfe
commit be0b76c02b
13 changed files with 69 additions and 31 deletions

View File

@@ -6,13 +6,14 @@
#include "strpool.h"
enum splithttpreq { split_none = 0, split_method, split_host };
enum bindll { unwanted=0, no, prefer, force };
#define MAX_BINDS 32
struct bind_s
{
char bindaddr[64],bindiface[IF_NAMESIZE];
bool bind_if6;
bool bindll,bindll_force;
enum bindll bindll;
int bind_wait_ifup,bind_wait_ip,bind_wait_ip_ll;
};

View File

@@ -113,10 +113,11 @@ static void exithelp()
" --bind-addr=<v4_addr>|<v6_addr>; for v6 link locals append %%interface_name\n"
" --bind-iface4=<interface_name>\t; bind to the first ipv4 addr of interface\n"
" --bind-iface6=<interface_name>\t; bind to the first ipv6 addr of interface\n"
" --bind-linklocal=prefer|force\t; prefer or force ipv6 link local\n"
" --bind-linklocal=no|unwanted|prefer|force\n"
"\t\t\t\t; prohibit, accept, prefer or force ipv6 link local bind\n"
" --bind-wait-ifup=<sec>\t\t; wait for interface to appear and up\n"
" --bind-wait-ip=<sec>\t\t; after ifup wait for ip address to appear up to N seconds\n"
" --bind-wait-ip-linklocal=<sec>\t; accept only link locals first N seconds then any\n"
" --bind-wait-ip-linklocal=<sec>\t; (prefer) accept only LL first N seconds then any (unwanted) accept only globals first N seconds then LL\n"
" --bind-wait-only\t\t; wait for bind conditions satisfaction then exit. return code 0 if success.\n"
" * multiple binds are supported. each bind-addr, bind-iface* start new bind\n"
" --port=<port>\t\t\t; only one port number for all binds is supported\n"
@@ -290,9 +291,15 @@ void parse_params(int argc, char *argv[])
case 5: /* bind-linklocal */
checkbind_clean();
params.binds[params.binds_last].bindll = true;
if (!strcmp(optarg, "force"))
params.binds[params.binds_last].bindll_force=true;
else if (strcmp(optarg, "prefer"))
if (!strcmp(optarg, "no"))
params.binds[params.binds_last].bindll=no;
else if (!strcmp(optarg, "prefer"))
params.binds[params.binds_last].bindll=prefer;
else if (!strcmp(optarg, "force"))
params.binds[params.binds_last].bindll=force;
else if (!strcmp(optarg, "unwanted"))
params.binds[params.binds_last].bindll=unwanted;
else
{
fprintf(stderr, "invalid parameter in bind-linklocal : %s\n",optarg);
exit_clean(1);
@@ -497,10 +504,11 @@ void parse_params(int argc, char *argv[])
}
static bool find_listen_addr(struct sockaddr_storage *salisten, const char *bindiface, bool bind_if6, bool bindll, int *if_index)
static bool find_listen_addr(struct sockaddr_storage *salisten, const char *bindiface, bool bind_if6, enum bindll bindll, int *if_index)
{
struct ifaddrs *addrs,*a;
bool found=false;
bool bindll_want = bindll==prefer || bindll==force;
if (getifaddrs(&addrs)<0)
return false;
@@ -526,11 +534,13 @@ static bool find_listen_addr(struct sockaddr_storage *salisten, const char *bind
// ipv6 links locals are fe80::/10
else if (a->ifa_addr->sa_family==AF_INET6
&&
(!*bindiface && bindll ||
(!*bindiface && (bindll==prefer || bindll==force) ||
*bindiface && bind_if6 && !strcmp(a->ifa_name, bindiface))
&&
(bindll && is_linklocal((struct sockaddr_in6*)a->ifa_addr) ||
!bindll && (pass==2 || pass==0 && is_private6((struct sockaddr_in6*)a->ifa_addr) || pass==1 && !is_linklocal((struct sockaddr_in6*)a->ifa_addr)))
(bindll==force && is_linklocal((struct sockaddr_in6*)a->ifa_addr) ||
bindll==prefer && (pass==0 && is_linklocal((struct sockaddr_in6*)a->ifa_addr) || pass==1 && is_private6((struct sockaddr_in6*)a->ifa_addr) || pass==2) ||
bindll==no && (pass==0 && is_private6((struct sockaddr_in6*)a->ifa_addr) || pass==1 && !is_linklocal((struct sockaddr_in6*)a->ifa_addr)) ||
bindll==unwanted && (pass==0 && is_private6((struct sockaddr_in6*)a->ifa_addr) || pass==1 && !is_linklocal((struct sockaddr_in6*)a->ifa_addr) || pass==2))
)
{
salisten->ss_family = AF_INET6;
@@ -640,6 +650,7 @@ struct salisten_s
int ipv6_only;
int bind_wait_ip_left; // how much seconds left from bind_wait_ip
};
static const char *bindll_s[] = { "unwanted","no","prefer","force" };
int main(int argc, char *argv[])
{
int i, listen_fd[MAX_BINDS], yes = 1, retval = 0, if_index, exit_v=EXIT_FAILURE;
@@ -662,8 +673,8 @@ int main(int argc, char *argv[])
for(i=0;i<=params.binds_last;i++)
{
VPRINT("Prepare bind %d : addr=%s iface=%s v6=%u link_local=%u link_local_force=%u wait_ifup=%d wait_ip=%d wait_ip_ll=%d",i,
params.binds[i].bindaddr,params.binds[i].bindiface,params.binds[i].bind_if6,params.binds[i].bindll,params.binds[i].bindll_force,
VPRINT("Prepare bind %d : addr=%s iface=%s v6=%u link_local=%s wait_ifup=%d wait_ip=%d wait_ip_ll=%d",i,
params.binds[i].bindaddr,params.binds[i].bindiface,params.binds[i].bind_if6,bindll_s[params.binds[i].bindll],
params.binds[i].bind_wait_ifup,params.binds[i].bind_wait_ip,params.binds[i].bind_wait_ip_ll);
if_index=0;
if (*params.binds[i].bindiface)
@@ -716,27 +727,37 @@ int main(int argc, char *argv[])
if (*params.binds[i].bindiface || params.binds[i].bindll)
{
bool found;
enum bindll bindll_1;
int sec=0;
if (params.binds[i].bind_wait_ip > 0)
{
printf("waiting for ip on %s for up to %d second(s)...\n", *params.binds[i].bindiface ? params.binds[i].bindiface : "<any>", params.binds[i].bind_wait_ip);
if (params.binds[i].bindll && !params.binds[i].bindll_force && params.binds[i].bind_wait_ip_ll>0)
printf("during the first %d second(s) accepting only link locals...\n", params.binds[i].bind_wait_ip_ll);
if (params.binds[i].bind_wait_ip_ll>0)
{
if (params.binds[i].bindll==prefer)
printf("during the first %d second(s) accepting only link locals...\n", params.binds[i].bind_wait_ip_ll);
else if (params.binds[i].bindll==unwanted)
printf("during the first %d second(s) accepting only ipv6 globals...\n", params.binds[i].bind_wait_ip_ll);
}
}
for(;;)
{
found = find_listen_addr(&list[i].salisten,params.binds[i].bindiface,params.binds[i].bind_if6,params.binds[i].bindll,&if_index);
// allow, no, prefer, force
bindll_1 = (params.binds[i].bindll==prefer && sec<params.binds[i].bind_wait_ip_ll) ? force :
(params.binds[i].bindll==unwanted && sec<params.binds[i].bind_wait_ip_ll) ? no :
params.binds[i].bindll;
if (sec && sec==params.binds[i].bind_wait_ip_ll)
{
if (params.binds[i].bindll==prefer)
printf("link local address wait timeout. now accepting globals\n");
else if (params.binds[i].bindll==unwanted)
printf("global ipv6 address wait timeout. now accepting link locals\n");
}
found = find_listen_addr(&list[i].salisten,params.binds[i].bindiface,params.binds[i].bind_if6,bindll_1,&if_index);
if (found) break;
if (params.binds[i].bindll && !params.binds[i].bindll_force && sec>=params.binds[i].bind_wait_ip_ll)
if ((found = find_listen_addr(&list[i].salisten,params.binds[i].bindiface,params.binds[i].bind_if6,false,&if_index)))
{
printf("link local address wait timeout. using global address\n");
break;
}
if (sec>=params.binds[i].bind_wait_ip)
break;