version 1.1.1.1, 2012/02/21 23:32:47
|
version 1.1.1.2, 2013/07/22 08:44:29
|
Line 19
|
Line 19
|
#include "netgraph.h" |
#include "netgraph.h" |
#include "util.h" |
#include "util.h" |
|
|
|
#include <sys/types.h> |
#include <sys/sockio.h> |
#include <sys/sockio.h> |
#include <sys/sysctl.h> |
#include <sys/sysctl.h> |
|
#include <sys/param.h> |
#include <net/if.h> |
#include <net/if.h> |
#include <net/if_types.h> |
#include <net/if_types.h> |
#include <net/if_dl.h> |
#include <net/if_dl.h> |
Line 59
|
Line 61
|
#include <pcap.h> |
#include <pcap.h> |
#endif |
#endif |
|
|
|
#include <string.h> |
|
|
/* |
/* |
* DEFINITIONS |
* DEFINITIONS |
*/ |
*/ |
Line 94
|
Line 98
|
static void IfaceNgIpv6Shutdown(Bund b); |
static void IfaceNgIpv6Shutdown(Bund b); |
|
|
#ifdef USE_NG_NETFLOW |
#ifdef USE_NG_NETFLOW |
static int IfaceInitNetflow(Bund b, char *path, char *hook, char in, char out); | static int IfaceInitNetflow(Bund b, char *path, char *hook, char in, char out, int v6); |
static int IfaceSetupNetflow(Bund b, char in, char out); |
static int IfaceSetupNetflow(Bund b, char in, char out); |
static void IfaceShutdownNetflow(Bund b, char in, char out); |
static void IfaceShutdownNetflow(Bund b, char in, char out); |
#endif |
#endif |
Line 142
|
Line 146
|
static int IfaceSetName(Bund b, const char * ifname); |
static int IfaceSetName(Bund b, const char * ifname); |
#ifdef SIOCSIFDESCR |
#ifdef SIOCSIFDESCR |
static int IfaceSetDescr(Bund b, const char * ifdescr); |
static int IfaceSetDescr(Bund b, const char * ifdescr); |
|
static void IfaceFreeDescr(IfaceState iface); |
#endif |
#endif |
#ifdef SIOCAIFGROUP |
#ifdef SIOCAIFGROUP |
static int IfaceAddGroup(Bund b, const char * ifgroup); |
static int IfaceAddGroup(Bund b, const char * ifgroup); |
Line 258
|
Line 263
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }}} |
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }}} |
static const struct in6_addr in6mask128 = IN6MASK128; |
static const struct in6_addr in6mask128 = IN6MASK128; |
|
|
|
#ifdef SIOCSIFDESCR |
|
void |
|
IfaceFreeDescr(IfaceState iface) |
|
{ |
|
if (iface->ifdescr != NULL) |
|
Freee(iface->ifdescr); |
|
if (iface->conf.ifdescr != NULL) |
|
Freee(iface->conf.ifdescr); |
|
iface->ifdescr = iface->conf.ifdescr = NULL; |
|
} |
|
#endif |
|
|
/* |
/* |
* IfaceInit() |
* IfaceInit() |
Line 298 IfaceInst(Bund b, Bund bt)
|
Line 314 IfaceInst(Bund b, Bund bt)
|
|
|
memcpy(iface, &bt->iface, sizeof(*iface)); |
memcpy(iface, &bt->iface, sizeof(*iface)); |
|
|
|
#ifdef SIOCSIFDESCR |
|
/* Copy interface description from template config to current */ |
|
if (bt->iface.conf.ifdescr) |
|
iface->conf.ifdescr = Mstrdup(MB_IFACE, bt->iface.conf.ifdescr); |
|
if (bt->iface.ifdescr) |
|
iface->ifdescr = Mstrdup(MB_IFACE, bt->iface.ifdescr); |
|
#endif |
/* Copy interface name from template config to current */ |
/* Copy interface name from template config to current */ |
if (bt->iface.conf.ifname[0] != 0 && b->tmpl == 0) { |
if (bt->iface.conf.ifname[0] != 0 && b->tmpl == 0) { |
snprintf(iface->conf.ifname, sizeof(iface->conf.ifname), "%s%d", |
snprintf(iface->conf.ifname, sizeof(iface->conf.ifname), "%s%d", |
Line 316 IfaceDestroy(Bund b)
|
Line 339 IfaceDestroy(Bund b)
|
#ifdef SIOCSIFDESCR |
#ifdef SIOCSIFDESCR |
IfaceState const iface = &b->iface; |
IfaceState const iface = &b->iface; |
|
|
if (iface->conf.ifdescr != NULL) | IfaceFreeDescr(iface); |
Freee(iface->conf.ifdescr); | |
#endif |
#endif |
} |
} |
|
|
Line 488 IfaceUp(Bund b, int ready)
|
Line 510 IfaceUp(Bund b, int ready)
|
if (b->params.ifdescr != NULL) { |
if (b->params.ifdescr != NULL) { |
if (IfaceSetDescr(b, b->params.ifdescr) != -1) { |
if (IfaceSetDescr(b, b->params.ifdescr) != -1) { |
Log(LG_BUND|LG_IFACE, ("[%s] IFACE: Add description \"%s\"", |
Log(LG_BUND|LG_IFACE, ("[%s] IFACE: Add description \"%s\"", |
b->name, b->params.ifdescr)); | b->name, iface->ifdescr)); |
iface->ifdescr = b->params.ifdescr; | |
} |
} |
|
} else if (iface->conf.ifdescr != NULL) { |
|
if (IfaceSetDescr(b, iface->conf.ifdescr) != -1) { |
|
Log(LG_BUND|LG_IFACE, ("[%s] IFACE: Add description \"%s\"", |
|
b->name, iface->ifdescr)); |
|
} |
} |
} |
#endif |
#endif |
#ifdef SIOCAIFGROUP |
#ifdef SIOCAIFGROUP |
Line 565 IfaceUp(Bund b, int ready)
|
Line 591 IfaceUp(Bund b, int ready)
|
} |
} |
acls = b->params.acl_table; |
acls = b->params.acl_table; |
while (acls != NULL) { |
while (acls != NULL) { |
acl = Mdup(MB_IFACE, acls, sizeof(struct acl) + strlen(acls->rule)); | acl = Mdup(MB_IPFW, acls, sizeof(struct acl) + strlen(acls->rule)); |
acl->next = iface->tables; |
acl->next = iface->tables; |
iface->tables = acl; |
iface->tables = acl; |
ExecCmd(LG_IFACE2, b->name, "%s table %d add %s", PATH_IPFW, acls->real_number, acls->rule); |
ExecCmd(LG_IFACE2, b->name, "%s table %d add %s", PATH_IPFW, acls->real_number, acls->rule); |
Line 688 IfaceDown(Bund b)
|
Line 714 IfaceDown(Bund b)
|
PATH_IPFW, cb); |
PATH_IPFW, cb); |
#endif /* USE_IPFW */ |
#endif /* USE_IPFW */ |
|
|
|
/* Clearing self and peer addresses */ |
|
u_rangeclear(&iface->self_addr); |
|
u_addrclear(&iface->peer_addr); |
|
u_addrclear(&iface->self_ipv6_addr); |
|
u_addrclear(&iface->peer_ipv6_addr); |
|
|
/* Revert interface name and description */ |
/* Revert interface name and description */ |
|
|
if (strcmp(iface->ngname, iface->ifname) != 0) { |
if (strcmp(iface->ngname, iface->ifname) != 0) { |
Line 704 IfaceDown(Bund b)
|
Line 736 IfaceDown(Bund b)
|
} |
} |
} |
} |
#ifdef SIOCSIFDESCR |
#ifdef SIOCSIFDESCR |
if (iface->ifdescr != NULL) { | if ((iface->ifdescr != NULL) |
| && (IfaceSetDescr(b, iface->conf.ifdescr) != -1)) { |
if (iface->conf.ifdescr != NULL) { |
if (iface->conf.ifdescr != NULL) { |
/* Restore to config defined */ |
|
if (IfaceSetDescr(b, iface->conf.ifdescr) != -1) { |
|
Log(LG_BUND|LG_IFACE, ("[%s] IFACE: Set description \"%s\"", |
Log(LG_BUND|LG_IFACE, ("[%s] IFACE: Set description \"%s\"", |
b->name, iface->conf.ifdescr)); | b->name, iface->ifdescr)); |
iface->ifdescr = iface->conf.ifdescr; | |
} else | |
iface->ifdescr = NULL; | |
} else { |
} else { |
/* Restore to original (empty) */ |
|
if (IfaceSetDescr(b, "") != -1) { |
|
Log(LG_BUND|LG_IFACE, ("[%s] IFACE: Clear description", |
Log(LG_BUND|LG_IFACE, ("[%s] IFACE: Clear description", |
b->name)); |
b->name)); |
} |
|
iface->ifdescr = NULL; |
|
} |
} |
} |
} |
#endif |
#endif |
Line 770 IfaceAllocACL(struct acl_pool ***ap, int start, char *
|
Line 794 IfaceAllocACL(struct acl_pool ***ap, int start, char *
|
int i; |
int i; |
struct acl_pool **rp,*rp1; |
struct acl_pool **rp,*rp1; |
|
|
rp1 = Malloc(MB_IFACE, sizeof(struct acl_pool)); | rp1 = Malloc(MB_IPFW, sizeof(struct acl_pool)); |
strlcpy(rp1->ifname, ifname, sizeof(rp1->ifname)); |
strlcpy(rp1->ifname, ifname, sizeof(rp1->ifname)); |
rp1->acl_number = number; |
rp1->acl_number = number; |
|
|
Line 831 IFaceParseACL (char * src, char * ifname)
|
Line 855 IFaceParseACL (char * src, char * ifname)
|
int num,real_number; |
int num,real_number; |
struct acl_pool *ap; |
struct acl_pool *ap; |
|
|
buf = Malloc(MB_IFACE, ACL_LEN); | buf = Malloc(MB_IPFW, ACL_LEN); |
buf1 = Malloc(MB_IFACE, ACL_LEN); | buf1 = Malloc(MB_IPFW, ACL_LEN); |
|
|
strlcpy(buf, src, ACL_LEN); |
strlcpy(buf, src, ACL_LEN); |
do { |
do { |
Line 1512 IfaceSetCommand(Context ctx, int ac, char *av[], void
|
Line 1536 IfaceSetCommand(Context ctx, int ac, char *av[], void
|
break; |
break; |
#ifdef SIOCSIFDESCR |
#ifdef SIOCSIFDESCR |
case SET_DESCR: |
case SET_DESCR: |
if (ctx->bund->tmpl) | IfaceFreeDescr(iface); |
Error("Impossible to apply on template"); | |
if (iface->conf.ifdescr != NULL) | |
Freee(iface->conf.ifdescr); | |
iface->conf.ifdescr = NULL; | |
iface->ifdescr = NULL; | |
switch (ac) { |
switch (ac) { |
case 0: |
case 0: |
return IfaceSetDescr(ctx->bund, ""); |
return IfaceSetDescr(ctx->bund, ""); |
break; |
break; |
case 1: |
case 1: |
iface->conf.ifdescr = Mstrdup(MB_IFACE, av[0]); |
iface->conf.ifdescr = Mstrdup(MB_IFACE, av[0]); |
if (IfaceSetDescr(ctx->bund, av[0]) == 0) { | return IfaceSetDescr(ctx->bund, av[0]); |
iface->ifdescr = iface->conf.ifdescr; | |
return(0); | |
} else | |
return(-1); | |
break; |
break; |
default: |
default: |
return(-1); |
return(-1); |
Line 1612 IfaceStat(Context ctx, int ac, char *av[], void *arg)
|
Line 1627 IfaceStat(Context ctx, int ac, char *av[], void *arg)
|
Printf("\tName : %s\r\n", iface->conf.ifname); |
Printf("\tName : %s\r\n", iface->conf.ifname); |
#ifdef SIOCSIFDESCR |
#ifdef SIOCSIFDESCR |
Printf("\tDescription : \"%s\"\r\n", |
Printf("\tDescription : \"%s\"\r\n", |
(iface->conf.ifdescr != NULL) ? iface->conf.ifdescr : "<none>"); | (iface->ifdescr != NULL) ? iface->ifdescr : "<none>"); |
#endif |
#endif |
#ifdef SIOCAIFGROUP |
#ifdef SIOCAIFGROUP |
Printf("\tGroup : %s\r\n", iface->conf.ifgroup); |
Printf("\tGroup : %s\r\n", iface->conf.ifgroup); |
Line 1785 IfaceChangeFlags(Bund b, int clear, int set)
|
Line 1800 IfaceChangeFlags(Bund b, int clear, int set)
|
struct ifreq ifrq; |
struct ifreq ifrq; |
int s, new_flags; |
int s, new_flags; |
|
|
Log(LG_IFACE2, ("[%s] IFACE: Change interface flags: -%d +%d", | Log(LG_IFACE2, ("[%s] IFACE: Change interface %s flags: -%d +%d", |
b->name, clear, set)); | b->name, b->iface.ifname, clear, set)); |
|
|
if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { |
if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { |
Perror("[%s] IFACE: Can't get socket to change interface flags", b->name); |
Perror("[%s] IFACE: Can't get socket to change interface flags", b->name); |
Line 1795 IfaceChangeFlags(Bund b, int clear, int set)
|
Line 1810 IfaceChangeFlags(Bund b, int clear, int set)
|
|
|
memset(&ifrq, '\0', sizeof(ifrq)); |
memset(&ifrq, '\0', sizeof(ifrq)); |
strlcpy(ifrq.ifr_name, b->iface.ifname, sizeof(ifrq.ifr_name)); |
strlcpy(ifrq.ifr_name, b->iface.ifname, sizeof(ifrq.ifr_name)); |
ifrq.ifr_name[sizeof(ifrq.ifr_name) - 1] = '\0'; |
|
if (ioctl(s, SIOCGIFFLAGS, &ifrq) < 0) { |
if (ioctl(s, SIOCGIFFLAGS, &ifrq) < 0) { |
Perror("[%s] IFACE: ioctl(%s, %s)", b->name, b->iface.ifname, "SIOCGIFFLAGS"); | Perror("[%s] IFACE: ioctl(SIOCGIFFLAGS, %s)", b->name, b->iface.ifname); |
close(s); |
close(s); |
return; |
return; |
} |
} |
Line 1810 IfaceChangeFlags(Bund b, int clear, int set)
|
Line 1824 IfaceChangeFlags(Bund b, int clear, int set)
|
ifrq.ifr_flagshigh = new_flags >> 16; |
ifrq.ifr_flagshigh = new_flags >> 16; |
|
|
if (ioctl(s, SIOCSIFFLAGS, &ifrq) < 0) { |
if (ioctl(s, SIOCSIFFLAGS, &ifrq) < 0) { |
Perror("[%s] IFACE: ioctl(%s, %s)", b->name, b->iface.ifname, "SIOCSIFFLAGS"); | Perror("[%s] IFACE: ioctl(SIOCSIFFLAGS, %s)", b->name, b->iface.ifname); |
close(s); |
close(s); |
return; |
return; |
} |
} |
Line 1902 IfaceChangeAddr(Bund b, int add, struct u_range *self,
|
Line 1916 IfaceChangeAddr(Bund b, int add, struct u_range *self,
|
|
|
res = ioctl(s, add?SIOCAIFADDR_IN6:SIOCDIFADDR_IN6, &ifra6); |
res = ioctl(s, add?SIOCAIFADDR_IN6:SIOCDIFADDR_IN6, &ifra6); |
if (res == -1) { |
if (res == -1) { |
Perror("[%s] IFACE: %s IPv6 address %s %s failed", | if (add && errno == EEXIST) { |
b->name, add?"Adding":"Removing", add?"to":"from", b->iface.ifname); | /* this can happen if the kernel has already automatically added |
| the same link-local address - ignore the error */ |
| res = 0; |
| } else { |
| Perror("[%s] IFACE: %s IPv6 address %s %s failed", |
| b->name, add?"Adding":"Removing", add?"to":"from", b->iface.ifname); |
| } |
} |
} |
break; |
break; |
|
|
Line 2106 IfaceNgIpInit(Bund b, int ready)
|
Line 2126 IfaceNgIpInit(Bund b, int ready)
|
Enabled(&b->iface.options, IFACE_CONF_NETFLOW_OUT)) { |
Enabled(&b->iface.options, IFACE_CONF_NETFLOW_OUT)) { |
if (IfaceInitNetflow(b, path, hook, |
if (IfaceInitNetflow(b, path, hook, |
Enabled(&b->iface.options, IFACE_CONF_NETFLOW_IN)?1:0, |
Enabled(&b->iface.options, IFACE_CONF_NETFLOW_IN)?1:0, |
Enabled(&b->iface.options, IFACE_CONF_NETFLOW_OUT)?1:0)) | Enabled(&b->iface.options, IFACE_CONF_NETFLOW_OUT)?1:0, 0)) |
goto fail; |
goto fail; |
if (Enabled(&b->iface.options, IFACE_CONF_NETFLOW_IN)) |
if (Enabled(&b->iface.options, IFACE_CONF_NETFLOW_IN)) |
b->iface.nfin_up = 1; |
b->iface.nfin_up = 1; |
Line 2116 IfaceNgIpInit(Bund b, int ready)
|
Line 2136 IfaceNgIpInit(Bund b, int ready)
|
#else /* NG_NETFLOW_CONF_INGRESS */ |
#else /* NG_NETFLOW_CONF_INGRESS */ |
/* Connect a netflow node if configured */ |
/* Connect a netflow node if configured */ |
if (Enabled(&b->iface.options, IFACE_CONF_NETFLOW_IN)) { |
if (Enabled(&b->iface.options, IFACE_CONF_NETFLOW_IN)) { |
if (IfaceInitNetflow(b, path, hook, 1, 0)) | if (IfaceInitNetflow(b, path, hook, 1, 0, 0)) |
goto fail; |
goto fail; |
b->iface.nfin_up = 1; |
b->iface.nfin_up = 1; |
} |
} |
|
|
if (Enabled(&b->iface.options, IFACE_CONF_NETFLOW_OUT)) { |
if (Enabled(&b->iface.options, IFACE_CONF_NETFLOW_OUT)) { |
if (IfaceInitNetflow(b, path, hook, 0, 1)) | if (IfaceInitNetflow(b, path, hook, 0, 1, 0)) |
goto fail; |
goto fail; |
b->iface.nfout_up = 1; |
b->iface.nfout_up = 1; |
} |
} |
Line 2263 IfaceNgIpv6Init(Bund b, int ready)
|
Line 2283 IfaceNgIpv6Init(Bund b, int ready)
|
b->iface.tee6_up = 1; |
b->iface.tee6_up = 1; |
} |
} |
|
|
|
#ifdef USE_NG_NETFLOW |
|
#ifdef NG_NETFLOW_CONF_INGRESS |
|
/* Connect a netflow node if configured */ |
|
if (Enabled(&b->iface.options, IFACE_CONF_NETFLOW_IN) || |
|
Enabled(&b->iface.options, IFACE_CONF_NETFLOW_OUT)) { |
|
if (IfaceInitNetflow(b, path, hook, |
|
Enabled(&b->iface.options, IFACE_CONF_NETFLOW_IN)?1:0, |
|
Enabled(&b->iface.options, IFACE_CONF_NETFLOW_OUT)?1:0, 1)) |
|
goto fail; |
|
if (Enabled(&b->iface.options, IFACE_CONF_NETFLOW_IN)) |
|
b->iface.nfin_up = 1; |
|
if (Enabled(&b->iface.options, IFACE_CONF_NETFLOW_OUT)) |
|
b->iface.nfout_up = 1; |
|
} |
|
#else /* NG_NETFLOW_CONF_INGRESS */ |
|
/* Connect a netflow node if configured */ |
|
if (Enabled(&b->iface.options, IFACE_CONF_NETFLOW_IN, 1)) { |
|
if (IfaceInitNetflow(b, path, hook, 1, 0)) |
|
goto fail; |
|
b->iface.nfin_up = 1; |
|
} |
|
|
|
if (Enabled(&b->iface.options, IFACE_CONF_NETFLOW_OUT)) { |
|
if (IfaceInitNetflow(b, path, hook, 0, 1, 1)) |
|
goto fail; |
|
b->iface.nfout_up = 1; |
|
} |
|
#endif /* NG_NETFLOW_CONF_INGRESS */ |
|
#endif /* USE_NG_NETFLOW */ |
} |
} |
|
|
/* Connect graph to the iface node. */ |
/* Connect graph to the iface node. */ |
Line 2276 IfaceNgIpv6Init(Bund b, int ready)
|
Line 2325 IfaceNgIpv6Init(Bund b, int ready)
|
goto fail; |
goto fail; |
} |
} |
|
|
|
if (ready) { |
|
#ifdef USE_NG_NETFLOW |
|
#ifdef NG_NETFLOW_CONF_INGRESS |
|
if (b->iface.nfin_up || b->iface.nfout_up) |
|
IfaceSetupNetflow(b, b->iface.nfin_up, b->iface.nfout_up); |
|
#else /* NG_NETFLOW_CONF_INGRESS */ |
|
if (b->iface.nfin_up) |
|
IfaceSetupNetflow(b, 1, 0); |
|
|
|
if (b->iface.nfout_up) |
|
IfaceSetupNetflow(b, 0, 1); |
|
#endif /* NG_NETFLOW_CONF_INGRESS */ |
|
#endif /* USE_NG_NETFLOW */ |
|
} |
|
|
/* OK */ |
/* OK */ |
return(0); |
return(0); |
|
|
Line 2295 IfaceNgIpv6Shutdown(Bund b)
|
Line 2359 IfaceNgIpv6Shutdown(Bund b)
|
if (b->iface.tee6_up) |
if (b->iface.tee6_up) |
IfaceShutdownTee(b, 1); |
IfaceShutdownTee(b, 1); |
b->iface.tee6_up = 0; |
b->iface.tee6_up = 0; |
|
#ifdef USE_NG_NETFLOW |
|
#ifdef NG_NETFLOW_CONF_INGRESS |
|
if (b->iface.nfin_up || b->iface.nfout_up) |
|
IfaceShutdownNetflow(b, b->iface.nfin_up, b->iface.nfout_up); |
|
b->iface.nfin_up = 0; |
|
b->iface.nfout_up = 0; |
|
#else /* NG_NETFLOW_CONF_INGRESS */ |
|
if (b->iface.nfin_up) |
|
IfaceShutdownNetflow(b, 1, 0); |
|
b->iface.nfin_up = 0; |
|
if (b->iface.nfout_up) |
|
IfaceShutdownNetflow(b, 0, 1); |
|
b->iface.nfout_up = 0; |
|
#endif /* NG_NETFLOW_CONF_INGRESS */ |
|
#endif |
|
|
snprintf(path, sizeof(path), "[%x]:", b->nodeID); |
snprintf(path, sizeof(path), "[%x]:", b->nodeID); |
NgFuncDisconnect(gLinksCsock, b->name, path, NG_PPP_HOOK_IPV6); |
NgFuncDisconnect(gLinksCsock, b->name, path, NG_PPP_HOOK_IPV6); |
Line 2381 IfaceSetupNAT(Bund b)
|
Line 2460 IfaceSetupNAT(Bund b)
|
{ |
{ |
NatState const nat = &b->iface.nat; |
NatState const nat = &b->iface.nat; |
char path[NG_PATHSIZ]; |
char path[NG_PATHSIZ]; |
|
#ifdef NG_NAT_DESC_LENGTH |
int k; |
int k; |
|
union { |
|
u_char buf[sizeof(struct ng_mesg) + sizeof(uint32_t)]; |
|
struct ng_mesg reply; |
|
} u; |
|
uint32_t *const nat_id = (uint32_t *)(void *)u.reply.data; |
|
#endif |
|
|
if (u_addrempty(&nat->alias_addr)) { |
if (u_addrempty(&nat->alias_addr)) { |
snprintf(path, sizeof(path), "mpd%d-%s-nat:", gPid, b->name); |
snprintf(path, sizeof(path), "mpd%d-%s-nat:", gPid, b->name); |
Line 2396 IfaceSetupNAT(Bund b)
|
Line 2482 IfaceSetupNAT(Bund b)
|
#ifdef NG_NAT_DESC_LENGTH |
#ifdef NG_NAT_DESC_LENGTH |
/* redirect-port */ |
/* redirect-port */ |
for(k = 0; k < NM_PORT; k++) { |
for(k = 0; k < NM_PORT; k++) { |
if(nat->nrpt_id[k]) { | if(nat->nrpt_id[k] == -1) { |
if (NgSendMsg(gLinksCsock, path, |
if (NgSendMsg(gLinksCsock, path, |
NGM_NAT_COOKIE, NGM_NAT_REDIRECT_PORT, &nat->nrpt[k], |
NGM_NAT_COOKIE, NGM_NAT_REDIRECT_PORT, &nat->nrpt[k], |
sizeof(struct ng_nat_redirect_port)) < 0) { |
sizeof(struct ng_nat_redirect_port)) < 0) { |
Perror("[%s] can't set NAT redirect-port", b->name); |
Perror("[%s] can't set NAT redirect-port", b->name); |
|
} else { |
|
if (NgRecvMsg(gLinksCsock, &u.reply, sizeof(u), NULL) < 0) { |
|
Perror("[%s] can't recv NAT redirect-port message", b->name); |
|
} else |
|
nat->nrpt_id[k] = *nat_id; |
} |
} |
} |
} |
} |
} |
/* redirect-addr */ |
/* redirect-addr */ |
for(k = 0; k < NM_ADDR; k++) { |
for(k = 0; k < NM_ADDR; k++) { |
if(nat->nrad_id[k]) { | if(nat->nrad_id[k] == -1) { |
if (NgSendMsg(gLinksCsock, path, |
if (NgSendMsg(gLinksCsock, path, |
NGM_NAT_COOKIE, NGM_NAT_REDIRECT_ADDR, &nat->nrad[k], |
NGM_NAT_COOKIE, NGM_NAT_REDIRECT_ADDR, &nat->nrad[k], |
sizeof(struct ng_nat_redirect_addr)) < 0) { |
sizeof(struct ng_nat_redirect_addr)) < 0) { |
Perror("[%s] can't set NAT redirect-addr", b->name); |
Perror("[%s] can't set NAT redirect-addr", b->name); |
|
} else { |
|
if (NgRecvMsg(gLinksCsock, &u.reply, sizeof(u), NULL) < 0) { |
|
Perror("[%s] can't recv NAT redirect-addr message", b->name); |
|
} else |
|
nat->nrad_id[k] = *nat_id; |
} |
} |
} |
} |
} |
} |
/* redirect-proto */ |
/* redirect-proto */ |
for(k = 0; k < NM_PROTO; k++) { |
for(k = 0; k < NM_PROTO; k++) { |
if(nat->nrpr_id[k]) { | if(nat->nrpr_id[k] == -1) { |
if (NgSendMsg(gLinksCsock, path, |
if (NgSendMsg(gLinksCsock, path, |
NGM_NAT_COOKIE, NGM_NAT_REDIRECT_PROTO, &nat->nrpr[k], |
NGM_NAT_COOKIE, NGM_NAT_REDIRECT_PROTO, &nat->nrpr[k], |
sizeof(struct ng_nat_redirect_proto)) < 0) { |
sizeof(struct ng_nat_redirect_proto)) < 0) { |
Perror("[%s] can't set NAT redirect-proto", b->name); |
Perror("[%s] can't set NAT redirect-proto", b->name); |
|
} else { |
|
if (NgRecvMsg(gLinksCsock, &u.reply, sizeof(u), NULL) < 0) { |
|
Perror("[%s] can't recv NAT redirect-proto message", b->name); |
|
} else |
|
nat->nrpr_id[k] = *nat_id; |
} |
} |
} |
} |
} |
} |
Line 2432 static void
|
Line 2533 static void
|
IfaceShutdownNAT(Bund b) |
IfaceShutdownNAT(Bund b) |
{ |
{ |
char path[NG_PATHSIZ]; |
char path[NG_PATHSIZ]; |
|
#ifdef NG_NAT_DESC_LENGTH |
|
NatState const nat = &b->iface.nat; |
|
int k; |
|
#endif |
|
|
snprintf(path, sizeof(path), "mpd%d-%s-nat:", gPid, b->name); |
snprintf(path, sizeof(path), "mpd%d-%s-nat:", gPid, b->name); |
NgFuncShutdownNode(gLinksCsock, b->name, path); |
NgFuncShutdownNode(gLinksCsock, b->name, path); |
|
#ifdef NG_NAT_DESC_LENGTH |
|
/* redirect-port */ |
|
for(k = 0; k < NM_PORT; k++) |
|
if(nat->nrpt_id[k] > 0) |
|
nat->nrpt_id[k] = -1; |
|
/* redirect-addr */ |
|
for(k = 0; k < NM_ADDR; k++) |
|
if(nat->nrad_id[k] > 0) |
|
nat->nrad_id[k] = -1; |
|
/* redirect-proto */ |
|
for(k = 0; k < NM_PROTO; k++) |
|
if(nat->nrpr_id[k] > 0) |
|
nat->nrpr_id[k] = -1; |
|
#endif |
} |
} |
#endif /* USE_NG_NAT */ |
#endif /* USE_NG_NAT */ |
|
|
Line 2580 IfaceShutdownIpacct(Bund b)
|
Line 2699 IfaceShutdownIpacct(Bund b)
|
|
|
#ifdef USE_NG_NETFLOW |
#ifdef USE_NG_NETFLOW |
static int |
static int |
IfaceInitNetflow(Bund b, char *path, char *hook, char in, char out) | IfaceInitNetflow(Bund b, char *path, char *hook, char in, char out, int v6) |
{ |
{ |
struct ngm_connect cn; |
struct ngm_connect cn; |
int nif; |
int nif; |
Line 2591 IfaceInitNetflow(Bund b, char *path, char *hook, char
|
Line 2710 IfaceInitNetflow(Bund b, char *path, char *hook, char
|
nif = gNetflowIface + b->id*2 + out; |
nif = gNetflowIface + b->id*2 + out; |
#endif |
#endif |
|
|
Log(LG_IFACE2, ("[%s] IFACE: Connecting netflow (%s)", b->name, out?"out":"in")); | Log(LG_IFACE2, ("[%s] IFACE: Connecting netflow%s (%s)", |
| b->name, v6?"6":"", out?"out":"in")); |
|
|
/* Create global ng_netflow(4) node if not yet. */ |
/* Create global ng_netflow(4) node if not yet. */ |
if (gNetflowNodeID == 0) { |
if (gNetflowNodeID == 0) { |
Line 2970 IfaceSetupLimits(Bund b)
|
Line 3090 IfaceSetupLimits(Bund b)
|
struct ngm_connect cn; |
struct ngm_connect cn; |
int i; |
int i; |
|
|
hpu = Malloc(MB_IFACE, sizeof(*hpu)); | hpu = Malloc(MB_ACL, sizeof(*hpu)); |
hp = &hpu->hprog; |
hp = &hpu->hprog; |
|
|
if (b->params.acl_limits[0] || b->params.acl_limits[1]) { |
if (b->params.acl_limits[0] || b->params.acl_limits[1]) { |
Line 3016 IfaceSetupLimits(Bund b)
|
Line 3136 IfaceSetupLimits(Bund b)
|
} |
} |
|
|
stathook[0] = 0; |
stathook[0] = 0; |
memset(hpu, 0, sizeof(hpu)); | memset(hpu, 0, sizeof(*hpu)); |
/* Prepare filter */ |
/* Prepare filter */ |
if (strcasecmp(av[0], "all") == 0) { |
if (strcasecmp(av[0], "all") == 0) { |
hp->bpf_prog_len = MATCH_PROG_LEN; |
hp->bpf_prog_len = MATCH_PROG_LEN; |
Line 3040 IfaceSetupLimits(Bund b)
|
Line 3160 IfaceSetupLimits(Bund b)
|
int bufbraces; |
int bufbraces; |
|
|
#define ACL_BUF_SIZE 256*1024 |
#define ACL_BUF_SIZE 256*1024 |
buf = Malloc(MB_IFACE, ACL_BUF_SIZE); | buf = Malloc(MB_ACL, ACL_BUF_SIZE); |
buf[0] = 0; |
buf[0] = 0; |
bufbraces = 0; |
bufbraces = 0; |
while (f) { |
while (f) { |
char *b1, *b2, *sbuf; |
char *b1, *b2, *sbuf; |
sbuf = Mstrdup(MB_IFACE, f->rule); | sbuf = Mstrdup(MB_ACL, f->rule); |
b2 = sbuf; |
b2 = sbuf; |
b1 = strsep(&b2, " "); |
b1 = strsep(&b2, " "); |
if (b2 != NULL) { |
if (b2 != NULL) { |
Line 3278 IfaceSetupLimits(Bund b)
|
Line 3398 IfaceSetupLimits(Bund b)
|
break; |
break; |
} |
} |
if (ss == NULL) { |
if (ss == NULL) { |
ss = Malloc(MB_IFACE, sizeof(*ss)); | ss = Malloc(MB_ACL, sizeof(*ss)); |
strlcpy(ss->name, l->name, sizeof(ss->name)); |
strlcpy(ss->name, l->name, sizeof(ss->name)); |
SLIST_INIT(&ss->src); |
SLIST_INIT(&ss->src); |
SLIST_INSERT_HEAD(&b->iface.ss[dir], ss, next); |
SLIST_INSERT_HEAD(&b->iface.ss[dir], ss, next); |
} |
} |
if (stathook[0]) { |
if (stathook[0]) { |
sss = Malloc(MB_IFACE, sizeof(*sss)); | sss = Malloc(MB_ACL, sizeof(*sss)); |
strlcpy(sss->hook, stathook, sizeof(sss->hook)); |
strlcpy(sss->hook, stathook, sizeof(sss->hook)); |
sss->type = SSSS_IN; |
sss->type = SSSS_IN; |
SLIST_INSERT_HEAD(&ss->src, sss, next); |
SLIST_INSERT_HEAD(&ss->src, sss, next); |
Line 3294 IfaceSetupLimits(Bund b)
|
Line 3414 IfaceSetupLimits(Bund b)
|
for (i = 0; i < 2; i++) { |
for (i = 0; i < 2; i++) { |
if (inhook[i][0] != 0) { |
if (inhook[i][0] != 0) { |
if (l->name[0] && !stathook[0]) { |
if (l->name[0] && !stathook[0]) { |
sss = Malloc(MB_IFACE, sizeof(*sss)); | sss = Malloc(MB_ACL, sizeof(*sss)); |
strlcpy(sss->hook, inhook[i], sizeof(sss->hook)); |
strlcpy(sss->hook, inhook[i], sizeof(sss->hook)); |
sss->type = SSSS_MATCH; |
sss->type = SSSS_MATCH; |
SLIST_INSERT_HEAD(&ss->src, sss, next); |
SLIST_INSERT_HEAD(&ss->src, sss, next); |
Line 3392 IfaceGetStats(Bund b, struct svcstat *stat)
|
Line 3512 IfaceGetStats(Bund b, struct svcstat *stat)
|
break; |
break; |
} |
} |
if (!ssr) { |
if (!ssr) { |
ssr = Malloc(MB_IFACE, sizeof(*ssr)); | ssr = Malloc(MB_ACL, sizeof(*ssr)); |
strlcpy(ssr->name, ss->name, sizeof(ssr->name)); |
strlcpy(ssr->name, ss->name, sizeof(ssr->name)); |
SLIST_INSERT_HEAD(&stat->stat[dir], ssr, next); |
SLIST_INSERT_HEAD(&stat->stat[dir], ssr, next); |
} |
} |
Line 3440 IfaceAddStats(struct svcstat *stat1, struct svcstat *s
|
Line 3560 IfaceAddStats(struct svcstat *stat1, struct svcstat *s
|
break; |
break; |
} |
} |
if (!ssr1) { |
if (!ssr1) { |
ssr1 = Malloc(MB_IFACE, sizeof(*ssr1)); | ssr1 = Malloc(MB_ACL, sizeof(*ssr1)); |
strlcpy(ssr1->name, ssr2->name, sizeof(ssr1->name)); |
strlcpy(ssr1->name, ssr2->name, sizeof(ssr1->name)); |
SLIST_INSERT_HEAD(&stat1->stat[dir], ssr1, next); |
SLIST_INSERT_HEAD(&stat1->stat[dir], ssr1, next); |
} |
} |
Line 3486 IfaceSetName(Bund b, const char * ifname)
|
Line 3606 IfaceSetName(Bund b, const char * ifname)
|
|
|
/* Get socket */ |
/* Get socket */ |
if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { |
if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { |
Log(LG_ERR, ("[%s] IFACE: Can't get socket to set name", b->name)); | Perror("[%s] IFACE: Can't get socket to set name", b->name); |
return(-1); |
return(-1); |
} |
} |
|
|
Line 3512 IfaceSetName(Bund b, const char * ifname)
|
Line 3632 IfaceSetName(Bund b, const char * ifname)
|
#ifdef SIOCSIFDESCR |
#ifdef SIOCSIFDESCR |
/* |
/* |
* IfaceSetDescr() |
* IfaceSetDescr() |
|
* |
|
* Set/clear our own interface description accessible in console/web interface |
|
* and kernel level interface description if it is available. |
|
* |
|
* Template may contain conversion specifications: |
|
* |
|
* %% expands to single % sign; |
|
* %a for interface local address; |
|
* %A for peer address; |
|
* %i for system interface index; |
|
* %I for interface name; |
|
* %l for name of bundle's first link |
|
* %M for peer MAC address of bundle's first link |
|
* %S for interface status (DoD/UP/DOWN) |
|
* %t for type of bundle's first link (pppoe, pptp, l2tp etc.) |
|
* %u for self auth name (or dash if self auth name not used) |
|
* %U for peer auth name (or dash if peer has not authenticated) |
*/ |
*/ |
|
|
int |
int |
IfaceSetDescr(Bund b, const char * ifdescr) | IfaceSetDescr(Bund b, const char * template) |
{ |
{ |
IfaceState const iface = &b->iface; |
IfaceState const iface = &b->iface; |
struct ifreq ifr; |
struct ifreq ifr; |
int s, ifdescr_maxlen; | int s; |
| unsigned int ifdescr_maxlen = 1024; /* used as limit for old kernels */ |
char *newdescr; |
char *newdescr; |
size_t sz = sizeof(int); | size_t sz = sizeof(ifdescr_maxlen); |
| char *limit, *ifname; |
| const char *src; |
| int proceed; |
| char buf[64]; |
|
|
if (b->tmpl) { | static int mib[2] = { -1, 0 }; /* MIB for net.ifdescr_maxlen */ |
Log(LG_ERR, ("Impossible ioctl(SIOCSIFDESCR) on template")); | size_t miblen = sizeof(mib) / sizeof(mib[0]); |
return(-1); | |
| /* |
| * Check whether running kernel supports interface description. |
| * Perform the check only once. |
| */ |
| if (mib[0] < 0 && sysctlnametomib("net.ifdescr_maxlen", mib, &miblen) < 0) { |
| mib[0] = 0; |
| Perror("[%s] IFACE: sysctl net.ifdescr_maxlen failed", b->name); |
} |
} |
|
|
if (sysctlbyname("net.ifdescr_maxlen", &ifdescr_maxlen, &sz, NULL, 0) < 0) { | /* |
Perror("[%s] IFACE: sysctl net.ifdescr_maxlen failed", b->name); | * Fetch net.ifdescr_maxlen value every time to catch up with changes |
return(-1); | */ |
| if (mib[0] && sysctl(mib, 2, &ifdescr_maxlen, &sz, NULL, 0) < 0) { |
| /* unexpected error from the kernel, use default value */ |
| Perror("[%s] IFACE: sysctl net.ifdescr_maxlen failed", b->name); |
| ifdescr_maxlen = 1024; |
} |
} |
|
|
if (ifdescr_maxlen < strlen(ifdescr) + 1) { | newdescr = NULL; |
Log(LG_ERR, ("[%s] IFACE: Description too long, >%d characters", | ifname = iface->ifname; |
b->name, ifdescr_maxlen-1)); | if (iface->ifdescr != NULL) { |
return(-1); | Freee(iface->ifdescr); |
| iface->ifdescr = NULL; |
} |
} |
|
if ((src = template) != NULL) { |
|
|
|
/* Will use Mstrdup() later for iface->ifdescr to free extra memory */ |
|
if ((iface->ifdescr = newdescr = Malloc(MB_IFACE, ifdescr_maxlen)) == NULL) { |
|
Log(LG_IFACE2, ("[%s] IFACE: no memory for interface %s description", |
|
b->name, ifname ? ifname : "")); |
|
return(-1); |
|
} |
|
|
|
/* ifdescr_maxlen includes terminating zero */ |
|
limit = newdescr + ifdescr_maxlen - 1; |
|
|
|
/* |
|
* Perform template expansion |
|
*/ |
|
proceed = 1; |
|
while (proceed && *src && newdescr < limit) { |
|
if (*src != '%') { /* ordinary symbol, just copy it and proceed */ |
|
*newdescr++ = *src++; |
|
continue; |
|
} |
|
if (!*(src+1)) { /* '%' at the end of template, just copy */ |
|
*newdescr++ = *src++; |
|
continue; |
|
} |
|
switch(*++src) { /* expand */ |
|
case '%': /* %% got replaced with single % */ |
|
*newdescr++ = *src; |
|
break; |
|
|
|
#define DST_COPY(a) \ |
|
do { const char *temp = a; \ |
|
if (temp && *temp) { \ |
|
if ((newdescr + strlen (temp)) <= limit) {\ |
|
newdescr = stpcpy (newdescr, temp); \ |
|
} else { \ |
|
proceed = 0; \ |
|
} \ |
|
} else { \ |
|
*newdescr++ = '-'; \ |
|
} \ |
|
} while(0) |
|
|
|
/* self address */ |
|
case 'a': |
|
{ |
|
char *sep; |
|
u_rangetoa(&iface->self_addr, buf, sizeof(buf)); |
|
/* cut netmask */ |
|
if ((sep = strchr(buf, '/'))) |
|
*sep = '\0'; |
|
DST_COPY(buf); |
|
} |
|
break; |
|
/* peer address */ |
|
case 'A': |
|
{ |
|
u_addrtoa (&iface->peer_addr, buf, sizeof(buf)); |
|
DST_COPY(buf); |
|
} |
|
break; |
|
/* interface index */ |
|
case 'i': |
|
{ |
|
snprintf (buf, sizeof(buf), "%u", iface->ifindex); |
|
DST_COPY(buf); |
|
} |
|
break; |
|
/* interface name */ |
|
case 'I': |
|
DST_COPY(iface->ifname); |
|
break; |
|
/* first link name */ |
|
case 'l': |
|
DST_COPY(b->links[0] ? b->links[0]->name : NULL); |
|
break; |
|
case 'M': |
|
if(b->links[0]) { |
|
PhysType const pt = b->links[0]->type; |
|
if (pt && pt->peermacaddr) { |
|
(*pt->peermacaddr)(b->links[0], buf, sizeof(buf)); |
|
DST_COPY(buf); |
|
} else { |
|
DST_COPY("-"); |
|
} |
|
} else { |
|
DST_COPY("-"); |
|
} |
|
break; |
|
/* interface status */ |
|
case 'S': |
|
DST_COPY(iface->up ? (iface->dod ? "DoD" : "UP") : "DOWN"); |
|
break; |
|
/* first link type */ |
|
case 't': |
|
DST_COPY(b->links[0] ? b->links[0]->type->name : NULL); |
|
break; |
|
/* self auth name */ |
|
case 'u': |
|
DST_COPY(b->links[0] ? b->links[0]->lcp.auth.conf.authname : NULL); |
|
break; |
|
/* peer auth name */ |
|
case 'U': |
|
DST_COPY(b->params.authname); |
|
break; |
|
#undef DST_COPY |
|
default: /* unrecognized specification, just copy */ |
|
*newdescr++ = '%'; |
|
if (newdescr < limit) |
|
*newdescr++ = *src; |
|
} /* switch(*++src) */ |
|
++src; |
|
} /* while */ |
|
*newdescr = '\0'; |
|
|
|
/* includes terminating zero */ |
|
sz = newdescr - iface->ifdescr + 1; |
|
if ((newdescr = Mstrdup(MB_IFACE, iface->ifdescr)) == NULL) { |
|
Log(LG_IFACE2, ("[%s] IFACE: no memory for interface %s description", |
|
b->name, ifname ? ifname : "")); |
|
Freee(iface->ifdescr); |
|
iface->ifdescr = NULL; |
|
return(-1); |
|
} |
|
Freee(iface->ifdescr); |
|
iface->ifdescr = newdescr; |
|
} /* template != NULL */ |
|
|
|
/* Set description of interface */ |
|
if (mib[0] == 0) |
|
return(0); /* do not bother kernel if it is too old */ |
|
|
|
if (ifname == NULL || *ifname == '\0') |
|
return(0); /* we have not set system interface name yet */ |
|
|
/* Get socket */ |
/* Get socket */ |
if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { |
if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { |
Log(LG_ERR, ("[%s] IFACE: Can't get socket to set description", b->name)); | Perror("[%s] IFACE: Can't get socket to set description for %s", |
| b->name, ifname); |
return(-1); |
return(-1); |
} |
} |
|
|
/* Set description of interface */ |
|
memset(&ifr, 0, sizeof(ifr)); |
memset(&ifr, 0, sizeof(ifr)); |
strlcpy(ifr.ifr_name, iface->ifname, sizeof(ifr.ifr_name)); | strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); |
ifr.ifr_buffer.length = strlen(ifdescr) + 1; | |
if (ifr.ifr_buffer.length == 1) { | if (!newdescr || !*newdescr) { /* empty description or clearing request */ |
ifr.ifr_buffer.buffer = newdescr = NULL; | ifr.ifr_buffer.buffer = NULL; |
ifr.ifr_buffer.length = 0; |
ifr.ifr_buffer.length = 0; |
Log(LG_IFACE2, ("[%s] IFACE: clearing \"%s\" description", |
Log(LG_IFACE2, ("[%s] IFACE: clearing \"%s\" description", |
b->name, iface->ifname)); | b->name, ifname)); |
} else { |
} else { |
newdescr = Mstrdup(MB_IFACE, ifdescr); | ifr.ifr_buffer.length = (unsigned)sz; |
ifr.ifr_buffer.buffer = newdescr; |
ifr.ifr_buffer.buffer = newdescr; |
Log(LG_IFACE2, ("[%s] IFACE: setting \"%s\" description to \"%s\"", |
Log(LG_IFACE2, ("[%s] IFACE: setting \"%s\" description to \"%s\"", |
b->name, iface->ifname, ifdescr)); | b->name, ifname, newdescr)); |
} |
} |
|
|
if (ioctl(s, SIOCSIFDESCR, (caddr_t)&ifr) < 0) { |
if (ioctl(s, SIOCSIFDESCR, (caddr_t)&ifr) < 0) { |
Perror("[%s] IFACE: ioctl(%s, SIOCSIFDESCR)", b->name, iface->ifname); | Perror("[%s] IFACE: ioctl(%s, SIOCSIFDESCR, \"%s\")", |
Freee(newdescr); | b->name, ifname, newdescr ? newdescr : "" ); |
close(s); |
close(s); |
return(-1); |
return(-1); |
} |
} |
Freee(newdescr); |
|
close(s); |
close(s); |
return(0); |
return(0); |
} |
} |