summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--accel-pppd/ctrl/ipoe/ipoe.c122
-rw-r--r--accel-pppd/ctrl/ipoe/ipoe.h4
-rw-r--r--accel-pppd/ifcfg.c163
-rw-r--r--accel-pppd/include/ap_session.h1
-rw-r--r--accel-pppd/libnetlink/iplink.c138
-rw-r--r--accel-pppd/libnetlink/iplink.h5
-rw-r--r--drivers/ipoe/ipoe.c38
7 files changed, 374 insertions, 97 deletions
diff --git a/accel-pppd/ctrl/ipoe/ipoe.c b/accel-pppd/ctrl/ipoe/ipoe.c
index ae4dca20..69ffe36c 100644
--- a/accel-pppd/ctrl/ipoe/ipoe.c
+++ b/accel-pppd/ctrl/ipoe/ipoe.c
@@ -13,6 +13,7 @@
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <linux/if.h>
+#include <linux/route.h>
#include <pcre.h>
@@ -44,6 +45,7 @@ static int conf_dhcpv4 = 1;
static int conf_up = 0;
static int conf_mode = 0;
static int conf_shared = 1;
+static int conf_ifcfg = 1;
//static int conf_dhcpv6;
static int conf_username;
static int conf_unit_cache;
@@ -66,6 +68,13 @@ static mempool_t ses_pool;
static LIST_HEAD(serv_list);
+struct ifaddr
+{
+ struct list_head entry;
+ in_addr_t addr;
+ int refs;
+};
+
struct iplink_arg
{
pcre *re;
@@ -180,9 +189,10 @@ static void ipoe_session_start(struct ipoe_session *ses)
struct ifreq ifr;
struct unit_cache *uc;
- if (ses->serv->opt_shared == 0)
+ if (ses->serv->opt_shared == 0 && (!ses->ses.ipv4 || ses->ses.ipv4->peer_addr == ses->yiaddr)) {
strncpy(ses->ses.ifname, ses->serv->ifname, AP_IFNAME_LEN);
- else if (ses->ifindex == -1) {
+ ses->ses.ifindex = ses->serv->ifindex;
+ } else if (ses->ifindex == -1) {
pthread_mutex_lock(&uc_lock);
if (!list_empty(&uc_list)) {
uc = list_entry(uc_list.next, typeof(*uc), entry);
@@ -246,6 +256,10 @@ static void ipoe_session_start(struct ipoe_session *ses)
return;
}
+ dhcpv4_get_ip(ses->serv->dhcpv4, &ses->yiaddr, &ses->siaddr, &ses->mask);
+ if (ses->yiaddr)
+ ses->dhcp_addr = 1;
+
ses->ses.ipv4 = ipdb_get_ipv4(&ses->ses);
/*if (!ses->ses.ipv4) {
log_ppp_warn("no free IPv4 address\n");
@@ -289,14 +303,93 @@ static void ipoe_session_start(struct ipoe_session *ses)
}
}
+static void ipoe_ifcfg_add(struct ipoe_session *ses)
+{
+ struct ifaddr *a;
+ struct ipoe_serv *serv = ses->serv;
+ int f = 0;
+
+ pthread_mutex_lock(&serv->lock);
+
+ if (ses->serv->opt_shared) {
+ list_for_each_entry(a, &serv->addr_list, entry) {
+ if (a->addr == ses->siaddr) {
+ f = 1;
+ break;
+ }
+ }
+ if (!f) {
+ a = _malloc(sizeof(*a));
+ a->addr = ses->siaddr;
+ a->refs = 1;
+ list_add_tail(&a->entry, &serv->addr_list);
+
+ if (ipaddr_add(serv->ifindex, a->addr, 32))
+ log_ppp_warn("ipoe: failed to add addess to interface '%s'\n", serv->ifname);
+ } else
+ a->refs++;
+ } else {
+ if (ipaddr_add(serv->ifindex, ses->siaddr, 32))
+ log_ppp_warn("ipoe: failed to add addess to interface '%s'\n", serv->ifname);
+ }
+
+ pthread_mutex_unlock(&serv->lock);
+
+ if (iproute_add(serv->ifindex, ses->siaddr, ses->yiaddr))
+ 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)
+{
+ struct ifaddr *a;
+ struct ipoe_serv *serv = ses->serv;
+
+ if (iproute_del(serv->ifindex, ses->yiaddr))
+ log_ppp_warn("ipoe: failed to delete route from interface '%s'\n", serv->ifname);
+
+ pthread_mutex_lock(&serv->lock);
+
+ if (ses->serv->opt_shared) {
+ list_for_each_entry(a, &serv->addr_list, entry) {
+ if (a->addr == ses->siaddr)
+ break;
+ }
+ if (--a->refs == 0) {
+ if (ipaddr_del(serv->ifindex, a->addr))
+ log_ppp_warn("ipoe: failed to delete addess from interface '%s'\n", serv->ifname);
+ list_del(&a->entry);
+ _free(a);
+ }
+ } else {
+ if (ipaddr_del(serv->ifindex, ses->siaddr))
+ log_ppp_warn("ipoe: failed to add addess to interface '%s'\n", serv->ifname);
+ }
+
+ pthread_mutex_unlock(&serv->lock);
+}
+
static void ipoe_session_activate(struct ipoe_session *ses)
{
+ uint32_t addr;
+
if (ses->ifindex != -1) {
- if (ipoe_nl_modify(ses->ifindex, ses->yiaddr, ses->ses.ipv4->peer_addr, NULL, NULL)) {
+ if (!ses->ses.ipv4)
+ addr = 1;
+ else if (ses->ses.ipv4->peer_addr != ses->yiaddr)
+ addr = ses->ses.ipv4->peer_addr;
+ else
+ addr = 0;
+ if (ipoe_nl_modify(ses->ifindex, ses->yiaddr, addr, NULL, NULL)) {
ap_session_terminate(&ses->ses, TERM_NAS_ERROR, 0);
return;
}
- }
+ } else
+ ses->ctrl.dont_ifcfg = 1;
+
+ if (ses->serv->opt_ifcfg)
+ ipoe_ifcfg_add(ses);
ap_session_activate(&ses->ses);
@@ -387,9 +480,12 @@ static void ipoe_session_finished(struct ap_session *s)
serv_close = ses->serv->need_close && list_empty(&ses->serv->sessions);
pthread_mutex_unlock(&ses->serv->lock);
- if (ses->yiaddr && ses->serv->dhcpv4 && ses->serv->dhcpv4->range)
+ if (ses->dhcp_addr)
dhcpv4_put_ip(ses->serv->dhcpv4, ses->yiaddr);
+ if (ses->ifcfg)
+ ipoe_ifcfg_del(ses);
+
if (serv_close)
ipoe_serv_close(&ses->serv->ctx);
@@ -436,8 +532,6 @@ static struct ipoe_session *ipoe_session_create_dhcpv4(struct ipoe_serv *serv, s
memcpy(ses->hwaddr, pack->hdr->chaddr, 6);
ses->giaddr = pack->hdr->giaddr;
- dhcpv4_get_ip(serv->dhcpv4, &ses->yiaddr, &ses->siaddr, &ses->mask);
-
if (pack->agent_circuit_id)
dlen += sizeof(struct dhcp_opt) + pack->agent_circuit_id->len;
@@ -797,6 +891,7 @@ static void add_interface(const char *ifname, int ifindex, const char *opt)
int opt_dhcpv4 = 0;
int opt_up = 0;
int opt_mode = conf_mode;
+ int opt_ifcfg = conf_ifcfg;
str0 = strchr(opt, ',');
if (str0) {
@@ -837,6 +932,8 @@ static void add_interface(const char *ifname, int ifindex, const char *opt)
opt_mode = MODE_L3;
else
goto parse_err;
+ } else if (strcmp(str, "ifcfg") == 0) {
+ opt_ifcfg = atoi(ptr1);
}
if (end)
@@ -875,7 +972,8 @@ static void add_interface(const char *ifname, int ifindex, const char *opt)
}
serv->opt_up = opt_up;
- serv->opt_mode = conf_mode;
+ serv->opt_mode = opt_mode;
+ serv->opt_ifcfg = opt_ifcfg;
return;
}
@@ -889,8 +987,10 @@ static void add_interface(const char *ifname, int ifindex, const char *opt)
serv->opt_dhcpv4 = opt_dhcpv4;
serv->opt_up = opt_up;
serv->opt_mode = opt_mode;
+ serv->opt_ifcfg = opt_ifcfg;
serv->active = 1;
INIT_LIST_HEAD(&serv->sessions);
+ INIT_LIST_HEAD(&serv->addr_list);
pthread_mutex_init(&serv->lock, NULL);
triton_context_register(&serv->ctx, NULL);
@@ -1116,6 +1216,12 @@ static void load_config(void)
else
conf_shared = 1;
+ opt = conf_get_opt("ipoe", "ifcfg");
+ if (opt)
+ conf_ifcfg = atoi(opt);
+ else
+ conf_ifcfg = 1;
+
opt = conf_get_opt("ipoe", "mode");
if (opt) {
if (!strcmp(opt, "L2"))
diff --git a/accel-pppd/ctrl/ipoe/ipoe.h b/accel-pppd/ctrl/ipoe/ipoe.h
index d18db698..edf97540 100644
--- a/accel-pppd/ctrl/ipoe/ipoe.h
+++ b/accel-pppd/ctrl/ipoe/ipoe.h
@@ -16,12 +16,14 @@ struct ipoe_serv
int ifindex;
int active;
struct list_head sessions;
+ struct list_head addr_list;
struct dhcpv4_serv *dhcpv4;
pthread_mutex_t lock;
int opt_mode;
int opt_shared:1;
int opt_dhcpv4:1;
int opt_up:1;
+ int opt_ifcfg:1;
int need_close:1;
};
@@ -51,6 +53,8 @@ struct ipoe_session
uint8_t *data;
struct dhcpv4_packet *dhcpv4_request;
int ifindex;
+ int ifcfg:1;
+ int dhcp_addr:1;
};
struct ipoe_session_info
diff --git a/accel-pppd/ifcfg.c b/accel-pppd/ifcfg.c
index 0b4927b6..ac88a0d1 100644
--- a/accel-pppd/ifcfg.c
+++ b/accel-pppd/ifcfg.c
@@ -71,104 +71,106 @@ void ap_session_ifup(struct ap_session *ses)
if (ses->stop_time)
return;
- memset(&ifr, 0, sizeof(ifr));
- strcpy(ifr.ifr_name, ses->ifname);
+ if (!ses->ctrl->dont_ifcfg) {
+ memset(&ifr, 0, sizeof(ifr));
+ strcpy(ifr.ifr_name, ses->ifname);
#ifdef USE_BACKUP
- if (!ses->backup || !ses->backup->internal) {
+ if (!ses->backup || !ses->backup->internal) {
#endif
- if (ses->ipv4) {
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = ses->ipv4->addr;
- memcpy(&ifr.ifr_addr, &addr, sizeof(addr));
-
- if (ioctl(sock_fd, SIOCSIFADDR, &ifr))
- log_ppp_error("failed to set IPv4 address: %s\n", strerror(errno));
-
- /*if (ses->ctrl->type == CTRL_TYPE_IPOE) {
- addr.sin_addr.s_addr = 0xffffffff;
- memcpy(&ifr.ifr_netmask, &addr, sizeof(addr));
- if (ioctl(sock_fd, SIOCSIFNETMASK, &ifr))
- log_ppp_error("failed to set IPv4 nask: %s\n", strerror(errno));
- }*/
+ if (ses->ipv4) {
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = ses->ipv4->addr;
+ memcpy(&ifr.ifr_addr, &addr, sizeof(addr));
+
+ if (ioctl(sock_fd, SIOCSIFADDR, &ifr))
+ log_ppp_error("failed to set IPv4 address: %s\n", strerror(errno));
- addr.sin_addr.s_addr = ses->ipv4->peer_addr;
-
- /*if (ses->ctrl->type == CTRL_TYPE_IPOE) {
- memset(&rt, 0, sizeof(rt));
- memcpy(&rt.rt_dst, &addr, sizeof(addr));
- rt.rt_flags = RTF_HOST | RTF_UP;
- rt.rt_metric = 1;
- rt.rt_dev = ifr.ifr_name;
- if (ioctl(sock_fd, SIOCADDRT, &rt, sizeof(rt)))
- log_ppp_error("failed to add route: %s\n", strerror(errno));
- } else*/ {
- memcpy(&ifr.ifr_dstaddr, &addr, sizeof(addr));
+ /*if (ses->ctrl->type == CTRL_TYPE_IPOE) {
+ addr.sin_addr.s_addr = 0xffffffff;
+ memcpy(&ifr.ifr_netmask, &addr, sizeof(addr));
+ if (ioctl(sock_fd, SIOCSIFNETMASK, &ifr))
+ log_ppp_error("failed to set IPv4 nask: %s\n", strerror(errno));
+ }*/
- if (ioctl(sock_fd, SIOCSIFDSTADDR, &ifr))
- log_ppp_error("failed to set peer IPv4 address: %s\n", strerror(errno));
+ addr.sin_addr.s_addr = ses->ipv4->peer_addr;
+
+ /*if (ses->ctrl->type == CTRL_TYPE_IPOE) {
+ memset(&rt, 0, sizeof(rt));
+ memcpy(&rt.rt_dst, &addr, sizeof(addr));
+ rt.rt_flags = RTF_HOST | RTF_UP;
+ rt.rt_metric = 1;
+ rt.rt_dev = ifr.ifr_name;
+ if (ioctl(sock_fd, SIOCADDRT, &rt, sizeof(rt)))
+ log_ppp_error("failed to add route: %s\n", strerror(errno));
+ } else*/ {
+ memcpy(&ifr.ifr_dstaddr, &addr, sizeof(addr));
+
+ if (ioctl(sock_fd, SIOCSIFDSTADDR, &ifr))
+ log_ppp_error("failed to set peer IPv4 address: %s\n", strerror(errno));
+ }
}
- }
-
- if (ses->ipv6) {
- devconf(ses, "accept_ra", "0");
- devconf(ses, "autoconf", "0");
- devconf(ses, "forwarding", "1");
- memset(&ifr6, 0, sizeof(ifr6));
-
- if (ses->ctrl->type != CTRL_TYPE_IPOE) {
- ifr6.ifr6_addr.s6_addr32[0] = htons(0xfe80);
- *(uint64_t *)(ifr6.ifr6_addr.s6_addr + 8) = ses->ipv6->intf_id;
- ifr6.ifr6_prefixlen = 64;
- ifr6.ifr6_ifindex = ses->ifindex;
+ if (ses->ipv6) {
+ devconf(ses, "accept_ra", "0");
+ devconf(ses, "autoconf", "0");
+ devconf(ses, "forwarding", "1");
- if (ioctl(sock6_fd, SIOCSIFADDR, &ifr6))
- log_ppp_error("faild to set LL IPv6 address: %s\n", strerror(errno));
- }
-
- list_for_each_entry(a, &ses->ipv6->addr_list, entry) {
- if (a->prefix_len == 128)
- continue;
+ memset(&ifr6, 0, sizeof(ifr6));
+
+ if (ses->ctrl->type != CTRL_TYPE_IPOE) {
+ ifr6.ifr6_addr.s6_addr32[0] = htons(0xfe80);
+ *(uint64_t *)(ifr6.ifr6_addr.s6_addr + 8) = ses->ipv6->intf_id;
+ ifr6.ifr6_prefixlen = 64;
+ ifr6.ifr6_ifindex = ses->ifindex;
+
+ if (ioctl(sock6_fd, SIOCSIFADDR, &ifr6))
+ log_ppp_error("faild to set LL IPv6 address: %s\n", strerror(errno));
+ }
+
+ list_for_each_entry(a, &ses->ipv6->addr_list, entry) {
+ if (a->prefix_len == 128)
+ continue;
- build_addr(a, ses->ipv6->intf_id, &ifr6.ifr6_addr);
- ifr6.ifr6_prefixlen = a->prefix_len;
+ build_addr(a, ses->ipv6->intf_id, &ifr6.ifr6_addr);
+ ifr6.ifr6_prefixlen = a->prefix_len;
- if (ioctl(sock6_fd, SIOCSIFADDR, &ifr6))
- log_ppp_error("failed to add IPv6 address: %s\n", strerror(errno));
+ if (ioctl(sock6_fd, SIOCSIFADDR, &ifr6))
+ log_ppp_error("failed to add IPv6 address: %s\n", strerror(errno));
+ }
}
- }
-
- if (ioctl(sock_fd, SIOCGIFFLAGS, &ifr))
- log_ppp_error("failed to get interface flags: %s\n", strerror(errno));
- ifr.ifr_flags |= IFF_UP;
+ if (ioctl(sock_fd, SIOCGIFFLAGS, &ifr))
+ log_ppp_error("failed to get interface flags: %s\n", strerror(errno));
- if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr))
- log_ppp_error("failed to set interface flags: %s\n", strerror(errno));
+ ifr.ifr_flags |= IFF_UP;
- if (ses->ctrl->type != CTRL_TYPE_IPOE) {
- ppp = container_of(ses, typeof(*ppp), ses);
- if (ses->ipv4) {
- np.protocol = PPP_IP;
- np.mode = NPMODE_PASS;
+ if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr))
+ log_ppp_error("failed to set interface flags: %s\n", strerror(errno));
- if (ioctl(ppp->unit_fd, PPPIOCSNPMODE, &np))
- log_ppp_error("failed to set NP (IPv4) mode: %s\n", strerror(errno));
- }
-
- if (ses->ipv6) {
- np.protocol = PPP_IPV6;
- np.mode = NPMODE_PASS;
+ if (ses->ctrl->type != CTRL_TYPE_IPOE) {
+ ppp = container_of(ses, typeof(*ppp), ses);
+ if (ses->ipv4) {
+ np.protocol = PPP_IP;
+ np.mode = NPMODE_PASS;
+
+ if (ioctl(ppp->unit_fd, PPPIOCSNPMODE, &np))
+ log_ppp_error("failed to set NP (IPv4) mode: %s\n", strerror(errno));
+ }
+
+ if (ses->ipv6) {
+ np.protocol = PPP_IPV6;
+ np.mode = NPMODE_PASS;
- if (ioctl(ppp->unit_fd, PPPIOCSNPMODE, &np))
- log_ppp_error("failed to set NP (IPv6) mode: %s\n", strerror(errno));
+ if (ioctl(ppp->unit_fd, PPPIOCSNPMODE, &np))
+ log_ppp_error("failed to set NP (IPv6) mode: %s\n", strerror(errno));
+ }
}
- }
#ifdef USE_BACKUP
- }
+ }
#endif
+ }
ses->ctrl->started(ses);
@@ -182,6 +184,9 @@ void __export ap_session_ifdown(struct ap_session *ses)
struct in6_ifreq ifr6;
struct ipv6db_addr_t *a;
+ if (ses->ctrl->dont_ifcfg)
+ return;
+
memset(&ifr, 0, sizeof(ifr));
strcpy(ifr.ifr_name, ses->ifname);
diff --git a/accel-pppd/include/ap_session.h b/accel-pppd/include/ap_session.h
index ab6f699c..ac0704ba 100644
--- a/accel-pppd/include/ap_session.h
+++ b/accel-pppd/include/ap_session.h
@@ -42,6 +42,7 @@ struct ap_ctrl
int mppe;
char *calling_station_id;
char *called_station_id;
+ int dont_ifcfg:1;
void (*started)(struct ap_session*);
void (*finished)(struct ap_session *);
void (*terminate)(struct ap_session *, int hard);
diff --git a/accel-pppd/libnetlink/iplink.c b/accel-pppd/libnetlink/iplink.c
index df00285b..779a8aeb 100644
--- a/accel-pppd/libnetlink/iplink.c
+++ b/accel-pppd/libnetlink/iplink.c
@@ -11,6 +11,9 @@
#include <errno.h>
#include <time.h>
#include <sys/uio.h>
+//#include <linux/if_link.h>
+//#include <linux/if_addr.h>
+//#include <linux/rtnetlink.h>
#include "triton.h"
#include "log.h"
@@ -158,6 +161,141 @@ int __export iplink_get_stats(int ifindex, struct rtnl_link_stats *stats)
return 0;
}
+int __export ipaddr_add(int ifindex, in_addr_t addr, int mask)
+{
+ struct ipaddr_req {
+ struct nlmsghdr n;
+ struct ifaddrmsg i;
+ char buf[1024];
+ } req;
+
+ if (!rth)
+ open_rth();
+
+ if (!rth)
+ return -1;
+
+ memset(&req, 0, sizeof(req) - 1024);
+
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
+ req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE;
+ req.n.nlmsg_type = RTM_NEWADDR;
+ req.i.ifa_family = AF_INET;
+ req.i.ifa_index = ifindex;
+ req.i.ifa_prefixlen = mask;
+
+ addattr32(&req.n, sizeof(req), IFA_LOCAL, addr);
+
+ if (rtnl_talk(rth, &req.n, 0, 0, NULL, NULL, NULL, 0) < 0)
+ return -1;
+
+ return 0;
+}
+
+int __export ipaddr_del(int ifindex, in_addr_t addr)
+{
+ struct ipaddr_req {
+ struct nlmsghdr n;
+ struct ifaddrmsg i;
+ char buf[1024];
+ } req;
+
+ if (!rth)
+ open_rth();
+
+ if (!rth)
+ return -1;
+
+ memset(&req, 0, sizeof(req) - 1024);
+
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
+ req.n.nlmsg_flags = NLM_F_REQUEST;
+ req.n.nlmsg_type = RTM_DELADDR;
+ req.i.ifa_family = AF_INET;
+ req.i.ifa_index = ifindex;
+ req.i.ifa_prefixlen = 32;
+
+ addattr32(&req.n, sizeof(req), IFA_LOCAL, addr);
+
+ if (rtnl_talk(rth, &req.n, 0, 0, NULL, NULL, NULL, 0) < 0)
+ return -1;
+
+ return 0;
+}
+
+int __export iproute_add(int ifindex, in_addr_t src, in_addr_t dst)
+{
+ struct ipaddr_req {
+ struct nlmsghdr n;
+ struct rtmsg i;
+ char buf[1024];
+ } req;
+
+ if (!rth)
+ open_rth();
+
+ if (!rth)
+ return -1;
+
+ memset(&req, 0, sizeof(req) - 1024);
+
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
+ req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE;
+ req.n.nlmsg_type = RTM_NEWROUTE;
+ req.i.rtm_family = AF_INET;
+ req.i.rtm_table = RT_TABLE_MAIN;
+ req.i.rtm_scope = RT_SCOPE_LINK;
+ req.i.rtm_protocol = RTPROT_BOOT;
+ req.i.rtm_type = RTN_UNICAST;
+ req.i.rtm_dst_len = 32;
+
+ addattr32(&req.n, sizeof(req), RTA_PREFSRC, src);
+ addattr32(&req.n, sizeof(req), RTA_DST, dst);
+ addattr32(&req.n, sizeof(req), RTA_OIF, ifindex);
+
+ if (rtnl_talk(rth, &req.n, 0, 0, NULL, NULL, NULL, 0) < 0)
+ return -1;
+
+ return 0;
+}
+
+int __export iproute_del(int ifindex, in_addr_t dst)
+{
+ struct ipaddr_req {
+ struct nlmsghdr n;
+ struct rtmsg i;
+ char buf[1024];
+ } req;
+
+ if (!rth)
+ open_rth();
+
+ if (!rth)
+ return -1;
+
+ memset(&req, 0, sizeof(req) - 1024);
+
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
+ req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+ req.n.nlmsg_type = RTM_DELROUTE;
+ req.i.rtm_family = AF_INET;
+ req.i.rtm_table = RT_TABLE_MAIN;
+ req.i.rtm_scope = RT_SCOPE_LINK;
+ req.i.rtm_protocol = RTPROT_BOOT;
+ req.i.rtm_type = RTN_UNICAST;
+ req.i.rtm_dst_len = 32;
+
+ addattr32(&req.n, sizeof(req), RTA_DST, dst);
+ addattr32(&req.n, sizeof(req), RTA_OIF, ifindex);
+
+ if (rtnl_talk(rth, &req.n, 0, 0, NULL, NULL, NULL, 0) < 0)
+ return -1;
+
+ return 0;
+}
+
+
+
static void init(void)
{
pthread_key_create(&rth_key, free_rth);
diff --git a/accel-pppd/libnetlink/iplink.h b/accel-pppd/libnetlink/iplink.h
index e67e8ed5..a6af6627 100644
--- a/accel-pppd/libnetlink/iplink.h
+++ b/accel-pppd/libnetlink/iplink.h
@@ -8,4 +8,9 @@ typedef int (*iplink_list_func)(int index, int flags, const char *name, void *ar
int iplink_list(iplink_list_func func, void *arg);
int iplink_get_stats(int ifindex, struct rtnl_link_stats *stats);
+int ipaddr_add(int ifindex, in_addr_t addr, int mask);
+int ipaddr_del(int ifindex, in_addr_t addr);
+
+int iproute_add(int ifindex, in_addr_t src, in_addr_t dst);
+int iproute_del(int ifindex, in_addr_t dst);
#endif
diff --git a/drivers/ipoe/ipoe.c b/drivers/ipoe/ipoe.c
index f2fbd828..c2c9b344 100644
--- a/drivers/ipoe/ipoe.c
+++ b/drivers/ipoe/ipoe.c
@@ -113,7 +113,7 @@ 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_lookup1_u(__be32 addr, unsigned long *ts);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)
static const struct net_device_ops ipoe_netdev_ops;
#endif
@@ -554,7 +554,11 @@ 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))
@@ -703,8 +707,12 @@ static unsigned int ipt_in_hook(unsigned int hook, struct sk_buff *skb, const st
}
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
+
cb_ptr = skb1->cb + sizeof(skb1->cb) - 2;
*(__u16 *)cb_ptr = IPOE_MAGIC;
@@ -843,7 +851,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,34)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)
dev->hard_start_xmit = ipoe_xmit;
#else
dev->netdev_ops = &ipoe_netdev_ops;
@@ -973,7 +981,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,34)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)
return genlmsg_unicast(msg, info->snd_pid);
#else
return genlmsg_unicast(genl_info_net(info), msg, info->snd_pid);
@@ -1044,7 +1052,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,34)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)
return genlmsg_unicast(msg, info->snd_pid);
#else
return genlmsg_unicast(genl_info_net(info), msg, info->snd_pid);
@@ -1072,15 +1080,20 @@ static int ipoe_nl_cmd_delete(struct sk_buff *skb, struct genl_info *info)
down(&ipoe_wlock);
- rcu_read_lock();
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34)
- dev = dev_get_by_index_rcu(ifindex);
+ 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;
@@ -1129,15 +1142,20 @@ static int ipoe_nl_cmd_modify(struct sk_buff *skb, struct genl_info *info)
ifindex = nla_get_u32(info->attrs[IPOE_ATTR_IFINDEX]);
- rcu_read_lock();
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34)
- dev = dev_get_by_index_rcu(ifindex);
+ 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;
@@ -1382,7 +1400,7 @@ static struct genl_multicast_group ipoe_nl_mcg = {
.name = IPOE_GENL_MCG_PKT,
};
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34)
+#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)