提交 d9e66279 编写于 作者: D Dmitry Kozlov

ipoe: restored local-net function

local-net is used to filter incomming packets which may start UP session
上级 dbebb99e
......@@ -143,6 +143,7 @@ start=dhcpv4
#soft-terminate=0
#check-mac-change=1
#calling-sid=mac
#local-net=192.168.0.0/16
interface=eth0
......
......@@ -354,6 +354,9 @@ 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
......
......@@ -89,6 +89,13 @@ struct request_item {
int cnt;
};
struct local_net {
struct list_head entry;
in_addr_t addr;
int mask;
int active;
};
enum {SID_MAC, SID_IP};
static int conf_dhcpv4 = 1;
......@@ -171,6 +178,8 @@ static LIST_HEAD(uc_list);
static int uc_size;
static mempool_t uc_pool;
static LIST_HEAD(local_nets);
static pthread_rwlock_t l4_list_lock = PTHREAD_RWLOCK_INITIALIZER;
static LIST_HEAD(l4_redirect_list);
static struct triton_timer_t l4_redirect_timer;
......@@ -3019,6 +3028,79 @@ static void load_vlan_mon(struct conf_sect_t *sect)
}
}
static void parse_local_net(const char *opt)
{
const char *ptr;
char str[17];
in_addr_t addr;
int mask;
char *endptr;
struct local_net *n;
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;
}
list_for_each_entry(n, &local_nets, entry) {
if (n->addr == addr && n->mask == mask) {
n->active = 1;
return;
}
}
n = _malloc(sizeof(*n));
n->addr = addr;
n->mask = mask;
n->active = 1;
list_add_tail(&n->entry, &local_nets);
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;
struct local_net *n;
struct list_head *pos, *t;
list_for_each_entry(n, &local_nets, entry)
n->active = 0;
list_for_each_entry(opt, &sect->items, entry) {
if (strcmp(opt->name, "local-net"))
continue;
if (!opt->val)
continue;
parse_local_net(opt->val);
}
list_for_each_safe(pos, t, &local_nets) {
n = list_entry(pos, typeof(*n), entry);
if (!n->active) {
ipoe_nl_del_net(n->addr);
list_del(&n->entry);
_free(n);
}
}
}
static void load_config(void)
{
......@@ -3280,6 +3362,7 @@ static void load_config(void)
load_interfaces(s);
load_vlan_mon(s);
load_gw_addr(s);
load_local_nets(s);
}
static struct triton_context_t l4_redirect_ctx = {
......
......@@ -128,6 +128,8 @@ int ipoe_nl_modify(int ifindex, uint32_t peer_addr, uint32_t addr, uint32_t gw,
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);
int ipoe_nl_add_net(uint32_t addr, int mask);
void ipoe_nl_del_net(uint32_t addr);
void *arpd_start(struct ipoe_serv *ipoe);
void arpd_stop(void *arp);
......
......@@ -98,6 +98,76 @@ void ipoe_nl_del_exclude(uint32_t addr)
rtnl_close(&rth);
}
int ipoe_nl_add_net(uint32_t addr, int mask)
{
struct rtnl_handle rth;
struct nlmsghdr *nlh;
struct genlmsghdr *ghdr;
struct {
struct nlmsghdr n;
char buf[1024];
} req;
int ret = 0;
if (rtnl_open_byproto(&rth, 0, NETLINK_GENERIC)) {
log_ppp_error("ipoe: cannot open generic netlink socket\n");
return -1;
}
nlh = &req.n;
nlh->nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
nlh->nlmsg_type = ipoe_genl_id;
ghdr = NLMSG_DATA(&req.n);
ghdr->cmd = IPOE_CMD_ADD_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_ppp_error("ipoe: nl_add_net: error talking to kernel\n");
ret = -1;
}
rtnl_close(&rth);
return ret;
}
void ipoe_nl_del_net(uint32_t addr)
{
struct rtnl_handle rth;
struct nlmsghdr *nlh;
struct genlmsghdr *ghdr;
struct {
struct nlmsghdr n;
char buf[1024];
} req;
if (rtnl_open_byproto(&rth, 0, NETLINK_GENERIC)) {
log_ppp_error("ipoe: cannot open generic netlink socket\n");
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, addr);
if (rtnl_talk(&rth, nlh, 0, 0, nlh, NULL, NULL, 0) < 0 )
log_ppp_error("ipoe: nl_del_net: error talking to kernel\n");
rtnl_close(&rth);
}
void ipoe_nl_add_interface(int ifindex, uint8_t mode)
{
struct rtnl_handle rth;
......@@ -544,6 +614,7 @@ static void init(void)
triton_context_wakeup(&mc_ctx);
ipoe_nl_del_exclude(0);
ipoe_nl_del_net(0);
ipoe_nl_delete_interfaces();
}
......
......@@ -108,6 +108,7 @@ static LIST_HEAD(ipoe_list2);
static LIST_HEAD(ipoe_list2_u);
static DEFINE_SEMAPHORE(ipoe_wlock);
static LIST_HEAD(ipoe_interfaces);
static LIST_HEAD(ipoe_networks);
static struct work_struct ipoe_queue_work;
static struct sk_buff_head ipoe_queue;
......@@ -159,6 +160,29 @@ static void ipoe_update_stats(struct sk_buff *skb, struct ipoe_stats *st, int co
u64_stats_update_end(&st->sync);
}
static int ipoe_check_network(__be32 addr)
{
struct ipoe_network *n;
int r;
if (list_empty(&ipoe_networks))
return 1;
r = 0;
addr = ntohl(addr);
rcu_read_lock();
list_for_each_entry_rcu(n, &ipoe_networks, entry) {
if ((addr & n->mask) == n->addr) {
r = 1;
break;
}
}
rcu_read_unlock();
return r;
}
static int ipoe_check_exclude(__be32 addr)
{
struct ipoe_network *n;
......@@ -689,8 +713,11 @@ static rx_handler_result_t ipoe_recv(struct sk_buff **pskb)
if (ipoe_check_exclude(iph->saddr))
return RX_HANDLER_PASS;
if (ipoe_queue_u(skb, iph->saddr))
kfree_skb(skb);
if (ipoe_check_network(iph->saddr)) {
if (ipoe_queue_u(skb, iph->saddr))
kfree_skb(skb);
} else
return RX_HANDLER_PASS;
return RX_HANDLER_CONSUMED;
}
......@@ -1369,13 +1396,12 @@ static int ipoe_nl_cmd_del_exclude(struct sk_buff *skb, struct genl_info *info)
if (n->addr == addr) {
list_del_rcu(&n->entry);
kfree_rcu(n, rcu_head);
break;
}
}
rcu_read_unlock();
up(&ipoe_wlock);
synchronize_rcu();
return 0;
}
......@@ -1444,7 +1470,7 @@ static int ipoe_nl_cmd_del_interface(struct sk_buff *skb, struct genl_info *info
if (ifindex == -1 || ifindex == i->ifindex) {
dev = __dev_get_by_index(&init_net, i->ifindex);
if (dev)
if (dev && rcu_dereference(dev->rx_handler) == ipoe_recv)
netdev_rx_handler_unregister(dev);
list_del(&i->entry);
......@@ -1460,6 +1486,54 @@ static int ipoe_nl_cmd_del_interface(struct sk_buff *skb, struct genl_info *info
return 0;
}
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;
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 = ntohl(nla_get_u32(info->attrs[IPOE_ATTR_ADDR]));
down(&ipoe_wlock);
rcu_read_lock();
list_for_each_entry_rcu(n, &ipoe_networks, entry) {
if (!addr || (addr & n->mask) == n->addr) {
list_del_rcu(&n->entry);
kfree_rcu(n, rcu_head);
if (addr)
break;
}
}
rcu_read_unlock();
up(&ipoe_wlock);
return 0;
}
static struct nla_policy ipoe_nl_policy[IPOE_ATTR_MAX + 1] = {
[IPOE_ATTR_NONE] = { .type = NLA_UNSPEC, },
[IPOE_ATTR_ADDR] = { .type = NLA_U32, },
......@@ -1526,6 +1600,18 @@ static struct genl_ops ipoe_nl_ops[] = {
.policy = ipoe_nl_policy,
.flags = GENL_ADMIN_PERM,
},
{
.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,
},
};
static struct genl_family ipoe_nl_family = {
......
......@@ -14,6 +14,8 @@ enum {
IPOE_REP_PKT,
IPOE_CMD_ADD_EXCLUDE,
IPOE_CMD_DEL_EXCLUDE,
IPOE_CMD_ADD_NET,
IPOE_CMD_DEL_NET,
__IPOE_CMD_MAX,
};
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册