summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--accel-pppd/accel-ppp.conf1
-rw-r--r--accel-pppd/accel-ppp.conf.53
-rw-r--r--accel-pppd/ctrl/ipoe/ipoe.c241
-rw-r--r--accel-pppd/ctrl/ipoe/ipoe.h13
-rw-r--r--accel-pppd/ctrl/ipoe/ipoe_netlink.c128
-rw-r--r--drivers/ipoe/ipoe.c675
-rw-r--r--drivers/ipoe/ipoe.h8
7 files changed, 272 insertions, 797 deletions
diff --git a/accel-pppd/accel-ppp.conf b/accel-pppd/accel-ppp.conf
index fc0fc762..bd58a7a7 100644
--- a/accel-pppd/accel-ppp.conf
+++ b/accel-pppd/accel-ppp.conf
@@ -132,7 +132,6 @@ start=dhcpv4
#attr-l4-redirect=L4-Redirect
#attr-l4-redirect-table=4
#attr-l4-redirect-ipset=l4-redirect
-#local-net=192.168.0.0/16
#lua-file=/etc/accel-ppp.lua
#offer-delay=0,100:100,200:200,-1:1000
#vlan-mon=eth0,10-200
diff --git a/accel-pppd/accel-ppp.conf.5 b/accel-pppd/accel-ppp.conf.5
index 648fd247..4deec4e1 100644
--- a/accel-pppd/accel-ppp.conf.5
+++ b/accel-pppd/accel-ppp.conf.5
@@ -354,9 +354,6 @@ The
.B proxy-arp
parameter specifies whether accel-ppp should reply to arp requests.
.TP
-.BI "local-net=" x.x.x.x/mask
-Specifies networks from which packets will be treated as unclassified. You may specify multiple local-net options.
-.TP
.BI "proto=" n
Specifies number of protocol to be used for inserted routes.
.TP
diff --git a/accel-pppd/ctrl/ipoe/ipoe.c b/accel-pppd/ctrl/ipoe/ipoe.c
index e7f1ca50..55bedac8 100644
--- a/accel-pppd/ctrl/ipoe/ipoe.c
+++ b/accel-pppd/ctrl/ipoe/ipoe.c
@@ -43,15 +43,8 @@
#define USERNAME_IFNAME 1
#define USERNAME_LUA 2
-#define MODE_L2 0
-#define MODE_L3 1
-
-struct ifaddr {
- struct list_head entry;
- in_addr_t addr;
- int mask;
- int refs;
-};
+#define MODE_L2 2
+#define MODE_L3 3
struct iplink_arg {
pcre *re;
@@ -510,7 +503,8 @@ static int ipoe_create_interface(struct ipoe_session *ses)
mempool_free(uc);
} else {
pthread_mutex_unlock(&uc_lock);
- ses->ifindex = ipoe_nl_create(0, 0, ses->serv->opt_mode == MODE_L2 ? ses->serv->ifname : NULL, ses->hwaddr);
+
+ ses->ifindex = ipoe_nl_create(ses->serv->ifindex);
if (ses->ifindex == -1) {
log_ppp_error("ipoe: failed to create interface\n");
ap_session_terminate(&ses->ses, TERM_NAS_ERROR, 1);
@@ -530,7 +524,6 @@ static int ipoe_create_interface(struct ipoe_session *ses)
strncpy(ses->ses.ifname, ifr.ifr_name, AP_IFNAME_LEN);
ses->ses.ifindex = ses->ifindex;
ses->ses.unit_idx = ses->ifindex;
- ses->ctrl.dont_ifcfg = !conf_ip_unnumbered;
log_ppp_info2("create interface %s parent %s\n", ifr.ifr_name, ses->serv->ifname);
@@ -802,115 +795,39 @@ static void __ipoe_session_start(struct ipoe_session *ses)
}
}
-static void ipoe_serv_add_addr(struct ipoe_serv *serv, in_addr_t addr, int mask)
-{
- struct ifaddr *a;
-
- pthread_mutex_lock(&serv->lock);
-
- if (serv->opt_shared) {
- list_for_each_entry(a, &serv->addr_list, entry) {
- if (a->addr == addr) {
- a->refs++;
- pthread_mutex_unlock(&serv->lock);
-
- return;
- }
- }
- }
-
- a = _malloc(sizeof(*a));
- a->addr = addr;
- a->mask = mask;
- a->refs = 1;
- list_add_tail(&a->entry, &serv->addr_list);
-
- if (ipaddr_add(serv->ifindex, a->addr, mask))
- log_warn("ipoe: failed to add addess to interface '%s'\n", serv->ifname);
-
- pthread_mutex_unlock(&serv->lock);
-}
-
-static void ipoe_serv_del_addr(struct ipoe_serv *serv, in_addr_t addr, int lock)
-{
- struct ifaddr *a;
-
- if (lock)
- pthread_mutex_lock(&serv->lock);
-
- list_for_each_entry(a, &serv->addr_list, entry) {
- if (a->addr == addr) {
- if (--a->refs == 0) {
- if (ipaddr_del(serv->ifindex, a->addr, a->mask))
- log_warn("ipoe: failed to delete addess from interface '%s'\n", serv->ifname);
- list_del(&a->entry);
- _free(a);
- }
- break;
- }
- }
-
- if (lock)
- pthread_mutex_unlock(&serv->lock);
-}
-
-static void ipoe_ifcfg_add(struct ipoe_session *ses)
-{
- struct ipoe_serv *serv = ses->serv;
-
- if (ses->serv->opt_ifcfg)
- ipoe_serv_add_addr(ses->serv, ses->siaddr, conf_ip_unnumbered ? 32 : ses->mask);
-
- if (conf_ip_unnumbered) {
- if (iproute_add(serv->ifindex, ses->serv->opt_src ? ses->serv->opt_src : ses->router, ses->yiaddr, 0, conf_proto, 32))
- log_ppp_warn("ipoe: failed to add route to interface '%s'\n", serv->ifname);
- }
-
- ses->ifcfg = 1;
-}
-
-static void ipoe_ifcfg_del(struct ipoe_session *ses, int lock)
-{
- struct ipoe_serv *serv = ses->serv;
-
- if (conf_ip_unnumbered) {
- if (iproute_del(serv->ifindex, ses->yiaddr, conf_proto, 32))
- log_ppp_warn("ipoe: failed to delete route from interface '%s'\n", serv->ifname);
- }
-
- if (ses->serv->opt_ifcfg)
- ipoe_serv_del_addr(ses->serv, ses->siaddr, lock);
-}
-
static void __ipoe_session_activate(struct ipoe_session *ses)
{
- uint32_t addr;
+ uint32_t addr, gw = 0;
+ struct ipoe_serv *serv = ses->serv;
if (ses->terminating)
return;
if (ses->ifindex != -1) {
addr = 0;
- if (!ses->ses.ipv4) {
+ /*if (!ses->ses.ipv4) {
if (ses->serv->opt_mode == MODE_L3) {
addr = 1;
ses->ctrl.dont_ifcfg = 1;
}
- } else if (ses->ses.ipv4->peer_addr != ses->yiaddr)
+ } else*/
+ if (ses->ses.ipv4 && ses->ses.ipv4->peer_addr != ses->yiaddr)
addr = ses->ses.ipv4->peer_addr;
- else if (!conf_ip_unnumbered)
- ses->ctrl.dont_ifcfg = 1;
- if (ses->dhcpv4_request && ses->serv->opt_mode == MODE_L3) {
+ /*if (ses->dhcpv4_request && ses->serv->opt_mode == MODE_L3) {
in_addr_t gw;
- iproute_get(ses->router, &gw);
+ iproute_get(ses->router, &gw, NULL);
if (gw)
iproute_add(0, ses->siaddr, ses->yiaddr, gw, conf_proto, 32);
else
iproute_add(0, ses->siaddr, ses->router, gw, conf_proto, 32);
- }
+ }*/
- if (ipoe_nl_modify(ses->ifindex, ses->yiaddr, addr, NULL, NULL)) {
+ if (serv->opt_mode == MODE_L3)
+ iproute_get(ses->yiaddr, &gw);
+
+ //if (ipoe_nl_modify(ses->ifindex, ses->yiaddr, addr, gw, gw ? 0 : ses->serv->ifindex, gw ? NULL : ses->hwaddr)) {
+ if (ipoe_nl_modify(ses->ifindex, ses->yiaddr, addr, gw, serv->ifindex, ses->hwaddr)) {
ap_session_terminate(&ses->ses, TERM_NAS_ERROR, 1);
return;
}
@@ -924,17 +841,15 @@ static void __ipoe_session_activate(struct ipoe_session *ses)
}
if (ses->ifindex == -1) {
- if (ses->serv->opt_ifcfg || (ses->serv->opt_mode == MODE_L2))
- ipoe_ifcfg_add(ses);
-
- ipoe_nl_add_exclude(ses->yiaddr, 32);
-
- ses->ctrl.dont_ifcfg = 1;
- } else if (ses->ctrl.dont_ifcfg && ses->serv->opt_mode == MODE_L2)
- ipaddr_add(ses->ifindex, ses->siaddr, ses->mask);
+ if (serv->opt_ifcfg)
+ ipaddr_add(serv->ifindex, ses->router, conf_ip_unnumbered ? 32 : ses->mask);
+ else if (!conf_ip_unnumbered)
+ iproute_add(serv->ifindex, ses->router, ses->yiaddr, 0, conf_proto, ses->mask);
- if (ses->l4_redirect)
- ipoe_change_l4_redirect(ses, 0);
+ if (conf_ip_unnumbered)
+ iproute_add(serv->ifindex, serv->opt_src ?: ses->router, ses->yiaddr, 0, conf_proto, 32);
+ } else
+ ses->ctrl.dont_ifcfg = 0;
if (ses->serv->opt_mode == MODE_L2 && ses->serv->opt_ipv6 && sock6_fd != -1) {
ses->ses.ipv6 = ipdb_get_ipv6(&ses->ses);
@@ -950,6 +865,9 @@ static void __ipoe_session_activate(struct ipoe_session *ses)
ap_session_activate(&ses->ses);
+ if (ses->l4_redirect)
+ ipoe_change_l4_redirect(ses, 0);
+
if (ses->dhcpv4_request) {
if (ses->ses.state == AP_STATE_ACTIVE)
dhcpv4_send_reply(DHCPACK, ses->dhcpv4 ?: ses->serv->dhcpv4, ses->dhcpv4_request, ses->yiaddr, ses->siaddr, ses->router, ses->mask, ses->lease_time, ses->renew_time, ses->dhcpv4_relay_reply);
@@ -1090,12 +1008,13 @@ static void ipoe_session_free(struct ipoe_session *ses)
static void ipoe_session_finished(struct ap_session *s)
{
struct ipoe_session *ses = container_of(s, typeof(*ses), ses);
+ struct ipoe_serv *serv = ses->serv;
struct unit_cache *uc;
log_ppp_info1("ipoe: session finished\n");
if (ses->ifindex != -1) {
- if (uc_size < conf_unit_cache && ipoe_nl_modify(ses->ifindex, 0, 0, "", NULL)) {
+ if (uc_size < conf_unit_cache && !ipoe_nl_modify(ses->ifindex, 0, 0, 0, 0, NULL)) {
uc = mempool_alloc(uc_pool);
uc->ifindex = ses->ifindex;
pthread_mutex_lock(&uc_lock);
@@ -1104,8 +1023,14 @@ static void ipoe_session_finished(struct ap_session *s)
pthread_mutex_unlock(&uc_lock);
} else
ipoe_nl_delete(ses->ifindex);
- } else
- ipoe_nl_del_exclude(ses->yiaddr);
+ } else if (ses->started) {
+ if (serv->opt_ifcfg)
+ ipaddr_del(serv->ifindex, ses->router, conf_ip_unnumbered ? 32 : ses->mask);
+ else if (conf_ip_unnumbered)
+ iproute_del(serv->ifindex, ses->yiaddr, conf_proto, 32);
+ else
+ iproute_del(serv->ifindex, ses->yiaddr, conf_proto, ses->mask);
+ }
if (ses->dhcp_addr)
dhcpv4_put_ip(ses->serv->dhcpv4, ses->yiaddr);
@@ -1113,9 +1038,6 @@ static void ipoe_session_finished(struct ap_session *s)
if (ses->relay_addr && ses->serv->dhcpv4_relay)
dhcpv4_relay_send_release(ses->serv->dhcpv4_relay, ses->hwaddr, ses->xid, ses->yiaddr, ses->client_id, ses->relay_agent, ses->serv->ifname, conf_agent_remote_id);
- if (ses->ifcfg)
- ipoe_ifcfg_del(ses, 1);
-
if (ses->dhcpv4)
dhcpv4_free(ses->dhcpv4);
@@ -1152,9 +1074,6 @@ static void ipoe_session_terminated(struct ipoe_session *ses)
if (ses->l4_redirect_set)
ipoe_change_l4_redirect(ses, 1);
- if (!ses->serv->opt_shared)
- ses->ctrl.dont_ifcfg = 1;
-
ap_session_finished(&ses->ses);
}
@@ -1850,6 +1769,8 @@ static struct ipoe_session *ipoe_session_create_up(struct ipoe_serv *serv, struc
if (conf_ip_pool)
ses->ses.ipv4_pool_name = _strdup(conf_ip_pool);
+ ses->ctrl.dont_ifcfg = 1;
+
triton_context_register(&ses->ctx, &ses->ses);
triton_context_wakeup(&ses->ctx);
@@ -2098,10 +2019,8 @@ static void ipoe_serv_release(struct ipoe_serv *serv)
if (serv->dhcpv4)
dhcpv4_free(serv->dhcpv4);
- if (serv->dhcpv4_relay) {
- ipoe_serv_del_addr(serv, serv->dhcpv4_relay->giaddr, 0);
+ if (serv->dhcpv4_relay)
dhcpv4_relay_free(serv->dhcpv4_relay, &serv->ctx);
- }
if (serv->arp)
arpd_stop(serv->arp);
@@ -2126,8 +2045,7 @@ static void ipoe_serv_release(struct ipoe_serv *serv)
if (serv->timer.tpd)
triton_timer_del(&serv->timer);
- if (serv->opt_up)
- ipoe_nl_del_interface(serv->ifindex);
+ ipoe_nl_del_interface(serv->ifindex);
if (serv->vid) {
log_info2("ipoe: remove vlan %s\n", serv->ifname);
@@ -2226,10 +2144,6 @@ static void ipoe_drop_sessions(struct ipoe_serv *serv, struct ipoe_session *skip
continue;
ses->terminating = 1;
- if (ses->ifcfg) {
- ipoe_ifcfg_del(ses, 0);
- ses->ifcfg = 0;
- }
if (ses->ses.state == AP_STATE_ACTIVE)
ap_session_ifdown(&ses->ses);
@@ -2490,7 +2404,9 @@ static void add_interface(const char *ifname, int ifindex, const char *opt, int
}
if (opt_up)
- ipoe_nl_add_interface(ifindex);
+ ipoe_nl_add_interface(ifindex, opt_mode);
+ else
+ ipoe_nl_add_interface(ifindex, 0);
pthread_mutex_lock(&serv_lock);
list_for_each_entry(serv, &serv_list, entry) {
@@ -2516,17 +2432,12 @@ static void add_interface(const char *ifname, int ifindex, const char *opt, int
if (serv->dhcpv4_relay &&
(serv->dhcpv4_relay->addr != relay_addr || serv->dhcpv4_relay->giaddr != opt_giaddr)) {
- if (serv->opt_ifcfg)
- ipoe_serv_del_addr(serv, serv->dhcpv4_relay->giaddr, 0);
dhcpv4_relay_free(serv->dhcpv4_relay, &serv->ctx);
serv->dhcpv4_relay = NULL;
}
- if (!serv->dhcpv4_relay && serv->opt_dhcpv4 && opt_relay) {
- if (opt_ifcfg)
- ipoe_serv_add_addr(serv, opt_giaddr, 32);
+ if (!serv->dhcpv4_relay && serv->opt_dhcpv4 && opt_relay)
serv->dhcpv4_relay = dhcpv4_relay_create(opt_relay, opt_giaddr, &serv->ctx, (triton_event_func)ipoe_recv_dhcpv4_relay);
- }
if (serv->arp && !conf_arp) {
arpd_stop(serv->arp);
@@ -2589,7 +2500,7 @@ static void add_interface(const char *ifname, int ifindex, const char *opt, int
serv->ctx.close = ipoe_serv_close;
serv->ctx.before_switch = ipoe_ctx_switch;
pthread_mutex_init(&serv->lock, NULL);
- serv->ifname = _strdup(ifname);
+ strcpy(serv->ifname, ifname);
serv->ifindex = ifindex;
serv->opt_shared = opt_shared;
serv->opt_dhcpv4 = opt_dhcpv4;
@@ -2608,7 +2519,6 @@ static void add_interface(const char *ifname, int ifindex, const char *opt, int
serv->vid = vid;
serv->active = 1;
INIT_LIST_HEAD(&serv->sessions);
- INIT_LIST_HEAD(&serv->addr_list);
INIT_LIST_HEAD(&serv->disc_list);
INIT_LIST_HEAD(&serv->req_list);
memcpy(serv->hwaddr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
@@ -2621,11 +2531,8 @@ static void add_interface(const char *ifname, int ifindex, const char *opt, int
if (serv->dhcpv4)
serv->dhcpv4->recv = ipoe_recv_dhcpv4;
- if (opt_relay) {
- if (opt_ifcfg)
- ipoe_serv_add_addr(serv, opt_giaddr, 32);
+ if (opt_relay)
serv->dhcpv4_relay = dhcpv4_relay_create(opt_relay, opt_giaddr, &serv->ctx, (triton_event_func)ipoe_recv_dhcpv4_relay);
- }
}
if (serv->opt_arp)
@@ -2741,8 +2648,6 @@ static void load_interfaces(struct conf_sect_t *sect)
struct ipoe_serv *serv;
struct conf_option_t *opt;
- ipoe_nl_delete_interfaces();
-
list_for_each_entry(serv, &serv_list, entry)
serv->active = 0;
@@ -2760,60 +2665,13 @@ static void load_interfaces(struct conf_sect_t *sect)
list_for_each_entry(serv, &serv_list, entry) {
if (!serv->active && !serv->vid) {
+ ipoe_nl_del_interface(serv->ifindex);
ipoe_drop_sessions(serv, NULL);
triton_context_call(&serv->ctx, (triton_event_func)ipoe_serv_release, serv);
}
}
}
-static void parse_local_net(const char *opt)
-{
- const char *ptr;
- char str[17];
- in_addr_t addr;
- int mask;
- char *endptr;
-
- ptr = strchr(opt, '/');
- if (ptr) {
- memcpy(str, opt, ptr - opt);
- str[ptr - opt] = 0;
- addr = inet_addr(str);
- if (addr == INADDR_NONE)
- goto out_err;
- mask = strtoul(ptr + 1, &endptr, 10);
- if (mask > 32)
- goto out_err;
- } else {
- addr = inet_addr(opt);
- if (addr == INADDR_NONE)
- goto out_err;
- mask = 24;
- }
-
- ipoe_nl_add_net(addr, mask);
-
- return;
-
-out_err:
- log_error("ipoe: failed to parse 'local-net=%s'\n", opt);
-}
-
-static void load_local_nets(struct conf_sect_t *sect)
-{
- struct conf_option_t *opt;
-
- ipoe_nl_delete_nets();
-
- list_for_each_entry(opt, &sect->items, entry) {
- if (strcmp(opt->name, "local-net"))
- continue;
- if (!opt->val)
- continue;
- parse_local_net(opt->val);
- }
-}
-
static void load_gw_addr(struct conf_sect_t *sect)
{
struct conf_option_t *opt;
@@ -3369,7 +3227,6 @@ static void load_config(void)
parse_offer_delay(conf_get_opt("ipoe", "offer-delay"));
load_interfaces(s);
- load_local_nets(s);
load_vlan_mon(s);
load_gw_addr(s);
}
diff --git a/accel-pppd/ctrl/ipoe/ipoe.h b/accel-pppd/ctrl/ipoe/ipoe.h
index 8c647b78..5561646d 100644
--- a/accel-pppd/ctrl/ipoe/ipoe.h
+++ b/accel-pppd/ctrl/ipoe/ipoe.h
@@ -3,6 +3,7 @@
#include <stdint.h>
#include <pthread.h>
+#include <linux/if.h>
#include "triton.h"
#include "ap_session.h"
@@ -20,11 +21,10 @@
struct ipoe_serv {
struct list_head entry;
struct triton_context_t ctx;
- char *ifname;
+ char ifname[IFNAMSIZ];
int ifindex;
uint8_t hwaddr[ETH_ALEN];
struct list_head sessions;
- struct list_head addr_list;
struct dhcpv4_serv *dhcpv4;
struct dhcpv4_relay *dhcpv4_relay;
void *arp;
@@ -88,7 +88,6 @@ struct ipoe_session {
#ifdef RADIUS
struct rad_plugin_t radius;
#endif
- int ifcfg:1;
int started:1;
int terminating:1;
int dhcp_addr:1;
@@ -120,14 +119,12 @@ struct ipoe_session *ipoe_session_alloc(void);
struct ipoe_serv *ipoe_find_serv(const char *ifname);
-void ipoe_nl_add_net(uint32_t addr, int mask);
-void ipoe_nl_delete_nets(void);
-void ipoe_nl_add_interface(int ifindex);
+void ipoe_nl_add_interface(int ifindex, uint8_t mode);
void ipoe_nl_del_interface(int ifindex);
void ipoe_nl_delete_interfaces(void);
-int ipoe_nl_create(uint32_t peer_addr, uint32_t addr, const char *ifname, uint8_t *hwaddr);
+int ipoe_nl_create(int ifindex);
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);
+int ipoe_nl_modify(int ifindex, uint32_t peer_addr, uint32_t addr, uint32_t gw, int link_ifindex, uint8_t *hwaddr);
void ipoe_nl_get_sessions(struct list_head *list);
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 fa7b0a22..cd2433e9 100644
--- a/accel-pppd/ctrl/ipoe/ipoe_netlink.c
+++ b/accel-pppd/ctrl/ipoe/ipoe_netlink.c
@@ -17,6 +17,7 @@
#include "log.h"
#include "genl.h"
#include "libnetlink.h"
+#include "iputils.h"
#include "ipoe.h"
#include "if_ipoe.h"
@@ -29,61 +30,6 @@ static struct rtnl_handle rth;
static struct triton_md_handler_t mc_hnd;
static int ipoe_genl_id;
-void ipoe_nl_delete_nets(void)
-{
- struct nlmsghdr *nlh;
- struct genlmsghdr *ghdr;
- struct {
- struct nlmsghdr n;
- char buf[1024];
- } req;
-
- if (rth.fd == -1)
- return;
-
- 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_NET;
-
- addattr32(nlh, 1024, IPOE_ATTR_ADDR, 0);
-
- if (rtnl_talk(&rth, nlh, 0, 0, nlh, NULL, NULL, 0) < 0 )
- log_error("ipoe: nl_del_net: error talking to kernel\n");
-}
-
-void ipoe_nl_add_net(uint32_t addr, int mask)
-{
- struct nlmsghdr *nlh;
- struct genlmsghdr *ghdr;
- struct {
- struct nlmsghdr n;
- char buf[1024];
- } req;
-
- if (rth.fd == -1)
- return;
-
- 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_NET;
-
- mask = mask ? ~0 << (32 - mask) : 0;
-
- addattr32(nlh, 1024, IPOE_ATTR_ADDR, addr);
- addattr32(nlh, 1024, IPOE_ATTR_MASK, mask);
-
- if (rtnl_talk(&rth, nlh, 0, 0, nlh, NULL, NULL, 0) < 0 )
- log_error("ipoe: nl_add_net: error talking to kernel\n");
-}
-
int ipoe_nl_add_exclude(uint32_t addr, int mask)
{
struct rtnl_handle rth;
@@ -152,33 +98,7 @@ void ipoe_nl_del_exclude(uint32_t addr)
rtnl_close(&rth);
}
-void ipoe_nl_delete_interfaces(void)
-{
- struct nlmsghdr *nlh;
- struct genlmsghdr *ghdr;
- struct {
- struct nlmsghdr n;
- char buf[1024];
- } req;
-
- if (rth.fd == -1)
- return;
-
- 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_IF;
-
- addattr32(nlh, 1024, IPOE_ATTR_IFINDEX, -1);
-
- if (rtnl_talk(&rth, nlh, 0, 0, nlh, NULL, NULL, 0) < 0 )
- log_error("ipoe: nl_del_iface: error talking to kernel\n");
-}
-
-void ipoe_nl_add_interface(int ifindex)
+void ipoe_nl_add_interface(int ifindex, uint8_t mode)
{
struct nlmsghdr *nlh;
struct genlmsghdr *ghdr;
@@ -199,6 +119,7 @@ void ipoe_nl_add_interface(int ifindex)
ghdr->cmd = IPOE_CMD_ADD_IF;
addattr32(nlh, 1024, IPOE_ATTR_IFINDEX, ifindex);
+ addattr_l(nlh, 1024, IPOE_ATTR_MODE, &mode, 1);
if (rtnl_talk(&rth, nlh, 0, 0, nlh, NULL, NULL, 0) < 0 )
log_error("ipoe: nl_add_iface: error talking to kernel\n");
@@ -230,7 +151,12 @@ void ipoe_nl_del_interface(int ifindex)
log_error("ipoe: nl_del_iface: error talking to kernel\n");
}
-int ipoe_nl_create(uint32_t peer_addr, uint32_t addr, const char *ifname, uint8_t *hwaddr)
+void ipoe_nl_delete_interfaces(void)
+{
+ ipoe_nl_del_interface(-1);
+}
+
+int ipoe_nl_create(int ifindex)
{
struct rtnl_handle rth;
struct nlmsghdr *nlh;
@@ -243,10 +169,6 @@ int ipoe_nl_create(uint32_t peer_addr, uint32_t addr, const char *ifname, uint8_
struct nlmsghdr n;
char buf[1024];
} req;
- union {
- uint8_t hwaddr[6];
- uint64_t u64;
- } u;
if (rtnl_open_byproto(&rth, 0, NETLINK_GENERIC)) {
log_ppp_error("ipoe: cannot open generic netlink socket\n");
@@ -261,19 +183,7 @@ int ipoe_nl_create(uint32_t peer_addr, uint32_t addr, const char *ifname, uint8_
ghdr = NLMSG_DATA(&req.n);
ghdr->cmd = IPOE_CMD_CREATE;
- if (peer_addr)
- addattr32(nlh, 1024, IPOE_ATTR_PEER_ADDR, peer_addr);
-
- if (addr)
- addattr32(nlh, 1024, IPOE_ATTR_ADDR, addr);
-
- if (hwaddr) {
- memcpy(u.hwaddr, hwaddr, 6);
- addattr_l(nlh, 1024, IPOE_ATTR_HWADDR, &u.u64, 8);
- }
-
- if (ifname)
- addattr_l(nlh, 1024, IPOE_ATTR_IFNAME, ifname, strlen(ifname) + 1);
+ addattr32(nlh, 1024, IPOE_ATTR_IFINDEX, ifindex);
if (rtnl_talk(&rth, nlh, 0, 0, nlh, NULL, NULL, 0) < 0 )
log_ppp_error("ipoe: nl_create: error talking to kernel\n");
@@ -313,7 +223,7 @@ out:
return ret;
}
-int ipoe_nl_modify(int ifindex, uint32_t peer_addr, uint32_t addr, const char *ifname, uint8_t *hwaddr)
+int ipoe_nl_modify(int ifindex, uint32_t peer_addr, uint32_t addr, uint32_t gw, int link_ifindex, uint8_t *hwaddr)
{
struct rtnl_handle rth;
struct nlmsghdr *nlh;
@@ -323,10 +233,6 @@ int ipoe_nl_modify(int ifindex, uint32_t peer_addr, uint32_t addr, const char *i
struct nlmsghdr n;
char buf[1024];
} req;
- union {
- uint8_t hwaddr[6];
- uint64_t u64;
- } u;
if (rtnl_open_byproto(&rth, 0, NETLINK_GENERIC)) {
log_ppp_error("ipoe: cannot open generic netlink socket\n");
@@ -344,14 +250,11 @@ int ipoe_nl_modify(int ifindex, uint32_t peer_addr, uint32_t addr, const char *i
addattr32(nlh, 1024, IPOE_ATTR_IFINDEX, ifindex);
addattr32(nlh, 1024, IPOE_ATTR_PEER_ADDR, peer_addr);
addattr32(nlh, 1024, IPOE_ATTR_ADDR, addr);
+ addattr32(nlh, 1024, IPOE_ATTR_GW_ADDR, gw);
+ addattr32(nlh, 1024, IPOE_ATTR_LINK_IFINDEX, link_ifindex);
- if (hwaddr) {
- memcpy(u.hwaddr, hwaddr, 6);
- addattr_l(nlh, 1024, IPOE_ATTR_HWADDR, &u.u64, 8);
- }
-
- if (ifname)
- addattr_l(nlh, 1024, IPOE_ATTR_IFNAME, ifname, strlen(ifname) + 1);
+ if (hwaddr)
+ addattr_l(nlh, 1024, IPOE_ATTR_HWADDR, hwaddr, 6);
if (rtnl_talk(&rth, nlh, 0, 0, nlh, NULL, NULL, 0) < 0 ) {
log_ppp_error("ipoe: nl_create: error talking to kernel\n");
@@ -631,6 +534,7 @@ static void init(void)
triton_context_wakeup(&mc_ctx);
ipoe_nl_del_exclude(0);
+ ipoe_nl_delete_interfaces();
}
DEFINE_INIT(19, init);
diff --git a/drivers/ipoe/ipoe.c b/drivers/ipoe/ipoe.c
index dd5120c4..f0483066 100644
--- a/drivers/ipoe/ipoe.c
+++ b/drivers/ipoe/ipoe.c
@@ -52,13 +52,11 @@
#define DEFINE_SEMAPHORE(name) struct semaphore name = __SEMAPHORE_INITIALIZER(name, 1)
#endif
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
struct ipoe_stats {
struct u64_stats_sync sync;
u64 packets;
u64 bytes;
};
-#endif
struct ipoe_session {
struct list_head entry;
@@ -66,6 +64,7 @@ struct ipoe_session {
__be32 addr;
__be32 peer_addr;
+ __be32 gw;
__u8 hwaddr[ETH_ALEN];
struct net_device *dev;
@@ -73,10 +72,8 @@ struct ipoe_session {
atomic_t refs;
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
struct ipoe_stats __percpu *rx_stats;
struct ipoe_stats __percpu *tx_stats;
-#endif
};
struct ipoe_network {
@@ -92,6 +89,7 @@ struct ipoe_iface {
struct list_head entry;
int ifindex;
+ int mode;
};
struct ipoe_entry_u {
@@ -109,7 +107,6 @@ static struct list_head ipoe_excl_list[HASH_BITS + 1];
static LIST_HEAD(ipoe_list2);
static LIST_HEAD(ipoe_list2_u);
static DEFINE_SEMAPHORE(ipoe_wlock);
-static LIST_HEAD(ipoe_networks);
static LIST_HEAD(ipoe_interfaces);
static struct work_struct ipoe_queue_work;
static struct sk_buff_head ipoe_queue;
@@ -119,12 +116,10 @@ static DEFINE_TIMER(ipoe_timer_u, ipoe_start_queue_work, 0, 0);
static struct ipoe_session *ipoe_lookup(__be32 addr);
static int ipoe_do_nat(struct sk_buff *skb, __be32 new_addr, int to_peer);
-static void ipoe_queue_u(struct sk_buff *skb, __be32 addr);
+static int ipoe_queue_u(struct sk_buff *skb, __be32 addr);
static int ipoe_lookup1_u(__be32 addr, unsigned long *ts);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)
static const struct net_device_ops ipoe_netdev_ops;
-#endif
static struct genl_family ipoe_nl_family;
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0)
@@ -156,7 +151,6 @@ static inline int hash_addr(__be32 addr)
#endif
}
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
static void ipoe_update_stats(struct sk_buff *skb, struct ipoe_stats *st, int corr)
{
u64_stats_update_begin(&st->sync);
@@ -164,33 +158,6 @@ static void ipoe_update_stats(struct sk_buff *skb, struct ipoe_stats *st, int co
st->bytes += skb->len - corr;
u64_stats_update_end(&st->sync);
}
-#endif
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0)
-static void ipoe_kfree_rcu(struct rcu_head *head)
-{
- kfree(head);
-}
-#endif
-
-static int ipoe_check_network(__be32 addr)
-{
- struct ipoe_network *n;
- int r = 0;
-
- rcu_read_lock();
-
- list_for_each_entry_rcu(n, &ipoe_networks, entry) {
- if ((ntohl(addr) & n->mask) == n->addr) {
- r = 1;
- break;
- }
- }
-
- rcu_read_unlock();
-
- return r;
-}
static int ipoe_check_exclude(__be32 addr)
{
@@ -214,25 +181,6 @@ static int ipoe_check_exclude(__be32 addr)
return r;
}
-static int ipoe_check_interface(int ifindex)
-{
- struct ipoe_iface *i;
- int r = 0;
-
- rcu_read_lock();
-
- list_for_each_entry_rcu(i, &ipoe_interfaces, entry) {
- if (i->ifindex == ifindex) {
- r = 1;
- break;
- }
- }
-
- rcu_read_unlock();
-
- return r;
-}
-
static int ipoe_do_nat(struct sk_buff *skb, __be32 new_addr, int to_peer)
{
struct iphdr *iph;
@@ -356,62 +304,41 @@ static struct net *pick_net(struct sk_buff *skb)
return &init_net;
}
-static int ipoe_route4(struct sk_buff *skb)
+/*static int ipoe_route4(struct sk_buff *skb, __be32 gw, int oif)
{
const struct iphdr *iph = ip_hdr(skb);
struct net *net = pick_net(skb);
struct rtable *rt;
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,38)
- struct flowi fl4;
-#else
struct flowi4 fl4;
-#endif
memset(&fl4, 0, sizeof(fl4));
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,38)
- fl4.fl4_dst = iph->daddr;
- fl4.fl4_tos = RT_TOS(iph->tos);
- fl4.fl4_scope = RT_SCOPE_UNIVERSE;
- if (ip_route_output_key(net, &rt, &fl4))
- return -1;
-#else
- fl4.daddr = iph->daddr;
- fl4.flowi4_tos = RT_TOS(iph->tos);
+ fl4.daddr = gw;
+ fl4.flowi4_oif = oif;
+ fl4.flowi4_tos = RT_TOS(iph->tos) | RTO_ONLINK;
fl4.flowi4_scope = RT_SCOPE_UNIVERSE;
rt = ip_route_output_key(net, &fl4);
if (IS_ERR(rt))
return -1;
-#endif
skb_dst_drop(skb);
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,37)
- skb_dst_set(skb, &rt->u.dst);
- skb->dev = rt->u.dst.dev;
-#else
skb_dst_set(skb, &rt->dst);
- skb->dev = rt->dst.dev;
-#endif
+ skb->dev = rt->dst.dev;
return 0;
-}
+}*/
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
-static int ipoe_xmit(struct sk_buff *skb, struct net_device *dev)
-#else
static netdev_tx_t ipoe_xmit(struct sk_buff *skb, struct net_device *dev)
-#endif
{
struct ipoe_session *ses = netdev_priv(dev);
struct net_device_stats *stats = &dev->stats;
struct iphdr *iph;
struct sk_buff *skb1;
- struct dst_entry *dst;
+ //struct dst_entry *dst;
/*struct arphdr *arp;
unsigned char *arp_ptr;
__be32 tip;*/
int noff;
- unsigned char *cb_ptr;
if (!ses->peer_addr)
goto drop;
@@ -428,25 +355,6 @@ static netdev_tx_t ipoe_xmit(struct sk_buff *skb, struct net_device *dev)
//pr_info("ipoe: xmit %08x %08x\n", iph->saddr, iph->daddr);
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
- ipoe_update_stats(skb, this_cpu_ptr(ses->tx_stats), ETH_HLEN);
-#else
- stats->tx_packets++;
- stats->tx_bytes += skb->len - ETH_HLEN;
-#endif
-
-
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,30)
- dst = skb_dst(skb);
-#else
- dst = skb->dst;
-#endif
- if (dst && dst->dev != skb->dev) {
- skb->dev = dst->dev;
- dev_queue_xmit(skb);
- return NETDEV_TX_OK;
- }
-
//pr_info("ipoe: xmit1 %08x %08x\n", iph->saddr, iph->daddr);
if (iph->daddr == ses->addr) {
if (skb_shared(skb)) {
@@ -461,24 +369,18 @@ static netdev_tx_t ipoe_xmit(struct sk_buff *skb, struct net_device *dev)
goto drop;
}
- if (!ses->link_dev) {
+ /*if (ses->gw) {
iph = ip_hdr(skb);
ip_send_check(iph);
- if (ipoe_route4(skb))
+ if (ipoe_route4(skb, ses->gw, ses->link_dev->ifindex))
goto drop;
pskb_pull(skb, ETH_HLEN);
skb_reset_network_header(skb);
- cb_ptr = skb->cb + sizeof(skb->cb) - 2;
- *(__u16 *)cb_ptr = IPOE_MAGIC;
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,32)
- skb->skb_iif = dev->ifindex;
-#else
- skb->iif = dev->ifindex;
-#endif
+ //skb->skb_iif = dev->ifindex;
//pr_info("ipoe: xmit2 %08x %08x %p %p\n", iph->saddr, iph->daddr, dev, skb->dev);
nf_reset(skb);
@@ -493,27 +395,22 @@ static netdev_tx_t ipoe_xmit(struct sk_buff *skb, struct net_device *dev)
#endif
return NETDEV_TX_OK;
- } else {
- struct ethhdr *eth = (struct ethhdr *)skb->data;
-
- memcpy(eth->h_dest, ses->hwaddr, ETH_ALEN);
- memcpy(eth->h_source, ses->link_dev->dev_addr, ETH_ALEN);
- }
+ } else*/
}
+ ipoe_update_stats(skb, this_cpu_ptr(ses->tx_stats), ETH_HLEN);
+
if (ses->link_dev) {
- cb_ptr = skb->cb + sizeof(skb->cb) - 2;
- *(__u16 *)cb_ptr = IPOE_MAGIC;
+ struct ethhdr *eth = (struct ethhdr *)skb->data;
+ memcpy(eth->h_dest, ses->hwaddr, ETH_ALEN);
+ memcpy(eth->h_source, ses->link_dev->dev_addr, ETH_ALEN);
+
skb->dev = ses->link_dev;
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,32)
- skb->skb_iif = dev->ifindex;
-#else
- skb->iif = dev->ifindex;
-#endif
dev_queue_xmit(skb);
return NETDEV_TX_OK;
}
+
drop:
stats->tx_dropped++;
dev_kfree_skb(skb);
@@ -555,26 +452,24 @@ static struct ipoe_entry_u *ipoe_lookup2_u(__be32 addr)
}
-static void ipoe_queue_u(struct sk_buff *skb, __u32 addr)
+static int ipoe_queue_u(struct sk_buff *skb, __u32 addr)
{
unsigned long ts;
if (ipoe_lookup1_u(addr, &ts) && jiffies_to_msecs(jiffies - ts) < IPOE_RATE_U) {
//pr_info("not queue %08x\n", addr);
- return;
+ return -1;
}
if (skb_queue_len(&ipoe_queue) > IPOE_QUEUE_LEN)
- return;
-
- skb = skb_clone(skb, GFP_ATOMIC);
- if (!skb)
- return;
+ return -1;
//pr_info("queue %08x\n", addr);
skb_queue_tail(&ipoe_queue, skb);
schedule_work(&ipoe_queue_work);
+
+ return 0;
}
static void ipoe_start_queue_work(unsigned long dummy)
@@ -634,11 +529,7 @@ static void ipoe_process_queue(struct work_struct *w)
if (!ns)
goto nl_err;
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,32)
if (nla_put_u32(report_skb, IPOE_ATTR_IFINDEX, skb->dev ? skb->dev->ifindex : skb->skb_iif))
-#else
- if (nla_put_u32(report_skb, IPOE_ATTR_IFINDEX, skb->dev ? skb->dev->ifindex : skb->iif))
-#endif
goto nl_err;
if (nla_put(report_skb, IPOE_ATTR_ETH_HDR, sizeof(*eth), eth))
@@ -677,11 +568,7 @@ nl_err:
//pr_info("free %08x\n", e->addr);
list_del(&e->entry2);
list_del_rcu(&e->entry1);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0)
kfree_rcu(e, rcu_head);
-#else
- call_rcu(&e->rcu_head, ipoe_kfree_rcu);
-#endif
}
synchronize_rcu();
@@ -724,47 +611,30 @@ static struct ipoe_session *ipoe_lookup(__be32 addr)
return NULL;
}
-static struct ipoe_session *ipoe_lookup_rt(struct sk_buff *skb, __be32 addr)
+static struct ipoe_session *ipoe_lookup_rt(struct sk_buff *skb, __be32 addr, struct net_device **dev)
{
struct net *net = pick_net(skb);
struct rtable *rt;
- struct net_device *dev;
struct ipoe_session *ses;
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,38)
- struct flowi fl4;
-#else
struct flowi4 fl4;
-#endif
memset(&fl4, 0, sizeof(fl4));
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,38)
- fl4.fl4_dst = addr;
- fl4.fl4_tos = RT_TOS(0);
- fl4.fl4_scope = RT_SCOPE_UNIVERSE;
- if (ip_route_output_key(net, &rt, &fl4))
- return NULL;
-#else
fl4.daddr = addr;
fl4.flowi4_tos = RT_TOS(0);
fl4.flowi4_scope = RT_SCOPE_UNIVERSE;
rt = ip_route_output_key(net, &fl4);
if (IS_ERR(rt))
return NULL;
-#endif
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,37)
- dev = rt->u.dst.dev;
-#else
- dev = rt->dst.dev;
-#endif
+ *dev = rt->dst.dev;
- if (dev->netdev_ops != &ipoe_netdev_ops) {
+ if ((*dev)->netdev_ops != &ipoe_netdev_ops) {
ip_rt_put(rt);
return NULL;
}
- ses = netdev_priv(dev);
+ ses = netdev_priv(*dev);
atomic_inc(&ses->refs);
ip_rt_put(rt);
@@ -772,122 +642,96 @@ static struct ipoe_session *ipoe_lookup_rt(struct sk_buff *skb, __be32 addr)
return ses;
}
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0)
-static unsigned int ipt_in_hook(unsigned int hook, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *skb))
-#elif LINUX_VERSION_CODE < KERNEL_VERSION(4,1,0)
-static unsigned int ipt_in_hook(const struct nf_hook_ops *ops, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *skb))
-#elif LINUX_VERSION_CODE < KERNEL_VERSION(4,4,0)
-static unsigned int ipt_in_hook(const struct nf_hook_ops *ops, struct sk_buff *skb, const struct nf_hook_state *state)
-#else
-static unsigned int ipt_in_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *state)
-#endif
+static rx_handler_result_t ipoe_recv(struct sk_buff **pskb)
{
+ struct sk_buff *skb = *pskb;
+ struct net_device *dev = skb->dev;
+ struct ipoe_iface *i = rcu_dereference(dev->rx_handler_data);
+ struct net_device *out = NULL;
struct ipoe_session *ses = NULL;
struct iphdr *iph;
struct ethhdr *eth;
int noff;
- struct sk_buff *skb1;
- unsigned char *cb_ptr;
struct net_device_stats *stats;
- int ret = NF_DROP;
- if (skb->protocol != htons(ETH_P_IP))
- return NF_ACCEPT;
+ if (!i)
+ return RX_HANDLER_PASS;
- cb_ptr = skb->cb + sizeof(skb->cb) - 2;
+ if (unlikely(skb->pkt_type == PACKET_LOOPBACK))
+ return RX_HANDLER_PASS;
- if (*(__u16 *)cb_ptr == IPOE_MAGIC)
- return NF_ACCEPT;
+ if (skb->protocol != htons(ETH_P_IP))
+ return RX_HANDLER_PASS;
noff = skb_network_offset(skb);
if (!pskb_may_pull(skb, sizeof(*iph) + noff))
- return NF_ACCEPT;
+ return RX_HANDLER_PASS;
iph = ip_hdr(skb);
if (!iph->saddr)
- return NF_ACCEPT;
+ return RX_HANDLER_PASS;
//pr_info("ipoe: recv %08x %08x\n", iph->saddr, iph->daddr);
- ses = ipoe_lookup_rt(skb, iph->saddr);
+ ses = ipoe_lookup_rt(skb, iph->saddr, &out);
if (!ses) {
- if (ipoe_check_exclude(iph->saddr))
- return NF_ACCEPT;
+ if (i->mode == 0)
+ return RX_HANDLER_PASS;
- if (!ipoe_check_network(iph->saddr))
- return NF_ACCEPT;
+ if (out == dev && i->mode == 2)
+ return RX_HANDLER_PASS;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(4,1,0)
- if (!ipoe_check_interface(in->ifindex))
-#else
- if (!ipoe_check_interface(state->in->ifindex))
-#endif
- return NF_ACCEPT;
+ if (out != dev && i->mode == 3) {
+ kfree_skb(skb);
+ return RX_HANDLER_CONSUMED;
+ }
- ipoe_queue_u(skb, iph->saddr);
- return NF_DROP;
+ if (ipoe_check_exclude(iph->saddr))
+ return RX_HANDLER_PASS;
+
+ if (ipoe_queue_u(skb, iph->saddr))
+ kfree_skb(skb);
+
+ return RX_HANDLER_CONSUMED;
}
stats = &ses->dev->stats;
- if (ses->link_dev) {
+ /*if (ses->link_dev) {
eth = eth_hdr(skb);
if (memcmp(eth->h_source, ses->hwaddr, ETH_ALEN)) {
stats->rx_dropped++;
- goto out;
+ kfree_skb(skb);
+ return RX_HANDLER_CONSUMED;
}
- }
-
- if (skb->dev == ses->dev) {
- ret = NF_ACCEPT;
- goto out;
- }
-
- if (ses->addr && ipoe_check_network(iph->daddr)) {
- ret = NF_ACCEPT;
- goto out;
- }
+ }*/
+ eth = eth_hdr(skb);
+ memcpy(ses->hwaddr, eth->h_source, ETH_ALEN);
- skb1 = skb_clone(skb, GFP_ATOMIC);
- if (!skb1) {
- stats->rx_dropped++;
- goto out;
- }
-
- if (ses->addr > 1 && ipoe_do_nat(skb1, ses->addr, 0)) {
- kfree_skb(skb1);
- goto out;
- }
-
- skb1->dev = ses->dev;
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,32)
- skb1->skb_iif = skb->dev->ifindex;
-#else
- skb1->iif = skb->dev->ifindex;
-#endif
+ if (ses->addr > 1 && ipoe_do_nat(skb, ses->addr, 0))
+ goto drop;
- cb_ptr = skb1->cb + sizeof(skb1->cb) - 2;
- *(__u16 *)cb_ptr = IPOE_MAGIC;
+ skb->dev = ses->dev;
+ skb->skb_iif = ses->dev->ifindex;
+ skb->tc_verd = SET_TC_NCLS(0);
+ memset(skb->cb, 0, sizeof(skb->cb));
- //skb1->tc_verd = SET_TC_NCLS(0);
+ ipoe_update_stats(skb, this_cpu_ptr(ses->rx_stats), 0);
- netif_rx(skb1);
+ atomic_dec(&ses->refs);
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
- ipoe_update_stats(skb, this_cpu_ptr(ses->rx_stats), 0);
-#else
- stats->rx_packets++;
- stats->rx_bytes += skb->len;
-#endif
+ return RX_HANDLER_ANOTHER;
-out:
+drop:
atomic_dec(&ses->refs);
- return ret;
+ stats->rx_dropped++;
+ kfree_skb(skb);
+ return RX_HANDLER_CONSUMED;
}
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0)
+/*#if LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0)
static unsigned int ipt_out_hook(unsigned int hook, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *skb))
#elif LINUX_VERSION_CODE < KERNEL_VERSION(4,1,0)
static unsigned int ipt_out_hook(const struct nf_hook_ops *ops, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *skb))
@@ -901,6 +745,13 @@ static unsigned int ipt_out_hook(void *priv, struct sk_buff *skb, const struct n
struct iphdr *iph;
struct ipoe_session *ses;
unsigned char *cb_ptr;
+ struct net_device *dev;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,2,0)
+ struct net_device *out = state->out;
+#endif
+
+ if (!out->atalk_ptr)
+ return NF_ACCEPT;
if (skb->protocol != htons(ETH_P_IP))
return NF_ACCEPT;
@@ -919,13 +770,7 @@ static unsigned int ipt_out_hook(void *priv, struct sk_buff *skb, const struct n
if (ipoe_check_exclude(iph->daddr))
return NF_ACCEPT;
- if (!ipoe_check_network(iph->daddr))
- return NF_ACCEPT;
-
- if (ipoe_check_network(iph->saddr))
- return NF_ACCEPT;
-
- ses = ipoe_lookup_rt(skb, iph->daddr);
+ ses = ipoe_lookup_rt(skb, iph->daddr, &dev);
if (!ses)
return NF_ACCEPT;
@@ -944,9 +789,8 @@ static unsigned int ipt_out_hook(void *priv, struct sk_buff *skb, const struct n
atomic_dec(&ses->refs);
return NF_ACCEPT;
-}
+}*/
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
static struct rtnl_link_stats64 *ipoe_stats64(struct net_device *dev,
struct rtnl_link_stats64 *stats)
{
@@ -991,18 +835,15 @@ static struct rtnl_link_stats64 *ipoe_stats64(struct net_device *dev,
return stats;
}
-#endif
static void ipoe_free_netdev(struct net_device *dev)
{
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
struct ipoe_session *ses = netdev_priv(dev);
if (ses->rx_stats)
free_percpu(ses->rx_stats);
if (ses->tx_stats)
free_percpu(ses->tx_stats);
-#endif
free_netdev(dev);
}
@@ -1032,11 +873,7 @@ static const struct header_ops ipoe_hard_header_ops = {
static void ipoe_netdev_setup(struct net_device *dev)
{
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)
- dev->hard_start_xmit = ipoe_xmit;
-#else
dev->netdev_ops = &ipoe_netdev_ops;
-#endif
dev->destructor = ipoe_free_netdev;
dev->type = ARPHRD_ETHER;
@@ -1050,22 +887,20 @@ static void ipoe_netdev_setup(struct net_device *dev)
dev->features |= NETIF_F_NETNS_LOCAL;
dev->features &= ~NETIF_F_HW_VLAN_FILTER;
dev->header_ops = &ipoe_hard_header_ops;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)
dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
-#endif
}
-static int ipoe_create(__be32 peer_addr, __be32 addr, const char *link_ifname, const __u8 *hwaddr)
+static int ipoe_create(__be32 peer_addr, __be32 addr, __be32 gw, int ifindex, const __u8 *hwaddr)
{
struct ipoe_session *ses;
struct net_device *dev, *link_dev = NULL;
char name[IFNAMSIZ];
int r = -EINVAL;
int h = hash_addr(peer_addr);
- struct in_device *in_dev;
+ //struct in_device *in_dev;
- if (link_ifname) {
- link_dev = dev_get_by_name(&init_net, link_ifname);
+ if (ifindex) {
+ link_dev = dev_get_by_index(&init_net, ifindex);
if (!link_dev)
return -EINVAL;
}
@@ -1095,16 +930,15 @@ static int ipoe_create(__be32 peer_addr, __be32 addr, const char *link_ifname, c
ses->dev = dev;
ses->addr = addr;
ses->peer_addr = peer_addr;
+ ses->gw = gw;
ses->link_dev = link_dev;
memcpy(ses->hwaddr, hwaddr, ETH_ALEN);
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
ses->rx_stats = alloc_percpu(struct ipoe_stats);
ses->tx_stats = alloc_percpu(struct ipoe_stats);
if (!ses->rx_stats || !ses->tx_stats) {
r = -ENOMEM;
goto failed_free;
}
-#endif
if (link_dev) {
dev->features = link_dev->features & ~NETIF_F_HW_VLAN_FILTER;
@@ -1117,13 +951,13 @@ static int ipoe_create(__be32 peer_addr, __be32 addr, const char *link_ifname, c
else
dev->flags &= ~IFF_NOARP;
- in_dev = __in_dev_get_rtnl(dev);
+ /*in_dev = __in_dev_get_rtnl(dev);
if (in_dev) {
if (addr == 1)
IPV4_DEVCONF(in_dev->cnf, RP_FILTER) = 0;
else
IPV4_DEVCONF(in_dev->cnf, RP_FILTER) = 1;
- }
+ }*/
dev->tx_queue_len = 100;
@@ -1163,11 +997,10 @@ static int ipoe_nl_cmd_noop(struct sk_buff *skb, struct genl_info *info)
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0)
- hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq,
+ hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq, &ipoe_nl_family, 0, IPOE_CMD_NOOP);
#else
- hdr = genlmsg_put(msg, info->snd_portid, info->snd_seq,
+ hdr = genlmsg_put(msg, info->snd_portid, info->snd_seq, &ipoe_nl_family, 0, IPOE_CMD_NOOP);
#endif
- &ipoe_nl_family, 0, IPOE_CMD_NOOP);
if (IS_ERR(hdr)) {
ret = PTR_ERR(hdr);
goto err_out;
@@ -1175,9 +1008,7 @@ static int ipoe_nl_cmd_noop(struct sk_buff *skb, struct genl_info *info)
genlmsg_end(msg, hdr);
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)
- return genlmsg_unicast(msg, info->snd_pid);
-#elif LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0)
return genlmsg_unicast(genl_info_net(info), msg, info->snd_pid);
#else
return genlmsg_unicast(genl_info_net(info), msg, info->snd_portid);
@@ -1194,9 +1025,9 @@ static int ipoe_nl_cmd_create(struct sk_buff *skb, struct genl_info *info)
{
struct sk_buff *msg;
void *hdr;
- __be32 peer_addr = 0, addr = 0;
+ __be32 peer_addr = 0, addr = 0, gw = 0;
+ int ifindex = 0;
int ret = 0;
- char ifname[IFNAMSIZ];
__u8 hwaddr[ETH_ALEN];
struct ipoe_session *ses;
//struct net *net = genl_info_net(info);
@@ -1215,8 +1046,11 @@ static int ipoe_nl_cmd_create(struct sk_buff *skb, struct genl_info *info)
if (info->attrs[IPOE_ATTR_ADDR])
addr = nla_get_be32(info->attrs[IPOE_ATTR_ADDR]);
- if (info->attrs[IPOE_ATTR_IFNAME])
- nla_strlcpy(ifname, info->attrs[IPOE_ATTR_IFNAME], IFNAMSIZ - 1);
+ if (info->attrs[IPOE_ATTR_GW_ADDR])
+ gw = nla_get_be32(info->attrs[IPOE_ATTR_GW_ADDR]);
+
+ if (info->attrs[IPOE_ATTR_IFINDEX])
+ ifindex = nla_get_u32(info->attrs[IPOE_ATTR_IFINDEX]);
if (info->attrs[IPOE_ATTR_HWADDR])
nla_memcpy(hwaddr, info->attrs[IPOE_ATTR_HWADDR], ETH_ALEN);
@@ -1230,11 +1064,10 @@ static int ipoe_nl_cmd_create(struct sk_buff *skb, struct genl_info *info)
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0)
- hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq,
+ hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq, &ipoe_nl_family, 0, IPOE_CMD_CREATE);
#else
- hdr = genlmsg_put(msg, info->snd_portid, info->snd_seq,
+ hdr = genlmsg_put(msg, info->snd_portid, info->snd_seq, &ipoe_nl_family, 0, IPOE_CMD_CREATE);
#endif
- &ipoe_nl_family, 0, IPOE_CMD_CREATE);
if (IS_ERR(hdr)) {
ret = PTR_ERR(hdr);
goto err_out;
@@ -1242,7 +1075,7 @@ static int ipoe_nl_cmd_create(struct sk_buff *skb, struct genl_info *info)
//pr_info("ipoe: create %08x %08x %s\n", peer_addr, addr, info->attrs[IPOE_ATTR_IFNAME] ? ifname : "-");
- ret = ipoe_create(peer_addr, addr, info->attrs[IPOE_ATTR_IFNAME] ? ifname : NULL, hwaddr);
+ ret = ipoe_create(peer_addr, addr, gw, ifindex, hwaddr);
if (ret < 0) {
nlmsg_free(msg);
@@ -1252,9 +1085,7 @@ static int ipoe_nl_cmd_create(struct sk_buff *skb, struct genl_info *info)
nla_put_u32(msg, IPOE_ATTR_IFINDEX, ret);
genlmsg_end(msg, hdr);
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)
- return genlmsg_unicast(msg, info->snd_pid);
-#elif LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0)
return genlmsg_unicast(genl_info_net(info), msg, info->snd_pid);
#else
return genlmsg_unicast(genl_info_net(info), msg, info->snd_portid);
@@ -1282,20 +1113,11 @@ static int ipoe_nl_cmd_delete(struct sk_buff *skb, struct genl_info *info)
down(&ipoe_wlock);
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34)
- rtnl_lock();
- dev = __dev_get_by_index(&init_net, ifindex);
-#else
rcu_read_lock();
dev = dev_get_by_index_rcu(&init_net, ifindex);
-#endif
if (!dev || dev->header_ops != &ipoe_hard_header_ops)
r = 1;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34)
- rtnl_unlock();
-#else
rcu_read_unlock();
-#endif
if (r)
goto out_unlock;
@@ -1330,7 +1152,6 @@ out_unlock:
static int ipoe_nl_cmd_modify(struct sk_buff *skb, struct genl_info *info)
{
int ret = -EINVAL, r = 0;
- char ifname[IFNAMSIZ];
struct net_device *dev, *link_dev, *old_dev;
struct in_device *in_dev;
struct ipoe_session *ses, *ses1;
@@ -1344,20 +1165,11 @@ static int ipoe_nl_cmd_modify(struct sk_buff *skb, struct genl_info *info)
ifindex = nla_get_u32(info->attrs[IPOE_ATTR_IFINDEX]);
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34)
- rtnl_lock();
- dev = __dev_get_by_index(&init_net, ifindex);
-#else
rcu_read_lock();
dev = dev_get_by_index_rcu(&init_net, ifindex);
-#endif
if (!dev || dev->header_ops != &ipoe_hard_header_ops)
r = 1;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34)
- rtnl_unlock();
-#else
rcu_read_unlock();
-#endif
if (r)
goto out_unlock;
@@ -1386,13 +1198,15 @@ static int ipoe_nl_cmd_modify(struct sk_buff *skb, struct genl_info *info)
if (peer_addr)
list_add_tail_rcu(&ses->entry, &ipoe_list[hash_addr(peer_addr)]);
+ else
+ ses->dev->flags &= ~IFF_UP;
}
- if (info->attrs[IPOE_ATTR_IFNAME]) {
- nla_strlcpy(ifname, info->attrs[IPOE_ATTR_IFNAME], IFNAMSIZ - 1);
+ if (info->attrs[IPOE_ATTR_LINK_IFINDEX]) {
+ int ifindex = nla_get_u32(info->attrs[IPOE_ATTR_LINK_IFINDEX]);
- if (*ifname) {
- link_dev = dev_get_by_name(&init_net, ifname);
+ if (ifindex) {
+ link_dev = dev_get_by_index(&init_net, ifindex);
if (!link_dev)
goto out_unlock;
@@ -1428,6 +1242,9 @@ static int ipoe_nl_cmd_modify(struct sk_buff *skb, struct genl_info *info)
}
}
+ if (info->attrs[IPOE_ATTR_GW_ADDR])
+ ses->gw = nla_get_u32(info->attrs[IPOE_ATTR_GW_ADDR]);
+
if (info->attrs[IPOE_ATTR_HWADDR])
nla_memcpy(ses->hwaddr, info->attrs[IPOE_ATTR_HWADDR], ETH_ALEN);
@@ -1453,12 +1270,8 @@ static int fill_info(struct sk_buff *skb, struct ipoe_session *ses, u32 pid, u32
nla_put_u32(skb, IPOE_ATTR_ADDR, ses->addr))
goto nla_put_failure;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,0,0)
genlmsg_end(skb, hdr);
return 0;
-#else
- return genlmsg_end(skb, hdr);
-#endif
nla_put_failure:
genlmsg_cancel(skb, hdr);
@@ -1494,58 +1307,6 @@ static int ipoe_nl_cmd_dump_sessions(struct sk_buff *skb, struct netlink_callbac
return skb->len;
}
-static int ipoe_nl_cmd_add_net(struct sk_buff *skb, struct genl_info *info)
-{
- struct ipoe_network *n;
-
- if (!info->attrs[IPOE_ATTR_ADDR] || !info->attrs[IPOE_ATTR_MASK])
- return -EINVAL;
-
- n = kmalloc(sizeof(*n), GFP_KERNEL);
- if (!n)
- return -ENOMEM;
-
- n->addr = nla_get_u32(info->attrs[IPOE_ATTR_ADDR]);
- n->mask = nla_get_u32(info->attrs[IPOE_ATTR_MASK]);
- n->addr = ntohl(n->addr) & n->mask;
- //pr_info("add net %08x/%08x\n", n->addr, n->mask);
-
- down(&ipoe_wlock);
- list_add_tail_rcu(&n->entry, &ipoe_networks);
- up(&ipoe_wlock);
-
- return 0;
-}
-
-static int ipoe_nl_cmd_del_net(struct sk_buff *skb, struct genl_info *info)
-{
- struct ipoe_network *n;
- __be32 addr;
-
- if (!info->attrs[IPOE_ATTR_ADDR])
- return -EINVAL;
-
- addr = nla_get_u32(info->attrs[IPOE_ATTR_ADDR]);
-
- rcu_read_lock();
- list_for_each_entry_rcu(n, &ipoe_networks, entry) {
- if (!addr || addr == n->addr) {
- //pr_info("del net %08x/%08x\n", n->addr, n->mask);
- list_del_rcu(&n->entry);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0)
- kfree_rcu(n, rcu_head);
-#else
- call_rcu(&n->rcu_head, ipoe_kfree_rcu);
-#endif
- }
- }
- rcu_read_unlock();
-
- synchronize_rcu();
-
- return 0;
-}
-
static int ipoe_nl_cmd_add_exclude(struct sk_buff *skb, struct genl_info *info)
{
struct ipoe_network *n;
@@ -1581,11 +1342,7 @@ static void clean_excl_list(void)
ht = &ipoe_excl_list[i];
list_for_each_entry_rcu(n, ht, entry) {
list_del_rcu(&n->entry);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0)
kfree_rcu(n, rcu_head);
-#else
- call_rcu(&n->rcu_head, ipoe_kfree_rcu);
-#endif
}
}
rcu_read_unlock();
@@ -1614,11 +1371,7 @@ static int ipoe_nl_cmd_del_exclude(struct sk_buff *skb, struct genl_info *info)
list_for_each_entry_rcu(n, ht, entry) {
if (n->addr == addr) {
list_del_rcu(&n->entry);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0)
kfree_rcu(n, rcu_head);
-#else
- call_rcu(&n->rcu_head, ipoe_kfree_rcu);
-#endif
}
}
rcu_read_unlock();
@@ -1632,48 +1385,79 @@ static int ipoe_nl_cmd_del_exclude(struct sk_buff *skb, struct genl_info *info)
static int ipoe_nl_cmd_add_interface(struct sk_buff *skb, struct genl_info *info)
{
struct ipoe_iface *i;
+ struct net_device *dev;
+ int ret = 0;
+ int ifindex;
if (!info->attrs[IPOE_ATTR_IFINDEX])
return -EINVAL;
+ ifindex = nla_get_u32(info->attrs[IPOE_ATTR_IFINDEX]);
+
+ rtnl_lock();
+
+ dev = __dev_get_by_index(&init_net, ifindex);
+
+ if (!dev) {
+ rtnl_unlock();
+ return -ENODEV;
+ }
+
i = kmalloc(sizeof(*i), GFP_KERNEL);
- if (!i)
- return -ENOMEM;
+ if (!i) {
+ ret = -ENOMEM;
+ goto out;
+ }
- i->ifindex = nla_get_u32(info->attrs[IPOE_ATTR_IFINDEX]);
+ i->ifindex = ifindex;
- down(&ipoe_wlock);
- list_add_tail_rcu(&i->entry, &ipoe_interfaces);
- up(&ipoe_wlock);
+ if (info->attrs[IPOE_ATTR_MODE])
+ i->mode = nla_get_u8(info->attrs[IPOE_ATTR_MODE]);
+ else
+ i->mode = 2;
- return 0;
+ ret = netdev_rx_handler_register(dev, ipoe_recv, i);
+
+ if (ret)
+ kfree(i);
+ else
+ list_add_tail(&i->entry, &ipoe_interfaces);
+
+out:
+ rtnl_unlock();
+
+ return ret;
}
static int ipoe_nl_cmd_del_interface(struct sk_buff *skb, struct genl_info *info)
{
struct ipoe_iface *i;
int ifindex;
+ struct list_head *pos, *n;
+ struct net_device *dev;
if (!info->attrs[IPOE_ATTR_IFINDEX])
return -EINVAL;
ifindex = nla_get_u32(info->attrs[IPOE_ATTR_IFINDEX]);
- rcu_read_lock();
- list_for_each_entry_rcu(i, &ipoe_interfaces, entry) {
+ rtnl_lock();
+ list_for_each_safe(pos, n, &ipoe_interfaces) {
+ i = list_entry(pos, typeof(*i), entry);
if (ifindex == -1 || ifindex == i->ifindex) {
- //pr_info("del net %08x/%08x\n", n->addr, n->mask);
- list_del_rcu(&i->entry);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0)
+ dev = __dev_get_by_index(&init_net, i->ifindex);
+
+ netdev_rx_handler_unregister(dev);
+
+ list_del(&i->entry);
+
kfree_rcu(i, rcu_head);
-#else
- call_rcu(&i->rcu_head, ipoe_kfree_rcu);
-#endif
+
+ if (ifindex == -1)
+ break;
}
}
- rcu_read_unlock();
-
- synchronize_rcu();
+ rtnl_unlock();
return 0;
}
@@ -1681,11 +1465,13 @@ static int ipoe_nl_cmd_del_interface(struct sk_buff *skb, struct genl_info *info
static struct nla_policy ipoe_nl_policy[IPOE_ATTR_MAX + 1] = {
[IPOE_ATTR_NONE] = { .type = NLA_UNSPEC, },
[IPOE_ATTR_ADDR] = { .type = NLA_U32, },
- [IPOE_ATTR_PEER_ADDR] = { .type = NLA_U32, },
- [IPOE_ATTR_IFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 },
- [IPOE_ATTR_HWADDR] = { .type = NLA_U64 },
- [IPOE_ATTR_IFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 },
+ [IPOE_ATTR_PEER_ADDR] = { .type = NLA_U32, },
[IPOE_ATTR_MASK] = { .type = NLA_U32, },
+ [IPOE_ATTR_MODE] = { .type = NLA_U8, },
+ [IPOE_ATTR_GW_ADDR] = { .type = NLA_U32, },
+ [IPOE_ATTR_HWADDR] = { .len = ETH_ALEN, },
+ [IPOE_ATTR_IFINDEX] = { .type = NLA_U32, },
+ [IPOE_ATTR_LINK_IFINDEX]= { .type = NLA_U32, },
};
static struct genl_ops ipoe_nl_ops[] = {
@@ -1719,18 +1505,6 @@ static struct genl_ops ipoe_nl_ops[] = {
.policy = ipoe_nl_policy,
},
{
- .cmd = IPOE_CMD_ADD_NET,
- .doit = ipoe_nl_cmd_add_net,
- .policy = ipoe_nl_policy,
- .flags = GENL_ADMIN_PERM,
- },
- {
- .cmd = IPOE_CMD_DEL_NET,
- .doit = ipoe_nl_cmd_del_net,
- .policy = ipoe_nl_policy,
- .flags = GENL_ADMIN_PERM,
- },
- {
.cmd = IPOE_CMD_ADD_IF,
.doit = ipoe_nl_cmd_add_interface,
.policy = ipoe_nl_policy,
@@ -1774,44 +1548,10 @@ static struct genl_multicast_group ipoe_nl_mcgs[] = {
};
#endif
-static struct nf_hook_ops ipt_ops[] __read_mostly = {
- {
- .hook = ipt_out_hook,
- .pf = PF_INET,
- .hooknum = NF_INET_POST_ROUTING,
- .priority = NF_IP_PRI_LAST,
-#if LINUX_VERSION_CODE < KERNEL_VERSION(4,4,0)
- .owner = THIS_MODULE,
-#endif
- },
- {
- .hook = ipt_out_hook,
- .pf = PF_INET,
- .hooknum = NF_INET_LOCAL_OUT,
- .priority = NF_IP_PRI_LAST,
-#if LINUX_VERSION_CODE < KERNEL_VERSION(4,4,0)
- .owner = THIS_MODULE,
-#endif
- },
- {
- .hook = ipt_in_hook,
- .pf = PF_INET,
- .hooknum = NF_INET_PRE_ROUTING,
- .priority = NF_IP_PRI_FIRST,
-#if LINUX_VERSION_CODE < KERNEL_VERSION(4,4,0)
- .owner = THIS_MODULE,
-#endif
- },
-};
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)
static const struct net_device_ops ipoe_netdev_ops = {
.ndo_start_xmit = ipoe_xmit,
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
.ndo_get_stats64 = ipoe_stats64,
-#endif
};
-#endif
/*static struct pernet_operations ipoe_net_ops = {
.init = ipoe_init_net,
@@ -1829,6 +1569,7 @@ static int __init ipoe_init(void)
/*err = register_pernet_device(&ipoe_net_ops);
if (err < 0)
return err;*/
+
for (i = 0; i <= HASH_BITS; i++) {
INIT_LIST_HEAD(&ipoe_list[i]);
INIT_LIST_HEAD(&ipoe_list1_u[i]);
@@ -1838,24 +1579,6 @@ static int __init ipoe_init(void)
skb_queue_head_init(&ipoe_queue);
INIT_WORK(&ipoe_queue_work, ipoe_process_queue);
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
- err = genl_register_family(&ipoe_nl_family);
- if (err < 0) {
- printk(KERN_INFO "ipoe: can't register netlink interface\n");
- goto out;
- }
-
- for (i = 0; i < ARRAY_SIZE(ipoe_nl_ops); i++) {
- err = genl_register_ops(&ipoe_nl_family, &ipoe_nl_ops[i]);
- if (err)
- break;
- }
-
- if (err < 0) {
- printk(KERN_INFO "ipoe: can't register netlink interface\n");
- goto out_unreg;
- }
-#else
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0)
err = genl_register_family_with_ops(&ipoe_nl_family, ipoe_nl_ops, ARRAY_SIZE(ipoe_nl_ops));
#else
@@ -1863,54 +1586,58 @@ static int __init ipoe_init(void)
#endif
if (err < 0) {
printk(KERN_INFO "ipoe: can't register netlink interface\n");
- goto out;
+ return err;
}
-#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0)
err = genl_register_mc_group(&ipoe_nl_family, &ipoe_nl_mcg);
if (err < 0) {
printk(KERN_INFO "ipoe: can't register netlink multicast group\n");
- goto out_unreg;
+ genl_unregister_family(&ipoe_nl_family);
+ return err;
}
#endif
- err = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
- if (err < 0) {
- printk(KERN_INFO "ipoe: can't register nf hooks\n");
- goto out_unreg;
- }
-
return 0;
-
-out_unreg:
- genl_unregister_family(&ipoe_nl_family);
-out:
- return err;
}
static void __exit ipoe_fini(void)
{
- struct ipoe_network *n;
struct ipoe_entry_u *e;
struct ipoe_session *ses;
+ struct net_device *dev;
int i;
- nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
-
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0)
genl_unregister_mc_group(&ipoe_nl_family, &ipoe_nl_mcg);
#endif
genl_unregister_family(&ipoe_nl_family);
+ down(&ipoe_wlock);
+ up(&ipoe_wlock);
+
+ rtnl_lock();
+ while (!list_empty(&ipoe_interfaces)) {
+ struct ipoe_iface *i = list_entry(ipoe_interfaces.next, typeof(*i), entry);
+
+ dev = __dev_get_by_index(&init_net, i->ifindex);
+
+ if (dev && rcu_dereference(dev->rx_handler) == ipoe_recv)
+ netdev_rx_handler_unregister(dev);
+
+ list_del(&i->entry);
+
+ kfree_rcu(i, rcu_head);
+ }
+ rtnl_unlock();
+
+ synchronize_net();
+
flush_work(&ipoe_queue_work);
skb_queue_purge(&ipoe_queue);
del_timer(&ipoe_timer_u);
- down(&ipoe_wlock);
- up(&ipoe_wlock);
-
for (i = 0; i <= HASH_BITS; i++)
rcu_assign_pointer(ipoe_list[i].next, &ipoe_list[i]);
@@ -1926,12 +1653,6 @@ static void __exit ipoe_fini(void)
unregister_netdev(ses->dev);
}
- while (!list_empty(&ipoe_networks)) {
- n = list_entry(ipoe_networks.next, typeof(*n), entry);
- list_del(&n->entry);
- kfree(n);
- }
-
while (!list_empty(&ipoe_list2_u)) {
e = list_entry(ipoe_list2_u.next, typeof(*e), entry2);
list_del(&e->entry2);
diff --git a/drivers/ipoe/ipoe.h b/drivers/ipoe/ipoe.h
index e0cfc4e5..c37cb73e 100644
--- a/drivers/ipoe/ipoe.h
+++ b/drivers/ipoe/ipoe.h
@@ -9,8 +9,6 @@ enum {
IPOE_CMD_DELETE,
IPOE_CMD_MODIFY,
IPOE_CMD_GET,
- IPOE_CMD_ADD_NET,
- IPOE_CMD_DEL_NET,
IPOE_CMD_ADD_IF,
IPOE_CMD_DEL_IF,
IPOE_REP_PKT,
@@ -25,12 +23,14 @@ enum {
IPOE_ATTR_NONE, /* no data */
IPOE_ATTR_ADDR, /* u32 */
IPOE_ATTR_PEER_ADDR, /* u32 */
- IPOE_ATTR_IFNAME, /* u32 */
+ IPOE_ATTR_GW_ADDR, /* u32 */
IPOE_ATTR_HWADDR, /* u32 */
IPOE_ATTR_MASK, /* u32 */
IPOE_ATTR_IFINDEX, /* u32 */
+ IPOE_ATTR_LINK_IFINDEX, /* u32 */
IPOE_ATTR_ETH_HDR, /* u32 */
IPOE_ATTR_IP_HDR, /* u32 */
+ IPOE_ATTR_MODE, /* u8 */
__IPOE_ATTR_MAX,
};
@@ -41,7 +41,7 @@ enum {
*/
#define IPOE_GENL_NAME "IPoE"
#define IPOE_GENL_MCG_PKT "Packet"
-#define IPOE_GENL_VERSION 0x1
+#define IPOE_GENL_VERSION 0x02
#endif