diff options
author | Dmitry Kozlov <xeb@mail.ru> | 2016-07-11 09:47:04 +0300 |
---|---|---|
committer | Dmitry Kozlov <xeb@mail.ru> | 2016-07-11 09:47:04 +0300 |
commit | e0cca4344f70b9c9e23e3c6a7e17c8e93c765184 (patch) | |
tree | 1068654b025b2e24c983d99776696ad889a0c138 | |
parent | 6fb04941ca41312909208938bfac4f753d3c277c (diff) | |
download | accel-ppp-e0cca4344f70b9c9e23e3c6a7e17c8e93c765184.tar.gz accel-ppp-e0cca4344f70b9c9e23e3c6a7e17c8e93c765184.zip |
implemented support for network namespace
This is done using radius attribute NAS-Port-Id. The new format of this attribute is NAS-Port-Id=[ns/][name].
Namespaces must be created malually by "ip netns add ..." command
-rw-r--r-- | accel-pppd/ctrl/ipoe/ipoe.c | 4 | ||||
-rw-r--r-- | accel-pppd/ctrl/l2tp/l2tp.c | 3 | ||||
-rw-r--r-- | accel-pppd/ctrl/pppoe/pppoe.c | 9 | ||||
-rw-r--r-- | accel-pppd/ctrl/pppoe/pppoe.h | 2 | ||||
-rw-r--r-- | accel-pppd/ctrl/pptp/pptp.c | 6 | ||||
-rw-r--r-- | accel-pppd/ifcfg.c | 82 | ||||
-rw-r--r-- | accel-pppd/include/ap_net.h | 22 | ||||
-rw-r--r-- | accel-pppd/include/ap_session.h | 8 | ||||
-rw-r--r-- | accel-pppd/ipv6/dhcpv6.c | 22 | ||||
-rw-r--r-- | accel-pppd/ipv6/nd.c | 21 | ||||
-rw-r--r-- | accel-pppd/libnetlink/iputils.c | 220 | ||||
-rw-r--r-- | accel-pppd/libnetlink/libnetlink.h | 2 | ||||
-rw-r--r-- | accel-pppd/net.c | 308 | ||||
-rw-r--r-- | accel-pppd/session.c | 4 | ||||
-rw-r--r-- | accel-pppd/shaper/limiter.c | 37 |
15 files changed, 509 insertions, 241 deletions
diff --git a/accel-pppd/ctrl/ipoe/ipoe.c b/accel-pppd/ctrl/ipoe/ipoe.c index c7db14aa..84f8ad7c 100644 --- a/accel-pppd/ctrl/ipoe/ipoe.c +++ b/accel-pppd/ctrl/ipoe/ipoe.c @@ -203,7 +203,7 @@ static void ipoe_serv_timeout(struct triton_timer_t *t); static void ipoe_ctx_switch(struct triton_context_t *ctx, void *arg) { - net = &def_net; + net = def_net; log_switch(ctx, arg); } @@ -3263,7 +3263,7 @@ static void load_config(void) if (!s) return; - net = &def_net; + net = def_net; opt = conf_get_opt("ipoe", "username"); if (opt) { diff --git a/accel-pppd/ctrl/l2tp/l2tp.c b/accel-pppd/ctrl/l2tp/l2tp.c index 76c679c7..5d9041fa 100644 --- a/accel-pppd/ctrl/l2tp/l2tp.c +++ b/accel-pppd/ctrl/l2tp/l2tp.c @@ -255,7 +255,8 @@ static inline int nsnr_cmp(uint16_t ns, uint16_t nr) static void l2tp_ctx_switch(struct triton_context_t *ctx, void *arg) { - net = &def_net; + struct ap_session *s = arg; + net = s->net; log_switch(ctx, arg); } diff --git a/accel-pppd/ctrl/pppoe/pppoe.c b/accel-pppd/ctrl/pppoe/pppoe.c index 242f7e07..4536040d 100644 --- a/accel-pppd/ctrl/pppoe/pppoe.c +++ b/accel-pppd/ctrl/pppoe/pppoe.c @@ -264,7 +264,7 @@ static int pppoe_rad_send_accounting_request(struct rad_plugin_t *rad, struct ra static void pppoe_conn_ctx_switch(struct triton_context_t *ctx, void *arg) { struct pppoe_conn_t *conn = arg; - net = conn->serv->net; + net = conn->ppp.ses.net; log_switch(ctx, &conn->ppp.ses); } @@ -400,6 +400,7 @@ static struct pppoe_conn_t *allocate_channel(struct pppoe_serv_t *serv, const ui ppp_init(&conn->ppp); + conn->ppp.ses.net = serv->net; conn->ppp.ses.ctrl = &conn->ctrl; conn->ppp.ses.chan_name = conn->ctrl.calling_station_id; @@ -1266,7 +1267,7 @@ static void pppoe_serv_timeout(struct triton_timer_t *t) pppoe_server_free(serv); } -static int parse_server(const char *opt, int *padi_limit, const struct ap_net **net) +static int parse_server(const char *opt, int *padi_limit, struct ap_net **net) { char *ptr, *endptr; char name[64]; @@ -1374,7 +1375,7 @@ static void __pppoe_server_start(const char *ifname, const char *opt, void *cli, struct pppoe_serv_t *serv; struct ifreq ifr; int padi_limit = conf_padi_limit; - const struct ap_net *net = &def_net; + struct ap_net *net = def_net; if (parse_server(opt, &padi_limit, &net)) { if (cli) @@ -1462,7 +1463,7 @@ static void __pppoe_server_start(const char *ifname, const char *opt, void *cli, goto out_err; } - if (parent_ifindex == -1 && net == &def_net) + if (parent_ifindex == -1 && net == def_net) vid = iplink_vlan_get_vid(ifr.ifr_ifindex, &parent_ifindex); serv->ctx.close = pppoe_serv_close; diff --git a/accel-pppd/ctrl/pppoe/pppoe.h b/accel-pppd/ctrl/pppoe/pppoe.h index aac169ed..75e0eed9 100644 --- a/accel-pppd/ctrl/pppoe/pppoe.h +++ b/accel-pppd/ctrl/pppoe/pppoe.h @@ -70,7 +70,7 @@ struct pppoe_serv_t struct triton_context_t ctx; struct rb_node node; - const struct ap_net *net; + struct ap_net *net; int disc_sock; uint8_t hwaddr[ETH_ALEN]; diff --git a/accel-pppd/ctrl/pptp/pptp.c b/accel-pppd/ctrl/pptp/pptp.c index ec20586f..4aba5767 100644 --- a/accel-pppd/ctrl/pptp/pptp.c +++ b/accel-pppd/ctrl/pptp/pptp.c @@ -75,7 +75,11 @@ static void ppp_finished(struct ap_session *); static void pptp_ctx_switch(struct triton_context_t *ctx, void *arg) { - net = &def_net; + if (arg) { + struct ap_session *s = arg; + net = s->net; + } else + net = def_net; log_switch(ctx, arg); } diff --git a/accel-pppd/ifcfg.c b/accel-pppd/ifcfg.c index 246aa643..5e7c790a 100644 --- a/accel-pppd/ifcfg.c +++ b/accel-pppd/ifcfg.c @@ -149,9 +149,11 @@ void __export ap_session_accounting_started(struct ap_session *ses) } if (ses->ipv6) { + net->enter_ns(); devconf(ses, "accept_ra", "0"); devconf(ses, "autoconf", "0"); devconf(ses, "forwarding", "1"); + net->exit_ns(); memset(&ifr6, 0, sizeof(ifr6)); @@ -161,7 +163,7 @@ void __export ap_session_accounting_started(struct ap_session *ses) ifr6.ifr6_prefixlen = 64; ifr6.ifr6_ifindex = ses->ifindex; - if (ioctl(sock6_fd, SIOCSIFADDR, &ifr6)) + if (net->sock6_ioctl(SIOCSIFADDR, &ifr6)) log_ppp_error("faild to set LL IPv6 address: %s\n", strerror(errno)); } @@ -246,7 +248,7 @@ void __export ap_session_ifdown(struct ap_session *ses) ifr6.ifr6_addr.s6_addr32[0] = htonl(0xfe800000); *(uint64_t *)(ifr6.ifr6_addr.s6_addr + 8) = ses->ipv6->intf_id; ifr6.ifr6_prefixlen = 64; - ioctl(sock6_fd, SIOCDIFADDR, &ifr6); + net->sock6_ioctl(SIOCDIFADDR, &ifr6); } list_for_each_entry(a, &ses->ipv6->addr_list, entry) { @@ -267,42 +269,72 @@ void __export ap_session_ifdown(struct ap_session *ses) int __export ap_session_rename(struct ap_session *ses, const char *ifname, int len) { struct ifreq ifr; - int r, up = 0; + int i, r, up = 0; + struct ap_net *ns = NULL; + char ns_name[256]; if (len == -1) len = strlen(ifname); + for (i = 0; i < len; i++) { + if (ifname[i] == '/') { + memcpy(ns_name, ifname, i); + ns_name[i] = 0; + + ns = ap_net_open_ns(ns_name); + if (!ns) + return -1; + + ifname += i + 1; + len -= i + 1; + break; + } + } + if (len >= IFNAMSIZ) { - log_ppp_warn("cannot rename interface (name is too long)\n"); + log_ppp_error("cannot rename interface (name is too long)\n"); return -1; } - strcpy(ifr.ifr_name, ses->ifname); - memcpy(ifr.ifr_newname, ifname, len); - ifr.ifr_newname[len] = 0; - - r = net->sock_ioctl(SIOCSIFNAME, &ifr); - if (r && errno == EBUSY) { - net->sock_ioctl(SIOCGIFFLAGS, &ifr); - ifr.ifr_flags &= ~IFF_UP; - net->sock_ioctl(SIOCSIFFLAGS, &ifr); - + if (len) { + strcpy(ifr.ifr_name, ses->ifname); memcpy(ifr.ifr_newname, ifname, len); ifr.ifr_newname[len] = 0; + r = net->sock_ioctl(SIOCSIFNAME, &ifr); + if (r && errno == EBUSY) { + net->sock_ioctl(SIOCGIFFLAGS, &ifr); + ifr.ifr_flags &= ~IFF_UP; + net->sock_ioctl(SIOCSIFFLAGS, &ifr); + + memcpy(ifr.ifr_newname, ifname, len); + ifr.ifr_newname[len] = 0; + r = net->sock_ioctl(SIOCSIFNAME, &ifr); + + up = 1; + } - up = 1; + if (r) { + if (!ses->ifname_rename) + ses->ifname_rename = _strdup(ifr.ifr_newname); + else + log_ppp_warn("interface rename to %s failed: %s\n", ifr.ifr_newname, strerror(errno)); + } else { + log_ppp_info2("rename interface to '%s'\n", ifr.ifr_newname); + memcpy(ses->ifname, ifname, len); + ses->ifname[len] = 0; + } } - if (r) { - if (!ses->ifname_rename) - ses->ifname_rename = _strdup(ifr.ifr_newname); - else - log_ppp_warn("interface rename to %s failed: %s\n", ifr.ifr_newname, strerror(errno)); - } else { - log_ppp_info2("rename interface to '%s'\n", ifr.ifr_newname); - memcpy(ses->ifname, ifname, len); - ses->ifname[len] = 0; + if (ns) { + if (net->move_link(ns, ses->ifindex)) { + log_ppp_error("failed to attach namespace\n"); + ns->release(ns); + return -1; + } + ses->net = ns; + net = ns; + log_ppp_info2("move to namespace %s\n", ns->name); } if (up) { @@ -311,6 +343,6 @@ int __export ap_session_rename(struct ap_session *ses, const char *ifname, int l net->sock_ioctl(SIOCSIFFLAGS, &ifr); } - return r; + return 0; } diff --git a/accel-pppd/include/ap_net.h b/accel-pppd/include/ap_net.h index 40544d58..25121d94 100644 --- a/accel-pppd/include/ap_net.h +++ b/accel-pppd/include/ap_net.h @@ -1,8 +1,12 @@ #ifndef __AP_NET_H #define __AP_NET_H +struct rtnl_handle; + struct ap_net { - const char *name; + struct list_head entry; + int refs; + char *name; int (*socket)(int domain, int type, int proto); int (*connect)(int sock, const struct sockaddr *, socklen_t len); int (*bind)(int sock, const struct sockaddr *, socklen_t len); @@ -14,11 +18,23 @@ struct ap_net { int (*set_nonblocking)(int sock, int f); int (*setsockopt)(int sockfd, int level, int optname, const void *optval, socklen_t optlen); int (*sock_ioctl)(unsigned long request, void *arg); + int (*sock6_ioctl)(unsigned long request, void *arg); int (*ppp_open)(); int (*ppp_ioctl)(int fd, unsigned long request, void *arg); + void (*enter_ns)(); + void (*exit_ns)(); + struct rtnl_handle *(*rtnl_get)(); + void (*rtnl_put)(struct rtnl_handle *); + int (*rtnl_open)(struct rtnl_handle *h, int proto); + int (*move_link)(struct ap_net *net, int ifindex); + void (*release)(struct ap_net *net); }; -int ap_net_register(const struct ap_net *net); -const struct ap_net *ap_net_find(const char *name); +extern __thread struct ap_net *net; +extern struct ap_net *def_net; + +int ap_net_register(struct ap_net *net); +struct ap_net *ap_net_find(const char *name); +struct ap_net *ap_net_open_ns(const char *name); #endif diff --git a/accel-pppd/include/ap_session.h b/accel-pppd/include/ap_session.h index 0baaab2c..82e7e8c6 100644 --- a/accel-pppd/include/ap_session.h +++ b/accel-pppd/include/ap_session.h @@ -81,6 +81,7 @@ struct ap_session struct ipv6db_prefix_t *ipv6_dp; char *ipv4_pool_name; char *ipv6_pool_name; + struct ap_net *net; const struct ap_ctrl *ctrl; @@ -125,14 +126,11 @@ struct ap_session_stat extern pthread_rwlock_t ses_lock; extern struct list_head ses_list; extern int ap_shutdown; -extern int sock_fd; // internet socket for ioctls -extern int sock6_fd; // internet socket for ioctls +extern int sock_fd; +extern int sock6_fd; extern int urandom_fd; extern struct ap_session_stat ap_session_stat; -extern __thread const struct ap_net *net; -extern const struct ap_net def_net; - void ap_session_init(struct ap_session *ses); void ap_session_set_ifindex(struct ap_session *ses); int ap_session_starting(struct ap_session *ses); diff --git a/accel-pppd/ipv6/dhcpv6.c b/accel-pppd/ipv6/dhcpv6.c index e170ae21..f147a8cd 100644 --- a/accel-pppd/ipv6/dhcpv6.c +++ b/accel-pppd/ipv6/dhcpv6.c @@ -66,15 +66,15 @@ static void ev_ses_started(struct ap_session *ses) if (!ses->ipv6) return; - sock = socket(AF_INET6, SOCK_DGRAM, 0); + sock = net->socket(AF_INET6, SOCK_DGRAM, 0); if (!sock) { log_ppp_error("dhcpv6: socket: %s\n", strerror(errno)); return; } - setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &f, sizeof(f)); + net->setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &f, sizeof(f)); - if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, ses->ifname, strlen(ses->ifname))) { + if (net->setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, ses->ifname, strlen(ses->ifname))) { log_ppp_error("ipv6_nd: setsockopt(SO_BINDTODEVICE): %s\n", strerror(errno)); close(sock); return; @@ -84,7 +84,7 @@ static void ev_ses_started(struct ap_session *ses) addr.sin6_family = AF_INET6; addr.sin6_port = htons(DHCPV6_SERV_PORT); - if (bind(sock, (struct sockaddr *)&addr, sizeof(addr))) { + if (net->bind(sock, (struct sockaddr *)&addr, sizeof(addr))) { log_ppp_error("dhcpv6: bind: %s\n", strerror(errno)); close(sock); return; @@ -95,14 +95,14 @@ static void ev_ses_started(struct ap_session *ses) mreq.ipv6mr_multiaddr.s6_addr32[0] = htonl(0xff020000); mreq.ipv6mr_multiaddr.s6_addr32[3] = htonl(0x010002); - if (setsockopt(sock, SOL_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq))) { + if (net->setsockopt(sock, SOL_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq))) { log_ppp_error("dhcpv6: failed to join to All_DHCP_Relay_Agents_and_Servers\n"); close(sock); return; } - fcntl(sock, F_SETFL, O_NONBLOCK); fcntl(sock, F_SETFD, fcntl(sock, F_GETFD) | FD_CLOEXEC); + net->set_nonblocking(sock, 1); pd = _malloc(sizeof(*pd)); memset(pd, 0, sizeof(*pd)); @@ -189,7 +189,7 @@ static void insert_dp_routes(struct ap_session *ses, struct dhcpv6_pd *pd) rt6.rtmsg_flags |= RTF_GATEWAY; list_for_each_entry(a, &ses->ipv6->addr_list, entry) { build_addr(a, ses->ipv6->peer_intf_id, &rt6.rtmsg_gateway); - if (ioctl(sock6_fd, SIOCADDRT, &rt6)) { + if (net->sock6_ioctl(SIOCADDRT, &rt6)) { err = errno; inet_ntop(AF_INET6, &p->addr, str1, sizeof(str1)); inet_ntop(AF_INET6, &rt6.rtmsg_gateway, str2, sizeof(str2)); @@ -202,7 +202,7 @@ static void insert_dp_routes(struct ap_session *ses, struct dhcpv6_pd *pd) rt6.rtmsg_metric++; } } else { - if (ioctl(sock6_fd, SIOCADDRT, &rt6)) { + if (net->sock6_ioctl(SIOCADDRT, &rt6)) { err = errno; inet_ntop(AF_INET6, &p->addr, str1, sizeof(str1)); log_ppp_error("dhcpv6: route add %s/%i: %s\n", @@ -457,7 +457,7 @@ static void dhcpv6_send_reply(struct dhcpv6_packet *req, struct dhcpv6_pd *pd, i dhcpv6_packet_print(reply, log_ppp_info2); } - sendto(pd->hnd.fd, reply->hdr, reply->endptr - (void *)reply->hdr, 0, (struct sockaddr *)&req->addr, sizeof(req->addr)); + net->sendto(pd->hnd.fd, reply->hdr, reply->endptr - (void *)reply->hdr, 0, (struct sockaddr *)&req->addr, sizeof(req->addr)); dhcpv6_packet_free(reply); } @@ -609,7 +609,7 @@ static void dhcpv6_send_reply2(struct dhcpv6_packet *req, struct dhcpv6_pd *pd, dhcpv6_packet_print(reply, log_ppp_info2); } - sendto(pd->hnd.fd, reply->hdr, reply->endptr - (void *)reply->hdr, 0, (struct sockaddr *)&req->addr, sizeof(req->addr)); + net->sendto(pd->hnd.fd, reply->hdr, reply->endptr - (void *)reply->hdr, 0, (struct sockaddr *)&req->addr, sizeof(req->addr)); out: dhcpv6_packet_free(reply); @@ -799,7 +799,7 @@ static int dhcpv6_read(struct triton_md_handler_t *h) uint8_t *buf = _malloc(BUF_SIZE); while (1) { - n = recvfrom(h->fd, buf, BUF_SIZE, 0, &addr, &len); + n = net->recvfrom(h->fd, buf, BUF_SIZE, 0, (struct sockaddr *)&addr, &len); if (n == -1) { if (errno == EAGAIN) break; diff --git a/accel-pppd/ipv6/nd.c b/accel-pppd/ipv6/nd.c index 19a3d7d3..1d70ae95 100644 --- a/accel-pppd/ipv6/nd.c +++ b/accel-pppd/ipv6/nd.c @@ -185,7 +185,7 @@ static void ipv6_nd_send_ra(struct ipv6_nd_handler_t *h, struct sockaddr_in6 *ad } else endptr = rdnss_addr; - sendto(h->hnd.fd, buf, endptr - buf, 0, (struct sockaddr *)addr, sizeof(*addr)); + net->sendto(h->hnd.fd, buf, endptr - buf, 0, (struct sockaddr *)addr, sizeof(*addr)); mempool_free(buf); } @@ -225,7 +225,7 @@ static int ipv6_nd_read(struct triton_md_handler_t *_h) } while (1) { - n = recvfrom(h->hnd.fd, icmph, BUF_SIZE, 0, &addr, &addr_len); + n = net->recvfrom(h->hnd.fd, icmph, BUF_SIZE, 0, (struct sockaddr *)&addr, &addr_len); if (n == -1) { if (errno == EAGAIN) break; @@ -269,31 +269,31 @@ static int ipv6_nd_start(struct ap_session *ses) int val; struct ipv6_nd_handler_t *h; - sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); + sock = net->socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); if (sock < 0) { log_ppp_error("socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6): %s\n", strerror(errno)); return -1; } - if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, ses->ifname, strlen(ses->ifname))) { + if (net->setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, ses->ifname, strlen(ses->ifname))) { log_ppp_error("ipv6_nd: setsockopt(SO_BINDTODEVICE): %s\n", strerror(errno)); goto out_err; } val = 2; - if (setsockopt(sock, IPPROTO_RAW, IPV6_CHECKSUM, &val, sizeof(val))) { + if (net->setsockopt(sock, IPPROTO_RAW, IPV6_CHECKSUM, &val, sizeof(val))) { log_ppp_error("ipv6_nd: setsockopt(IPV6_CHECKSUM): %s\n", strerror(errno)); goto out_err; } val = 255; - if (setsockopt(sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &val, sizeof(val))) { + if (net->setsockopt(sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &val, sizeof(val))) { log_ppp_error("ipv6_nd: setsockopt(IPV6_UNICAST_HOPS): %s\n", strerror(errno)); goto out_err; } - if (setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &val, sizeof(val))) { + if (net->setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &val, sizeof(val))) { log_ppp_error("ipv6_nd: setsockopt(IPV6_MULTICAST_HOPS): %s\n", strerror(errno)); goto out_err; } @@ -307,7 +307,7 @@ static int ipv6_nd_start(struct ap_session *ses) ICMP6_FILTER_SETBLOCKALL(&filter); ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &filter); - if (setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, sizeof(filter))) { + if (net->setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, sizeof(filter))) { log_ppp_error("ipv6_nd: setsockopt(ICMP6_FILTER): %s\n", strerror(errno)); goto out_err; } @@ -317,13 +317,14 @@ static int ipv6_nd_start(struct ap_session *ses) mreq.ipv6mr_multiaddr.s6_addr32[0] = htonl(0xff020000); mreq.ipv6mr_multiaddr.s6_addr32[3] = htonl(0x2); - if (setsockopt(sock, SOL_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq))) { + if (net->setsockopt(sock, SOL_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq))) { log_ppp_error("ipv6_nd: failed to join ipv6 allrouters\n"); goto out_err; } fcntl(sock, F_SETFD, fcntl(sock, F_GETFD) | FD_CLOEXEC); - fcntl(sock, F_SETFL, O_NONBLOCK); + + net->set_nonblocking(sock, 1); h = _malloc(sizeof(*h)); memset(h, 0, sizeof(*h)); diff --git a/accel-pppd/libnetlink/iputils.c b/accel-pppd/libnetlink/iputils.c index 30a06d1f..7a29d08f 100644 --- a/accel-pppd/libnetlink/iputils.c +++ b/accel-pppd/libnetlink/iputils.c @@ -20,6 +20,7 @@ #include "libnetlink.h" #include "iputils.h" +#include "ap_net.h" #ifdef ACCEL_DP #define _malloc(x) malloc(x) @@ -37,37 +38,6 @@ struct arg void *arg; }; -static pthread_key_t rth_key; -static __thread struct rtnl_handle *rth; - -static void open_rth(void) -{ - rth = _malloc(sizeof(*rth)); - - if (!rth) - return; - - memset(rth, 0, sizeof(*rth)); - - if (rtnl_open(rth, 0)) { - log_ppp_error("radius: cannot open rtnetlink\n"); - _free(rth); - rth = NULL; - return; - } - - pthread_setspecific(rth_key, rth); -} - -static void free_rth(void *arg) -{ - struct rtnl_handle *rth = arg; - - rtnl_close(rth); - - _free(rth); -} - static int store_nlmsg(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { struct ifinfomsg *ifi = NLMSG_DATA(n); @@ -143,9 +113,8 @@ int __export iplink_get_stats(int ifindex, struct rtnl_link_stats *stats) struct ifinfomsg *ifi; int len; struct rtattr *tb[IFLA_MAX + 1]; - - if (!rth) - open_rth(); + struct rtnl_handle *rth = net->rtnl_get(); + int r = -1; if (!rth) return -1; @@ -159,10 +128,10 @@ int __export iplink_get_stats(int ifindex, struct rtnl_link_stats *stats) req.i.ifi_index = ifindex; if (rtnl_talk(rth, &req.n, 0, 0, &req.n, NULL, NULL, 0) < 0) - return -1; + goto out; if (req.n.nlmsg_type != RTM_NEWLINK) - return -1; + goto out; ifi = NLMSG_DATA(&req.n); @@ -170,15 +139,18 @@ int __export iplink_get_stats(int ifindex, struct rtnl_link_stats *stats) len -= NLMSG_LENGTH(sizeof(*ifi)); if (len < 0) - return -1; + goto out; parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len); - if (tb[IFLA_STATS]) + if (tb[IFLA_STATS]) { memcpy(stats, RTA_DATA(tb[IFLA_STATS]), sizeof(*stats)); - else - return -1; + r = 0; + } - return 0; +out: + net->rtnl_put(rth); + + return r; } int __export iplink_vlan_add(const char *ifname, int ifindex, int vid) @@ -189,9 +161,8 @@ int __export iplink_vlan_add(const char *ifname, int ifindex, int vid) char buf[4096]; } req; struct rtattr *linkinfo, *data; - - if (!rth) - open_rth(); + struct rtnl_handle *rth = net->rtnl_get(); + int r = 0; if (!rth) return -1; @@ -218,9 +189,11 @@ int __export iplink_vlan_add(const char *ifname, int ifindex, int vid) linkinfo->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)linkinfo; if (rtnl_talk(rth, &req.n, 0, 0, NULL, NULL, NULL, 0) < 0) - return -1; + r = -1; - return 0; + net->rtnl_put(rth); + + return r; } int __export iplink_vlan_del(int ifindex) @@ -231,9 +204,8 @@ int __export iplink_vlan_del(int ifindex) char buf[4096]; } req; struct rtattr *linkinfo; - - if (!rth) - open_rth(); + struct rtnl_handle *rth = net->rtnl_get(); + int r = 0; if (!rth) return -1; @@ -257,9 +229,11 @@ int __export iplink_vlan_del(int ifindex) linkinfo->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)linkinfo; if (rtnl_talk(rth, &req.n, 0, 0, NULL, NULL, NULL, 0) < 0) - return -1; + r = -1; - return 0; + net->rtnl_put(rth); + + return r; } int __export iplink_vlan_get_vid(int ifindex, int *iflink) @@ -272,9 +246,8 @@ int __export iplink_vlan_get_vid(int ifindex, int *iflink) struct ifinfomsg *ifi; int len; struct rtattr *tb[IFLA_MAX + 1]; - - if (!rth) - open_rth(); + struct rtnl_handle *rth = net->rtnl_get(); + int r = 0; if (!rth) return -1; @@ -288,10 +261,10 @@ int __export iplink_vlan_get_vid(int ifindex, int *iflink) req.i.ifi_index = ifindex; if (rtnl_talk(rth, &req.n, 0, 0, &req.n, NULL, NULL, 0) < 0) - return -1; + goto out; if (req.n.nlmsg_type != RTM_NEWLINK) - return -1; + goto out; ifi = NLMSG_DATA(&req.n); @@ -299,12 +272,12 @@ int __export iplink_vlan_get_vid(int ifindex, int *iflink) len -= NLMSG_LENGTH(sizeof(*ifi)); if (len < 0) - return -1; + goto out; parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len); if (!tb[IFLA_LINKINFO]) - return 0; + goto out; if (iflink && tb[IFLA_LINK]) *iflink = *(int *)RTA_DATA(tb[IFLA_LINK]); @@ -312,10 +285,15 @@ int __export iplink_vlan_get_vid(int ifindex, int *iflink) parse_rtattr_nested(tb, IFLA_MAX, tb[IFLA_LINKINFO]); if (strcmp(RTA_DATA(tb[IFLA_INFO_KIND]), "vlan")) - return 0; + goto out; parse_rtattr_nested(tb, IFLA_MAX, tb[IFLA_INFO_DATA]); - return *(uint16_t *)RTA_DATA(tb[IFLA_VLAN_ID]); + r = *(uint16_t *)RTA_DATA(tb[IFLA_VLAN_ID]); + +out: + net->rtnl_put(rth); + + return r; } @@ -326,9 +304,8 @@ int __export ipaddr_add(int ifindex, in_addr_t addr, int mask) struct ifaddrmsg i; char buf[4096]; } req; - - if (!rth) - open_rth(); + struct rtnl_handle *rth = net->rtnl_get(); + int r = 0; if (!rth) return -1; @@ -345,9 +322,11 @@ int __export ipaddr_add(int ifindex, in_addr_t addr, int mask) addattr32(&req.n, sizeof(req), IFA_LOCAL, addr); if (rtnl_talk(rth, &req.n, 0, 0, NULL, NULL, NULL, 0) < 0) - return -1; + r = -1; - return 0; + net->rtnl_put(rth); + + return r; } int __export ipaddr_del(int ifindex, in_addr_t addr, int mask) @@ -357,9 +336,8 @@ int __export ipaddr_del(int ifindex, in_addr_t addr, int mask) struct ifaddrmsg i; char buf[4096]; } req; - - if (!rth) - open_rth(); + struct rtnl_handle *rth = net->rtnl_get(); + int r = 0; if (!rth) return -1; @@ -376,9 +354,11 @@ int __export ipaddr_del(int ifindex, in_addr_t addr, int mask) addattr32(&req.n, sizeof(req), IFA_LOCAL, addr); if (rtnl_talk(rth, &req.n, 0, 0, NULL, NULL, NULL, 0) < 0) - return -1; + r = -1; - return 0; + net->rtnl_put(rth); + + return r; } int __export iproute_add(int ifindex, in_addr_t src, in_addr_t dst, in_addr_t gw, int proto, int mask) @@ -388,9 +368,8 @@ int __export iproute_add(int ifindex, in_addr_t src, in_addr_t dst, in_addr_t gw struct rtmsg i; char buf[4096]; } req; - - if (!rth) - open_rth(); + struct rtnl_handle *rth = net->rtnl_get(); + int r = 0; if (!rth) return -1; @@ -416,9 +395,11 @@ int __export iproute_add(int ifindex, in_addr_t src, in_addr_t dst, in_addr_t gw addattr32(&req.n, sizeof(req), RTA_DST, dst); if (rtnl_talk(rth, &req.n, 0, 0, NULL, NULL, NULL, 0) < 0) - return -1; + r = -1; - return 0; + net->rtnl_put(rth); + + return r; } int __export iproute_del(int ifindex, in_addr_t dst, int proto, int mask) @@ -428,9 +409,8 @@ int __export iproute_del(int ifindex, in_addr_t dst, int proto, int mask) struct rtmsg i; char buf[4096]; } req; - - if (!rth) - open_rth(); + struct rtnl_handle *rth = net->rtnl_get(); + int r = 0; if (!rth) return -1; @@ -453,9 +433,11 @@ int __export iproute_del(int ifindex, in_addr_t dst, int proto, int mask) addattr32(&req.n, sizeof(req), RTA_OIF, ifindex); if (rtnl_talk(rth, &req.n, 0, 0, NULL, NULL, NULL, 0) < 0) - return -1; + r = -1; - return 0; + net->rtnl_put(rth); + + return r; } int __export ip6route_add(int ifindex, struct in6_addr *dst, int pref_len, int proto) @@ -465,9 +447,8 @@ int __export ip6route_add(int ifindex, struct in6_addr *dst, int pref_len, int p struct rtmsg i; char buf[4096]; } req; - - if (!rth) - open_rth(); + struct rtnl_handle *rth = net->rtnl_get(); + int r = 0; if (!rth) return -1; @@ -488,9 +469,11 @@ int __export ip6route_add(int ifindex, struct in6_addr *dst, int pref_len, int p addattr32(&req.n, sizeof(req), RTA_OIF, ifindex); if (rtnl_talk(rth, &req.n, 0, 0, NULL, NULL, NULL, 0) < 0) - return -1; + r = -1; - return 0; + net->rtnl_put(rth); + + return r; } int __export ip6route_del(int ifindex, struct in6_addr *dst, int pref_len) @@ -500,9 +483,8 @@ int __export ip6route_del(int ifindex, struct in6_addr *dst, int pref_len) struct rtmsg i; char buf[4096]; } req; - - if (!rth) - open_rth(); + struct rtnl_handle *rth = net->rtnl_get(); + int r = 0; if (!rth) return -1; @@ -521,9 +503,11 @@ int __export ip6route_del(int ifindex, struct in6_addr *dst, int pref_len) addattr_l(&req.n, sizeof(req), RTA_DST, dst, sizeof(*dst)); if (rtnl_talk(rth, &req.n, 0, 0, NULL, NULL, NULL, 0) < 0) - return -1; + r = -1; - return 0; + net->rtnl_put(rth); + + return r; } int __export ip6addr_add(int ifindex, struct in6_addr *addr, int prefix_len) @@ -533,9 +517,8 @@ int __export ip6addr_add(int ifindex, struct in6_addr *addr, int prefix_len) struct ifaddrmsg i; char buf[4096]; } req; - - if (!rth) - open_rth(); + struct rtnl_handle *rth = net->rtnl_get(); + int r = 0; if (!rth) return -1; @@ -553,9 +536,11 @@ int __export ip6addr_add(int ifindex, struct in6_addr *addr, int prefix_len) addattr_l(&req.n, sizeof(req), IFA_ADDRESS, addr, 16); if (rtnl_talk(rth, &req.n, 0, 0, NULL, NULL, NULL, 0) < 0) - return -1; + r = -1; - return 0; + net->rtnl_put(rth); + + return r; } int __export ip6addr_del(int ifindex, struct in6_addr *addr, int prefix_len) @@ -565,9 +550,8 @@ int __export ip6addr_del(int ifindex, struct in6_addr *addr, int prefix_len) struct ifaddrmsg i; char buf[4096]; } req; - - if (!rth) - open_rth(); + struct rtnl_handle *rth = net->rtnl_get(); + int r = 0; if (!rth) return -1; @@ -584,9 +568,11 @@ int __export ip6addr_del(int ifindex, struct in6_addr *addr, int prefix_len) addattr_l(&req.n, sizeof(req), IFA_ADDRESS, addr, 16); if (rtnl_talk(rth, &req.n, 0, 0, NULL, NULL, NULL, 0) < 0) - return -1; + r = -1; - return 0; + net->rtnl_put(rth); + + return r; } in_addr_t __export iproute_get(in_addr_t dst, in_addr_t *gw) @@ -600,14 +586,12 @@ in_addr_t __export iproute_get(in_addr_t dst, in_addr_t *gw) struct rtattr *tb[RTA_MAX+1]; int len; in_addr_t res = 0; + struct rtnl_handle *rth = net->rtnl_get(); if (gw) *gw = 0; if (!rth) - open_rth(); - - if (!rth) return -1; memset(&req, 0, sizeof(req) - 4096); @@ -654,6 +638,8 @@ in_addr_t __export iproute_get(in_addr_t dst, in_addr_t *gw) *gw = *(uint32_t *)RTA_DATA(tb[RTA_GATEWAY]); out: + net->rtnl_put(rth); + return res; } @@ -664,9 +650,8 @@ int __export iprule_add(uint32_t addr, int table) struct rtmsg i; char buf[4096]; } req; - - if (!rth) - open_rth(); + struct rtnl_handle *rth = net->rtnl_get(); + int r = 0; if (!rth) return -1; @@ -688,9 +673,11 @@ int __export iprule_add(uint32_t addr, int table) addattr32(&req.n, sizeof(req), FRA_TABLE, table); if (rtnl_talk(rth, &req.n, 0, 0, NULL, NULL, NULL, 0) < 0) - return -1; + r = -1; - return 0; + net->rtnl_put(rth); + + return r; } int __export iprule_del(uint32_t addr, int table) @@ -700,9 +687,8 @@ int __export iprule_del(uint32_t addr, int table) struct rtmsg i; char buf[4096]; } req; - - if (!rth) - open_rth(); + struct rtnl_handle *rth = net->rtnl_get(); + int r = 0; if (!rth) return -1; @@ -724,15 +710,9 @@ int __export iprule_del(uint32_t addr, int table) addattr32(&req.n, sizeof(req), FRA_TABLE, table); if (rtnl_talk(rth, &req.n, 0, 0, NULL, NULL, NULL, 0) < 0) - return -1; - - return 0; -} + r = -1; + net->rtnl_put(rth); -static void init(void) -{ - pthread_key_create(&rth_key, free_rth); + return r; } - -DEFINE_INIT(100, init); diff --git a/accel-pppd/libnetlink/libnetlink.h b/accel-pppd/libnetlink/libnetlink.h index f68bf8a1..5089c46f 100644 --- a/accel-pppd/libnetlink/libnetlink.h +++ b/accel-pppd/libnetlink/libnetlink.h @@ -76,8 +76,6 @@ extern int __parse_rtattr_nested_compat(struct rtattr *tb[], int max, struct rta extern int rtnl_listen(struct rtnl_handle *, rtnl_filter_t handler, void *jarg); -extern int rtnl_from_file(FILE *, rtnl_filter_t handler, - void *jarg); #define NLMSG_TAIL(nmsg) \ ((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len))) diff --git a/accel-pppd/net.c b/accel-pppd/net.c index d2bd4e03..0fc6e354 100644 --- a/accel-pppd/net.c +++ b/accel-pppd/net.c @@ -1,21 +1,37 @@ +#include <stdlib.h> +#include <stdio.h> #include <unistd.h> #include <fcntl.h> #include <string.h> +#include <pthread.h> +#include <sched.h> +#include <limits.h> +#include <errno.h> #include <sys/socket.h> #include <sys/ioctl.h> #include "triton.h" - +#include "log.h" +#include "libnetlink.h" #include "ap_net.h" +#include "memdebug.h" -#define MAX_NET 2 +struct kern_net { + struct ap_net net; + struct rtnl_handle *rth; + int ns_fd; + int sock; + int sock6; +}; -static const struct ap_net *nets[MAX_NET]; -static int net_cnt; +static const char *conf_netns_run_dir; -extern int sock_fd; +static LIST_HEAD(nets); +static pthread_mutex_t nets_lock = PTHREAD_MUTEX_INITIALIZER; -__export __thread const struct ap_net *net; +__export __thread struct ap_net *net; +__export struct ap_net *def_net; +static int def_ns_fd; static int def_socket(int domain, int type, int proto) { @@ -79,57 +95,269 @@ static int def_ppp_ioctl(int fd, unsigned long request, void *arg) static int def_sock_ioctl(unsigned long request, void *arg) { - return ioctl(sock_fd, request, arg); -} - -__export const struct ap_net def_net = { - .name = "kernel", - .socket = def_socket, - .connect = def_connect, - .bind = def_bind, - .listen = def_listen, - .read = def_read, - .recvfrom = def_recvfrom, - .write = def_write, - .sendto = def_sendto, - .set_nonblocking = def_set_nonblocking, - .setsockopt = def_setsockopt, - .ppp_open = def_ppp_open, - .ppp_ioctl = def_ppp_ioctl, - .sock_ioctl = def_sock_ioctl, -}; + struct kern_net *n = container_of(net, typeof(*n), net); -static void __init init() + return ioctl(n->sock, request, arg); +} + +static int def_sock6_ioctl(unsigned long request, void *arg) { - nets[0] = &def_net; - net_cnt = 1; + struct kern_net *n = container_of(net, typeof(*n), net); + + return ioctl(n->sock6, request, arg); +} + +static void enter_ns() +{ + if (net != def_net) { + struct kern_net *n = container_of(net, typeof(*n), net); + setns(n->ns_fd, CLONE_NEWNET); + } +} + +static void exit_ns() +{ + if (net != def_net) + setns(def_ns_fd, CLONE_NEWNET); +} + +static struct rtnl_handle *def_rtnl_get() +{ + struct kern_net *n = container_of(net, typeof(*n), net); + struct rtnl_handle *rth = __sync_lock_test_and_set(&n->rth, NULL); + int r; + + if (!rth) { + rth = _malloc(sizeof(*rth)); + enter_ns(); + r = rtnl_open(rth, 0); + exit_ns(); + + if (r) { + _free(rth); + return NULL; + } + } + + return rth; } -int __export ap_net_register(const struct ap_net *net) +static void def_rtnl_put(struct rtnl_handle *rth) { - int i; + struct kern_net *n = container_of(net, typeof(*n), net); - if (net_cnt == MAX_NET) + if (!__sync_bool_compare_and_swap(&n->rth, NULL, rth)) { + rtnl_close(rth); + _free(rth); + } +} + +static int def_rtnl_open(struct rtnl_handle *rth, int proto) +{ + struct kern_net *n = container_of(net, typeof(*n), net); + int r; + + enter_ns(); + r = rtnl_open_byproto(rth, 0, proto); + exit_ns(); + + return r; +} + +static int def_move_link(struct ap_net *new_net, int ifindex) +{ + struct iplink_req { + struct nlmsghdr n; + struct ifinfomsg i; + char buf[1024]; + } req; + struct rtnl_handle *rth = new_net->rtnl_get(); + struct kern_net *n = container_of(new_net, typeof(*n), net); + int r = 0; + + if (!rth) return -1; - for (i = 0; i < net_cnt; i++) { - if (!strcmp(net->name, nets[i]->name)) - return -1; + memset(&req, 0, sizeof(req) - 1024); + + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); + req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; + req.n.nlmsg_type = RTM_SETLINK; + req.i.ifi_family = AF_UNSPEC; + req.i.ifi_index = ifindex; + + addattr_l(&req.n, 4096, IFLA_NET_NS_FD, &n->ns_fd, sizeof(n->ns_fd)); + + //if (setns(n->ns_fd, CLONE_NEWNET)) + //perror("setns"); + + if (rtnl_talk(rth, &req.n, 0, 0, NULL, NULL, NULL, 0) < 0) + r = -1; + + //setns(def_ns_fd, CLONE_NEWNET); + + new_net->rtnl_put(rth); + + return r; +} + +static void def_release(struct ap_net *d) +{ + struct kern_net *n = container_of(d, typeof(*n), net); + + if (d == def_net) + return; + + pthread_mutex_lock(&nets_lock); + if (--d->refs) { + pthread_mutex_unlock(&nets_lock); + return; } - nets[net_cnt++] = net; + list_del(&d->entry); + pthread_mutex_unlock(&nets_lock); + + net = def_net; + + log_debug("close ns %s\n", n->net.name); + + close(n->sock); + close(n->sock6); + close(n->ns_fd); + + if (n->rth) { + rtnl_close(n->rth); + _free(n->rth); + } + + _free(n); +} + +static struct ap_net *alloc_net(const char *name) +{ + struct kern_net *n; + struct ap_net *net; + int ns_fd; + + if (name) { + char fname[PATH_MAX]; + sprintf(fname, "%s/%s", conf_netns_run_dir, name); + ns_fd = open(fname, O_RDONLY); + if (ns_fd == -1) { + log_ppp_error("open %s: %s\n", fname, strerror(errno)); + return NULL; + } + + if (setns(ns_fd, CLONE_NEWNET)) { + log_ppp_error("setns %s: %s\n", fname, strerror(errno)); + close(ns_fd); + return NULL; + } + } else + def_ns_fd = ns_fd = open("/proc/self/ns/net", O_RDONLY); + + log_debug("open ns %s\n", name); + + n = _malloc(sizeof(*n)); + net = &n->net; + + net->refs = 1; + net->name = name ? _strdup(name) : "def"; + net->socket = def_socket; + net->connect = def_connect; + net->bind = def_bind; + net->listen = def_listen; + net->read = def_read; + net->recvfrom = def_recvfrom; + net->write = def_write; + net->sendto = def_sendto; + net->set_nonblocking = def_set_nonblocking; + net->setsockopt = def_setsockopt; + net->ppp_open = def_ppp_open; + net->ppp_ioctl = def_ppp_ioctl; + net->sock_ioctl = def_sock_ioctl; + net->sock6_ioctl = def_sock6_ioctl; + net->enter_ns = enter_ns; + net->exit_ns = exit_ns; + net->rtnl_get = def_rtnl_get; + net->rtnl_put = def_rtnl_put; + net->rtnl_open = def_rtnl_open; + net->move_link = def_move_link; + net->release = def_release; + + n->ns_fd = ns_fd; + + n->sock = socket(AF_INET, SOCK_DGRAM, 0); + n->sock6 = socket(AF_INET6, SOCK_DGRAM, 0); + n->rth = _malloc(sizeof(*n->rth)); + rtnl_open(n->rth, 0); + + if (ns_fd != def_ns_fd) + setns(def_ns_fd, CLONE_NEWNET); + + list_add_tail(&net->entry, &nets); + + return net; +}; + +int __export ap_net_register(struct ap_net *net) +{ + pthread_mutex_lock(&nets_lock); + list_add_tail(&net->entry, &nets); + pthread_mutex_unlock(&nets_lock); return 0; } -__export const struct ap_net *ap_net_find(const char *name) +static struct ap_net *find_net(const char *name) { - int i; + struct ap_net *n; - for (i = 0; i < net_cnt; i++) { - if (!strcmp(name, nets[i]->name)) - return nets[i]; + list_for_each_entry(n, &nets, entry) { + if (!strcmp(name, n->name)) { + n->refs++; + return n; + } } return NULL; } + +__export struct ap_net *ap_net_find(const char *name) +{ + struct ap_net *n; + + pthread_mutex_lock(&nets_lock); + n = find_net(name); + pthread_mutex_unlock(&nets_lock); + + return n; +} + +__export struct ap_net *ap_net_open_ns(const char *name) +{ + struct ap_net *n; + + pthread_mutex_lock(&nets_lock); + n = find_net(name); + if (!n) + n = alloc_net(name); + pthread_mutex_unlock(&nets_lock); + + return n; +} + +static void __init init() +{ + const char *opt; + + opt = conf_get_opt("common", "netns-run-dir"); + if (opt) + conf_netns_run_dir = opt; + else + conf_netns_run_dir = "/var/run/netns"; + + def_net = net = alloc_net(NULL); +} + +DEFINE_INIT(1, init); diff --git a/accel-pppd/session.c b/accel-pppd/session.c index ad164f3f..730a57aa 100644 --- a/accel-pppd/session.c +++ b/accel-pppd/session.c @@ -62,6 +62,7 @@ void __export ap_session_init(struct ap_session *ses) INIT_LIST_HEAD(&ses->pd_list); ses->ifindex = -1; ses->unit_idx = -1; + ses->net = net; } void __export ap_session_set_ifindex(struct ap_session *ses) @@ -235,6 +236,9 @@ void __export ap_session_finished(struct ap_session *ses) ses->ifname_rename = NULL; } + if (ses->net) + ses->net->release(ses->net); + if (ses->timer.tpd) triton_timer_del(&ses->timer); diff --git a/accel-pppd/shaper/limiter.c b/accel-pppd/shaper/limiter.c index 738f747e..0945e982 100644 --- a/accel-pppd/shaper/limiter.c +++ b/accel-pppd/shaper/limiter.c @@ -455,10 +455,10 @@ static int remove_htb_ifb(struct rtnl_handle *rth, int ifindex, int priority) int install_limiter(struct ap_session *ses, int down_speed, int down_burst, int up_speed, int up_burst, int idx) { - struct rtnl_handle rth; + struct rtnl_handle *rth = net->rtnl_get(); int r; - if (rtnl_open(&rth, 0)) { + if (!rth) { log_ppp_error("shaper: cannot open rtnetlink\n"); return -1; } @@ -469,45 +469,45 @@ int install_limiter(struct ap_session *ses, int down_speed, int down_burst, int up_burst = up_burst ? up_burst : conf_up_burst_factor * up_speed; if (conf_down_limiter == LIM_TBF) - r = install_tbf(&rth, ses->ifindex, down_speed, down_burst); + r = install_tbf(rth, ses->ifindex, down_speed, down_burst); else { - r = install_htb(&rth, ses->ifindex, down_speed, down_burst); + r = install_htb(rth, ses->ifindex, down_speed, down_burst); if (r == 0) - r = install_leaf_qdisc(&rth, ses->ifindex, 0x00010001, 0x00020000); + r = install_leaf_qdisc(rth, ses->ifindex, 0x00010001, 0x00020000); } if (conf_up_limiter == LIM_POLICE) - r = install_police(&rth, ses->ifindex, up_speed, up_burst); + r = install_police(rth, ses->ifindex, up_speed, up_burst); else { - r = install_htb_ifb(&rth, ses->ifindex, idx, up_speed, up_burst); + r = install_htb_ifb(rth, ses->ifindex, idx, up_speed, up_burst); if (r == 0) - r = install_leaf_qdisc(&rth, conf_ifb_ifindex, 0x00010000 + idx, idx << 16); + r = install_leaf_qdisc(rth, conf_ifb_ifindex, 0x00010000 + idx, idx << 16); } if (conf_fwmark) - install_fwmark(&rth, ses->ifindex, 0x00010000); + install_fwmark(rth, ses->ifindex, 0x00010000); - rtnl_close(&rth); + net->rtnl_put(rth); return r; } int remove_limiter(struct ap_session *ses, int idx) { - struct rtnl_handle rth; + struct rtnl_handle *rth = net->rtnl_get(); - if (rtnl_open(&rth, 0)) { + if (!rth) { log_ppp_error("shaper: cannot open rtnetlink\n"); return -1; } - remove_root(&rth, ses->ifindex); - remove_ingress(&rth, ses->ifindex); + remove_root(rth, ses->ifindex); + remove_ingress(rth, ses->ifindex); if (conf_up_limiter == LIM_HTB) - remove_htb_ifb(&rth, ses->ifindex, idx); + remove_htb_ifb(rth, ses->ifindex, idx); - rtnl_close(&rth); + net->rtnl_put(rth); return 0; } @@ -518,6 +518,7 @@ int init_ifb(const char *name) struct rtattr *tail; struct ifreq ifr; int r; + int sock_fd = socket(AF_INET, SOCK_DGRAM, 0); struct { struct nlmsghdr n; @@ -541,6 +542,7 @@ int init_ifb(const char *name) if (ioctl(sock_fd, SIOCGIFINDEX, &ifr)) { log_emerg("shaper: ioctl(SIOCGIFINDEX): %s\n", strerror(errno)); + close(sock_fd); return -1; } @@ -550,11 +552,13 @@ int init_ifb(const char *name) if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr)) { log_emerg("shaper: ioctl(SIOCSIFINDEX): %s\n", strerror(errno)); + close(sock_fd); return -1; } if (rtnl_open(&rth, 0)) { log_emerg("shaper: cannot open rtnetlink\n"); + close(sock_fd); return -1; } @@ -587,6 +591,7 @@ int init_ifb(const char *name) out: rtnl_close(&rth); + close(sock_fd); return r; } |