From 28c47fa1ccf6a6550f335046349b1716745a2189 Mon Sep 17 00:00:00 2001 From: Kozlov Dmitry Date: Wed, 5 Sep 2012 21:56:53 +0400 Subject: gather interface statistics via netlink --- accel-pppd/CMakeLists.txt | 4 + accel-pppd/extra/CMakeLists.txt | 1 + accel-pppd/extra/pppd_compat.c | 34 +- accel-pppd/extra/sigchld.c | 3 +- accel-pppd/ppp/ppp.c | 42 +++ accel-pppd/ppp/ppp.h | 12 + accel-pppd/ppp/ppp_lcp.c | 19 +- accel-pppd/radius/acct.c | 31 +- accel-pppd/radius/radius_p.h | 5 - accel-pppd/shaper/CMakeLists.txt | 2 +- accel-pppd/shaper/libnetlink.c | 692 --------------------------------------- accel-pppd/shaper/libnetlink.h | 118 ------- 12 files changed, 83 insertions(+), 880 deletions(-) delete mode 100644 accel-pppd/shaper/libnetlink.c delete mode 100644 accel-pppd/shaper/libnetlink.h diff --git a/accel-pppd/CMakeLists.txt b/accel-pppd/CMakeLists.txt index 1db4137d..fb44b503 100644 --- a/accel-pppd/CMakeLists.txt +++ b/accel-pppd/CMakeLists.txt @@ -65,6 +65,10 @@ ADD_EXECUTABLE(accel-pppd cli/tcp.c cli/cli.c + libnetlink/libnetlink.c + libnetlink/iputils.c + libnetlink/genl.c + pwdb.c ipdb.c diff --git a/accel-pppd/extra/CMakeLists.txt b/accel-pppd/extra/CMakeLists.txt index 365f5421..e7b9f072 100644 --- a/accel-pppd/extra/CMakeLists.txt +++ b/accel-pppd/extra/CMakeLists.txt @@ -1,4 +1,5 @@ ADD_LIBRARY(pppd_compat SHARED pppd_compat.c) +TARGET_LINK_LIBRARIES(pppd_compat sigchld) ADD_LIBRARY(ippool SHARED ippool.c) ADD_LIBRARY(ipv6pool SHARED ipv6pool.c) ADD_LIBRARY(sigchld SHARED sigchld.c) diff --git a/accel-pppd/extra/pppd_compat.c b/accel-pppd/extra/pppd_compat.c index d89a6a6a..d4de18ff 100644 --- a/accel-pppd/extra/pppd_compat.c +++ b/accel-pppd/extra/pppd_compat.c @@ -47,8 +47,6 @@ struct pppd_compat_pd_t #endif int started:1; int res; - int bytes_sent; - int bytes_rcvd; in_addr_t ipv4_addr; in_addr_t ipv4_peer_addr; }; @@ -224,27 +222,6 @@ static void ev_ppp_started(struct ppp_t *ppp) pd->started = 1; } -static void ev_ppp_finishing(struct ppp_t *ppp) -{ - struct ifpppstatsreq ifreq; - struct pppd_compat_pd_t *pd = find_pd(ppp); - - if (!pd) - return; - - memset(&ifreq, 0, sizeof(ifreq)); - ifreq.stats_ptr = (void *)&ifreq.stats; - strcpy(ifreq.ifr__name, ppp->ifname); - - if (ioctl(sock_fd, SIOCGPPPSTATS, &ifreq)) { - log_ppp_error("pppd_compat: failed to get ppp statistics: %s\n", strerror(errno)); - return; - } - - pd->bytes_sent = ifreq.stats.p.ppp_obytes; - pd->bytes_rcvd = ifreq.stats.p.ppp_ibytes; -} - static void ev_ppp_finished(struct ppp_t *ppp) { pid_t pid; @@ -497,12 +474,18 @@ static void fill_argv(char **argv, struct pppd_compat_pd_t *pd, char *path) static void fill_env(char **env, struct pppd_compat_pd_t *pd) { + struct ppp_t *ppp = pd->ppp; + uint64_t tx_bytes, rx_bytes; + + tx_bytes = (uint64_t)ppp->acct_tx_bytes + ppp->acct_output_gigawords*4294967296llu; + rx_bytes = (uint64_t)ppp->acct_rx_bytes + ppp->acct_input_gigawords*4294967296llu; + snprintf(env[0], 64, "PEERNAME=%s", pd->ppp->username); if (pd->ppp->stop_time && env[1]) { snprintf(env[1], 24, "CONNECT_TIME=%lu", pd->ppp->stop_time - pd->ppp->start_time); - snprintf(env[2], 24, "BYTES_SENT=%u", pd->bytes_sent); - snprintf(env[3], 24, "BYTES_RCVD=%u", pd->bytes_rcvd); + snprintf(env[2], 24, "BYTES_SENT=%llu", (long long unsigned)tx_bytes); + snprintf(env[3], 24, "BYTES_RCVD=%llu", (long long unsigned)rx_bytes); } } @@ -537,7 +520,6 @@ static void init(void) triton_event_register_handler(EV_PPP_STARTING, (triton_event_func)ev_ppp_starting); triton_event_register_handler(EV_PPP_PRE_UP, (triton_event_func)ev_ppp_pre_up); triton_event_register_handler(EV_PPP_STARTED, (triton_event_func)ev_ppp_started); - triton_event_register_handler(EV_PPP_FINISHING, (triton_event_func)ev_ppp_finishing); triton_event_register_handler(EV_PPP_PRE_FINISHED, (triton_event_func)ev_ppp_finished); #ifdef RADIUS if (triton_module_loaded("radius")) { diff --git a/accel-pppd/extra/sigchld.c b/accel-pppd/extra/sigchld.c index 8f1a979e..d6b0df5f 100644 --- a/accel-pppd/extra/sigchld.c +++ b/accel-pppd/extra/sigchld.c @@ -109,10 +109,9 @@ void __export sigchld_unlock() pthread_mutex_unlock(&handlers_lock); } -static void init(void) +static void __init init(void) { if (pthread_create(&sigchld_thr, NULL, sigchld_thread, NULL)) log_emerg("sigchld: pthread_create: %s\n", strerror(errno)); } -DEFINE_INIT(100, init); \ No newline at end of file diff --git a/accel-pppd/ppp/ppp.c b/accel-pppd/ppp/ppp.c index b8feaa1f..3e1386b7 100644 --- a/accel-pppd/ppp/ppp.c +++ b/accel-pppd/ppp/ppp.c @@ -108,6 +108,7 @@ static void generate_sessionid(struct ppp_t *ppp) int __export establish_ppp(struct ppp_t *ppp) { + struct rtnl_link_stats stats; struct ifreq ifr; struct pppunit_cache *uc = NULL; @@ -188,6 +189,17 @@ int __export establish_ppp(struct ppp_t *ppp) } ppp->ifindex = ifr.ifr_ifindex; + if (uc) { + if (iplink_get_stats(ppp->ifindex, &stats)) + log_ppp_warn("ppp: failed to get interface statistics\n"); + else { + ppp->acct_rx_packets_i = stats.rx_packets; + ppp->acct_tx_packets_i = stats.tx_packets; + ppp->acct_rx_bytes_i = stats.rx_bytes; + ppp->acct_tx_bytes_i = stats.tx_bytes; + } + } + log_ppp_info1("connect: %s <--> %s(%s)\n", ppp->ifname, ppp->ctrl->name, ppp->chan_name); init_layers(ppp); @@ -239,6 +251,8 @@ static void destablish_ppp(struct ppp_t *ppp) { struct pppunit_cache *uc; + ppp_read_stats(ppp, NULL); + triton_event_fire(EV_PPP_PRE_FINISHED, ppp); pthread_rwlock_wrlock(&ppp_lock); @@ -732,6 +746,34 @@ static void save_seq(void) } } +int __export ppp_read_stats(struct ppp_t *ppp, struct rtnl_link_stats *stats) +{ + struct rtnl_link_stats lstats; + + if (!stats) + stats = &lstats; + + if (iplink_get_stats(ppp->ifindex, stats)) { + log_ppp_warn("ppp: failed to get interface statistics\n"); + return -1; + } + + stats->rx_packets -= ppp->acct_rx_packets_i; + stats->tx_packets -= ppp->acct_tx_packets_i; + stats->rx_bytes -= ppp->acct_rx_bytes_i; + stats->tx_bytes -= ppp->acct_tx_bytes_i; + + if (stats->rx_bytes < ppp->acct_rx_bytes) + ppp->acct_input_gigawords++; + ppp->acct_rx_bytes = stats->rx_bytes; + + if (stats->tx_bytes < ppp->acct_tx_bytes) + ppp->acct_output_gigawords++; + ppp->acct_tx_bytes = stats->tx_bytes; + + return 0; +} + static void load_config(void) { char *opt; diff --git a/accel-pppd/ppp/ppp.h b/accel-pppd/ppp/ppp.h index ca97d5ab..5e47607a 100644 --- a/accel-pppd/ppp/ppp.h +++ b/accel-pppd/ppp/ppp.h @@ -8,6 +8,7 @@ #include "triton.h" #include "list.h" +#include "iputils.h" /* * Packet header = Code, id, length. @@ -134,6 +135,15 @@ struct ppp_t struct ppp_lcp_t *lcp; struct list_head pd_list; + + uint32_t acct_rx_bytes; + uint32_t acct_tx_bytes; + uint32_t acct_input_gigawords; + uint32_t acct_output_gigawords; + uint32_t acct_rx_packets_i; + uint32_t acct_tx_packets_i; + uint32_t acct_rx_bytes_i; + uint32_t acct_tx_bytes_i; }; struct ppp_layer_t; @@ -200,6 +210,8 @@ int ppp_register_layer(const char *name, struct ppp_layer_t *); void ppp_unregister_layer(struct ppp_layer_t *); struct ppp_layer_data_t *ppp_find_layer_data(struct ppp_t *, struct ppp_layer_t *); +int ppp_read_stats(struct ppp_t *ppp, struct rtnl_link_stats *stats); + extern int ppp_shutdown; void ppp_shutdown_soft(void); diff --git a/accel-pppd/ppp/ppp_lcp.c b/accel-pppd/ppp/ppp_lcp.c index e61738c6..9b56ed18 100644 --- a/accel-pppd/ppp/ppp_lcp.c +++ b/accel-pppd/ppp/ppp_lcp.c @@ -638,9 +638,9 @@ static void send_echo_reply(struct ppp_lcp_t *lcp) static void send_echo_request(struct triton_timer_t *t) { struct ppp_lcp_t *lcp = container_of(t, typeof(*lcp), echo_timer); - struct ifpppstatsreq ifreq; - int f = 0; + int f = 0, r; time_t ts; + struct rtnl_link_stats stats; struct lcp_echo_req_t { struct lcp_hdr_t hdr; @@ -655,22 +655,15 @@ static void send_echo_request(struct triton_timer_t *t) ++lcp->echo_sent; + r = ppp_read_stats(lcp->ppp, &stats); + if (conf_echo_timeout) { if (lcp->echo_sent == 2) { - memset(&ifreq, 0, sizeof(ifreq)); - ifreq.stats_ptr = (void *)&ifreq.stats; - strcpy(ifreq.ifr__name, lcp->ppp->ifname); - - if (ioctl(sock_fd, SIOCGPPPSTATS, &ifreq) == 0) - lcp->last_ipackets = ifreq.stats.p.ppp_ipackets; - + lcp->last_ipackets = stats.rx_packets; time(&lcp->last_echo_ts); } else if (lcp->echo_sent > 2) { time(&ts); - memset(&ifreq, 0, sizeof(ifreq)); - ifreq.stats_ptr = (void *)&ifreq.stats; - strcpy(ifreq.ifr__name, lcp->ppp->ifname); - if (ioctl(sock_fd, SIOCGPPPSTATS, &ifreq) == 0 && lcp->last_ipackets != ifreq.stats.p.ppp_ipackets) { + if (r == 0 && lcp->last_ipackets != stats.rx_packets) { lcp->echo_sent = 1; lcp_update_echo_timer(lcp); } else if (ts - lcp->last_echo_ts > conf_echo_timeout) { diff --git a/accel-pppd/radius/acct.c b/accel-pppd/radius/acct.c index 76ad3299..9a832a9c 100644 --- a/accel-pppd/radius/acct.c +++ b/accel-pppd/radius/acct.c @@ -34,7 +34,7 @@ static int req_set_RA(struct rad_req_t *req, const char *secret) static void req_set_stat(struct rad_req_t *req, struct ppp_t *ppp) { - struct ifpppstatsreq ifreq; + struct rtnl_link_stats stats; time_t stop_time; if (ppp->stop_time) @@ -42,29 +42,14 @@ static void req_set_stat(struct rad_req_t *req, struct ppp_t *ppp) else time(&stop_time); - memset(&ifreq, 0, sizeof(ifreq)); - ifreq.stats_ptr = (void *)&ifreq.stats; - strcpy(ifreq.ifr__name, ppp->ifname); - - if (ioctl(sock_fd, SIOCGPPPSTATS, &ifreq)) { - log_ppp_error("radius: failed to get ppp statistics: %s\n", strerror(errno)); - return; + if (ppp_read_stats(ppp, &stats) == 0) { + rad_packet_change_int(req->pack, NULL, "Acct-Input-Octets", stats.rx_bytes); + rad_packet_change_int(req->pack, NULL, "Acct-Output-Octets", stats.tx_bytes); + rad_packet_change_int(req->pack, NULL, "Acct-Input-Packets", stats.rx_packets); + rad_packet_change_int(req->pack, NULL, "Acct-Output-Packets", stats.tx_packets); + rad_packet_change_int(req->pack, NULL, "Acct-Input-Gigawords", ppp->acct_input_gigawords); + rad_packet_change_int(req->pack, NULL, "Acct-Output-Gigawords", ppp->acct_output_gigawords); } - - if (ifreq.stats.p.ppp_ibytes < req->rpd->acct_input_octets) - req->rpd->acct_input_gigawords++; - req->rpd->acct_input_octets = ifreq.stats.p.ppp_ibytes; - - if (ifreq.stats.p.ppp_obytes < req->rpd->acct_output_octets) - req->rpd->acct_output_gigawords++; - req->rpd->acct_output_octets = ifreq.stats.p.ppp_obytes; - - rad_packet_change_int(req->pack, NULL, "Acct-Input-Octets", ifreq.stats.p.ppp_ibytes); - rad_packet_change_int(req->pack, NULL, "Acct-Output-Octets", ifreq.stats.p.ppp_obytes); - rad_packet_change_int(req->pack, NULL, "Acct-Input-Packets", ifreq.stats.p.ppp_ipackets); - rad_packet_change_int(req->pack, NULL, "Acct-Output-Packets", ifreq.stats.p.ppp_opackets); - rad_packet_change_int(req->pack, NULL, "Acct-Input-Gigawords", req->rpd->acct_input_gigawords); - rad_packet_change_int(req->pack, NULL, "Acct-Output-Gigawords", req->rpd->acct_output_gigawords); rad_packet_change_int(req->pack, NULL, "Acct-Session-Time", stop_time - ppp->start_time); } diff --git a/accel-pppd/radius/radius_p.h b/accel-pppd/radius/radius_p.h index 7422bbf3..65d9b6a3 100644 --- a/accel-pppd/radius/radius_p.h +++ b/accel-pppd/radius/radius_p.h @@ -23,11 +23,6 @@ struct radius_pd_t struct rad_req_t *auth_req; struct rad_req_t *acct_req; struct triton_timer_t acct_interim_timer; - uint32_t acct_input_octets; - uint32_t acct_output_octets; - uint32_t acct_input_gigawords; - uint32_t acct_output_gigawords; - struct triton_timer_t session_timeout; struct rad_packet_t *dm_coa_req; diff --git a/accel-pppd/shaper/CMakeLists.txt b/accel-pppd/shaper/CMakeLists.txt index 515fd839..3c1ac951 100644 --- a/accel-pppd/shaper/CMakeLists.txt +++ b/accel-pppd/shaper/CMakeLists.txt @@ -1,4 +1,4 @@ -ADD_LIBRARY(shaper SHARED shaper.c limiter.c leaf_qdisc.c tc_core.c libnetlink.c) +ADD_LIBRARY(shaper SHARED shaper.c limiter.c leaf_qdisc.c tc_core.c) INSTALL(TARGETS shaper LIBRARY DESTINATION lib/accel-ppp diff --git a/accel-pppd/shaper/libnetlink.c b/accel-pppd/shaper/libnetlink.c deleted file mode 100644 index 74cd5cb5..00000000 --- a/accel-pppd/shaper/libnetlink.c +++ /dev/null @@ -1,692 +0,0 @@ -/* - * libnetlink.c RTnetlink service routines. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * Authors: Alexey Kuznetsov, - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "libnetlink.h" -#include "log.h" - -int rcvbuf = 1024 * 1024; - -void rtnl_close(struct rtnl_handle *rth) -{ - if (rth->fd >= 0) { - close(rth->fd); - rth->fd = -1; - } -} - -int rtnl_open_byproto(struct rtnl_handle *rth, unsigned subscriptions, - int protocol) -{ - socklen_t addr_len; - int sndbuf = 32768; - - memset(rth, 0, sizeof(*rth)); - - rth->fd = socket(AF_NETLINK, SOCK_RAW, protocol); - if (rth->fd < 0) { - log_error("libnetlink: ""Cannot open netlink socket: %s\n", strerror(errno)); - return -1; - } - - if (setsockopt(rth->fd,SOL_SOCKET,SO_SNDBUF,&sndbuf,sizeof(sndbuf)) < 0) { - log_error("libnetlink: ""SO_SNDBUF: %s\n", strerror(errno)); - return -1; - } - - if (setsockopt(rth->fd,SOL_SOCKET,SO_RCVBUF,&rcvbuf,sizeof(rcvbuf)) < 0) { - log_error("libnetlink: ""SO_RCVBUF: %s\n", strerror(errno)); - return -1; - } - - memset(&rth->local, 0, sizeof(rth->local)); - rth->local.nl_family = AF_NETLINK; - rth->local.nl_groups = subscriptions; - - if (bind(rth->fd, (struct sockaddr*)&rth->local, sizeof(rth->local)) < 0) { - log_error("libnetlink: ""Cannot bind netlink socket: %s\n", strerror(errno)); - return -1; - } - addr_len = sizeof(rth->local); - if (getsockname(rth->fd, (struct sockaddr*)&rth->local, &addr_len) < 0) { - log_error("libnetlink: ""Cannot getsockname: %s\n", strerror(errno)); - return -1; - } - if (addr_len != sizeof(rth->local)) { - log_error("libnetlink: ""Wrong address length %d\n", addr_len); - return -1; - } - if (rth->local.nl_family != AF_NETLINK) { - log_error("libnetlink: ""Wrong address family %d\n", rth->local.nl_family); - return -1; - } - rth->seq = time(NULL); - return 0; -} - -int rtnl_open(struct rtnl_handle *rth, unsigned subscriptions) -{ - return rtnl_open_byproto(rth, subscriptions, NETLINK_ROUTE); -} - -int rtnl_wilddump_request(struct rtnl_handle *rth, int family, int type) -{ - struct { - struct nlmsghdr nlh; - struct rtgenmsg g; - } req; - - memset(&req, 0, sizeof(req)); - req.nlh.nlmsg_len = sizeof(req); - req.nlh.nlmsg_type = type; - req.nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST; - req.nlh.nlmsg_pid = 0; - req.nlh.nlmsg_seq = rth->dump = ++rth->seq; - req.g.rtgen_family = family; - - return send(rth->fd, (void*)&req, sizeof(req), 0); -} - -int rtnl_send(struct rtnl_handle *rth, const char *buf, int len) -{ - return send(rth->fd, buf, len, 0); -} - -int rtnl_send_check(struct rtnl_handle *rth, const char *buf, int len) -{ - struct nlmsghdr *h; - int status; - char resp[1024]; - - status = send(rth->fd, buf, len, 0); - if (status < 0) - return status; - - /* Check for immediate errors */ - status = recv(rth->fd, resp, sizeof(resp), MSG_DONTWAIT|MSG_PEEK); - if (status < 0) { - if (errno == EAGAIN) - return 0; - return -1; - } - - for (h = (struct nlmsghdr *)resp; NLMSG_OK(h, status); - h = NLMSG_NEXT(h, status)) { - if (h->nlmsg_type == NLMSG_ERROR) { - struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h); - if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr))) - log_error("libnetlink: ""ERROR truncated\n"); - else - errno = -err->error; - return -1; - } - } - - return 0; -} - -int rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len) -{ - struct nlmsghdr nlh; - struct sockaddr_nl nladdr; - struct iovec iov[2] = { - { .iov_base = &nlh, .iov_len = sizeof(nlh) }, - { .iov_base = req, .iov_len = len } - }; - struct msghdr msg = { - .msg_name = &nladdr, - .msg_namelen = sizeof(nladdr), - .msg_iov = iov, - .msg_iovlen = 2, - }; - - memset(&nladdr, 0, sizeof(nladdr)); - nladdr.nl_family = AF_NETLINK; - - nlh.nlmsg_len = NLMSG_LENGTH(len); - nlh.nlmsg_type = type; - nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST; - nlh.nlmsg_pid = 0; - nlh.nlmsg_seq = rth->dump = ++rth->seq; - - return sendmsg(rth->fd, &msg, 0); -} - -int rtnl_dump_filter_l(struct rtnl_handle *rth, - const struct rtnl_dump_filter_arg *arg) -{ - struct sockaddr_nl nladdr; - struct iovec iov; - struct msghdr msg = { - .msg_name = &nladdr, - .msg_namelen = sizeof(nladdr), - .msg_iov = &iov, - .msg_iovlen = 1, - }; - char buf[16384]; - - iov.iov_base = buf; - while (1) { - int status; - const struct rtnl_dump_filter_arg *a; - int found_done = 0; - int msglen = 0; - - iov.iov_len = sizeof(buf); - status = recvmsg(rth->fd, &msg, 0); - - if (status < 0) { - if (errno == EINTR || errno == EAGAIN) - continue; - log_error("libnetlink: ""netlink receive error %s (%d)\n", - strerror(errno), errno); - return -1; - } - - if (status == 0) { - log_error("libnetlink: ""EOF on netlink\n"); - return -1; - } - - for (a = arg; a->filter; a++) { - struct nlmsghdr *h = (struct nlmsghdr*)buf; - msglen = status; - - while (NLMSG_OK(h, msglen)) { - int err; - - if (nladdr.nl_pid != 0 || - h->nlmsg_pid != rth->local.nl_pid || - h->nlmsg_seq != rth->dump) { - if (a->junk) { - err = a->junk(&nladdr, h, - a->arg2); - if (err < 0) - return err; - } - goto skip_it; - } - - if (h->nlmsg_type == NLMSG_DONE) { - found_done = 1; - break; /* process next filter */ - } - if (h->nlmsg_type == NLMSG_ERROR) { - struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h); - if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr))) { - fprintf(stderr, - "ERROR truncated\n"); - } else { - errno = -err->error; - log_error("libnetlink: ""RTNETLINK answers: %s\n", strerror(errno)); - } - return -1; - } - err = a->filter(&nladdr, h, a->arg1); - if (err < 0) - return err; - -skip_it: - h = NLMSG_NEXT(h, msglen); - } - } - - if (found_done) - return 0; - - if (msg.msg_flags & MSG_TRUNC) { - log_error("libnetlink: ""Message truncated\n"); - continue; - } - if (msglen) { - log_error("libnetlink: ""!!!Remnant of size %d\n", msglen); - exit(1); - } - } -} - -int rtnl_dump_filter(struct rtnl_handle *rth, - rtnl_filter_t filter, - void *arg1, - rtnl_filter_t junk, - void *arg2) -{ - const struct rtnl_dump_filter_arg a[2] = { - { .filter = filter, .arg1 = arg1, .junk = junk, .arg2 = arg2 }, - { .filter = NULL, .arg1 = NULL, .junk = NULL, .arg2 = NULL } - }; - - return rtnl_dump_filter_l(rth, a); -} - -int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, - unsigned groups, struct nlmsghdr *answer, - rtnl_filter_t junk, - void *jarg, int ignore_einval) -{ - int status; - unsigned seq; - struct nlmsghdr *h; - struct sockaddr_nl nladdr; - struct iovec iov = { - .iov_base = (void*) n, - .iov_len = n->nlmsg_len - }; - struct msghdr msg = { - .msg_name = &nladdr, - .msg_namelen = sizeof(nladdr), - .msg_iov = &iov, - .msg_iovlen = 1, - }; - char buf[16384]; - - memset(&nladdr, 0, sizeof(nladdr)); - nladdr.nl_family = AF_NETLINK; - nladdr.nl_pid = peer; - nladdr.nl_groups = groups; - - n->nlmsg_seq = seq = ++rtnl->seq; - - if (answer == NULL) - n->nlmsg_flags |= NLM_F_ACK; - - status = sendmsg(rtnl->fd, &msg, 0); - - if (status < 0) { - log_error("libnetlink: ""Cannot talk to rtnetlink: %s\n", strerror(errno)); - return -1; - } - - memset(buf,0,sizeof(buf)); - - iov.iov_base = buf; - - while (1) { - iov.iov_len = sizeof(buf); - status = recvmsg(rtnl->fd, &msg, 0); - - if (status < 0) { - if (errno == EINTR || errno == EAGAIN) - continue; - log_error("libnetlink: ""netlink receive error %s (%d)\n", - strerror(errno), errno); - return -1; - } - if (status == 0) { - log_error("libnetlink: ""EOF on netlink\n"); - return -1; - } - if (msg.msg_namelen != sizeof(nladdr)) { - log_error("libnetlink: ""sender address length == %d\n", msg.msg_namelen); - exit(1); - } - for (h = (struct nlmsghdr*)buf; status >= sizeof(*h); ) { - int err; - int len = h->nlmsg_len; - int l = len - sizeof(*h); - - if (l<0 || len>status) { - if (msg.msg_flags & MSG_TRUNC) { - log_error("libnetlink: ""Truncated message\n"); - return -1; - } - log_error("libnetlink: ""!!!malformed message: len=%d\n", len); - exit(1); - } - - if (nladdr.nl_pid != peer || - h->nlmsg_pid != rtnl->local.nl_pid || - h->nlmsg_seq != seq) { - if (junk) { - err = junk(&nladdr, h, jarg); - if (err < 0) - return err; - } - /* Don't forget to skip that message. */ - status -= NLMSG_ALIGN(len); - h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len)); - continue; - } - - if (h->nlmsg_type == NLMSG_ERROR) { - struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h); - if (l < sizeof(struct nlmsgerr)) { - log_error("libnetlink: ""ERROR truncated\n"); - } else { - errno = -err->error; - if (errno == 0 || (errno == EINVAL && ignore_einval)) { - if (answer) - memcpy(answer, h, h->nlmsg_len); - return 0; - } - log_error("libnetlink: ""RTNETLINK answers: %s\n", strerror(errno)); - } - return -1; - } - if (answer) { - memcpy(answer, h, h->nlmsg_len); - return 0; - } - - log_error("libnetlink: ""Unexpected reply!!!\n"); - - status -= NLMSG_ALIGN(len); - h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len)); - } - if (msg.msg_flags & MSG_TRUNC) { - log_error("libnetlink: ""Message truncated\n"); - continue; - } - if (status) { - log_error("libnetlink: ""!!!Remnant of size %d\n", status); - exit(1); - } - } -} - -int rtnl_listen(struct rtnl_handle *rtnl, - rtnl_filter_t handler, - void *jarg) -{ - int status; - struct nlmsghdr *h; - struct sockaddr_nl nladdr; - struct iovec iov; - struct msghdr msg = { - .msg_name = &nladdr, - .msg_namelen = sizeof(nladdr), - .msg_iov = &iov, - .msg_iovlen = 1, - }; - char buf[8192]; - - memset(&nladdr, 0, sizeof(nladdr)); - nladdr.nl_family = AF_NETLINK; - nladdr.nl_pid = 0; - nladdr.nl_groups = 0; - - iov.iov_base = buf; - while (1) { - iov.iov_len = sizeof(buf); - status = recvmsg(rtnl->fd, &msg, 0); - - if (status < 0) { - if (errno == EINTR || errno == EAGAIN) - continue; - log_error("libnetlink: ""netlink receive error %s (%d)\n", - strerror(errno), errno); - if (errno == ENOBUFS) - continue; - return -1; - } - if (status == 0) { - log_error("libnetlink: ""EOF on netlink\n"); - return -1; - } - if (msg.msg_namelen != sizeof(nladdr)) { - log_error("libnetlink: ""Sender address length == %d\n", msg.msg_namelen); - exit(1); - } - for (h = (struct nlmsghdr*)buf; status >= sizeof(*h); ) { - int err; - int len = h->nlmsg_len; - int l = len - sizeof(*h); - - if (l<0 || len>status) { - if (msg.msg_flags & MSG_TRUNC) { - log_error("libnetlink: ""Truncated message\n"); - return -1; - } - log_error("libnetlink: ""!!!malformed message: len=%d\n", len); - exit(1); - } - - err = handler(&nladdr, h, jarg); - if (err < 0) - return err; - - status -= NLMSG_ALIGN(len); - h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len)); - } - if (msg.msg_flags & MSG_TRUNC) { - log_error("libnetlink: ""Message truncated\n"); - continue; - } - if (status) { - log_error("libnetlink: ""!!!Remnant of size %d\n", status); - exit(1); - } - } -} - -int rtnl_from_file(FILE *rtnl, rtnl_filter_t handler, - void *jarg) -{ - int status; - struct sockaddr_nl nladdr; - char buf[8192]; - struct nlmsghdr *h = (void*)buf; - - memset(&nladdr, 0, sizeof(nladdr)); - nladdr.nl_family = AF_NETLINK; - nladdr.nl_pid = 0; - nladdr.nl_groups = 0; - - while (1) { - int err, len, type; - int l; - - status = fread(&buf, 1, sizeof(*h), rtnl); - - if (status < 0) { - if (errno == EINTR) - continue; - log_error("libnetlink: ""rtnl_from_file: fread"); - return -1; - } - if (status == 0) - return 0; - - len = h->nlmsg_len; - type= h->nlmsg_type; - l = len - sizeof(*h); - - if (l<0 || len>sizeof(buf)) { - log_error("libnetlink: ""!!!malformed message: len=%d @%lu\n", - len, ftell(rtnl)); - return -1; - } - - status = fread(NLMSG_DATA(h), 1, NLMSG_ALIGN(l), rtnl); - - if (status < 0) { - log_error("libnetlink: ""rtnl_from_file: fread"); - return -1; - } - if (status < l) { - log_error("libnetlink: ""rtnl-from_file: truncated message\n"); - return -1; - } - - err = handler(&nladdr, h, jarg); - if (err < 0) - return err; - } -} - -int addattr32(struct nlmsghdr *n, int maxlen, int type, __u32 data) -{ - int len = RTA_LENGTH(4); - struct rtattr *rta; - if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen) { - fprintf(stderr,"addattr32: Error! max allowed bound %d exceeded\n",maxlen); - return -1; - } - rta = NLMSG_TAIL(n); - rta->rta_type = type; - rta->rta_len = len; - memcpy(RTA_DATA(rta), &data, 4); - n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + len; - return 0; -} - -int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data, - int alen) -{ - int len = RTA_LENGTH(alen); - struct rtattr *rta; - - if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) { - log_error("libnetlink: ""addattr_l ERROR: message exceeded bound of %d\n",maxlen); - return -1; - } - rta = NLMSG_TAIL(n); - rta->rta_type = type; - rta->rta_len = len; - memcpy(RTA_DATA(rta), data, alen); - n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len); - return 0; -} - -int addraw_l(struct nlmsghdr *n, int maxlen, const void *data, int len) -{ - if (NLMSG_ALIGN(n->nlmsg_len) + NLMSG_ALIGN(len) > maxlen) { - log_error("libnetlink: ""addraw_l ERROR: message exceeded bound of %d\n",maxlen); - return -1; - } - - memcpy(NLMSG_TAIL(n), data, len); - memset((void *) NLMSG_TAIL(n) + len, 0, NLMSG_ALIGN(len) - len); - n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + NLMSG_ALIGN(len); - return 0; -} - -struct rtattr *addattr_nest(struct nlmsghdr *n, int maxlen, int type) -{ - struct rtattr *nest = NLMSG_TAIL(n); - - addattr_l(n, maxlen, type, NULL, 0); - return nest; -} - -int addattr_nest_end(struct nlmsghdr *n, struct rtattr *nest) -{ - nest->rta_len = (void *)NLMSG_TAIL(n) - (void *)nest; - return n->nlmsg_len; -} - -struct rtattr *addattr_nest_compat(struct nlmsghdr *n, int maxlen, int type, - const void *data, int len) -{ - struct rtattr *start = NLMSG_TAIL(n); - - addattr_l(n, maxlen, type, data, len); - addattr_nest(n, maxlen, type); - return start; -} - -int addattr_nest_compat_end(struct nlmsghdr *n, struct rtattr *start) -{ - struct rtattr *nest = (void *)start + NLMSG_ALIGN(start->rta_len); - - start->rta_len = (void *)NLMSG_TAIL(n) - (void *)start; - addattr_nest_end(n, nest); - return n->nlmsg_len; -} - -int rta_addattr32(struct rtattr *rta, int maxlen, int type, __u32 data) -{ - int len = RTA_LENGTH(4); - struct rtattr *subrta; - - if (RTA_ALIGN(rta->rta_len) + len > maxlen) { - fprintf(stderr,"rta_addattr32: Error! max allowed bound %d exceeded\n",maxlen); - return -1; - } - subrta = (struct rtattr*)(((char*)rta) + RTA_ALIGN(rta->rta_len)); - subrta->rta_type = type; - subrta->rta_len = len; - memcpy(RTA_DATA(subrta), &data, 4); - rta->rta_len = NLMSG_ALIGN(rta->rta_len) + len; - return 0; -} - -int rta_addattr_l(struct rtattr *rta, int maxlen, int type, - const void *data, int alen) -{ - struct rtattr *subrta; - int len = RTA_LENGTH(alen); - - if (RTA_ALIGN(rta->rta_len) + RTA_ALIGN(len) > maxlen) { - fprintf(stderr,"rta_addattr_l: Error! max allowed bound %d exceeded\n",maxlen); - return -1; - } - subrta = (struct rtattr*)(((char*)rta) + RTA_ALIGN(rta->rta_len)); - subrta->rta_type = type; - subrta->rta_len = len; - memcpy(RTA_DATA(subrta), data, alen); - rta->rta_len = NLMSG_ALIGN(rta->rta_len) + RTA_ALIGN(len); - return 0; -} - -int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len) -{ - memset(tb, 0, sizeof(struct rtattr *) * (max + 1)); - while (RTA_OK(rta, len)) { - if ((rta->rta_type <= max) && (!tb[rta->rta_type])) - tb[rta->rta_type] = rta; - rta = RTA_NEXT(rta,len); - } - if (len) - log_error("libnetlink: ""!!!Deficit %d, rta_len=%d\n", len, rta->rta_len); - return 0; -} - -int parse_rtattr_byindex(struct rtattr *tb[], int max, struct rtattr *rta, int len) -{ - int i = 0; - - memset(tb, 0, sizeof(struct rtattr *) * max); - while (RTA_OK(rta, len)) { - if (rta->rta_type <= max && i < max) - tb[i++] = rta; - rta = RTA_NEXT(rta,len); - } - if (len) - log_error("libnetlink: ""!!!Deficit %d, rta_len=%d\n", len, rta->rta_len); - return i; -} - -int __parse_rtattr_nested_compat(struct rtattr *tb[], int max, struct rtattr *rta, - int len) -{ - if (RTA_PAYLOAD(rta) < len) - return -1; - if (RTA_PAYLOAD(rta) >= RTA_ALIGN(len) + sizeof(struct rtattr)) { - rta = RTA_DATA(rta) + RTA_ALIGN(len); - return parse_rtattr_nested(tb, max, rta); - } - memset(tb, 0, sizeof(struct rtattr *) * (max + 1)); - return 0; -} diff --git a/accel-pppd/shaper/libnetlink.h b/accel-pppd/shaper/libnetlink.h deleted file mode 100644 index f68bf8a1..00000000 --- a/accel-pppd/shaper/libnetlink.h +++ /dev/null @@ -1,118 +0,0 @@ -#ifndef __LIBNETLINK_H__ -#define __LIBNETLINK_H__ 1 - -#include -#include -#include -#include -#include -#include - -#define TCA_BUF_MAX 64*1024 -#define MAX_MSG 16384 - -struct rtnl_handle -{ - int fd; - struct sockaddr_nl local; - struct sockaddr_nl peer; - __u32 seq; - __u32 dump; -}; - -extern int rcvbuf; - -extern int rtnl_open(struct rtnl_handle *rth, unsigned subscriptions); -extern int rtnl_open_byproto(struct rtnl_handle *rth, unsigned subscriptions, int protocol); -extern void rtnl_close(struct rtnl_handle *rth); -extern int rtnl_wilddump_request(struct rtnl_handle *rth, int fam, int type); -extern int rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len); - -typedef int (*rtnl_filter_t)(const struct sockaddr_nl *, - struct nlmsghdr *n, void *); - -struct rtnl_dump_filter_arg -{ - rtnl_filter_t filter; - void *arg1; - rtnl_filter_t junk; - void *arg2; -}; - -extern int rtnl_dump_filter_l(struct rtnl_handle *rth, - const struct rtnl_dump_filter_arg *arg); -extern int rtnl_dump_filter(struct rtnl_handle *rth, rtnl_filter_t filter, - void *arg1, - rtnl_filter_t junk, - void *arg2); - -extern int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, - unsigned groups, struct nlmsghdr *answer, - rtnl_filter_t junk, - void *jarg, int ignore_einval); -extern int rtnl_send(struct rtnl_handle *rth, const char *buf, int); -extern int rtnl_send_check(struct rtnl_handle *rth, const char *buf, int); - -extern int addattr32(struct nlmsghdr *n, int maxlen, int type, __u32 data); -extern int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data, int alen); -extern int addraw_l(struct nlmsghdr *n, int maxlen, const void *data, int len); -extern struct rtattr *addattr_nest(struct nlmsghdr *n, int maxlen, int type); -extern int addattr_nest_end(struct nlmsghdr *n, struct rtattr *nest); -extern struct rtattr *addattr_nest_compat(struct nlmsghdr *n, int maxlen, int type, const void *data, int len); -extern int addattr_nest_compat_end(struct nlmsghdr *n, struct rtattr *nest); -extern int rta_addattr32(struct rtattr *rta, int maxlen, int type, __u32 data); -extern int rta_addattr_l(struct rtattr *rta, int maxlen, int type, const void *data, int alen); - -extern int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len); -extern int parse_rtattr_byindex(struct rtattr *tb[], int max, struct rtattr *rta, int len); -extern int __parse_rtattr_nested_compat(struct rtattr *tb[], int max, struct rtattr *rta, int len); - -#define parse_rtattr_nested(tb, max, rta) \ - (parse_rtattr((tb), (max), RTA_DATA(rta), RTA_PAYLOAD(rta))) - -#define parse_rtattr_nested_compat(tb, max, rta, data, len) \ -({ data = RTA_PAYLOAD(rta) >= len ? RTA_DATA(rta) : NULL; \ - __parse_rtattr_nested_compat(tb, max, rta, len); }) - -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))) - -#ifndef IFA_RTA -#define IFA_RTA(r) \ - ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifaddrmsg)))) -#endif -#ifndef IFA_PAYLOAD -#define IFA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifaddrmsg)) -#endif - -#ifndef IFLA_RTA -#define IFLA_RTA(r) \ - ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifinfomsg)))) -#endif -#ifndef IFLA_PAYLOAD -#define IFLA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifinfomsg)) -#endif - -#ifndef NDA_RTA -#define NDA_RTA(r) \ - ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg)))) -#endif -#ifndef NDA_PAYLOAD -#define NDA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ndmsg)) -#endif - -#ifndef NDTA_RTA -#define NDTA_RTA(r) \ - ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ndtmsg)))) -#endif -#ifndef NDTA_PAYLOAD -#define NDTA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ndtmsg)) -#endif - -#endif /* __LIBNETLINK_H__ */ - -- cgit v1.2.3 From 07ead7eed242981335aadd34aa3d7b3e7da33b81 Mon Sep 17 00:00:00 2001 From: Guillaume Nault Date: Tue, 4 Sep 2012 20:29:08 +0200 Subject: Add compilation checks for printf-style format strings Append the format() __attribute__ to function prototypes which use a format string. This allows GCC to check for consistency between the format string and its arguments when these functions are called. Signed-off-by: Guillaume Nault --- accel-pppd/cli/cli.h | 2 +- accel-pppd/log.h | 30 +++++++++++++++--------------- accel-pppd/triton/triton_p.h | 4 ++-- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/accel-pppd/cli/cli.h b/accel-pppd/cli/cli.h index cdceb2fa..c2d058a5 100644 --- a/accel-pppd/cli/cli.h +++ b/accel-pppd/cli/cli.h @@ -42,7 +42,7 @@ void cli_register_regexp_cmd(struct cli_regexp_cmd_t *cmd); void cli_show_ses_register(const char *name, const char *desc, void (*print)(const struct ppp_t *ppp, char *buf)); int cli_send(void *client, const char *data); -int cli_sendv(void *client, const char *fmt, ...); +int cli_sendv(void *client, const char *fmt, ...) __attribute__((format(gnu_printf, 2, 3))); #endif diff --git a/accel-pppd/log.h b/accel-pppd/log.h index 58461465..45f0035c 100644 --- a/accel-pppd/log.h +++ b/accel-pppd/log.h @@ -39,21 +39,21 @@ struct log_target_t void log_free_msg(struct log_msg_t *msg); -void log_emerg(const char *fmt, ...); - -void log_error(const char *fmt,...); -void log_warn(const char *fmt,...); -void log_info1(const char *fmt,...); -void log_info2(const char *fmt,...); -void log_debug(const char *fmt,...); -void log_msg(const char *fmt,...); - -void log_ppp_error(const char *fmt,...); -void log_ppp_warn(const char *fmt,...); -void log_ppp_info1(const char *fmt,...); -void log_ppp_info2(const char *fmt,...); -void log_ppp_debug(const char *fmt,...); -void log_ppp_msg(const char *fmt,...); +void log_emerg(const char *fmt, ...) __attribute__((format(gnu_printf, 1, 2))); + +void log_error(const char *fmt, ...) __attribute__((format(gnu_printf, 1, 2))); +void log_warn(const char *fmt, ...) __attribute__((format(gnu_printf, 1, 2))); +void log_info1(const char *fmt, ...) __attribute__((format(gnu_printf, 1, 2))); +void log_info2(const char *fmt, ...) __attribute__((format(gnu_printf, 1, 2))); +void log_debug(const char *fmt, ...) __attribute__((format(gnu_printf, 1, 2))); +void log_msg(const char *fmt, ...) __attribute__((format(gnu_printf, 1, 2))); + +void log_ppp_error(const char *fmt, ...) __attribute__((format(gnu_printf, 1, 2))); +void log_ppp_warn(const char *fmt, ...) __attribute__((format(gnu_printf, 1, 2))); +void log_ppp_info1(const char *fmt, ...) __attribute__((format(gnu_printf, 1, 2))); +void log_ppp_info2(const char *fmt, ...) __attribute__((format(gnu_printf, 1, 2))); +void log_ppp_debug(const char *fmt, ...) __attribute__((format(gnu_printf, 1, 2))); +void log_ppp_msg(const char *fmt, ...) __attribute__((format(gnu_printf, 1, 2))); void log_switch(struct triton_context_t *ctx, void *arg); diff --git a/accel-pppd/triton/triton_p.h b/accel-pppd/triton/triton_p.h index 2eb2e62a..443cedea 100644 --- a/accel-pppd/triton/triton_p.h +++ b/accel-pppd/triton/triton_p.h @@ -104,8 +104,8 @@ int triton_queue_ctx(struct _triton_context_t*); void triton_thread_wakeup(struct _triton_thread_t*); int conf_load(const char *fname); int conf_reload(const char *fname); -void triton_log_error(const char *fmt,...); -void triton_log_debug(const char *fmt,...); +void triton_log_error(const char *fmt, ...) __attribute__((format(gnu_printf, 1, 2))); +void triton_log_debug(const char *fmt, ...) __attribute__((format(gnu_printf, 1, 2))); int load_modules(const char *name); #endif -- cgit v1.2.3 From 5f355048894ede9e983c7f02cc5915385620db3f Mon Sep 17 00:00:00 2001 From: Guillaume Nault Date: Tue, 4 Sep 2012 20:29:18 +0200 Subject: Fix format string errors Fix several errors and compiler warnings in format string arguments. Signed-off-by: Guillaume Nault --- accel-pppd/ctrl/l2tp/packet.c | 2 +- accel-pppd/ctrl/pppoe/cli.c | 2 +- accel-pppd/ctrl/pppoe/pppoe.c | 2 +- accel-pppd/ctrl/pptp/pptp.c | 3 ++- accel-pppd/extra/connlimit.c | 11 ++++++----- accel-pppd/ipv6/dhcpv6.c | 3 ++- accel-pppd/ppp/ppp_lcp.c | 2 +- accel-pppd/radius/serv.c | 4 ++-- 8 files changed, 16 insertions(+), 13 deletions(-) diff --git a/accel-pppd/ctrl/l2tp/packet.c b/accel-pppd/ctrl/l2tp/packet.c index 60b9d36c..70d8d5d9 100644 --- a/accel-pppd/ctrl/l2tp/packet.c +++ b/accel-pppd/ctrl/l2tp/packet.c @@ -158,7 +158,7 @@ int l2tp_recv(int fd, struct l2tp_packet_t **p, struct in_pktinfo *pkt_info) if (n < sizeof(*hdr)) { if (conf_verbose) - log_warn("l2tp: short packet received (%i/%i)\n", n, sizeof(*hdr)); + log_warn("l2tp: short packet received (%i/%zu)\n", n, sizeof(*hdr)); goto out_err_hdr; } diff --git a/accel-pppd/ctrl/pppoe/cli.c b/accel-pppd/ctrl/pppoe/cli.c index 847b8547..26846402 100644 --- a/accel-pppd/ctrl/pppoe/cli.c +++ b/accel-pppd/ctrl/pppoe/cli.c @@ -120,7 +120,7 @@ static int show_service_name_exec(const char *cmd, char * const *f, int f_cnt, v if (conf_service_name) cli_sendv(cli, "%s\r\n", conf_service_name); else - cli_sendv(cli, "*\r\n", conf_service_name); + cli_sendv(cli, "*\r\n"); return CLI_CMD_OK; } diff --git a/accel-pppd/ctrl/pppoe/pppoe.c b/accel-pppd/ctrl/pppoe/pppoe.c index e620668f..f36a1cc5 100644 --- a/accel-pppd/ctrl/pppoe/pppoe.c +++ b/accel-pppd/ctrl/pppoe/pppoe.c @@ -1350,7 +1350,7 @@ static int init_secret(struct pppoe_serv_t *serv) DES_cblock key; if (read(urandom_fd, serv->secret, SECRET_LENGTH) < 0) { - log_emerg("pppoe: failed to read /dev/urandom\n", strerror(errno)); + log_emerg("pppoe: failed to read /dev/urandom: %s\n", strerror(errno)); return -1; } diff --git a/accel-pppd/ctrl/pptp/pptp.c b/accel-pppd/ctrl/pptp/pptp.c index f2e9d43c..a3476c5e 100644 --- a/accel-pppd/ctrl/pptp/pptp.c +++ b/accel-pppd/ctrl/pptp/pptp.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -222,7 +223,7 @@ static int pptp_start_ctrl_conn_rqst(struct pptp_conn_t *conn) } if (msg->version != htons(PPTP_VERSION)) { - log_ppp_warn("PPTP version mismatch: expecting %x, received %s\n", PPTP_VERSION, msg->version); + log_ppp_warn("PPTP version mismatch: expecting %x, received %" PRIu32 "\n", PPTP_VERSION, msg->version); if (send_pptp_start_ctrl_conn_rply(conn, PPTP_CONN_RES_PROTOCOL, 0)) return -1; return 0; diff --git a/accel-pppd/extra/connlimit.c b/accel-pppd/extra/connlimit.c index dcfc2deb..fd7c952b 100644 --- a/accel-pppd/extra/connlimit.c +++ b/accel-pppd/extra/connlimit.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -38,7 +39,7 @@ int __export connlimit_check(uint64_t key) clock_gettime(CLOCK_MONOTONIC, &ts); pthread_mutex_lock(&lock); - log_debug("connlimit: check entry %llu\n", key); + log_debug("connlimit: check entry %" PRIu64 "\n", key); list_for_each_safe(pos, n, &items) { it = list_entry(pos, typeof(*it), entry); @@ -66,7 +67,7 @@ int __export connlimit_check(uint64_t key) } if (d > conf_burst_timeout) { - log_debug("connlimit: remove %llu\n", it->key); + log_debug("connlimit: remove %" PRIu64 "\n", it->key); list_move(&it->entry, &tmp_list); } } @@ -78,7 +79,7 @@ int __export connlimit_check(uint64_t key) it->ts = ts; it->key = key; - log_debug("connlimit: add entry %llu\n", key); + log_debug("connlimit: add entry %" PRIu64 "\n", key); pthread_mutex_lock(&lock); list_add(&it->entry, &items); @@ -88,9 +89,9 @@ int __export connlimit_check(uint64_t key) } if (r == 0) - log_debug("connlimit: accept %llu\n", key); + log_debug("connlimit: accept %" PRIu64 "\n", key); else - log_debug("connlimit: drop %llu\n", key); + log_debug("connlimit: drop %" PRIu64 "\n", key); while (!list_empty(&tmp_list)) { diff --git a/accel-pppd/ipv6/dhcpv6.c b/accel-pppd/ipv6/dhcpv6.c index 5ee7d347..c6201c0d 100644 --- a/accel-pppd/ipv6/dhcpv6.c +++ b/accel-pppd/ipv6/dhcpv6.c @@ -173,7 +173,8 @@ static void insert_dp_routes(struct ppp_t *ppp, struct dhcpv6_pd *pd) if (ioctl(sock6_fd, SIOCADDRT, &rt6)) { err = errno; inet_ntop(AF_INET6, &p->addr, str1, sizeof(str1)); - log_ppp_error("dhcpv6: route add %s/%i: %s\n", str1, p->prefix_len); + log_ppp_error("dhcpv6: route add %s/%i: %s\n", + str1, p->prefix_len, strerror(err)); } else if (conf_verbose) { inet_ntop(AF_INET6, &p->addr, str1, sizeof(str1)); log_ppp_info2("dhcpv6: route add %s/%i\n", str1, p->prefix_len); diff --git a/accel-pppd/ppp/ppp_lcp.c b/accel-pppd/ppp/ppp_lcp.c index 9b56ed18..cf0d003c 100644 --- a/accel-pppd/ppp/ppp_lcp.c +++ b/accel-pppd/ppp/ppp_lcp.c @@ -859,7 +859,7 @@ static void lcp_recv(struct ppp_handler_t*h) break; case PROTOREJ: if (conf_ppp_verbose) - log_ppp_info2("recv [LCP ProtoRej id=%x <%04x>]\n", hdr->code, hdr->id, ntohs(*(uint16_t*)(hdr + 1))); + log_ppp_info2("recv [LCP ProtoRej id=%x <%04x>]\n", hdr->id, ntohs(*(uint16_t*)(hdr + 1))); ppp_recv_proto_rej(lcp->ppp, ntohs(*(uint16_t *)(hdr + 1))); break; case IDENT: diff --git a/accel-pppd/radius/serv.c b/accel-pppd/radius/serv.c index b7ee0bee..5caf9e13 100644 --- a/accel-pppd/radius/serv.c +++ b/accel-pppd/radius/serv.c @@ -232,8 +232,8 @@ static void show_stat(struct rad_server_t *s, void *client) cli_sendv(client, " fail count: %lu\r\n", s->stat_fail_cnt); } - cli_sendv(client, " request count: %lu\r\n", s->req_cnt); - cli_sendv(client, " queue length: %lu\r\n", s->queue_cnt); + cli_sendv(client, " request count: %i\r\n", s->req_cnt); + cli_sendv(client, " queue length: %i\r\n", s->queue_cnt); if (s->auth_port) { cli_sendv(client, " auth sent: %lu\r\n", s->stat_auth_sent); -- cgit v1.2.3 From fab542ddd4f87947cee43966013da29685d10c6a Mon Sep 17 00:00:00 2001 From: Kozlov Dmitry Date: Wed, 5 Sep 2012 22:16:35 +0400 Subject: add missing netlink library --- accel-pppd/auth/auth_mschap_v2.c | 4 +- accel-pppd/cli/std_cmd.c | 2 +- accel-pppd/extra/pppd_compat.c | 5 +- accel-pppd/include/iputils.h | 1 + accel-pppd/include/libnetlink.h | 1 + accel-pppd/libnetlink/genl.c | 108 +++++++ accel-pppd/libnetlink/genl.h | 6 + accel-pppd/libnetlink/iputils.c | 376 ++++++++++++++++++++++ accel-pppd/libnetlink/iputils.h | 19 ++ accel-pppd/libnetlink/libnetlink.c | 639 +++++++++++++++++++++++++++++++++++++ accel-pppd/libnetlink/libnetlink.h | 118 +++++++ accel-pppd/logs/log_file.c | 2 - 12 files changed, 1274 insertions(+), 7 deletions(-) create mode 120000 accel-pppd/include/iputils.h create mode 120000 accel-pppd/include/libnetlink.h create mode 100644 accel-pppd/libnetlink/genl.c create mode 100644 accel-pppd/libnetlink/genl.h create mode 100644 accel-pppd/libnetlink/iputils.c create mode 100644 accel-pppd/libnetlink/iputils.h create mode 100644 accel-pppd/libnetlink/libnetlink.c create mode 100644 accel-pppd/libnetlink/libnetlink.h diff --git a/accel-pppd/auth/auth_mschap_v2.c b/accel-pppd/auth/auth_mschap_v2.c index 9f9ff7ba..980f8159 100644 --- a/accel-pppd/auth/auth_mschap_v2.c +++ b/accel-pppd/auth/auth_mschap_v2.c @@ -205,7 +205,7 @@ static void chap_send_failure(struct chap_auth_data_t *ad, char *mschap_error, c sprintf((char *)(hdr + 1), "%s M=%s", mschap_error, reply_msg); if (conf_ppp_verbose) - log_ppp_info2("send [MSCHAP-v2 Failure id=%x \"%s\"]\n", hdr->id, hdr + 1); + log_ppp_info2("send [MSCHAP-v2 Failure id=%x \"%s\"]\n", hdr->id, (char *)(hdr + 1)); ppp_chan_send(ad->ppp, hdr, ntohs(hdr->len) + 2); @@ -223,7 +223,7 @@ static void chap_send_success(struct chap_auth_data_t *ad, struct chap_response_ sprintf((char *)(hdr + 1), "S=%s M=%s", authenticator, conf_msg_success); if (conf_ppp_verbose) - log_ppp_info2("send [MSCHAP-v2 Success id=%x \"%s\"]\n", hdr->id, hdr + 1); + log_ppp_info2("send [MSCHAP-v2 Success id=%x \"%s\"]\n", hdr->id, (char *)(hdr + 1)); ppp_chan_send(ad->ppp, hdr, ntohs(hdr->len) + 2); diff --git a/accel-pppd/cli/std_cmd.c b/accel-pppd/cli/std_cmd.c index 24e52283..d5259a53 100644 --- a/accel-pppd/cli/std_cmd.c +++ b/accel-pppd/cli/std_cmd.c @@ -42,7 +42,7 @@ static int show_stat_exec(const char *cmd, char * const *fields, int fields_cnt, hour = dt / (60 * 60); dt %= 60 * 60; - cli_sendv(client, "uptime: %i.%02i:%02i:%02i\r\n", day, hour, dt / 60, dt % 60); + cli_sendv(client, "uptime: %i.%02i:%02lu:%02lu\r\n", day, hour, dt / 60, dt % 60); cli_sendv(client, "cpu: %i%%\r\n", triton_stat.cpu); #ifdef MEMDEBUG cli_send(client, "memory:\r\n"); diff --git a/accel-pppd/extra/pppd_compat.c b/accel-pppd/extra/pppd_compat.c index d4de18ff..98240f65 100644 --- a/accel-pppd/extra/pppd_compat.c +++ b/accel-pppd/extra/pppd_compat.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include "linux_ppp.h" @@ -484,8 +485,8 @@ static void fill_env(char **env, struct pppd_compat_pd_t *pd) if (pd->ppp->stop_time && env[1]) { snprintf(env[1], 24, "CONNECT_TIME=%lu", pd->ppp->stop_time - pd->ppp->start_time); - snprintf(env[2], 24, "BYTES_SENT=%llu", (long long unsigned)tx_bytes); - snprintf(env[3], 24, "BYTES_RCVD=%llu", (long long unsigned)rx_bytes); + snprintf(env[2], 24, "BYTES_SENT=%" PRIu64, tx_bytes); + snprintf(env[3], 24, "BYTES_RCVD=%" PRIu64, rx_bytes); } } diff --git a/accel-pppd/include/iputils.h b/accel-pppd/include/iputils.h new file mode 120000 index 00000000..c91d11c9 --- /dev/null +++ b/accel-pppd/include/iputils.h @@ -0,0 +1 @@ +../libnetlink/iputils.h \ No newline at end of file diff --git a/accel-pppd/include/libnetlink.h b/accel-pppd/include/libnetlink.h new file mode 120000 index 00000000..d494ddb4 --- /dev/null +++ b/accel-pppd/include/libnetlink.h @@ -0,0 +1 @@ +../libnetlink/libnetlink.h \ No newline at end of file diff --git a/accel-pppd/libnetlink/genl.c b/accel-pppd/libnetlink/genl.c new file mode 100644 index 00000000..7d745566 --- /dev/null +++ b/accel-pppd/libnetlink/genl.c @@ -0,0 +1,108 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "triton.h" +#include "log.h" + +#include "libnetlink.h" + +#define GENL_MAX_FAM_GRPS 128 + +int __export genl_resolve_mcg(const char *family, const char *name, int *fam_id) +{ + struct rtnl_handle rth; + struct nlmsghdr *nlh; + struct genlmsghdr *ghdr; + struct rtattr *tb[CTRL_ATTR_MAX + 1]; + struct rtattr *tb2[GENL_MAX_FAM_GRPS + 1]; + struct rtattr *tb3[CTRL_ATTR_MCAST_GRP_MAX + 1]; + struct rtattr *attrs; + int i, len, ret = -1; + struct { + struct nlmsghdr n; + char buf[4096]; + } req; + + if (rtnl_open_byproto(&rth, 0, NETLINK_GENERIC)) { + log_error("genl: cannot open rtnetlink\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 = GENL_ID_CTRL; + + ghdr = NLMSG_DATA(&req.n); + ghdr->cmd = CTRL_CMD_GETFAMILY; + + addattr_l(nlh, 128, CTRL_ATTR_FAMILY_NAME, family, strlen(family) + 1); + + if (rtnl_talk(&rth, nlh, 0, 0, nlh, NULL, NULL, 0) < 0 ) { + log_error("genl: error talking to kernel\n"); + goto out; + } + + if (nlh->nlmsg_type != GENL_ID_CTRL) { + log_error("genl: not a controller message %d\n", nlh->nlmsg_type); + goto out; + } + + ghdr = NLMSG_DATA(nlh); + + if (ghdr->cmd != CTRL_CMD_NEWFAMILY) { + log_error("genl: unknown controller command %d\n", ghdr->cmd); + goto out; + } + + len = nlh->nlmsg_len - NLMSG_LENGTH(GENL_HDRLEN); + + if (len < 0) { + log_error("genl: wrong controller message len %d\n", len); + goto out; + } + + attrs = (struct rtattr *)((char *)ghdr + GENL_HDRLEN); + parse_rtattr(tb, CTRL_ATTR_MAX, attrs, len); + + if (!tb[CTRL_ATTR_FAMILY_ID]) { + log_error("genl: missing CTRL_FAMILY_ID attribute\n"); + goto out; + } + + if (!tb[CTRL_ATTR_MCAST_GROUPS]) + goto out; + + if (fam_id) + *fam_id = *(uint32_t *)(RTA_DATA(tb[CTRL_ATTR_FAMILY_ID])); + + parse_rtattr_nested(tb2, GENL_MAX_FAM_GRPS, tb[CTRL_ATTR_MCAST_GROUPS]); + + for (i = 1; i < GENL_MAX_FAM_GRPS; i++) { + if (tb2[i]) { + parse_rtattr_nested(tb3, CTRL_ATTR_MCAST_GRP_MAX, tb2[i]); + if (!tb3[CTRL_ATTR_MCAST_GRP_ID] || !tb3[CTRL_ATTR_MCAST_GRP_NAME]) + continue; + if (strcmp(RTA_DATA(tb3[CTRL_ATTR_MCAST_GRP_NAME]), name)) + continue; + ret = *(uint32_t *)(RTA_DATA(tb3[CTRL_ATTR_MCAST_GRP_ID])); + break; + } + } + +out: + + rtnl_close(&rth); + return ret; +} diff --git a/accel-pppd/libnetlink/genl.h b/accel-pppd/libnetlink/genl.h new file mode 100644 index 00000000..5239d869 --- /dev/null +++ b/accel-pppd/libnetlink/genl.h @@ -0,0 +1,6 @@ +#ifndef __GENL_H +#define __GENL_H + +int genl_resolve_mcg(const char *family, const char *name, int *fam_id); + +#endif diff --git a/accel-pppd/libnetlink/iputils.c b/accel-pppd/libnetlink/iputils.c new file mode 100644 index 00000000..0ae4b04c --- /dev/null +++ b/accel-pppd/libnetlink/iputils.c @@ -0,0 +1,376 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +//#include +//#include +#include + +#include "triton.h" +#include "log.h" + +#include "libnetlink.h" +#include "iputils.h" + +#include "memdebug.h" + +struct arg +{ + iplink_list_func func; + 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); + struct rtattr *tb[IFLA_MAX + 1]; + struct arg *a = arg; + + if (n->nlmsg_type != RTM_NEWLINK) + return 0; + + if (n->nlmsg_len < NLMSG_LENGTH(sizeof(*ifi))) + return -1; + + memset(tb, 0, sizeof(tb)); + parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), IFLA_PAYLOAD(n)); + + if (tb[IFLA_IFNAME] == NULL) + return 0; + + //printf("%i %s\n", ifi->ifi_index, RTA_DATA(tb[IFLA_IFNAME])); + + return a->func(ifi->ifi_index, ifi->ifi_flags, RTA_DATA(tb[IFLA_IFNAME]), a->arg); +} + +int __export iplink_list(iplink_list_func func, void *arg) +{ + struct rtnl_handle rth; + struct arg a = { .func = func, .arg = arg }; + + if (rtnl_open(&rth, 0)) { + log_emerg("iplink: cannot open rtnetlink\n"); + return -1; + } + + if (rtnl_wilddump_request(&rth, AF_PACKET, RTM_GETLINK) < 0) { + log_emerg("iplink: cannot send dump request\n"); + goto out_err; + } + + if (rtnl_dump_filter(&rth, store_nlmsg, &a, NULL, NULL) < 0) { + log_emerg("iplink: dump terminated\n"); + goto out_err; + } + + rtnl_close(&rth); + + return 0; + +out_err: + rtnl_close(&rth); + + return -1; +} + +int __export iplink_get_stats(int ifindex, struct rtnl_link_stats *stats) +{ + struct iplink_req { + struct nlmsghdr n; + struct ifinfomsg i; + char buf[4096]; + } req; + struct ifinfomsg *ifi; + int len; + struct rtattr *tb[IFLA_MAX + 1]; + + if (!rth) + open_rth(); + + if (!rth) + 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_GETLINK; + req.i.ifi_family = AF_PACKET; + req.i.ifi_index = ifindex; + + if (rtnl_talk(rth, &req.n, 0, 0, &req.n, NULL, NULL, 0) < 0) + return -1; + + if (req.n.nlmsg_type != RTM_NEWLINK) + return -1; + + ifi = NLMSG_DATA(&req.n); + + len = req.n.nlmsg_len; + + len -= NLMSG_LENGTH(sizeof(*ifi)); + if (len < 0) + return -1; + + parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len); + if (tb[IFLA_STATS]) + memcpy(stats, RTA_DATA(tb[IFLA_STATS]), sizeof(*stats)); + else + return -1; + + 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; +} + +int __export iprule_add(uint32_t addr, int table) +{ + 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; + req.n.nlmsg_type = RTM_NEWRULE; + req.i.rtm_family = AF_INET; + req.i.rtm_table = table < 256 ? table : RT_TABLE_UNSPEC; + req.i.rtm_scope = RT_SCOPE_UNIVERSE; + req.i.rtm_protocol = RTPROT_BOOT; + req.i.rtm_type = RTN_UNICAST; + req.i.rtm_src_len = 32; + + addattr32(&req.n, sizeof(req), FRA_SRC, addr); + if (table >= 256) + 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; +} + +int __export iprule_del(uint32_t addr, int table) +{ + 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; + req.n.nlmsg_type = RTM_DELRULE; + req.i.rtm_family = AF_INET; + req.i.rtm_table = table < 256 ? table : RT_TABLE_UNSPEC; + req.i.rtm_scope = RT_SCOPE_UNIVERSE; + req.i.rtm_protocol = RTPROT_BOOT; + req.i.rtm_type = RTN_UNICAST; + req.i.rtm_src_len = 32; + + addattr32(&req.n, sizeof(req), FRA_SRC, addr); + if (table >= 256) + 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; +} + + +static void init(void) +{ + pthread_key_create(&rth_key, free_rth); +} + +DEFINE_INIT(100, init); diff --git a/accel-pppd/libnetlink/iputils.h b/accel-pppd/libnetlink/iputils.h new file mode 100644 index 00000000..f9124343 --- /dev/null +++ b/accel-pppd/libnetlink/iputils.h @@ -0,0 +1,19 @@ +#ifndef __IPLINK_H +#define __IPLINK_H + +#include + +typedef int (*iplink_list_func)(int index, int flags, const char *name, void *arg); + +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); + +int iprule_add(uint32_t addr, int table); +int iprule_del(uint32_t addr, int table); +#endif diff --git a/accel-pppd/libnetlink/libnetlink.c b/accel-pppd/libnetlink/libnetlink.c new file mode 100644 index 00000000..4630b302 --- /dev/null +++ b/accel-pppd/libnetlink/libnetlink.c @@ -0,0 +1,639 @@ +/* + * libnetlink.c RTnetlink service routines. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Authors: Alexey Kuznetsov, + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "libnetlink.h" +#include "log.h" + +#define __export __attribute__((visibility("default"))) + +int rcvbuf = 1024 * 1024; + +void __export rtnl_close(struct rtnl_handle *rth) +{ + if (rth->fd >= 0) { + close(rth->fd); + rth->fd = -1; + } +} + +int __export rtnl_open_byproto(struct rtnl_handle *rth, unsigned subscriptions, + int protocol) +{ + socklen_t addr_len; + int sndbuf = 32768; + + memset(rth, 0, sizeof(*rth)); + + rth->fd = socket(AF_NETLINK, SOCK_RAW, protocol); + if (rth->fd < 0) { + log_error("libnetlink: ""Cannot open netlink socket: %s\n", strerror(errno)); + return -1; + } + + if (setsockopt(rth->fd,SOL_SOCKET,SO_SNDBUF,&sndbuf,sizeof(sndbuf)) < 0) { + log_error("libnetlink: ""SO_SNDBUF: %s\n", strerror(errno)); + return -1; + } + + if (setsockopt(rth->fd,SOL_SOCKET,SO_RCVBUF,&rcvbuf,sizeof(rcvbuf)) < 0) { + log_error("libnetlink: ""SO_RCVBUF: %s\n", strerror(errno)); + return -1; + } + + memset(&rth->local, 0, sizeof(rth->local)); + rth->local.nl_family = AF_NETLINK; + rth->local.nl_groups = subscriptions; + + if (bind(rth->fd, (struct sockaddr*)&rth->local, sizeof(rth->local)) < 0) { + log_error("libnetlink: ""Cannot bind netlink socket: %s\n", strerror(errno)); + return -1; + } + addr_len = sizeof(rth->local); + if (getsockname(rth->fd, (struct sockaddr*)&rth->local, &addr_len) < 0) { + log_error("libnetlink: ""Cannot getsockname: %s\n", strerror(errno)); + return -1; + } + if (addr_len != sizeof(rth->local)) { + log_error("libnetlink: ""Wrong address length %d\n", addr_len); + return -1; + } + if (rth->local.nl_family != AF_NETLINK) { + log_error("libnetlink: ""Wrong address family %d\n", rth->local.nl_family); + return -1; + } + rth->seq = time(NULL); + return 0; +} + +int __export rtnl_open(struct rtnl_handle *rth, unsigned subscriptions) +{ + return rtnl_open_byproto(rth, subscriptions, NETLINK_ROUTE); +} + +int __export rtnl_wilddump_request(struct rtnl_handle *rth, int family, int type) +{ + struct { + struct nlmsghdr nlh; + struct rtgenmsg g; + } req; + + memset(&req, 0, sizeof(req)); + req.nlh.nlmsg_len = sizeof(req); + req.nlh.nlmsg_type = type; + req.nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST; + req.nlh.nlmsg_pid = 0; + req.nlh.nlmsg_seq = rth->dump = ++rth->seq; + req.g.rtgen_family = family; + + return send(rth->fd, (void*)&req, sizeof(req), 0); +} + +int __export rtnl_send(struct rtnl_handle *rth, const char *buf, int len) +{ + return send(rth->fd, buf, len, 0); +} + +int __export rtnl_send_check(struct rtnl_handle *rth, const char *buf, int len) +{ + struct nlmsghdr *h; + int status; + char resp[1024]; + + status = send(rth->fd, buf, len, 0); + if (status < 0) + return status; + + /* Check for immediate errors */ + status = recv(rth->fd, resp, sizeof(resp), MSG_DONTWAIT|MSG_PEEK); + if (status < 0) { + if (errno == EAGAIN) + return 0; + return -1; + } + + for (h = (struct nlmsghdr *)resp; NLMSG_OK(h, status); + h = NLMSG_NEXT(h, status)) { + if (h->nlmsg_type == NLMSG_ERROR) { + struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h); + if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr))) + log_error("libnetlink: ""ERROR truncated\n"); + else + errno = -err->error; + return -1; + } + } + + return 0; +} + +int __export rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len) +{ + struct nlmsghdr nlh; + struct sockaddr_nl nladdr; + struct iovec iov[2] = { + { .iov_base = &nlh, .iov_len = sizeof(nlh) }, + { .iov_base = req, .iov_len = len } + }; + struct msghdr msg = { + .msg_name = &nladdr, + .msg_namelen = sizeof(nladdr), + .msg_iov = iov, + .msg_iovlen = 2, + }; + + memset(&nladdr, 0, sizeof(nladdr)); + nladdr.nl_family = AF_NETLINK; + + nlh.nlmsg_len = NLMSG_LENGTH(len); + nlh.nlmsg_type = type; + nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST; + nlh.nlmsg_pid = 0; + nlh.nlmsg_seq = rth->dump = ++rth->seq; + + return sendmsg(rth->fd, &msg, 0); +} + +int __export rtnl_dump_filter_l(struct rtnl_handle *rth, + const struct rtnl_dump_filter_arg *arg) +{ + struct sockaddr_nl nladdr; + struct iovec iov; + struct msghdr msg = { + .msg_name = &nladdr, + .msg_namelen = sizeof(nladdr), + .msg_iov = &iov, + .msg_iovlen = 1, + }; + char buf[16384]; + + iov.iov_base = buf; + while (1) { + int status; + const struct rtnl_dump_filter_arg *a; + int found_done = 0; + int msglen = 0; + + iov.iov_len = sizeof(buf); + status = recvmsg(rth->fd, &msg, 0); + + if (status < 0) { + if (errno == EINTR || errno == EAGAIN) + continue; + log_error("libnetlink: ""netlink receive error %s (%d)\n", + strerror(errno), errno); + return -1; + } + + if (status == 0) { + log_error("libnetlink: ""EOF on netlink\n"); + return -1; + } + + for (a = arg; a->filter; a++) { + struct nlmsghdr *h = (struct nlmsghdr*)buf; + msglen = status; + + while (NLMSG_OK(h, msglen)) { + int err; + + if (nladdr.nl_pid != 0 || + h->nlmsg_pid != rth->local.nl_pid || + h->nlmsg_seq != rth->dump) { + if (a->junk) { + err = a->junk(&nladdr, h, + a->arg2); + if (err < 0) + return err; + } + goto skip_it; + } + + if (h->nlmsg_type == NLMSG_DONE) { + found_done = 1; + break; /* process next filter */ + } + if (h->nlmsg_type == NLMSG_ERROR) { + struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h); + if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr))) { + fprintf(stderr, + "ERROR truncated\n"); + } else { + errno = -err->error; + log_error("libnetlink: ""RTNETLINK answers: %s\n", strerror(errno)); + } + return -1; + } + err = a->filter(&nladdr, h, a->arg1); + if (err < 0) + return err; + +skip_it: + h = NLMSG_NEXT(h, msglen); + } + } + + if (found_done) + return 0; + + if (msg.msg_flags & MSG_TRUNC) { + log_error("libnetlink: ""Message truncated\n"); + continue; + } + if (msglen) { + log_error("libnetlink: ""!!!Remnant of size %d\n", msglen); + exit(1); + } + } +} + +int __export rtnl_dump_filter(struct rtnl_handle *rth, + rtnl_filter_t filter, + void *arg1, + rtnl_filter_t junk, + void *arg2) +{ + const struct rtnl_dump_filter_arg a[2] = { + { .filter = filter, .arg1 = arg1, .junk = junk, .arg2 = arg2 }, + { .filter = NULL, .arg1 = NULL, .junk = NULL, .arg2 = NULL } + }; + + return rtnl_dump_filter_l(rth, a); +} + +int __export rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, + unsigned groups, struct nlmsghdr *answer, + rtnl_filter_t junk, + void *jarg, int ignore_einval) +{ + int status; + unsigned seq; + struct nlmsghdr *h; + struct sockaddr_nl nladdr; + struct iovec iov = { + .iov_base = (void*) n, + .iov_len = n->nlmsg_len + }; + struct msghdr msg = { + .msg_name = &nladdr, + .msg_namelen = sizeof(nladdr), + .msg_iov = &iov, + .msg_iovlen = 1, + }; + char buf[16384]; + + memset(&nladdr, 0, sizeof(nladdr)); + nladdr.nl_family = AF_NETLINK; + nladdr.nl_pid = peer; + nladdr.nl_groups = groups; + + n->nlmsg_seq = seq = ++rtnl->seq; + + if (answer == NULL) + n->nlmsg_flags |= NLM_F_ACK; + + status = sendmsg(rtnl->fd, &msg, 0); + + if (status < 0) { + log_error("libnetlink: ""Cannot talk to rtnetlink: %s\n", strerror(errno)); + return -1; + } + + memset(buf,0,sizeof(buf)); + + iov.iov_base = buf; + + while (1) { + iov.iov_len = sizeof(buf); + status = recvmsg(rtnl->fd, &msg, 0); + + if (status < 0) { + if (errno == EINTR || errno == EAGAIN) + continue; + log_error("libnetlink: ""netlink receive error %s (%d)\n", + strerror(errno), errno); + return -1; + } + if (status == 0) { + log_error("libnetlink: ""EOF on netlink\n"); + return -1; + } + if (msg.msg_namelen != sizeof(nladdr)) { + log_error("libnetlink: ""sender address length == %d\n", msg.msg_namelen); + exit(1); + } + for (h = (struct nlmsghdr*)buf; status >= sizeof(*h); ) { + int err; + int len = h->nlmsg_len; + int l = len - sizeof(*h); + + if (l<0 || len>status) { + if (msg.msg_flags & MSG_TRUNC) { + log_error("libnetlink: ""Truncated message\n"); + return -1; + } + log_error("libnetlink: ""!!!malformed message: len=%d\n", len); + exit(1); + } + + if (nladdr.nl_pid != peer || + h->nlmsg_pid != rtnl->local.nl_pid || + h->nlmsg_seq != seq) { + if (junk) { + err = junk(&nladdr, h, jarg); + if (err < 0) + return err; + } + /* Don't forget to skip that message. */ + status -= NLMSG_ALIGN(len); + h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len)); + continue; + } + + if (h->nlmsg_type == NLMSG_ERROR) { + struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h); + if (l < sizeof(struct nlmsgerr)) { + log_error("libnetlink: ""ERROR truncated\n"); + } else { + errno = -err->error; + if (errno == 0 || (errno == EINVAL && ignore_einval)) { + if (answer) + memcpy(answer, h, h->nlmsg_len); + return 0; + } + log_error("libnetlink: ""RTNETLINK answers: %s\n", strerror(errno)); + } + return -1; + } + if (answer) { + memcpy(answer, h, h->nlmsg_len); + return 0; + } + + log_error("libnetlink: ""Unexpected reply!!!\n"); + + status -= NLMSG_ALIGN(len); + h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len)); + } + if (msg.msg_flags & MSG_TRUNC) { + log_error("libnetlink: ""Message truncated\n"); + continue; + } + if (status) { + log_error("libnetlink: ""!!!Remnant of size %d\n", status); + exit(1); + } + } +} + +int __export rtnl_listen(struct rtnl_handle *rtnl, + rtnl_filter_t handler, + void *jarg) +{ + int status; + struct nlmsghdr *h; + struct sockaddr_nl nladdr; + struct iovec iov; + struct msghdr msg = { + .msg_name = &nladdr, + .msg_namelen = sizeof(nladdr), + .msg_iov = &iov, + .msg_iovlen = 1, + }; + char buf[8192]; + + memset(&nladdr, 0, sizeof(nladdr)); + nladdr.nl_family = AF_NETLINK; + nladdr.nl_pid = 0; + nladdr.nl_groups = 0; + + iov.iov_base = buf; + while (1) { + iov.iov_len = sizeof(buf); + status = recvmsg(rtnl->fd, &msg, 0); + + if (status < 0) { + if (errno == EINTR || errno == EAGAIN) + continue; + log_error("libnetlink: ""netlink receive error %s (%d)\n", + strerror(errno), errno); + if (errno == ENOBUFS) + continue; + return -1; + } + if (status == 0) { + log_error("libnetlink: ""EOF on netlink\n"); + return -1; + } + if (msg.msg_namelen != sizeof(nladdr)) { + log_error("libnetlink: ""Sender address length == %d\n", msg.msg_namelen); + exit(1); + } + for (h = (struct nlmsghdr*)buf; status >= sizeof(*h); ) { + int err; + int len = h->nlmsg_len; + int l = len - sizeof(*h); + + if (l<0 || len>status) { + if (msg.msg_flags & MSG_TRUNC) { + log_error("libnetlink: ""Truncated message\n"); + return -1; + } + log_error("libnetlink: ""!!!malformed message: len=%d\n", len); + exit(1); + } + + err = handler(&nladdr, h, jarg); + if (err < 0) + return err; + + status -= NLMSG_ALIGN(len); + h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len)); + } + if (msg.msg_flags & MSG_TRUNC) { + log_error("libnetlink: ""Message truncated\n"); + continue; + } + if (status) { + log_error("libnetlink: ""!!!Remnant of size %d\n", status); + exit(1); + } + } +} + +int __export addattr32(struct nlmsghdr *n, int maxlen, int type, __u32 data) +{ + int len = RTA_LENGTH(4); + struct rtattr *rta; + if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen) { + fprintf(stderr,"addattr32: Error! max allowed bound %d exceeded\n",maxlen); + return -1; + } + rta = NLMSG_TAIL(n); + rta->rta_type = type; + rta->rta_len = len; + memcpy(RTA_DATA(rta), &data, 4); + n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + len; + return 0; +} + +int __export addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data, + int alen) +{ + int len = RTA_LENGTH(alen); + struct rtattr *rta; + + if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) { + log_error("libnetlink: ""addattr_l ERROR: message exceeded bound of %d\n",maxlen); + return -1; + } + rta = NLMSG_TAIL(n); + rta->rta_type = type; + rta->rta_len = len; + memcpy(RTA_DATA(rta), data, alen); + n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len); + return 0; +} + +int __export addraw_l(struct nlmsghdr *n, int maxlen, const void *data, int len) +{ + if (NLMSG_ALIGN(n->nlmsg_len) + NLMSG_ALIGN(len) > maxlen) { + log_error("libnetlink: ""addraw_l ERROR: message exceeded bound of %d\n",maxlen); + return -1; + } + + memcpy(NLMSG_TAIL(n), data, len); + memset((void *) NLMSG_TAIL(n) + len, 0, NLMSG_ALIGN(len) - len); + n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + NLMSG_ALIGN(len); + return 0; +} + +struct rtattr __export *addattr_nest(struct nlmsghdr *n, int maxlen, int type) +{ + struct rtattr *nest = NLMSG_TAIL(n); + + addattr_l(n, maxlen, type, NULL, 0); + return nest; +} + +int __export addattr_nest_end(struct nlmsghdr *n, struct rtattr *nest) +{ + nest->rta_len = (void *)NLMSG_TAIL(n) - (void *)nest; + return n->nlmsg_len; +} + +struct rtattr __export *addattr_nest_compat(struct nlmsghdr *n, int maxlen, int type, + const void *data, int len) +{ + struct rtattr *start = NLMSG_TAIL(n); + + addattr_l(n, maxlen, type, data, len); + addattr_nest(n, maxlen, type); + return start; +} + +int __export addattr_nest_compat_end(struct nlmsghdr *n, struct rtattr *start) +{ + struct rtattr *nest = (void *)start + NLMSG_ALIGN(start->rta_len); + + start->rta_len = (void *)NLMSG_TAIL(n) - (void *)start; + addattr_nest_end(n, nest); + return n->nlmsg_len; +} + +int __export rta_addattr32(struct rtattr *rta, int maxlen, int type, __u32 data) +{ + int len = RTA_LENGTH(4); + struct rtattr *subrta; + + if (RTA_ALIGN(rta->rta_len) + len > maxlen) { + fprintf(stderr,"rta_addattr32: Error! max allowed bound %d exceeded\n",maxlen); + return -1; + } + subrta = (struct rtattr*)(((char*)rta) + RTA_ALIGN(rta->rta_len)); + subrta->rta_type = type; + subrta->rta_len = len; + memcpy(RTA_DATA(subrta), &data, 4); + rta->rta_len = NLMSG_ALIGN(rta->rta_len) + len; + return 0; +} + +int __export rta_addattr_l(struct rtattr *rta, int maxlen, int type, + const void *data, int alen) +{ + struct rtattr *subrta; + int len = RTA_LENGTH(alen); + + if (RTA_ALIGN(rta->rta_len) + RTA_ALIGN(len) > maxlen) { + fprintf(stderr,"rta_addattr_l: Error! max allowed bound %d exceeded\n",maxlen); + return -1; + } + subrta = (struct rtattr*)(((char*)rta) + RTA_ALIGN(rta->rta_len)); + subrta->rta_type = type; + subrta->rta_len = len; + memcpy(RTA_DATA(subrta), data, alen); + rta->rta_len = NLMSG_ALIGN(rta->rta_len) + RTA_ALIGN(len); + return 0; +} + +int __export parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len) +{ + memset(tb, 0, sizeof(struct rtattr *) * (max + 1)); + while (RTA_OK(rta, len)) { + if ((rta->rta_type <= max) && (!tb[rta->rta_type])) + tb[rta->rta_type] = rta; + rta = RTA_NEXT(rta,len); + } + if (len) + log_error("libnetlink: ""!!!Deficit %d, rta_len=%d\n", len, rta->rta_len); + return 0; +} + +int parse_rtattr_byindex(struct rtattr *tb[], int max, struct rtattr *rta, int len) +{ + int i = 0; + + memset(tb, 0, sizeof(struct rtattr *) * max); + while (RTA_OK(rta, len)) { + if (rta->rta_type <= max && i < max) + tb[i++] = rta; + rta = RTA_NEXT(rta,len); + } + if (len) + log_error("libnetlink: ""!!!Deficit %d, rta_len=%d\n", len, rta->rta_len); + return i; +} + +int __parse_rtattr_nested_compat(struct rtattr *tb[], int max, struct rtattr *rta, + int len) +{ + if (RTA_PAYLOAD(rta) < len) + return -1; + if (RTA_PAYLOAD(rta) >= RTA_ALIGN(len) + sizeof(struct rtattr)) { + rta = RTA_DATA(rta) + RTA_ALIGN(len); + return parse_rtattr_nested(tb, max, rta); + } + memset(tb, 0, sizeof(struct rtattr *) * (max + 1)); + return 0; +} diff --git a/accel-pppd/libnetlink/libnetlink.h b/accel-pppd/libnetlink/libnetlink.h new file mode 100644 index 00000000..f68bf8a1 --- /dev/null +++ b/accel-pppd/libnetlink/libnetlink.h @@ -0,0 +1,118 @@ +#ifndef __LIBNETLINK_H__ +#define __LIBNETLINK_H__ 1 + +#include +#include +#include +#include +#include +#include + +#define TCA_BUF_MAX 64*1024 +#define MAX_MSG 16384 + +struct rtnl_handle +{ + int fd; + struct sockaddr_nl local; + struct sockaddr_nl peer; + __u32 seq; + __u32 dump; +}; + +extern int rcvbuf; + +extern int rtnl_open(struct rtnl_handle *rth, unsigned subscriptions); +extern int rtnl_open_byproto(struct rtnl_handle *rth, unsigned subscriptions, int protocol); +extern void rtnl_close(struct rtnl_handle *rth); +extern int rtnl_wilddump_request(struct rtnl_handle *rth, int fam, int type); +extern int rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len); + +typedef int (*rtnl_filter_t)(const struct sockaddr_nl *, + struct nlmsghdr *n, void *); + +struct rtnl_dump_filter_arg +{ + rtnl_filter_t filter; + void *arg1; + rtnl_filter_t junk; + void *arg2; +}; + +extern int rtnl_dump_filter_l(struct rtnl_handle *rth, + const struct rtnl_dump_filter_arg *arg); +extern int rtnl_dump_filter(struct rtnl_handle *rth, rtnl_filter_t filter, + void *arg1, + rtnl_filter_t junk, + void *arg2); + +extern int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, + unsigned groups, struct nlmsghdr *answer, + rtnl_filter_t junk, + void *jarg, int ignore_einval); +extern int rtnl_send(struct rtnl_handle *rth, const char *buf, int); +extern int rtnl_send_check(struct rtnl_handle *rth, const char *buf, int); + +extern int addattr32(struct nlmsghdr *n, int maxlen, int type, __u32 data); +extern int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data, int alen); +extern int addraw_l(struct nlmsghdr *n, int maxlen, const void *data, int len); +extern struct rtattr *addattr_nest(struct nlmsghdr *n, int maxlen, int type); +extern int addattr_nest_end(struct nlmsghdr *n, struct rtattr *nest); +extern struct rtattr *addattr_nest_compat(struct nlmsghdr *n, int maxlen, int type, const void *data, int len); +extern int addattr_nest_compat_end(struct nlmsghdr *n, struct rtattr *nest); +extern int rta_addattr32(struct rtattr *rta, int maxlen, int type, __u32 data); +extern int rta_addattr_l(struct rtattr *rta, int maxlen, int type, const void *data, int alen); + +extern int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len); +extern int parse_rtattr_byindex(struct rtattr *tb[], int max, struct rtattr *rta, int len); +extern int __parse_rtattr_nested_compat(struct rtattr *tb[], int max, struct rtattr *rta, int len); + +#define parse_rtattr_nested(tb, max, rta) \ + (parse_rtattr((tb), (max), RTA_DATA(rta), RTA_PAYLOAD(rta))) + +#define parse_rtattr_nested_compat(tb, max, rta, data, len) \ +({ data = RTA_PAYLOAD(rta) >= len ? RTA_DATA(rta) : NULL; \ + __parse_rtattr_nested_compat(tb, max, rta, len); }) + +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))) + +#ifndef IFA_RTA +#define IFA_RTA(r) \ + ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifaddrmsg)))) +#endif +#ifndef IFA_PAYLOAD +#define IFA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifaddrmsg)) +#endif + +#ifndef IFLA_RTA +#define IFLA_RTA(r) \ + ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifinfomsg)))) +#endif +#ifndef IFLA_PAYLOAD +#define IFLA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifinfomsg)) +#endif + +#ifndef NDA_RTA +#define NDA_RTA(r) \ + ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg)))) +#endif +#ifndef NDA_PAYLOAD +#define NDA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ndmsg)) +#endif + +#ifndef NDTA_RTA +#define NDTA_RTA(r) \ + ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ndtmsg)))) +#endif +#ifndef NDTA_PAYLOAD +#define NDTA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ndtmsg)) +#endif + +#endif /* __LIBNETLINK_H__ */ + diff --git a/accel-pppd/logs/log_file.c b/accel-pppd/logs/log_file.c index 0bba405b..e4e5122b 100644 --- a/accel-pppd/logs/log_file.c +++ b/accel-pppd/logs/log_file.c @@ -200,7 +200,6 @@ overrun: static void send_next_chunk(void) { struct log_file_t *lf; - int n; spin_lock(&lf_queue_lock); if (list_empty(&lf_queue)) { @@ -210,7 +209,6 @@ static void send_next_chunk(void) } lf = list_entry(lf_queue.next, typeof(*lf), entry); - n = log_file->entry.next == NULL; list_del(&lf->entry); spin_unlock(&lf_queue_lock); -- cgit v1.2.3 From c8b3efbc63c25b6c5e22e6a235e1fc501bb36ffc Mon Sep 17 00:00:00 2001 From: Kozlov Dmitry Date: Thu, 6 Sep 2012 09:05:09 +0400 Subject: 1.7.2 release * fixed connection dropping when mppe=prefer and user rejects ccp * improved tunnel termination (l2tp) * fixed sending incorrect magic in lcp echo request * fixed various typos * gather interface statistics via netlink --- accel-pppd/CMakeLists.txt | 2 +- cmake/cpack.cmake | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/accel-pppd/CMakeLists.txt b/accel-pppd/CMakeLists.txt index fb44b503..11df04fc 100644 --- a/accel-pppd/CMakeLists.txt +++ b/accel-pppd/CMakeLists.txt @@ -10,7 +10,7 @@ IF (EXISTS ${CMAKE_HOME_DIRECTORY}/.git AND NOT DEFINED IGNORE_GIT) ) STRING(STRIP ${ACCEL_PPP_VERSION} ACCEL_PPP_VERSION) ELSE (EXISTS ${CMAKE_HOME_DIRECTORY}/.git AND NOT DEFINED IGNORE_GIT) - SET (ACCEL_PPP_VERSION 1.7.1) + SET (ACCEL_PPP_VERSION 1.7.2) ENDIF (EXISTS ${CMAKE_HOME_DIRECTORY}/.git AND NOT DEFINED IGNORE_GIT) ADD_DEFINITIONS(-DACCEL_PPP_VERSION="${ACCEL_PPP_VERSION}") diff --git a/cmake/cpack.cmake b/cmake/cpack.cmake index 117786a8..25893ea8 100644 --- a/cmake/cpack.cmake +++ b/cmake/cpack.cmake @@ -2,7 +2,7 @@ INCLUDE(InstallRequiredSystemLibraries) SET(CPACK_PACKAGE_VERSION_MAJOR "1") SET(CPACK_PACKAGE_VERSION_MINOR "7") -SET(CPACK_PACKAGE_VERSION_PATCH "1") +SET(CPACK_PACKAGE_VERSION_PATCH "2") SET(CPACK_PACKAGE_NAME "accel-ppp") SET(CPACK_PACKAGE_CONTACT "Dmitry Kozlov ") -- cgit v1.2.3 From cbd29e841d4a90cf93515ba8341a8bbdbd4dea38 Mon Sep 17 00:00:00 2001 From: Kozlov Dmitry Date: Fri, 7 Sep 2012 15:52:11 +0400 Subject: l2tp: send ZLB when duplicate packet is received and retransmit queue is empty --- accel-pppd/ctrl/l2tp/l2tp.c | 4 ++-- accel-pppd/radius/req.c | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/accel-pppd/ctrl/l2tp/l2tp.c b/accel-pppd/ctrl/l2tp/l2tp.c index f6df3af7..3a7c15f5 100644 --- a/accel-pppd/ctrl/l2tp/l2tp.c +++ b/accel-pppd/ctrl/l2tp/l2tp.c @@ -961,10 +961,10 @@ static int l2tp_conn_read(struct triton_md_handler_t *h) } else { if (ntohs(pack->hdr.Ns) < conn->Nr + 1 || (ntohs(pack->hdr.Ns > 32767 && conn->Nr + 1 < 32767))) { log_ppp_debug("duplicate packet\n"); - //if (l2tp_send_ZLB(conn)) - // goto drop; if (!list_empty(&conn->send_queue)) l2tp_retransmit(conn); + else if (l2tp_send_ZLB(conn)) + goto drop; } else log_ppp_debug("reordered packet\n"); l2tp_packet_free(pack); diff --git a/accel-pppd/radius/req.c b/accel-pppd/radius/req.c index cc0b261a..1294e64f 100644 --- a/accel-pppd/radius/req.c +++ b/accel-pppd/radius/req.c @@ -67,6 +67,8 @@ struct rad_req_t *rad_req_alloc(struct radius_pd_t *rpd, int code, const char *u goto out_err; if (rad_packet_add_val(req->pack, NULL, "NAS-Port-Type", "Virtual")) goto out_err; + if (rad_packet_add_int(req->pack, NULL, "Tunnel-Type", rpd->ppp->ctrl->type)) + goto out_err; if (rad_packet_add_val(req->pack, NULL, "Service-Type", "Framed-User")) goto out_err; if (rad_packet_add_val(req->pack, NULL, "Framed-Protocol", "PPP")) -- cgit v1.2.3