summaryrefslogtreecommitdiff
path: root/accel-pppd/ctrl
diff options
context:
space:
mode:
authorDmitry Kozlov <xeb@mail.ru>2015-12-04 16:35:27 +0300
committerDmitry Kozlov <xeb@mail.ru>2015-12-04 16:35:27 +0300
commit1e30436e2e19e693e54cfdb0cb68ae162300ca55 (patch)
tree51b77b333aef92ea0c575fe46bb9b0a30b6fa3c7 /accel-pppd/ctrl
parentc0b2b260b2c9b8c3375d51e90cd1edf552d7655a (diff)
parent19dc965d29c7ec17929b8713d021b76107fdf557 (diff)
downloadaccel-ppp-1e30436e2e19e693e54cfdb0cb68ae162300ca55.tar.gz
accel-ppp-1e30436e2e19e693e54cfdb0cb68ae162300ca55.zip
Merge branch 'vlanmon'
Diffstat (limited to 'accel-pppd/ctrl')
-rw-r--r--accel-pppd/ctrl/ipoe/ipoe.c130
-rw-r--r--accel-pppd/ctrl/ipoe/ipoe.h4
-rw-r--r--accel-pppd/ctrl/ipoe/ipoe_netlink.c139
-rw-r--r--accel-pppd/ctrl/pppoe/pppoe.c327
-rw-r--r--accel-pppd/ctrl/pppoe/pppoe.h4
5 files changed, 345 insertions, 259 deletions
diff --git a/accel-pppd/ctrl/ipoe/ipoe.c b/accel-pppd/ctrl/ipoe/ipoe.c
index 95b75338..05a9ff53 100644
--- a/accel-pppd/ctrl/ipoe/ipoe.c
+++ b/accel-pppd/ctrl/ipoe/ipoe.c
@@ -33,6 +33,7 @@
#include "ipset.h"
#include "connlimit.h"
+#include "vlan_mon.h"
#include "ipoe.h"
@@ -2119,7 +2120,7 @@ static void ipoe_serv_release(struct ipoe_serv *serv)
if (serv->vid) {
log_info2("ipoe: remove vlan %s\n", serv->ifname);
iplink_vlan_del(serv->ifindex);
- ipoe_nl_add_vlan_mon_vid(serv->parent_ifindex, serv->vid);
+ vlan_mon_add_vid(serv->parent_ifindex, ETH_P_IP, serv->vid);
}
triton_context_unregister(&serv->ctx);
@@ -2255,48 +2256,7 @@ static int get_offer_delay()
return 0;
}
-static int make_vlan_name(const char *parent, int svid, int cvid, char *name)
-{
- char *ptr1 = name, *endptr = name + IFNAMSIZ;
- const char *ptr2 = conf_vlan_name;
- char svid_str[5], cvid_str[5], *ptr3;
-
-#ifdef USE_LUA
- if (!memcmp(conf_vlan_name, "lua:", 4))
- return ipoe_lua_make_vlan_name(conf_vlan_name + 4, parent, svid, cvid, name);
-#endif
-
- sprintf(svid_str, "%i", svid);
- sprintf(cvid_str, "%i", cvid);
-
- while (ptr1 < endptr && *ptr2) {
- if (ptr2[0] == '%' && ptr2[1] == 'I') {
- while (ptr1 < endptr && *parent)
- *ptr1++ = *parent++;
- ptr2 += 2;
- } else if (ptr2[0] == '%' && ptr2[1] == 'N') {
- ptr3 = cvid_str;
- while (ptr1 < endptr && *ptr3)
- *ptr1++ = *ptr3++;
- ptr2 += 2;
- } else if (ptr2[0] == '%' && ptr2[1] == 'P') {
- ptr3 = svid_str;
- while (ptr1 < endptr && *ptr3)
- *ptr1++ = *ptr3++;
- ptr2 += 2;
- } else
- *ptr1++ = *ptr2++;
- }
-
- if (ptr1 == endptr)
- return 1;
-
- *ptr1 = 0;
-
- return 0;
-}
-
-void ipoe_vlan_notify(int ifindex, int vid)
+void ipoe_vlan_mon_notify(int ifindex, int vid)
{
struct conf_sect_t *sect = conf_get_section("ipoe");
struct conf_option_t *opt;
@@ -2321,20 +2281,24 @@ void ipoe_vlan_notify(int ifindex, int vid)
svid = iplink_vlan_get_vid(ifindex);
- if (make_vlan_name(ifr.ifr_name, svid, vid, ifname)) {
+#ifdef USE_LUA
+ if (!memcmp(conf_vlan_name, "lua:", 4))
+ r = ipoe_lua_make_vlan_name(conf_vlan_name + 4, parent, svid, cvid, name);
+ else
+#endif
+ r = make_vlan_name(conf_vlan_name, ifr.ifr_name, svid, vid, ifname);
+ if (r) {
log_error("ipoe: vlan-mon: %s.%i: interface name is too long\n", ifr.ifr_name, vid);
return;
}
- log_info2("ipoe: create vlan %s parent %s\n", ifname, ifr.ifr_name);
-
strcpy(ifr.ifr_name, ifname);
len = strlen(ifr.ifr_name);
- if (iplink_vlan_add(ifr.ifr_name, ifindex, vid)) {
- log_warn("ipoe: vlan-mon: %s: failed to add vlan\n", ifr.ifr_name);
+ if (iplink_vlan_add(ifr.ifr_name, ifindex, vid))
return;
- }
+
+ log_info2("ipoe: create vlan %s parent %s\n", ifname, ifr.ifr_name);
ioctl(sock_fd, SIOCGIFFLAGS, &ifr, sizeof(ifr));
ifr.ifr_flags |= IFF_UP;
@@ -2993,59 +2957,6 @@ out_err:
return -1;
}
-static int parse_vlan_mon(const char *opt, long *mask)
-{
- char *ptr, *ptr2;
- int vid, vid2;
-
- ptr = strchr(opt, ',');
- if (!ptr)
- ptr = strchr(opt, 0);
-
- if (*ptr == ',')
- memset(mask, 0xff, 4096/8);
- else if (*ptr == 0) {
- memset(mask, 0, 4096/8);
- return 0;
- } else
- goto out_err;
-
- while (1) {
- vid = strtol(ptr + 1, &ptr2, 10);
- if (vid <= 0 || vid >= 4096) {
- log_error("ipoe: vlan-mon=%s: invalid vlan %i\n", opt, vid);
- return -1;
- }
-
- if (*ptr2 == '-') {
- vid2 = strtol(ptr2 + 1, &ptr2, 10);
- if (vid2 <= 0 || vid2 >= 4096) {
- log_error("ipoe: vlan-mon=%s: invalid vlan %i\n", opt, vid2);
- return -1;
- }
-
- for (; vid < vid2; vid++)
- mask[vid / (8*sizeof(long))] &= ~(1lu << (vid % (8*sizeof(long))));
- }
-
- mask[vid / (8*sizeof(long))] &= ~(1lu << (vid % (8*sizeof(long))));
-
- if (*ptr2 == 0)
- break;
-
- if (*ptr2 != ',')
- goto out_err;
-
- ptr = ptr2;
- }
-
- return 0;
-
-out_err:
- log_error("ipoe: vlan-mon=%s: failed to parse\n", opt);
- return -1;
-}
-
static void add_vlan_mon(const char *opt, long *mask)
{
const char *ptr;
@@ -3087,7 +2998,7 @@ static void add_vlan_mon(const char *opt, long *mask)
mask1[serv->vid / (8*sizeof(long))] |= 1lu << (serv->vid % (8*sizeof(long)));
}
- ipoe_nl_add_vlan_mon(ifindex, mask1, sizeof(mask1));
+ vlan_mon_add(ifindex, ETH_P_IP, mask1, sizeof(mask1));
}
static int __load_vlan_mon_re(int index, int flags, const char *name, struct iplink_arg *arg)
@@ -3116,7 +3027,7 @@ static int __load_vlan_mon_re(int index, int flags, const char *name, struct ipl
mask1[serv->vid / (8*sizeof(long))] |= 1lu << (serv->vid % (8*sizeof(long)));
}
- ipoe_nl_add_vlan_mon(index, mask1, sizeof(mask1));
+ vlan_mon_add(index, ETH_P_IP, mask1, sizeof(mask1));
return 0;
}
@@ -3158,8 +3069,17 @@ static void load_vlan_mon(struct conf_sect_t *sect)
{
struct conf_option_t *opt;
long mask[4096/8/sizeof(long)];
+ static int registered = 0;
+
+ if (!triton_module_loaded("vlan-mon"))
+ return;
+
+ if (!registered) {
+ vlan_mon_register_proto(ETH_P_IP, ipoe_vlan_mon_notify);
+ registered = 1;
+ }
- ipoe_nl_del_vlan_mon(-1);
+ vlan_mon_del(-1, ETH_P_IP);
list_for_each_entry(opt, &sect->items, entry) {
if (strcmp(opt->name, "vlan-mon"))
diff --git a/accel-pppd/ctrl/ipoe/ipoe.h b/accel-pppd/ctrl/ipoe/ipoe.h
index 036eda80..cd1993df 100644
--- a/accel-pppd/ctrl/ipoe/ipoe.h
+++ b/accel-pppd/ctrl/ipoe/ipoe.h
@@ -115,7 +115,6 @@ struct iphdr;
struct ethhdr;
void ipoe_recv_up(int ifindex, struct ethhdr *eth, struct iphdr *iph);
-void ipoe_vlan_notify(int ifindex, int vid);
struct ipoe_session *ipoe_session_alloc(void);
@@ -129,9 +128,6 @@ int ipoe_nl_create(uint32_t peer_addr, uint32_t addr, const char *ifname, uint8_
void ipoe_nl_delete(int ifindex);
int ipoe_nl_modify(int ifindex, uint32_t peer_addr, uint32_t addr, const char *ifname, uint8_t *hwaddr);
void ipoe_nl_get_sessions(struct list_head *list);
-int ipoe_nl_add_vlan_mon(int ifindex, long *mask, int len);
-int ipoe_nl_add_vlan_mon_vid(int ifindex, int vid);
-int ipoe_nl_del_vlan_mon(int ifindex);
int ipoe_nl_add_exclude(uint32_t addr, int mask);
void ipoe_nl_del_exclude(uint32_t addr);
diff --git a/accel-pppd/ctrl/ipoe/ipoe_netlink.c b/accel-pppd/ctrl/ipoe/ipoe_netlink.c
index c0610367..18542cde 100644
--- a/accel-pppd/ctrl/ipoe/ipoe_netlink.c
+++ b/accel-pppd/ctrl/ipoe/ipoe_netlink.c
@@ -448,106 +448,6 @@ void ipoe_nl_delete(int ifindex)
rtnl_close(&rth);
}
-int ipoe_nl_add_vlan_mon(int ifindex, long *mask, int len)
-{
- struct nlmsghdr *nlh;
- struct genlmsghdr *ghdr;
- struct {
- struct nlmsghdr n;
- char buf[1024];
- } req;
-
- if (rth.fd == -1)
- return -1;
-
- nlh = &req.n;
- nlh->nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
- nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
- nlh->nlmsg_type = ipoe_genl_id;
-
- ghdr = NLMSG_DATA(&req.n);
- ghdr->cmd = IPOE_CMD_ADD_VLAN_MON;
-
- addattr32(nlh, 1024, IPOE_ATTR_IFINDEX, ifindex);
- addattr_l(nlh, 1024, IPOE_ATTR_VLAN_MASK, mask, len);
-
- if (rtnl_talk(&rth, nlh, 0, 0, nlh, NULL, NULL, 0) < 0 ) {
- log_error("ipoe: nl_add_vlan_mon: error talking to kernel\n");
- return -1;
- }
-
- return 0;
-}
-
-int ipoe_nl_add_vlan_mon_vid(int ifindex, int vid)
-{
- struct rtnl_handle rth;
- struct nlmsghdr *nlh;
- struct genlmsghdr *ghdr;
- struct {
- struct nlmsghdr n;
- char buf[1024];
- } req;
- int r = 0;
-
- if (rtnl_open_byproto(&rth, 0, NETLINK_GENERIC)) {
- log_error("ipoe: cannot open generic netlink socket\n");
- return -1;
- }
-
- nlh = &req.n;
- nlh->nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
- nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
- nlh->nlmsg_type = ipoe_genl_id;
-
- ghdr = NLMSG_DATA(&req.n);
- ghdr->cmd = IPOE_CMD_ADD_VLAN_MON_VID;
-
- addattr32(nlh, 1024, IPOE_ATTR_IFINDEX, ifindex);
- addattr32(nlh, 1024, IPOE_ATTR_ADDR, vid);
-
- if (rtnl_talk(&rth, nlh, 0, 0, nlh, NULL, NULL, 0) < 0 ) {
- log_error("ipoe: nl_add_vlan_mon_vid: error talking to kernel\n");
- r = -1;
- }
-
- rtnl_close(&rth);
-
- return r;
-}
-
-
-int ipoe_nl_del_vlan_mon(int ifindex)
-{
- struct nlmsghdr *nlh;
- struct genlmsghdr *ghdr;
- struct {
- struct nlmsghdr n;
- char buf[1024];
- } req;
-
- if (rth.fd == -1)
- return -1;
-
- nlh = &req.n;
- nlh->nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
- nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
- nlh->nlmsg_type = ipoe_genl_id;
-
- ghdr = NLMSG_DATA(&req.n);
- ghdr->cmd = IPOE_CMD_DEL_VLAN_MON;
-
- addattr32(nlh, 1024, IPOE_ATTR_IFINDEX, ifindex);
-
- if (rtnl_talk(&rth, nlh, 0, 0, nlh, NULL, NULL, 0) < 0 ) {
- log_error("ipoe: nl_del_vlan_mon: error talking to kernel\n");
- return -1;
- }
-
- return 0;
-}
-
-
static void ipoe_up_handler(const struct sockaddr_nl *addr, struct nlmsghdr *h)
{
struct rtattr *tb[PKT_ATTR_MAX + 1];
@@ -587,43 +487,6 @@ static void ipoe_up_handler(const struct sockaddr_nl *addr, struct nlmsghdr *h)
}
}
-static void ipoe_vlan_mon_handler(const struct sockaddr_nl *addr, struct nlmsghdr *h)
-{
- struct rtattr *tb[PKT_ATTR_MAX + 1];
- struct rtattr *tb2[IPOE_ATTR_MAX + 1];
- struct genlmsghdr *ghdr = NLMSG_DATA(h);
- int len = h->nlmsg_len;
- struct rtattr *attrs;
- int i;
- int ifindex, vid;
-
- len -= NLMSG_LENGTH(GENL_HDRLEN);
-
- if (len < 0) {
- log_warn("ipoe: wrong controller message length %d\n", len);
- return;
- }
-
- attrs = (struct rtattr *)((char *)ghdr + GENL_HDRLEN);
- parse_rtattr(tb, PKT_ATTR_MAX, attrs, len);
-
- for (i = 1; i < PKT_ATTR_MAX; i++) {
- if (!tb[i])
- break;
-
- parse_rtattr_nested(tb2, IPOE_ATTR_MAX, tb[i]);
-
- if (!tb2[IPOE_ATTR_IFINDEX] || !tb2[IPOE_ATTR_ADDR])
- continue;
-
- ifindex = *(uint32_t *)(RTA_DATA(tb2[IPOE_ATTR_IFINDEX]));
- vid = *(uint32_t *)(RTA_DATA(tb2[IPOE_ATTR_ADDR]));
-
- ipoe_vlan_notify(ifindex, vid);
- }
-}
-
-
static int ipoe_mc_read(struct triton_md_handler_t *h)
{
int status;
@@ -685,8 +548,6 @@ static int ipoe_mc_read(struct triton_md_handler_t *h)
if (ghdr->cmd == IPOE_REP_PKT)
ipoe_up_handler(&nladdr, hdr);
- else if (ghdr->cmd == IPOE_VLAN_NOTIFY)
- ipoe_vlan_mon_handler(&nladdr, hdr);
status -= NLMSG_ALIGN(len);
hdr = (struct nlmsghdr*)((char*)hdr + NLMSG_ALIGN(len));
diff --git a/accel-pppd/ctrl/pppoe/pppoe.c b/accel-pppd/ctrl/pppoe/pppoe.c
index 995a60d4..fc8a0327 100644
--- a/accel-pppd/ctrl/pppoe/pppoe.c
+++ b/accel-pppd/ctrl/pppoe/pppoe.c
@@ -28,6 +28,7 @@
#include "iputils.h"
#include "connlimit.h"
+#include "vlan_mon.h"
#include "pppoe.h"
@@ -74,11 +75,11 @@ struct padi_t
uint8_t addr[ETH_ALEN];
};
-struct iplink_arg
-{
+struct iplink_arg {
pcre *re;
const char *opt;
void *cli;
+ long *arg1;
};
int conf_verbose;
@@ -94,6 +95,8 @@ static const char *conf_ip_pool;
enum {CSID_MAC, CSID_IFNAME, CSID_IFNAME_MAC};
static int conf_called_sid;
static int conf_cookie_timeout;
+static const char *conf_vlan_name;
+static int conf_vlan_timeout;
static mempool_t conn_pool;
static mempool_t pado_pool;
@@ -125,7 +128,30 @@ static uint8_t bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
static void pppoe_send_PADT(struct pppoe_conn_t *conn);
void pppoe_server_free(struct pppoe_serv_t *serv);
static int init_secret(struct pppoe_serv_t *serv);
-static void __pppoe_server_start(const char *ifname, const char *opt, void *cli);
+static void __pppoe_server_start(const char *ifname, const char *opt, void *cli, int parent_ifindex, int vid);
+static void pppoe_serv_timeout(struct triton_timer_t *t);
+
+static void pppoe_serv_start_timer(struct pppoe_serv_t *serv)
+{
+ pthread_mutex_lock(&serv->lock);
+ if (serv->conn_cnt) {
+ pthread_mutex_unlock(&serv->lock);
+ return;
+ }
+
+ if (conf_vlan_timeout) {
+ serv->timer.expire = pppoe_serv_timeout;
+ serv->timer.expire_tv.tv_sec = conf_vlan_timeout;
+ if (serv->timer.tpd)
+ triton_timer_mod(&serv->timer, 0);
+ else
+ triton_timer_add(&serv->ctx, &serv->timer, 0);
+ pthread_mutex_unlock(&serv->lock);
+ } else {
+ pthread_mutex_unlock(&serv->lock);
+ pppoe_server_free(serv);
+ }
+}
static void disconnect(struct pppoe_conn_t *conn)
{
@@ -144,9 +170,15 @@ static void disconnect(struct pppoe_conn_t *conn)
pthread_mutex_lock(&conn->serv->lock);
list_del(&conn->entry);
conn->serv->conn_cnt--;
- if (conn->serv->stopping && conn->serv->conn_cnt == 0) {
- pthread_mutex_unlock(&conn->serv->lock);
- pppoe_server_free(conn->serv);
+ if (conn->serv->conn_cnt == 0) {
+ if (conn->serv->stopping) {
+ pthread_mutex_unlock(&conn->serv->lock);
+ pppoe_server_free(conn->serv);
+ } else if (conn->serv->vid) {
+ triton_context_call(&conn->serv->ctx, (triton_event_func)pppoe_serv_start_timer, conn->serv);
+ pthread_mutex_unlock(&conn->serv->lock);
+ } else
+ pthread_mutex_unlock(&conn->serv->lock);
} else
pthread_mutex_unlock(&conn->serv->lock);
@@ -1176,6 +1208,21 @@ static void pppoe_serv_close(struct triton_context_t *ctx)
pthread_mutex_unlock(&serv->lock);
}
+static void pppoe_serv_timeout(struct triton_timer_t *t)
+{
+ struct pppoe_serv_t *serv = container_of(t, typeof(*serv), timer);
+
+ pthread_mutex_lock(&serv->lock);
+ if (serv->conn_cnt) {
+ triton_timer_del(&serv->timer);
+ pthread_mutex_unlock(&serv->lock);
+ return;
+ }
+
+ pthread_mutex_unlock(&serv->lock);
+ pppoe_server_free(serv);
+}
+
static int parse_server(const char *opt, int *padi_limit)
{
char *ptr, *endptr;
@@ -1198,7 +1245,7 @@ static int __pppoe_add_interface_re(int index, int flags, const char *name, stru
if (pcre_exec(arg->re, NULL, name, strlen(name), 0, 0, NULL, 0) < 0)
return 0;
- __pppoe_server_start(name, arg->opt, arg->cli);
+ __pppoe_server_start(name, arg->opt, arg->cli, 0, 0);
return 0;
}
@@ -1249,12 +1296,12 @@ void pppoe_server_start(const char *opt, void *cli)
if (ptr) {
memcpy(name, opt, ptr - opt);
name[ptr - opt] = 0;
- __pppoe_server_start(name, ptr, cli);
+ __pppoe_server_start(name, ptr, cli, 0, 0);
} else
- __pppoe_server_start(opt, opt, cli);
+ __pppoe_server_start(opt, opt, cli, 0, 0);
}
-static void __pppoe_server_start(const char *ifname, const char *opt, void *cli)
+static void __pppoe_server_start(const char *ifname, const char *opt, void *cli, int parent_ifindex, int vid)
{
struct pppoe_serv_t *serv;
struct ifreq ifr;
@@ -1344,12 +1391,23 @@ static void __pppoe_server_start(const char *ifname, const char *opt, void *cli)
serv->padi_limit = padi_limit;
triton_context_register(&serv->ctx, NULL);
- triton_context_wakeup(&serv->ctx);
+
+ if (vid) {
+ serv->parent_ifindex = parent_ifindex;
+ serv->vid = vid;
+ if (conf_vlan_timeout) {
+ serv->timer.expire = pppoe_serv_timeout;
+ serv->timer.expire_tv.tv_sec = conf_vlan_timeout;
+ triton_timer_add(&serv->ctx, &serv->timer, 0);
+ }
+ }
pthread_rwlock_wrlock(&serv_lock);
list_add_tail(&serv->entry, &serv_list);
pthread_rwlock_unlock(&serv_lock);
+ triton_context_wakeup(&serv->ctx);
+
pppoe_disc_start(serv);
return;
@@ -1397,6 +1455,15 @@ void pppoe_server_free(struct pppoe_serv_t *serv)
free_delayed_pado(pado);
}
+ if (serv->timer.tpd)
+ triton_timer_del(&serv->timer);
+
+ if (serv->vid) {
+ log_info2("ipoe: remove vlan %s\n", serv->ifname);
+ iplink_vlan_del(serv->ifindex);
+ vlan_mon_add_vid(serv->parent_ifindex, ETH_P_PPP_DISC, serv->vid);
+ }
+
triton_context_unregister(&serv->ctx);
_free(serv->ifname);
_free(serv);
@@ -1438,9 +1505,233 @@ static int init_secret(struct pppoe_serv_t *serv)
return 0;
}
+void pppoe_vlan_mon_notify(int ifindex, int vid)
+{
+ struct conf_sect_t *sect = conf_get_section("pppoe");
+ struct conf_option_t *opt;
+ struct ifreq ifr;
+ char *ptr;
+ int len, r, svid;
+ pcre *re = NULL;
+ const char *pcre_err;
+ char *pattern;
+ int pcre_offset;
+ char ifname[IFNAMSIZ];
+
+ if (!sect)
+ return;
+
+ memset(&ifr, 0, sizeof(ifr));
+ ifr.ifr_ifindex = ifindex;
+ if (ioctl(sock_fd, SIOCGIFNAME, &ifr, sizeof(ifr))) {
+ log_error("pppoe: vlan-mon: failed to get interface name, ifindex=%i\n", ifindex);
+ return;
+ }
+
+ svid = iplink_vlan_get_vid(ifindex);
+
+ if (make_vlan_name(conf_vlan_name, ifr.ifr_name, svid, vid, ifname)) {
+ log_error("pppoe: vlan-mon: %s.%i: interface name is too long\n", ifr.ifr_name, vid);
+ return;
+ }
+
+ strcpy(ifr.ifr_name, ifname);
+ len = strlen(ifr.ifr_name);
+
+ if (iplink_vlan_add(ifr.ifr_name, ifindex, vid))
+ return;
+
+ log_info2("pppoe: create vlan %s parent %s\n", ifname, ifr.ifr_name);
+
+ ioctl(sock_fd, SIOCGIFFLAGS, &ifr, sizeof(ifr));
+ ifr.ifr_flags |= IFF_UP;
+ ioctl(sock_fd, SIOCSIFFLAGS, &ifr, sizeof(ifr));
+
+ if (ioctl(sock_fd, SIOCGIFINDEX, &ifr, sizeof(ifr))) {
+ log_error("pppoe: vlan-mon: %s: failed to get interface index\n", ifr.ifr_name);
+ return;
+ }
+
+ list_for_each_entry(opt, &sect->items, entry) {
+ if (strcmp(opt->name, "interface"))
+ continue;
+ if (!opt->val)
+ continue;
+
+ ptr = strchr(opt->val, ',');
+ if (!ptr)
+ ptr = strchr(opt->val, 0);
+
+ if (ptr - opt->val > 3 && memcmp(opt->val, "re:", 3) == 0) {
+ pattern = _malloc(ptr - (opt->val + 3) + 1);
+ memcpy(pattern, opt->val + 3, ptr - (opt->val + 3));
+ pattern[ptr - (opt->val + 3)] = 0;
+
+ re = pcre_compile2(pattern, 0, NULL, &pcre_err, &pcre_offset, NULL);
+
+ _free(pattern);
+
+ if (!re)
+ continue;
+
+ r = pcre_exec(re, NULL, ifr.ifr_name, len, 0, 0, NULL, 0);
+ pcre_free(re);
+
+ if (r < 0)
+ continue;
+
+ __pppoe_server_start(ifr.ifr_name, opt->val, NULL, ifindex, vid);
+ } else if (ptr - opt->val == len && memcmp(opt->val, ifr.ifr_name, len) == 0)
+ __pppoe_server_start(ifr.ifr_name, opt->val, NULL, ifindex, vid);
+ }
+}
+
+static void add_vlan_mon(const char *opt, long *mask)
+{
+ const char *ptr;
+ struct ifreq ifr;
+ int ifindex;
+ long mask1[4096/8/sizeof(long)];
+ struct pppoe_serv_t *serv;
+
+ for (ptr = opt; *ptr && *ptr != ','; ptr++);
+
+ if (ptr - opt >= IFNAMSIZ) {
+ log_error("pppoe: vlan-mon=%s: interface name is too long\n", opt);
+ return;
+ }
+
+ memset(&ifr, 0, sizeof(ifr));
+
+ memcpy(ifr.ifr_name, opt, ptr - opt);
+ ifr.ifr_name[ptr - opt] = 0;
+
+ if (ioctl(sock_fd, SIOCGIFINDEX, &ifr)) {
+ log_error("pppoe: '%s': ioctl(SIOCGIFINDEX): %s\n", ifr.ifr_name, strerror(errno));
+ return;
+ }
+
+ ifindex = ifr.ifr_ifindex;
+
+ ioctl(sock_fd, SIOCGIFFLAGS, &ifr);
+
+ if (!(ifr.ifr_flags & IFF_UP)) {
+ ifr.ifr_flags |= IFF_UP;
+
+ ioctl(sock_fd, SIOCSIFFLAGS, &ifr);
+ }
+
+ memcpy(mask1, mask, sizeof(mask1));
+ list_for_each_entry(serv, &serv_list, entry) {
+ if (serv->vid && serv->parent_ifindex == ifindex)
+ mask1[serv->vid / (8*sizeof(long))] |= 1lu << (serv->vid % (8*sizeof(long)));
+ }
+
+ vlan_mon_add(ifindex, ETH_P_PPP_DISC, mask1, sizeof(mask1));
+}
+
+static int __load_vlan_mon_re(int index, int flags, const char *name, struct iplink_arg *arg)
+{
+ struct ifreq ifr;
+ long mask1[4096/8/sizeof(long)];
+ struct pppoe_serv_t *serv;
+
+ if (pcre_exec(arg->re, NULL, name, strlen(name), 0, 0, NULL, 0) < 0)
+ return 0;
+
+ memset(&ifr, 0, sizeof(ifr));
+ strcpy(ifr.ifr_name, name);
+
+ ioctl(sock_fd, SIOCGIFFLAGS, &ifr);
+
+ if (!(ifr.ifr_flags & IFF_UP)) {
+ ifr.ifr_flags |= IFF_UP;
+
+ ioctl(sock_fd, SIOCSIFFLAGS, &ifr);
+ }
+
+ memcpy(mask1, arg->arg1, sizeof(mask1));
+ list_for_each_entry(serv, &serv_list, entry) {
+ if (serv->vid && serv->parent_ifindex == index)
+ mask1[serv->vid / (8*sizeof(long))] |= 1lu << (serv->vid % (8*sizeof(long)));
+ }
+
+ vlan_mon_add(index, ETH_P_PPP_DISC, mask1, sizeof(mask1));
+
+ return 0;
+}
+
+static void load_vlan_mon_re(const char *opt, long *mask, int len)
+{
+ pcre *re = NULL;
+ const char *pcre_err;
+ char *pattern;
+ const char *ptr;
+ int pcre_offset;
+ struct iplink_arg arg;
+
+ for (ptr = opt; *ptr && *ptr != ','; ptr++);
+
+ pattern = _malloc(ptr - (opt + 3) + 1);
+ memcpy(pattern, opt + 3, ptr - (opt + 3));
+ pattern[ptr - (opt + 3)] = 0;
+
+ re = pcre_compile2(pattern, 0, NULL, &pcre_err, &pcre_offset, NULL);
+
+ if (!re) {
+ log_error("ipoe: '%s': %s at %i\r\n", pattern, pcre_err, pcre_offset);
+ return;
+ }
+
+ arg.re = re;
+ arg.opt = opt;
+ arg.arg1 = mask;
+
+ iplink_list((iplink_list_func)__load_vlan_mon_re, &arg);
+
+ pcre_free(re);
+ _free(pattern);
+
+}
+
+static void load_vlan_mon(struct conf_sect_t *sect)
+{
+ struct conf_option_t *opt;
+ long mask[4096/8/sizeof(long)];
+ static int registered = 0;
+
+ if (!triton_module_loaded("vlan-mon"))
+ return;
+
+ if (!registered) {
+ vlan_mon_register_proto(ETH_P_PPP_DISC, pppoe_vlan_mon_notify);
+ registered = 1;
+ }
+
+ vlan_mon_del(-1, ETH_P_PPP_DISC);
+
+ list_for_each_entry(opt, &sect->items, entry) {
+ if (strcmp(opt->name, "vlan-mon"))
+ continue;
+
+ if (!opt->val)
+ continue;
+
+ if (parse_vlan_mon(opt->val, mask))
+ continue;
+
+ if (strlen(opt->val) > 3 && !memcmp(opt->val, "re:", 3))
+ load_vlan_mon_re(opt->val, mask, sizeof(mask));
+ else
+ add_vlan_mon(opt->val, mask);
+ }
+}
+
+
static void load_config(void)
{
char *opt;
+ struct conf_sect_t *s = conf_get_section("pppoe");
opt = conf_get_opt("pppoe", "verbose");
if (opt)
@@ -1529,6 +1820,20 @@ static void load_config(void)
else
log_error("pppoe: unknown called-sid type\n");
}
+
+ opt = conf_get_opt("pppoe", "vlan-name");
+ if (opt)
+ conf_vlan_name = opt;
+ else
+ conf_vlan_name = "%I.%N";
+
+ opt = conf_get_opt("pppoe", "vlan-timeout");
+ if (opt && atoi(opt) > 0)
+ conf_vlan_timeout = atoi(opt);
+ else
+ conf_vlan_timeout = 60;
+
+ load_vlan_mon(s);
}
static void load_interfaces()
diff --git a/accel-pppd/ctrl/pppoe/pppoe.h b/accel-pppd/ctrl/pppoe/pppoe.h
index 0acc5613..d044e4cf 100644
--- a/accel-pppd/ctrl/pppoe/pppoe.h
+++ b/accel-pppd/ctrl/pppoe/pppoe.h
@@ -73,6 +73,10 @@ struct pppoe_serv_t
char *ifname;
int ifindex;
+ int parent_ifindex;
+ int vid;
+ struct triton_timer_t timer;
+
uint8_t secret[SECRET_LENGTH];
DES_key_schedule des_ks;