/* polypath
* send/receive module for secnet
* for multi-route setups */
+/*
+ * This file is part of secnet.
+ * See README for full list of copyright holders.
+ *
+ * secnet is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version d of the License, or
+ * (at your option) any later version.
+ *
+ * secnet is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 3 along with secnet; if not, see
+ * https://www.gnu.org/licenses/gpl.html.
+ */
#include "secnet.h"
#include "util.h"
const char *const *ifname_pats;
const char *const *monitor_command;
bool_t permit_loopback;
- LIST_HEAD(,interf) interfs;
+ LIST_HEAD(interf_list, interf) interfs;
struct buffer_if lbuf;
int monitor_fd;
pid_t monitor_pid;
}
static bool_t ifname_search_pats(struct polypath *st, struct cloc loc,
- const char *ifname, bool_t *want_io,
+ const char *ifname, char *want_io,
const char *const *pats) {
/* Returns True iff we found a list entry, in which case *want_io
* is set to the sense of that entry. Otherwise *want_io is set
const char *const *pati;
for (pati=pats; *pati; pati++) {
const char *pat=*pati;
- if (*pat=='!') { *want_io=False; pat++; }
- else if (*pat=='+') { *want_io=True; pat++; }
- else if (*pat=='*' || isalnum((unsigned char)*pat)) { *want_io=True; }
+ if (*pat=='!' || *pat=='+') { *want_io=*pat; pat++; }
+ else if (*pat=='*' || isalnum((unsigned char)*pat)) { *want_io='+'; }
else cfgfatal(loc,"polypath","invalid interface name pattern `%s'",pat);
int match=fnmatch(pat,ifname,0);
if (match==0) return True;
return False;
}
-static bool_t ifname_wanted(struct polypath *st, struct cloc loc,
- const char *ifname) {
- bool_t want=False; /* pretend an empty cfg ends with !<doesn'tmatch> */
+static char ifname_wanted(struct polypath *st, struct cloc loc,
+ const char *ifname) {
+ char want='!'; /* pretend an empty cfg ends with !<doesn'tmatch> */
if (ifname_search_pats(st,loc,ifname,&want, st->ifname_pats))
return want;
- if (want) /* last pattern was positive, do not search default */
- return False;
+ if (want!='!') /* last pattern was positive, do not search default */
+ return '!';
if (!st->permit_loopback &&
ifname_search_pats(st,loc,ifname,&want, default_loopback_ifname_pats))
return want;
typedef void polypath_ppml_callback_type(struct polypath *st,
bad_fn_type *bad, void *badctx,
- bool_t add, const char *ifname, const char *ifaddr,
+ bool_t add, char want,
+ const char *ifname, const char *ifaddr,
const union iaddr *ia, int fd /* -1 if none yet */);
struct ppml_bad_ctx {
goto out; \
}while(0)
- if (!ifname_wanted(st,st->uc.cc.loc,ifname))
- DONT("unwanted interface name");
+ char want=ifname_wanted(st,st->uc.cc.loc,ifname);
+ if (want=='!') DONT("unwanted interface name");
switch (ia.sa.sa_family) {
case AF_INET6: {
#undef DONT
/* OK, process it */
- callback(st, bad,badctx, add,ifname,ifaddr,&ia,-1);
+ callback(st, bad,badctx, add,want, ifname,ifaddr,&ia,-1);
out:;
}
-static void dump_pria(struct polypath *st, const char *ifname)
+static void dump_pria(struct polypath *st, struct interf_list *interfs,
+ const char *ifname, char want)
{
#ifdef POLYPATH_DEBUG
struct interf *interf;
if (ifname)
- lg_perror(LG,M_DEBUG,0, "polypath record ifaddr `%s'",ifname);
- LIST_FOREACH(interf, &st->interfs, entry) {
+ lg_perror(LG,M_DEBUG,0, "polypath record ifaddr `%s' (%c)",
+ ifname, want);
+ LIST_FOREACH(interf, interfs, entry) {
lg_perror(LG,M_DEBUG,0, " polypath interface `%s', nsocks=%d",
interf->name, interf->socks.n_socks);
int i;
static void polypath_record_ifaddr(struct polypath *st,
bad_fn_type *bad, void *badctx,
- bool_t add, const char *ifname,
+ bool_t add, char want,
+ const char *ifname,
const char *ifaddr,
const union iaddr *ia, int fd)
{
struct udpcommon *uc=&st->uc;
struct interf *interf=0;
+ int max_interfs;
struct udpsock *us=0;
- dump_pria(st,ifname);
+ struct interf_list *interfs;
+ switch (want) {
+ case '+': interfs=&st->interfs; max_interfs=st->max_interfs;
+ default: fatal("polypath: got bad want (%#x, %s)", want, ifname);
+ }
+
+ dump_pria(st,interfs,ifname,want);
int n_ifs=0;
- LIST_FOREACH(interf,&st->interfs,entry) {
+ LIST_FOREACH(interf,interfs,entry) {
if (!strcmp(interf->name,ifname))
goto found_interf;
n_ifs++;
}
/* not found */
- if (n_ifs==st->max_interfs) BAD("too many interfaces");
+ if (n_ifs==max_interfs) BAD("too many interfaces");
interf=malloc(sizeof(*interf));
if (!interf) BADE("malloc for new interface",errno);
interf->name=0;
interf->socks.n_socks=0;
FILLZERO(interf->experienced_xmit_noaf);
- LIST_INSERT_HEAD(&st->interfs,interf,entry);
+ LIST_INSERT_HEAD(interfs,interf,entry);
interf->name=strdup(ifname);
udp_socks_register(&st->uc,&interf->socks,interf->name);
if (!interf->name) BADE("strdup interface name",errno);
free(interf);
}
- dump_pria(st,0);
+ dump_pria(st,interfs,0,0);
}
static void subproc_problem(struct polypath *st,
/* Actual udp packet sending work */
static bool_t polypath_sendmsg(void *commst, struct buffer_if *buf,
- const struct comm_addr *dest)
+ const struct comm_addr *dest,
+ struct comm_clientinfo *clientinfo)
{
struct polypath *st=commst;
struct interf *interf;
bool_t add;
char ifname[100];
union iaddr ia;
+ char want; /* `+', for now */
};
static void papp_bad(struct polypath *st, void *badctx,
fatal("polypath (privsep): got message data but bad AF %d",af);
const char *addr_str=iaddr_to_string(&mdata->ia);
polypath_record_ifaddr(st,papp_bad,(void*)addr_str,
- mdata->add,mdata->ifname,addr_str,
+ mdata->add,mdata->want,
+ mdata->ifname,addr_str,
&mdata->ia, st->privsep_incoming_fd);
st->privsep_incoming_fd=-1;
st->lbuf.size=0;
static void privsep_handle_ifaddr(struct polypath *st,
bad_fn_type *bad, void *badctx,
- bool_t add, const char *ifname,
+ bool_t add, char want,
+ const char *ifname,
const char *ifaddr,
const union iaddr *ia, int fd_dummy)
/* In child: handles discovered wanted interfaces, making sockets
size_t l=strlen(ifname);
if (l>=sizeof(mdata.ifname)) BAD("interface name too long");
strcpy(mdata.ifname,ifname);
+ mdata.want=want;
COPY_OBJ(mdata.ia,*ia);