summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--accel-pppd/ctrl/ipoe/ipoe.c88
-rw-r--r--accel-pppd/ctrl/ipoe/ipoe.h1
-rw-r--r--accel-pppd/ctrl/pppoe/pppoe.c85
-rw-r--r--accel-pppd/ctrl/pppoe/pppoe.h4
-rw-r--r--accel-pppd/include/vlan_mon.h9
-rw-r--r--accel-pppd/libnetlink/iputils.c19
-rw-r--r--accel-pppd/libnetlink/iputils.h4
-rw-r--r--accel-pppd/libnetlink/libnetlink.c3
-rw-r--r--accel-pppd/vlan-mon/vlan_mon.c66
-rw-r--r--drivers/vlan_mon/vlan_mon.c36
-rw-r--r--drivers/vlan_mon/vlan_mon.h1
11 files changed, 228 insertions, 88 deletions
diff --git a/accel-pppd/ctrl/ipoe/ipoe.c b/accel-pppd/ctrl/ipoe/ipoe.c
index e05ce9a9..bb1f9629 100644
--- a/accel-pppd/ctrl/ipoe/ipoe.c
+++ b/accel-pppd/ctrl/ipoe/ipoe.c
@@ -131,7 +131,7 @@ static const char *conf_attr_dhcp_opt82_circuit_id;
static int conf_l4_redirect_table;
static int conf_l4_redirect_on_reject;
static const char *conf_l4_redirect_ipset;
-static int conf_vlan_timeout = 30;
+static int conf_vlan_timeout;
static int conf_max_request = 3;
static int conf_session_timeout;
static int conf_idle_timeout;
@@ -193,7 +193,7 @@ static void __ipoe_session_activate(struct ipoe_session *ses);
static void ipoe_ses_recv_dhcpv4(struct dhcpv4_serv *dhcpv4, struct dhcpv4_packet *pack);
static void __ipoe_recv_dhcpv4(struct dhcpv4_serv *dhcpv4, struct dhcpv4_packet *pack, int force);
static void ipoe_session_keepalive(struct dhcpv4_packet *pack);
-static void add_interface(const char *ifname, int ifindex, const char *opt, int parent_ifindex, int vid);
+static void add_interface(const char *ifname, int ifindex, const char *opt, int parent_ifindex, int vid, int vlan_mon);
static int get_offer_delay();
static void __ipoe_session_start(struct ipoe_session *ses);
static int ipoe_rad_send_auth_request(struct rad_plugin_t *rad, struct rad_packet_t *pack);
@@ -1109,7 +1109,7 @@ static void ipoe_session_finished(struct ap_session *s)
pthread_mutex_lock(&ses->serv->lock);
list_del(&ses->entry);
- if ((ses->serv->vid || ses->serv->need_close) && list_empty(&ses->serv->sessions))
+ if ((ses->serv->vlan_mon || ses->serv->need_close) && list_empty(&ses->serv->sessions))
triton_context_call(&ses->serv->ctx, (triton_event_func)ipoe_serv_release, ses->serv);
pthread_mutex_unlock(&ses->serv->lock);
@@ -1913,6 +1913,8 @@ void ipoe_recv_up(int ifindex, struct ethhdr *eth, struct iphdr *iph, struct _ar
struct ipoe_session *ses;
in_addr_t saddr = arph ? arph->ar_spa : iph->saddr;
+ log_debug("ipoe: recv up %08x\n", saddr);
+
pthread_mutex_lock(&serv_lock);
list_for_each_entry(serv, &serv_list, entry) {
if (serv->ifindex != ifindex)
@@ -2100,7 +2102,7 @@ static void ipoe_serv_release(struct ipoe_serv *serv)
}
pthread_mutex_unlock(&serv->lock);
- if (serv->vid && !serv->need_close && !ap_shutdown && !serv->opt_auto) {
+ if (serv->vlan_mon && !serv->need_close && !ap_shutdown && !serv->opt_auto) {
if (serv->timer.tpd)
triton_timer_mod(&serv->timer, 0);
else
@@ -2147,7 +2149,7 @@ static void ipoe_serv_release(struct ipoe_serv *serv)
if (!serv->opt_auto)
ipoe_nl_del_interface(serv->ifindex);
- if (serv->vid) {
+ if (serv->vlan_mon) {
log_info2("ipoe: remove vlan %s\n", serv->ifname);
iplink_vlan_del(serv->ifindex);
vlan_mon_add_vid(serv->parent_ifindex, ETH_P_IP, serv->vid);
@@ -2286,10 +2288,8 @@ static void set_vlan_timeout(struct ipoe_serv *serv)
serv->timer.expire = ipoe_serv_timeout;
serv->timer.expire_tv.tv_sec = conf_vlan_timeout;
- pthread_mutex_lock(&serv->lock);
if (list_empty(&serv->sessions))
triton_timer_add(&serv->ctx, &serv->timer, 0);
- pthread_mutex_unlock(&serv->lock);
}
void ipoe_vlan_mon_notify(int ifindex, int vid, int vlan_ifindex)
@@ -2315,7 +2315,7 @@ void ipoe_vlan_mon_notify(int ifindex, int vid, int vlan_ifindex)
return;
}
- svid = iplink_vlan_get_vid(ifindex);
+ svid = iplink_vlan_get_vid(ifindex, NULL);
#ifdef USE_LUA
if (!memcmp(conf_vlan_name, "lua:", 4))
@@ -2334,12 +2334,9 @@ void ipoe_vlan_mon_notify(int ifindex, int vid, int vlan_ifindex)
pthread_mutex_lock(&serv_lock);
list_for_each_entry(serv, &serv_list, entry) {
if (serv->ifindex == vlan_ifindex) {
- if (!serv->vid) {
- serv->vid = vid;
- serv->parent_ifindex = ifindex;
-
- if (conf_vlan_timeout)
- triton_context_call(&serv->ctx, (triton_event_func)set_vlan_timeout, serv);
+ if (!serv->vlan_mon) {
+ serv->vlan_mon = 1;
+ set_vlan_timeout(serv);
}
pthread_mutex_unlock(&serv_lock);
return;
@@ -2416,15 +2413,16 @@ void ipoe_vlan_mon_notify(int ifindex, int vid, int vlan_ifindex)
if (r < 0)
continue;
- add_interface(ifname, ifr.ifr_ifindex, opt->val, ifindex, vid);
+ add_interface(ifname, ifr.ifr_ifindex, opt->val, ifindex, vid, 1);
return;
} else if (ptr - opt->val == len && memcmp(opt->val, ifname, len) == 0) {
- add_interface(ifname, ifr.ifr_ifindex, opt->val, ifindex, vid);
+ add_interface(ifname, ifr.ifr_ifindex, opt->val, ifindex, vid, 1);
return;
}
}
log_warn("ipoe: vlan %s not started\n", ifname);
+ iplink_vlan_del(ifr.ifr_ifindex);
}
static void ipoe_serv_timeout(struct triton_timer_t *t)
@@ -2436,7 +2434,7 @@ static void ipoe_serv_timeout(struct triton_timer_t *t)
ipoe_serv_release(serv);
}
-static void add_interface(const char *ifname, int ifindex, const char *opt, int parent_ifindex, int vid)
+static void add_interface(const char *ifname, int ifindex, const char *opt, int parent_ifindex, int vid, int vlan_mon)
{
char *str0 = NULL, *str, *ptr1, *ptr2;
int end;
@@ -2633,6 +2631,9 @@ static void add_interface(const char *ifname, int ifindex, const char *opt, int
}
pthread_mutex_unlock(&serv_lock);
+ if (vid && !vlan_mon && vlan_mon_check_busy(parent_ifindex, vid))
+ return;
+
if (!opt_auto) {
if (opt_up)
ipoe_nl_add_interface(ifindex, opt_mode);
@@ -2695,7 +2696,7 @@ static void add_interface(const char *ifname, int ifindex, const char *opt, int
#ifdef USE_LUA
serv->opt_lua_username_func = opt_lua_username_func;
#endif
- serv->parent_ifindex = parent_ifindex = parent_ifindex;
+ serv->parent_ifindex = parent_ifindex;
serv->vid = vid;
serv->active = 1;
INIT_LIST_HEAD(&serv->sessions);
@@ -2718,10 +2719,9 @@ static void add_interface(const char *ifname, int ifindex, const char *opt, int
if (serv->opt_arp)
serv->arp = arpd_start(serv);
- if (vid) {
- serv->timer.expire = ipoe_serv_timeout;
- serv->timer.expire_tv.tv_sec = conf_vlan_timeout;
- triton_timer_add(&serv->ctx, &serv->timer, 0);
+ if (vlan_mon) {
+ serv->vlan_mon = 1;
+ set_vlan_timeout(serv);
}
if (serv->opt_auto && !serv->opt_shared)
@@ -2749,6 +2749,7 @@ static void load_interface(const char *opt)
const char *ptr;
struct ifreq ifr;
struct ipoe_serv *serv;
+ int vid, iflink = 0;
for (ptr = opt; *ptr && *ptr != ','; ptr++);
@@ -2763,7 +2764,7 @@ static void load_interface(const char *opt)
continue;
if (!strcmp(serv->ifname, ifr.ifr_name)) {
- add_interface(serv->ifname, serv->ifindex, opt, 0, 0);
+ add_interface(serv->ifname, serv->ifindex, opt, 0, 0, 0);
return;
}
}
@@ -2773,15 +2774,17 @@ static void load_interface(const char *opt)
return;
}
- add_interface(ifr.ifr_name, ifr.ifr_ifindex, opt, 0, 0);
+ vid = iplink_vlan_get_vid(ifr.ifr_ifindex, &iflink);
+
+ add_interface(ifr.ifr_name, ifr.ifr_ifindex, opt, iflink, vid, 0);
}
-static int __load_interface_re(int index, int flags, const char *name, struct iplink_arg *arg)
+static int __load_interface_re(int index, int flags, const char *name, int iflink, int vid, struct iplink_arg *arg)
{
if (pcre_exec(arg->re, NULL, name, strlen(name), 0, 0, NULL, 0) < 0)
return 0;
- add_interface(name, index, arg->opt, 0, 0);
+ add_interface(name, index, arg->opt, iflink, vid, 0);
return 0;
}
@@ -2819,7 +2822,7 @@ static void load_interface_re(const char *opt)
continue;
if (pcre_exec(re, NULL, serv->ifname, strlen(serv->ifname), 0, 0, NULL, 0) >= 0)
- add_interface(serv->ifname, serv->ifindex, opt, 0, 0);
+ add_interface(serv->ifname, serv->ifindex, opt, 0, 0, 0);
}
pcre_free(re);
@@ -3049,14 +3052,21 @@ static void add_vlan_mon(const char *opt, long *mask)
memcpy(mask1, mask, sizeof(mask1));
list_for_each_entry(serv, &serv_list, entry) {
- if (serv->vid && serv->parent_ifindex == ifindex)
+ if (serv->parent_ifindex == ifindex &&
+ !(mask1[serv->vid / (8*sizeof(long))] & 1lu << (serv->vid % (8*sizeof(long))))) {
mask1[serv->vid / (8*sizeof(long))] |= 1lu << (serv->vid % (8*sizeof(long)));
+
+ if (!serv->vlan_mon) {
+ serv->vlan_mon = 1;
+ set_vlan_timeout(serv);
+ }
+ }
}
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)
+static int __load_vlan_mon_re(int index, int flags, const char *name, int iflink, int vid, struct iplink_arg *arg)
{
struct ifreq ifr;
long mask1[4096/8/sizeof(long)];
@@ -3065,21 +3075,25 @@ static int __load_vlan_mon_re(int index, int flags, const char *name, struct ipl
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;
+ if (!(flags & IFF_UP)) {
+ memset(&ifr, 0, sizeof(ifr));
+ strcpy(ifr.ifr_name, name);
+ ifr.ifr_flags = 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)
+ if (serv->parent_ifindex == index &&
+ !(mask1[serv->vid / (8*sizeof(long))] & (1lu << (serv->vid % (8*sizeof(long)))))) {
mask1[serv->vid / (8*sizeof(long))] |= 1lu << (serv->vid % (8*sizeof(long)));
+
+ if (!serv->vlan_mon) {
+ serv->vlan_mon = 1;
+ set_vlan_timeout(serv);
+ }
+ }
}
vlan_mon_add(index, ETH_P_IP, mask1, sizeof(mask1));
diff --git a/accel-pppd/ctrl/ipoe/ipoe.h b/accel-pppd/ctrl/ipoe/ipoe.h
index c8b03b9c..33bd6dfe 100644
--- a/accel-pppd/ctrl/ipoe/ipoe.h
+++ b/accel-pppd/ctrl/ipoe/ipoe.h
@@ -64,6 +64,7 @@ struct ipoe_serv {
int opt_ipv6:1;
int need_close:1;
int active:1;
+ int vlan_mon:1;
};
struct ipoe_session {
diff --git a/accel-pppd/ctrl/pppoe/pppoe.c b/accel-pppd/ctrl/pppoe/pppoe.c
index be056908..70978cf3 100644
--- a/accel-pppd/ctrl/pppoe/pppoe.c
+++ b/accel-pppd/ctrl/pppoe/pppoe.c
@@ -133,8 +133,9 @@ 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, int parent_ifindex, int vid);
+static void __pppoe_server_start(const char *ifname, const char *opt, void *cli, int parent_ifindex, int vid, int vlan_mon);
static void pppoe_serv_timeout(struct triton_timer_t *t);
+static void set_vlan_timeout(struct pppoe_serv_t *serv);
static void pppoe_serv_start_timer(struct pppoe_serv_t *serv)
{
@@ -147,10 +148,7 @@ static void pppoe_serv_start_timer(struct pppoe_serv_t *serv)
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);
+ triton_timer_add(&serv->ctx, &serv->timer, 0);
pthread_mutex_unlock(&serv->lock);
} else {
pthread_mutex_unlock(&serv->lock);
@@ -179,7 +177,7 @@ static void disconnect(struct pppoe_conn_t *conn)
if (conn->serv->stopping) {
pthread_mutex_unlock(&conn->serv->lock);
pppoe_server_free(conn->serv);
- } else if (conn->serv->vid) {
+ } else if (conn->serv->vlan_mon) {
triton_context_call(&conn->serv->ctx, (triton_event_func)pppoe_serv_start_timer, conn->serv);
pthread_mutex_unlock(&conn->serv->lock);
} else
@@ -1291,12 +1289,12 @@ out_err:
return -1;
}
-static int __pppoe_add_interface_re(int index, int flags, const char *name, struct iplink_arg *arg)
+static int __pppoe_add_interface_re(int index, int flags, const char *name, int iflink, int vid, struct iplink_arg *arg)
{
if (pcre_exec(arg->re, NULL, name, strlen(name), 0, 0, NULL, 0) < 0)
return 0;
- __pppoe_server_start(name, arg->opt, arg->cli, 0, 0);
+ __pppoe_server_start(name, arg->opt, arg->cli, iflink, vid, 0);
return 0;
}
@@ -1347,9 +1345,9 @@ 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, 0, 0);
+ __pppoe_server_start(name, ptr, cli, -1, 0, 0);
} else
- __pppoe_server_start(opt, opt, cli, 0, 0);
+ __pppoe_server_start(opt, opt, cli, -1, 0, 0);
}
static void pppoe_serv_ctx_switch(struct triton_context_t *ctx, void *arg)
@@ -1359,7 +1357,7 @@ static void pppoe_serv_ctx_switch(struct triton_context_t *ctx, void *arg)
log_switch(ctx, NULL);
}
-static void __pppoe_server_start(const char *ifname, const char *opt, void *cli, int parent_ifindex, int vid)
+static void __pppoe_server_start(const char *ifname, const char *opt, void *cli, int parent_ifindex, int vid, int vlan_mon)
{
struct pppoe_serv_t *serv;
struct ifreq ifr;
@@ -1384,6 +1382,9 @@ static void __pppoe_server_start(const char *ifname, const char *opt, void *cli,
}
pthread_rwlock_unlock(&serv_lock);
+ if (vid && !vlan_mon && vlan_mon_check_busy(parent_ifindex, vid))
+ return;
+
serv = _malloc(sizeof(*serv));
memset(serv, 0, sizeof(*serv));
@@ -1447,10 +1448,15 @@ static void __pppoe_server_start(const char *ifname, const char *opt, void *cli,
goto out_err;
}
+ if (parent_ifindex == -1)
+ vid = iplink_vlan_get_vid(ifr.ifr_ifindex, &parent_ifindex);
+
serv->ctx.close = pppoe_serv_close;
serv->ctx.before_switch = pppoe_serv_ctx_switch;
serv->ifname = _strdup(ifname);
serv->ifindex = ifr.ifr_ifindex;
+ serv->parent_ifindex = parent_ifindex;
+ serv->vid = vid;
serv->net = net;
pthread_mutex_init(&serv->lock, NULL);
@@ -1468,14 +1474,9 @@ static void __pppoe_server_start(const char *ifname, const char *opt, void *cli,
goto out_err;
}
- 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);
- }
+ if (vlan_mon) {
+ serv->vlan_mon = 1;
+ set_vlan_timeout(serv);
}
pthread_rwlock_wrlock(&serv_lock);
@@ -1532,7 +1533,7 @@ void pppoe_server_free(struct pppoe_serv_t *serv)
if (serv->timer.tpd)
triton_timer_del(&serv->timer);
- if (serv->vid) {
+ if (serv->vlan_mon) {
log_info2("pppoe: remove vlan %s\n", serv->ifname);
iplink_vlan_del(serv->ifindex);
vlan_mon_add_vid(serv->parent_ifindex, ETH_P_PPP_DISC, serv->vid);
@@ -1579,6 +1580,16 @@ static int init_secret(struct pppoe_serv_t *serv)
return 0;
}
+static void set_vlan_timeout(struct pppoe_serv_t *serv)
+{
+ if (conf_vlan_timeout) {
+ serv->timer.expire = pppoe_serv_timeout;
+ serv->timer.expire_tv.tv_sec = conf_vlan_timeout;
+ if (!serv->conn_cnt)
+ triton_timer_add(&serv->ctx, &serv->timer, 0);
+ }
+}
+
void pppoe_vlan_mon_notify(int ifindex, int vid, int vlan_ifindex)
{
struct conf_sect_t *sect = conf_get_section("pppoe");
@@ -1602,7 +1613,7 @@ void pppoe_vlan_mon_notify(int ifindex, int vid, int vlan_ifindex)
return;
}
- svid = iplink_vlan_get_vid(ifindex);
+ svid = iplink_vlan_get_vid(ifindex, NULL);
#ifdef USE_LUA
if (!memcmp(conf_vlan_name, "lua:", 4))
@@ -1621,6 +1632,10 @@ void pppoe_vlan_mon_notify(int ifindex, int vid, int vlan_ifindex)
pthread_rwlock_rdlock(&serv_lock);
list_for_each_entry(serv, &serv_list, entry) {
if (serv->ifindex == vlan_ifindex) {
+ if (!serv->vlan_mon) {
+ serv->vlan_mon = 1;
+ set_vlan_timeout(serv);
+ }
pthread_rwlock_unlock(&serv_lock);
return;
}
@@ -1696,15 +1711,16 @@ void pppoe_vlan_mon_notify(int ifindex, int vid, int vlan_ifindex)
if (r < 0)
continue;
- __pppoe_server_start(ifr.ifr_name, opt->val, NULL, ifindex, vid);
+ __pppoe_server_start(ifr.ifr_name, opt->val, NULL, ifindex, vid, 1);
return;
} 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);
+ __pppoe_server_start(ifr.ifr_name, opt->val, NULL, ifindex, vid, 1);
return;
}
}
log_warn("pppoe: vlan %s not started\n", ifname);
+ iplink_vlan_del(ifr.ifr_ifindex);
}
static void add_vlan_mon(const char *opt, long *mask)
@@ -1744,14 +1760,21 @@ static void add_vlan_mon(const char *opt, long *mask)
memcpy(mask1, mask, sizeof(mask1));
list_for_each_entry(serv, &serv_list, entry) {
- if (serv->vid && serv->parent_ifindex == ifindex)
+ if (serv->parent_ifindex == ifindex &&
+ !(mask1[serv->vid / (8*sizeof(long))] & 1lu << (serv->vid % (8*sizeof(long))))) {
mask1[serv->vid / (8*sizeof(long))] |= 1lu << (serv->vid % (8*sizeof(long)));
+
+ if (!serv->vlan_mon) {
+ serv->vlan_mon = 1;
+ set_vlan_timeout(serv);
+ }
+ }
}
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)
+static int __load_vlan_mon_re(int index, int flags, const char *name, int iflink, int vid, struct iplink_arg *arg)
{
struct ifreq ifr;
long mask1[4096/8/sizeof(long)];
@@ -1773,8 +1796,15 @@ static int __load_vlan_mon_re(int index, int flags, const char *name, struct ipl
memcpy(mask1, arg->arg1, sizeof(mask1));
list_for_each_entry(serv, &serv_list, entry) {
- if (serv->vid && serv->parent_ifindex == index)
+ if (serv->parent_ifindex == index &&
+ !(mask1[serv->vid / (8*sizeof(long))] & (1lu << (serv->vid % (8*sizeof(long)))))) {
mask1[serv->vid / (8*sizeof(long))] |= 1lu << (serv->vid % (8*sizeof(long)));
+
+ if (!serv->vlan_mon) {
+ serv->vlan_mon = 1;
+ set_vlan_timeout(serv);
+ }
+ }
}
vlan_mon_add(index, ETH_P_PPP_DISC, mask1, sizeof(mask1));
@@ -1996,13 +2026,12 @@ static void pppoe_init(void)
return;
}
+ load_interfaces();
load_config();
connlimit_loaded = triton_module_loaded("connlimit");
triton_event_register_handler(EV_CONFIG_RELOAD, (triton_event_func)load_config);
-
- triton_context_call(NULL, (triton_event_func)load_interfaces, NULL);
}
DEFINE_INIT(21, pppoe_init);
diff --git a/accel-pppd/ctrl/pppoe/pppoe.h b/accel-pppd/ctrl/pppoe/pppoe.h
index a8830235..aac169ed 100644
--- a/accel-pppd/ctrl/pppoe/pppoe.h
+++ b/accel-pppd/ctrl/pppoe/pppoe.h
@@ -86,7 +86,6 @@ struct pppoe_serv_t
DES_key_schedule des_ks;
pthread_mutex_t lock;
- int stopping:1;
unsigned int conn_cnt;
struct list_head conn_list;
@@ -97,6 +96,9 @@ struct pppoe_serv_t
int padi_cnt;
int padi_limit;
time_t last_padi_limit_warn;
+
+ int stopping:1;
+ int vlan_mon:1;
};
extern int conf_verbose;
diff --git a/accel-pppd/include/vlan_mon.h b/accel-pppd/include/vlan_mon.h
index 328e2303..ebcfdc6c 100644
--- a/accel-pppd/include/vlan_mon.h
+++ b/accel-pppd/include/vlan_mon.h
@@ -3,11 +3,12 @@
typedef void (*vlan_mon_notify)(int ifindex, int vid, int vlan_ifindex);
-void vlan_mon_register_proto(int proto, vlan_mon_notify cb);
+void vlan_mon_register_proto(uint16_t proto, vlan_mon_notify cb);
-int vlan_mon_add(int ifindex, int proto, long *mask, int len);
-int vlan_mon_add_vid(int ifindex, int proto, int vid);
-int vlan_mon_del(int ifindex, int proto);
+int vlan_mon_add(int ifindex, uint16_t proto, long *mask, int len);
+int vlan_mon_add_vid(int ifindex, uint16_t proto, uint16_t vid);
+int vlan_mon_del(int ifindex, uint16_t proto);
+int vlan_mon_check_busy(int ifindex, uint16_t vid);
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);
diff --git a/accel-pppd/libnetlink/iputils.c b/accel-pppd/libnetlink/iputils.c
index e9b82857..ee536744 100644
--- a/accel-pppd/libnetlink/iputils.c
+++ b/accel-pppd/libnetlink/iputils.c
@@ -72,7 +72,9 @@ static int store_nlmsg(const struct sockaddr_nl *who, struct nlmsghdr *n, void *
{
struct ifinfomsg *ifi = NLMSG_DATA(n);
struct rtattr *tb[IFLA_MAX + 1];
+ struct rtattr *tb2[IFLA_MAX + 1];
struct arg *a = arg;
+ int vid = 0, iflink = 0;
if (n->nlmsg_type != RTM_NEWLINK)
return 0;
@@ -86,9 +88,19 @@ static int store_nlmsg(const struct sockaddr_nl *who, struct nlmsghdr *n, void *
if (tb[IFLA_IFNAME] == NULL)
return 0;
+ if (tb[IFLA_LINKINFO]) {
+ parse_rtattr_nested(tb2, IFLA_MAX, tb[IFLA_LINKINFO]);
+ if (!strcmp(RTA_DATA(tb2[IFLA_INFO_KIND]), "vlan")) {
+ parse_rtattr_nested(tb2, IFLA_MAX, tb2[IFLA_INFO_DATA]);
+ vid = *(uint16_t *)RTA_DATA(tb2[IFLA_VLAN_ID]);
+ }
+ }
+
+ if (tb[IFLA_LINK])
+ iflink = *(int *)RTA_DATA(tb[IFLA_LINK]);
//printf("%i %s\n", ifi->ifi_index, RTA_DATA(tb[IFLA_IFNAME]));
- return a->func(ifi->ifi_index, ifi->ifi_flags, RTA_DATA(tb[IFLA_IFNAME]), a->arg);
+ return a->func(ifi->ifi_index, ifi->ifi_flags, RTA_DATA(tb[IFLA_IFNAME]), iflink, vid, a->arg);
}
int __export iplink_list(iplink_list_func func, void *arg)
@@ -250,7 +262,7 @@ int __export iplink_vlan_del(int ifindex)
return 0;
}
-int __export iplink_vlan_get_vid(int ifindex)
+int __export iplink_vlan_get_vid(int ifindex, int *iflink)
{
struct iplink_req {
struct nlmsghdr n;
@@ -294,6 +306,9 @@ int __export iplink_vlan_get_vid(int ifindex)
if (!tb[IFLA_LINKINFO])
return 0;
+ if (iflink && tb[IFLA_LINK])
+ *iflink = *(int *)RTA_DATA(tb[IFLA_LINK]);
+
parse_rtattr_nested(tb, IFLA_MAX, tb[IFLA_LINKINFO]);
if (strcmp(RTA_DATA(tb[IFLA_INFO_KIND]), "vlan"))
diff --git a/accel-pppd/libnetlink/iputils.h b/accel-pppd/libnetlink/iputils.h
index 1ce04103..d5f9701d 100644
--- a/accel-pppd/libnetlink/iputils.h
+++ b/accel-pppd/libnetlink/iputils.h
@@ -3,14 +3,14 @@
#include <linux/if_link.h>
-typedef int (*iplink_list_func)(int index, int flags, const char *name, void *arg);
+typedef int (*iplink_list_func)(int index, int flags, const char *name, int iflink, int vid, void *arg);
int iplink_list(iplink_list_func func, void *arg);
int iplink_get_stats(int ifindex, struct rtnl_link_stats *stats);
int iplink_vlan_add(const char *ifname, int ifindex, int vid);
int iplink_vlan_del(int ifindex);
-int iplink_vlan_get_vid(int ifindex);
+int iplink_vlan_get_vid(int ifindex, int *iflink);
int ipaddr_add(int ifindex, in_addr_t addr, int mask);
int ipaddr_del(int ifindex, in_addr_t addr, int mask);
diff --git a/accel-pppd/libnetlink/libnetlink.c b/accel-pppd/libnetlink/libnetlink.c
index 0536783a..aca16aff 100644
--- a/accel-pppd/libnetlink/libnetlink.c
+++ b/accel-pppd/libnetlink/libnetlink.c
@@ -382,7 +382,8 @@ int __export rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer,
memcpy(answer, h, h->nlmsg_len);
return 0;
}
- log_debug("libnetlink: ""RTNETLINK answers: %s\n", strerror(errno));
+ if (!ignore_einval)
+ log_debug("libnetlink: ""RTNETLINK answers: %s\n", strerror(errno));
}
return -1;
}
diff --git a/accel-pppd/vlan-mon/vlan_mon.c b/accel-pppd/vlan-mon/vlan_mon.c
index 5dcd0fd3..c243b7a9 100644
--- a/accel-pppd/vlan-mon/vlan_mon.c
+++ b/accel-pppd/vlan-mon/vlan_mon.c
@@ -34,7 +34,7 @@ static vlan_mon_notify cb[2];
static void init(void);
-void __export vlan_mon_register_proto(int proto, vlan_mon_notify func)
+void __export vlan_mon_register_proto(uint16_t proto, vlan_mon_notify func)
{
if (proto == ETH_P_PPP_DISC)
proto = 1;
@@ -47,7 +47,7 @@ void __export vlan_mon_register_proto(int proto, vlan_mon_notify func)
init();
}
-int __export vlan_mon_add(int ifindex, int proto, long *mask, int len)
+int __export vlan_mon_add(int ifindex, uint16_t proto, long *mask, int len)
{
struct rtnl_handle rth;
struct nlmsghdr *nlh;
@@ -62,7 +62,7 @@ int __export vlan_mon_add(int ifindex, int proto, long *mask, int len)
return -1;
if (rtnl_open_byproto(&rth, 0, NETLINK_GENERIC)) {
- log_error("ipoe: cannot open generic netlink socket\n");
+ log_error("vlan_mon: cannot open generic netlink socket\n");
return -1;
}
@@ -76,7 +76,7 @@ int __export vlan_mon_add(int ifindex, int proto, long *mask, int len)
addattr32(nlh, 1024, VLAN_MON_ATTR_IFINDEX, ifindex);
addattr_l(nlh, 1024, VLAN_MON_ATTR_VLAN_MASK, mask, len);
- addattr32(nlh, 1024, VLAN_MON_ATTR_PROTO, proto);
+ addattr_l(nlh, 1024, VLAN_MON_ATTR_PROTO, &proto, 2);
if (rtnl_talk(&rth, nlh, 0, 0, nlh, NULL, NULL, 0) < 0 ) {
log_error("vlan_mon: nl_add_vlan_mon: error talking to kernel\n");
@@ -88,7 +88,7 @@ int __export vlan_mon_add(int ifindex, int proto, long *mask, int len)
return r;
}
-int __export vlan_mon_add_vid(int ifindex, int proto, int vid)
+int __export vlan_mon_add_vid(int ifindex, uint16_t proto, uint16_t vid)
{
struct rtnl_handle rth;
struct nlmsghdr *nlh;
@@ -103,7 +103,7 @@ int __export vlan_mon_add_vid(int ifindex, int proto, int vid)
return -1;
if (rtnl_open_byproto(&rth, 0, NETLINK_GENERIC)) {
- log_error("ipoe: cannot open generic netlink socket\n");
+ log_error("vlan_mon: cannot open generic netlink socket\n");
return -1;
}
@@ -116,8 +116,8 @@ int __export vlan_mon_add_vid(int ifindex, int proto, int vid)
ghdr->cmd = VLAN_MON_CMD_ADD_VID;
addattr32(nlh, 1024, VLAN_MON_ATTR_IFINDEX, ifindex);
- addattr32(nlh, 1024, VLAN_MON_ATTR_VID, vid);
- addattr32(nlh, 1024, VLAN_MON_ATTR_PROTO, proto);
+ addattr_l(nlh, 1024, VLAN_MON_ATTR_VID, &vid, 2);
+ addattr_l(nlh, 1024, VLAN_MON_ATTR_PROTO, &proto, 2);
if (rtnl_talk(&rth, nlh, 0, 0, nlh, NULL, NULL, 0) < 0 ) {
log_error("vlan_mon: nl_add_vlan_mon_vid: error talking to kernel\n");
@@ -129,7 +129,7 @@ int __export vlan_mon_add_vid(int ifindex, int proto, int vid)
return r;
}
-int __export vlan_mon_del(int ifindex, int proto)
+int __export vlan_mon_del(int ifindex, uint16_t proto)
{
struct rtnl_handle rth;
struct nlmsghdr *nlh;
@@ -144,7 +144,7 @@ int __export vlan_mon_del(int ifindex, int proto)
return -1;
if (rtnl_open_byproto(&rth, 0, NETLINK_GENERIC)) {
- log_error("ipoe: cannot open generic netlink socket\n");
+ log_error("vlan_mon: cannot open generic netlink socket\n");
return -1;
}
@@ -157,7 +157,7 @@ int __export vlan_mon_del(int ifindex, int proto)
ghdr->cmd = VLAN_MON_CMD_DEL;
addattr32(nlh, 1024, VLAN_MON_ATTR_IFINDEX, ifindex);
- addattr32(nlh, 1024, VLAN_MON_ATTR_PROTO, proto);
+ addattr_l(nlh, 1024, VLAN_MON_ATTR_PROTO, &proto, 2);
if (rtnl_talk(&rth, nlh, 0, 0, nlh, NULL, NULL, 0) < 0 ) {
log_error("vlan_mon: nl_del_vlan_mon: error talking to kernel\n");
@@ -197,6 +197,46 @@ void vlan_mon_clean()
rtnl_close(&rth);
}
+int __export vlan_mon_check_busy(int ifindex, uint16_t vid)
+{
+ struct rtnl_handle rth;
+ struct nlmsghdr *nlh;
+ struct genlmsghdr *ghdr;
+ struct {
+ struct nlmsghdr n;
+ char buf[1024];
+ } req;
+ int r = 0;
+
+ if (vlan_mon_genl_id < 0)
+ return 0;
+
+ if (rtnl_open_byproto(&rth, 0, NETLINK_GENERIC)) {
+ log_error("vlan_mon: cannot open generic netlink socket\n");
+ return 0;
+ }
+
+ nlh = &req.n;
+ nlh->nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
+ nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+ nlh->nlmsg_type = vlan_mon_genl_id;
+
+ ghdr = NLMSG_DATA(&req.n);
+ ghdr->cmd = VLAN_MON_CMD_CHECK_BUSY;
+
+ addattr32(nlh, 1024, VLAN_MON_ATTR_IFINDEX, ifindex);
+ addattr_l(nlh, 1024, VLAN_MON_ATTR_VID, &vid, 2);
+
+ if (rtnl_talk(&rth, nlh, 0, 0, nlh, NULL, NULL, 1) < 0 ) {
+ if (errno == EBUSY)
+ r = -1;
+ }
+
+ rtnl_close(&rth);
+
+ return r;
+}
+
static void vlan_mon_handler(const struct sockaddr_nl *addr, struct nlmsghdr *h)
{
struct rtattr *tb[PKT_ATTR_MAX + 1];
@@ -227,8 +267,8 @@ static void vlan_mon_handler(const struct sockaddr_nl *addr, struct nlmsghdr *h)
// continue;
ifindex = *(uint32_t *)(RTA_DATA(tb2[VLAN_MON_ATTR_IFINDEX]));
- vid = *(uint32_t *)(RTA_DATA(tb2[VLAN_MON_ATTR_VID]));
- proto = *(uint32_t *)(RTA_DATA(tb2[VLAN_MON_ATTR_PROTO]));
+ vid = *(uint16_t *)(RTA_DATA(tb2[VLAN_MON_ATTR_VID]));
+ proto = *(uint16_t *)(RTA_DATA(tb2[VLAN_MON_ATTR_PROTO]));
if (tb2[VLAN_MON_ATTR_VLAN_IFINDEX])
vlan_ifindex = *(uint32_t *)(RTA_DATA(tb2[VLAN_MON_ATTR_VLAN_IFINDEX]));
diff --git a/drivers/vlan_mon/vlan_mon.c b/drivers/vlan_mon/vlan_mon.c
index 16bb11e6..9a2d211d 100644
--- a/drivers/vlan_mon/vlan_mon.c
+++ b/drivers/vlan_mon/vlan_mon.c
@@ -490,6 +490,36 @@ static int vlan_mon_nl_cmd_del_vlan_mon(struct sk_buff *skb, struct genl_info *i
return 0;
}
+static int vlan_mon_nl_cmd_check_busy(struct sk_buff *skb, struct genl_info *info)
+{
+ int ifindex, vid;
+ struct net_device *dev;
+ int ret = 0;
+
+ if (!info->attrs[VLAN_MON_ATTR_IFINDEX] || !info->attrs[VLAN_MON_ATTR_VID])
+ return -EINVAL;
+
+ ifindex = nla_get_u32(info->attrs[VLAN_MON_ATTR_IFINDEX]);
+ vid = nla_get_u16(info->attrs[VLAN_MON_ATTR_VID]);
+
+ down(&vlan_mon_lock);
+
+ rtnl_lock();
+ dev = __dev_get_by_index(&init_net, ifindex);
+ if (dev) {
+ struct vlan_dev *d = dev->ml_priv;
+ if (d) {
+ if (d->busy[vid / (8*sizeof(long))] & (1lu << (vid % (8*sizeof(long)))))
+ ret = -EBUSY;
+ }
+ }
+ rtnl_unlock();
+
+ up(&vlan_mon_lock);
+
+ return ret;
+}
+
static struct nla_policy vlan_mon_nl_policy[VLAN_MON_ATTR_MAX + 1] = {
[VLAN_MON_ATTR_NONE] = { .type = NLA_UNSPEC, },
[VLAN_MON_ATTR_VLAN_MASK] = { .type = NLA_BINARY, .len = 4096/8 },
@@ -523,6 +553,12 @@ static struct genl_ops vlan_mon_nl_ops[] = {
.policy = vlan_mon_nl_policy,
.flags = GENL_ADMIN_PERM,
},
+ {
+ .cmd = VLAN_MON_CMD_CHECK_BUSY,
+ .doit = vlan_mon_nl_cmd_check_busy,
+ .policy = vlan_mon_nl_policy,
+ .flags = GENL_ADMIN_PERM,
+ },
};
static struct genl_family vlan_mon_nl_family = {
diff --git a/drivers/vlan_mon/vlan_mon.h b/drivers/vlan_mon/vlan_mon.h
index ff5c8523..d5f9f360 100644
--- a/drivers/vlan_mon/vlan_mon.h
+++ b/drivers/vlan_mon/vlan_mon.h
@@ -9,6 +9,7 @@ enum {
VLAN_MON_CMD_ADD_VID,
VLAN_MON_CMD_DEL,
VLAN_MON_NOTIFY,
+ VLAN_MON_CMD_CHECK_BUSY,
__VLAN_MON_CMD_MAX,
};