From 9190fe47e0ce57e8f0b3360f2fe0404169b44263 Mon Sep 17 00:00:00 2001 From: Dmitry Kozlov Date: Sat, 21 Nov 2015 12:34:02 +0300 Subject: split ipoe driver to ipoe and vlan_mon introduced new module "vlan-mon" --- accel-pppd/ctrl/ipoe/ipoe.c | 66 +++++------------ accel-pppd/ctrl/ipoe/ipoe.h | 4 -- accel-pppd/ctrl/ipoe/ipoe_netlink.c | 139 ------------------------------------ 3 files changed, 19 insertions(+), 190 deletions(-) (limited to 'accel-pppd/ctrl') diff --git a/accel-pppd/ctrl/ipoe/ipoe.c b/accel-pppd/ctrl/ipoe/ipoe.c index 594df29e..d77da31f 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" @@ -2082,7 +2083,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); @@ -2205,43 +2206,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; - - 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; @@ -2266,20 +2231,18 @@ void ipoe_vlan_notify(int ifindex, int vid) svid = iplink_vlan_get_vid(ifindex); - if (make_vlan_name(ifr.ifr_name, svid, vid, ifname)) { + if (make_vlan_name(conf_vlan_name, ifr.ifr_name, svid, vid, ifname)) { 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; @@ -3012,7 +2975,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) @@ -3041,7 +3004,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; } @@ -3083,8 +3046,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, §->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 1405092e..224b9e91 100644 --- a/accel-pppd/ctrl/ipoe/ipoe.h +++ b/accel-pppd/ctrl/ipoe/ipoe.h @@ -114,7 +114,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); @@ -128,9 +127,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)); -- cgit v1.2.3 From 4a41fc593e56691172a58b511a1d9ade63982c32 Mon Sep 17 00:00:00 2001 From: Dmitry Kozlov Date: Sat, 21 Nov 2015 15:57:49 +0300 Subject: move parse_vlan_mon function to vlan-mon module --- accel-pppd/ctrl/ipoe/ipoe.c | 53 ------------------------------------------ accel-pppd/include/vlan_mon.h | 2 +- accel-pppd/vlan-mon/vlan_mon.c | 53 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 54 deletions(-) (limited to 'accel-pppd/ctrl') diff --git a/accel-pppd/ctrl/ipoe/ipoe.c b/accel-pppd/ctrl/ipoe/ipoe.c index d77da31f..46ab130d 100644 --- a/accel-pppd/ctrl/ipoe/ipoe.c +++ b/accel-pppd/ctrl/ipoe/ipoe.c @@ -2881,59 +2881,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; diff --git a/accel-pppd/include/vlan_mon.h b/accel-pppd/include/vlan_mon.h index 928c732e..c6b2db76 100644 --- a/accel-pppd/include/vlan_mon.h +++ b/accel-pppd/include/vlan_mon.h @@ -10,6 +10,6 @@ int vlan_mon_add_vid(int ifindex, int proto, int vid); int vlan_mon_del(int ifindex, int proto); int make_vlan_name(const char *pattern, const char *parent, int svid, int cvid, char *name); - +int parse_vlan_mon(const char *opt, long *mask); #endif diff --git a/accel-pppd/vlan-mon/vlan_mon.c b/accel-pppd/vlan-mon/vlan_mon.c index 898d7dcd..7f15aa06 100644 --- a/accel-pppd/vlan-mon/vlan_mon.c +++ b/accel-pppd/vlan-mon/vlan_mon.c @@ -305,6 +305,59 @@ int __export make_vlan_name(const char *pattern, const char *parent, int svid, i return 0; } +int __export 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("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("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("vlan-mon=%s: failed to parse\n", opt); + return -1; +} + static void vlan_mon_mc_close(struct triton_context_t *ctx) { -- cgit v1.2.3 From 9db2f5a3f429b749e9c12919135c2b225b25a912 Mon Sep 17 00:00:00 2001 From: Dmitry Kozlov Date: Sat, 21 Nov 2015 16:00:56 +0300 Subject: pppoe: implemented vlan monitor --- accel-pppd/accel-ppp.conf | 5 +- accel-pppd/ctrl/pppoe/pppoe.c | 324 ++++++++++++++++++++++++++++++++++++++++-- accel-pppd/ctrl/pppoe/pppoe.h | 5 + 3 files changed, 323 insertions(+), 11 deletions(-) (limited to 'accel-pppd/ctrl') diff --git a/accel-pppd/accel-ppp.conf b/accel-pppd/accel-ppp.conf index 70dbef8d..fc0fc762 100644 --- a/accel-pppd/accel-ppp.conf +++ b/accel-pppd/accel-ppp.conf @@ -78,8 +78,11 @@ called-sid=mac #tr101=1 #padi-limit=0 #ip-pool=pppoe -#interface=eth1,padi-limit=1000 #sid-uppercase=0 +#vlan-mon=eth0,10-200 +#vlan-timeout=60 +#vlan-name=%I.%N +#interface=eth1,padi-limit=1000 interface=eth0 [l2tp] diff --git a/accel-pppd/ctrl/pppoe/pppoe.c b/accel-pppd/ctrl/pppoe/pppoe.c index 3f23ebcc..25950e79 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" @@ -75,11 +76,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; @@ -95,6 +96,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; @@ -127,7 +130,30 @@ static void pppoe_send_PADT(struct pppoe_conn_t *conn); static void _server_stop(struct pppoe_serv_t *serv); 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_lock(&serv->lock); + pppoe_server_free(serv); + } +} static void disconnect(struct pppoe_conn_t *conn) { @@ -148,9 +174,14 @@ 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) { + pthread_mutex_unlock(&conn->serv->lock); + triton_context_call(&conn->serv->ctx, (triton_event_func)pppoe_serv_start_timer, conn->serv); + } } else pthread_mutex_unlock(&conn->serv->lock); @@ -1238,6 +1269,18 @@ 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); + + if (serv->conn_cnt) { + triton_timer_del(&serv->timer); + return; + } + + _server_stop(serv); +} + static int parse_server(const char *opt, int *padi_limit) { char *ptr, *endptr; @@ -1260,7 +1303,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; } @@ -1311,12 +1354,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; int sock; @@ -1415,6 +1458,8 @@ static void __pppoe_server_start(const char *ifname, const char *opt, void *cli) goto out_err; } + serv->ifindex = ifr.ifr_ifindex; + memset(&sa, 0, sizeof(sa)); sa.sll_family = AF_PACKET; sa.sll_protocol = htons(ETH_P_PPP_DISC); @@ -1447,6 +1492,17 @@ static void __pppoe_server_start(const char *ifname, const char *opt, void *cli) serv->padi_limit = padi_limit; triton_context_register(&serv->ctx, NULL); + + 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); + } + } + triton_md_register_handler(&serv->ctx, &serv->hnd); triton_md_enable_handler(&serv->hnd, MD_MODE_READ); triton_context_wakeup(&serv->ctx); @@ -1501,7 +1557,17 @@ void pppoe_server_free(struct pppoe_serv_t *serv) free_delayed_pado(pado); } + if (serv->timer.tpd) + triton_timer_del(&serv->timer); + triton_md_unregister_handler(&serv->hnd, 1); + + 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); @@ -1543,9 +1609,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, §->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, §->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) @@ -1634,6 +1924,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 3b15d120..50d2d9b9 100644 --- a/accel-pppd/ctrl/pppoe/pppoe.h +++ b/accel-pppd/ctrl/pppoe/pppoe.h @@ -69,6 +69,11 @@ struct pppoe_serv_t struct triton_md_handler_t hnd; uint8_t hwaddr[ETH_ALEN]; char *ifname; + int ifindex; + + int parent_ifindex; + int vid; + struct triton_timer_t timer; uint8_t secret[SECRET_LENGTH]; DES_key_schedule des_ks; -- cgit v1.2.3 From de64a4d20ad6d2cd0238ab9a0ee776f6086a4bfb Mon Sep 17 00:00:00 2001 From: Dmitry Kozlov Date: Mon, 23 Nov 2015 11:21:58 +0300 Subject: pppoe: improved locking --- accel-pppd/ctrl/pppoe/pppoe.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'accel-pppd/ctrl') diff --git a/accel-pppd/ctrl/pppoe/pppoe.c b/accel-pppd/ctrl/pppoe/pppoe.c index 25950e79..8d20507a 100644 --- a/accel-pppd/ctrl/pppoe/pppoe.c +++ b/accel-pppd/ctrl/pppoe/pppoe.c @@ -150,7 +150,7 @@ static void pppoe_serv_start_timer(struct pppoe_serv_t *serv) triton_timer_add(&serv->ctx, &serv->timer, 0); pthread_mutex_unlock(&serv->lock); } else { - pthread_mutex_lock(&serv->lock); + pthread_mutex_unlock(&serv->lock); pppoe_server_free(serv); } } @@ -179,8 +179,8 @@ static void disconnect(struct pppoe_conn_t *conn) pthread_mutex_unlock(&conn->serv->lock); pppoe_server_free(conn->serv); } else if (conn->serv->vid) { - pthread_mutex_unlock(&conn->serv->lock); 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); @@ -1273,12 +1273,15 @@ 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; } - _server_stop(serv); + pthread_mutex_unlock(&serv->lock); + pppoe_server_free(serv); } static int parse_server(const char *opt, int *padi_limit) -- cgit v1.2.3 From dd0d5ed51e5351d7be2cbdf86b04965b7bcb136b Mon Sep 17 00:00:00 2001 From: Dmitry Kozlov Date: Tue, 24 Nov 2015 11:43:33 +0300 Subject: pppoe: fix missing pthread_mutex_unlock --- accel-pppd/ctrl/pppoe/pppoe.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'accel-pppd/ctrl') diff --git a/accel-pppd/ctrl/pppoe/pppoe.c b/accel-pppd/ctrl/pppoe/pppoe.c index 8d20507a..b51b4fed 100644 --- a/accel-pppd/ctrl/pppoe/pppoe.c +++ b/accel-pppd/ctrl/pppoe/pppoe.c @@ -181,7 +181,8 @@ static void disconnect(struct pppoe_conn_t *conn) } 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); -- cgit v1.2.3