diff options
author | Dmitry Kozlov <xeb@mail.ru> | 2014-12-01 16:24:11 +0300 |
---|---|---|
committer | Dmitry Kozlov <xeb@mail.ru> | 2014-12-01 16:39:35 +0300 |
commit | 3cc7fd0165e096be25761710b66b44fda9d09190 (patch) | |
tree | b6eef91b863c78858be060902a515b26a7b2bf4b /accel-pppd | |
parent | ebc0ec740280efd2ea7f22abbb84eda53ab06632 (diff) | |
download | accel-ppp-3cc7fd0165e096be25761710b66b44fda9d09190.tar.gz accel-ppp-3cc7fd0165e096be25761710b66b44fda9d09190.zip |
ipv6: if assigned prefix is <= 64 add it as address else add it as route
Diffstat (limited to 'accel-pppd')
-rw-r--r-- | accel-pppd/ifcfg.c | 33 | ||||
-rw-r--r-- | accel-pppd/ipdb.h | 5 | ||||
-rw-r--r-- | accel-pppd/ipv6/dhcpv6.c | 17 | ||||
-rw-r--r-- | accel-pppd/ipv6/nd.c | 57 | ||||
-rw-r--r-- | accel-pppd/libnetlink/iputils.c | 116 | ||||
-rw-r--r-- | accel-pppd/libnetlink/iputils.h | 1 |
6 files changed, 142 insertions, 87 deletions
diff --git a/accel-pppd/ifcfg.c b/accel-pppd/ifcfg.c index 26926fa..685e1de 100644 --- a/accel-pppd/ifcfg.c +++ b/accel-pppd/ifcfg.c @@ -25,7 +25,7 @@ struct in6_ifreq { struct in6_addr ifr6_addr; __u32 ifr6_prefixlen; - int ifr6_ifindex; + int ifr6_ifindex; }; static void devconf(struct ap_session *ses, const char *attr, const char *val) @@ -65,7 +65,7 @@ void ap_session_ifup(struct ap_session *ses) _free(ses->ifname_rename); ses->ifname_rename = NULL; } - + triton_event_fire(EV_SES_ACCT_START, ses); if (ses->stop_time) @@ -119,17 +119,17 @@ void __export ap_session_accounting_started(struct ap_session *ses) addr.sin_family = AF_INET; addr.sin_addr.s_addr = ses->ipv4->addr; memcpy(&ifr.ifr_addr, &addr, sizeof(addr)); - + if (ioctl(sock_fd, SIOCSIFADDR, &ifr)) log_ppp_error("failed to set IPv4 address: %s\n", strerror(errno)); - + /*if (ses->ctrl->type == CTRL_TYPE_IPOE) { addr.sin_addr.s_addr = 0xffffffff; memcpy(&ifr.ifr_netmask, &addr, sizeof(addr)); if (ioctl(sock_fd, SIOCSIFNETMASK, &ifr)) log_ppp_error("failed to set IPv4 nask: %s\n", strerror(errno)); }*/ - + addr.sin_addr.s_addr = ses->ipv4->peer_addr; /*if (ses->ctrl->type == CTRL_TYPE_IPOE) { @@ -142,7 +142,7 @@ void __export ap_session_accounting_started(struct ap_session *ses) log_ppp_error("failed to add route: %s\n", strerror(errno)); } else*/ { memcpy(&ifr.ifr_dstaddr, &addr, sizeof(addr)); - + if (ioctl(sock_fd, SIOCSIFDSTADDR, &ifr)) log_ppp_error("failed to set peer IPv4 address: %s\n", strerror(errno)); } @@ -154,7 +154,7 @@ void __export ap_session_accounting_started(struct ap_session *ses) devconf(ses, "forwarding", "1"); memset(&ifr6, 0, sizeof(ifr6)); - + if (ses->ctrl->ppp) { ifr6.ifr6_addr.s6_addr32[0] = htons(0xfe80); *(uint64_t *)(ifr6.ifr6_addr.s6_addr + 8) = ses->ipv6->intf_id; @@ -164,17 +164,18 @@ void __export ap_session_accounting_started(struct ap_session *ses) if (ioctl(sock6_fd, SIOCSIFADDR, &ifr6)) log_ppp_error("faild to set LL IPv6 address: %s\n", strerror(errno)); } - + list_for_each_entry(a, &ses->ipv6->addr_list, entry) { + a->installed = 0; /*if (a->prefix_len < 128) { build_addr(a, ses->ipv6->intf_id, &ifr6.ifr6_addr); ifr6.ifr6_prefixlen = a->prefix_len; if (ioctl(sock6_fd, SIOCSIFADDR, &ifr6)) log_ppp_error("failed to add IPv6 address: %s\n", strerror(errno)); - } else*/ + } else if (ip6route_add(ses->ifindex, &a->addr, a->prefix_len, 0)) - log_ppp_error("failed to add IPv6 route: %s\n", strerror(errno)); + log_ppp_error("failed to add IPv6 route: %s\n", strerror(errno));*/ } } @@ -195,7 +196,7 @@ void __export ap_session_accounting_started(struct ap_session *ses) if (ioctl(ppp->unit_fd, PPPIOCSNPMODE, &np)) log_ppp_error("failed to set NP (IPv4) mode: %s\n", strerror(errno)); } - + if (ses->ipv6) { np.protocol = PPP_IPV6; np.mode = NPMODE_PASS; @@ -208,7 +209,7 @@ void __export ap_session_accounting_started(struct ap_session *ses) } #endif } - + ses->ctrl->started(ses); triton_event_fire(EV_SES_STARTED, ses); @@ -244,7 +245,7 @@ void __export ap_session_ifdown(struct ap_session *ses) ifr6.ifr6_ifindex = ses->ifindex; ioctl(sock6_fd, SIOCDIFADDR, &ifr6); - + list_for_each_entry(a, &ses->ipv6->addr_list, entry) { if (a->prefix_len == 128) continue; @@ -263,7 +264,7 @@ int __export ap_session_rename(struct ap_session *ses, const char *ifname, int l if (len == -1) len = strlen(ifname); - + if (len >= IFNAMSIZ - 1) { log_ppp_warn("cannot rename interface (name is too long)\n"); return -1; @@ -272,7 +273,7 @@ int __export ap_session_rename(struct ap_session *ses, const char *ifname, int l strcpy(ifr.ifr_name, ses->ifname); memcpy(ifr.ifr_newname, ifname, len); ifr.ifr_newname[len] = 0; - + if (ioctl(sock_fd, SIOCSIFNAME, &ifr)) { if (!ses->ifname_rename) ses->ifname_rename = _strdup(ifr.ifr_newname); @@ -281,7 +282,7 @@ int __export ap_session_rename(struct ap_session *ses, const char *ifname, int l return -1; } } else { - log_ppp_info2("rename interface to '%s'\n", ifr.ifr_newname); + log_ppp_info2("rename interface to '%s'\n", ifr.ifr_newname); memcpy(ses->ifname, ifname, len); ses->ifname[len] = 0; } diff --git a/accel-pppd/ipdb.h b/accel-pppd/ipdb.h index 7f61b43..d461c88 100644 --- a/accel-pppd/ipdb.h +++ b/accel-pppd/ipdb.h @@ -1,8 +1,6 @@ #ifndef IPDB_H #define IPDB_H -#include <netinet/in.h> - #include "ppp.h" #include "list.h" @@ -20,6 +18,7 @@ struct ipv6db_addr_t struct in6_addr addr; int prefix_len; int flag_auto:1; + int installed:1; }; struct ipv6db_item_t @@ -40,7 +39,7 @@ struct ipv6db_prefix_t struct ipdb_t { struct list_head entry; - + struct ipv4db_item_t *(*get_ipv4)(struct ap_session *ses); void (*put_ipv4)(struct ap_session *ses, struct ipv4db_item_t *); diff --git a/accel-pppd/ipv6/dhcpv6.c b/accel-pppd/ipv6/dhcpv6.c index 62f20bb..3f9df71 100644 --- a/accel-pppd/ipv6/dhcpv6.c +++ b/accel-pppd/ipv6/dhcpv6.c @@ -21,11 +21,12 @@ #include "ppp.h" #include "ipdb.h" #include "events.h" - -#include "memdebug.h" +#include "iputils.h" #include "dhcpv6.h" +#include "memdebug.h" + #define BUF_SIZE 65536 #define MAX_DNS_COUNT 3 @@ -295,6 +296,18 @@ static void dhcpv6_send_reply(struct dhcpv6_packet *req, struct dhcpv6_pd *pd, i ia_addr->pref_lifetime = htonl(conf_pref_lifetime); ia_addr->valid_lifetime = htonl(conf_valid_lifetime); + + if (a->installed) { + if (a->prefix_len > 64) + ip6route_add(ses->ifindex, &a->addr, a->prefix_len, 0); + else { + struct in6_addr addr; + memcpy(addr.s6_addr, &a->addr, 8); + memcpy(addr.s6_addr + 8, &ses->ipv6->intf_id, 8); + ip6addr_add(ses->ifindex, &addr, a->prefix_len); + } + a->installed = 1; + } } list_for_each_entry(opt2, &opt->opt_list, entry) { diff --git a/accel-pppd/ipv6/nd.c b/accel-pppd/ipv6/nd.c index 1241380..19a3d7d 100644 --- a/accel-pppd/ipv6/nd.c +++ b/accel-pppd/ipv6/nd.c @@ -17,6 +17,7 @@ #include "events.h" #include "mempool.h" #include "ipdb.h" +#include "iputils.h" #include "memdebug.h" @@ -104,12 +105,12 @@ static void ipv6_nd_send_ra(struct ipv6_nd_handler_t *h, struct sockaddr_in6 *ad //struct nd_opt_mtu *mtu; struct ipv6db_addr_t *a; int i; - + if (!buf) { log_emerg("out of memory\n"); return; } - + if (!h->ses->ipv6) { triton_timer_del(&h->timer); return; @@ -119,12 +120,12 @@ static void ipv6_nd_send_ra(struct ipv6_nd_handler_t *h, struct sockaddr_in6 *ad adv->nd_ra_type = ND_ROUTER_ADVERT; adv->nd_ra_curhoplimit = conf_AdvCurHopLimit; adv->nd_ra_router_lifetime = htons(conf_AdvDefaultLifetime); - adv->nd_ra_flags_reserved = + adv->nd_ra_flags_reserved = (conf_AdvManagedFlag ? ND_RA_FLAG_MANAGED : 0) | (conf_AdvOtherConfigFlag ? ND_RA_FLAG_OTHER : 0); adv->nd_ra_reachable = htonl(conf_AdvReachableTime); adv->nd_ra_retransmit = htonl(conf_AdvRetransTimer); - + pinfo = (struct nd_opt_prefix_info *)(adv + 1); list_for_each_entry(a, &h->ses->ipv6->addr_list, entry) { memset(pinfo, 0, sizeof(*pinfo)); @@ -137,8 +138,16 @@ static void ipv6_nd_send_ra(struct ipv6_nd_handler_t *h, struct sockaddr_in6 *ad pinfo->nd_opt_pi_preferred_time = htonl(conf_AdvPrefixPreferredLifetime); memcpy(&pinfo->nd_opt_pi_prefix, &a->addr, 8); pinfo++; + + if (!a->installed) { + struct in6_addr addr; + memcpy(addr.s6_addr, &a->addr, 8); + memcpy(addr.s6_addr + 8, &h->ses->ipv6->intf_id, 8); + ip6addr_add(h->ses->ifindex, &addr, a->prefix_len); + a->installed = 1; + } } - + /*rinfo = (struct nd_opt_route_info_local *)pinfo; list_for_each_entry(a, &h->ses->ipv6->route_list, entry) { memset(rinfo, 0, sizeof(*rinfo)); @@ -163,7 +172,7 @@ static void ipv6_nd_send_ra(struct ipv6_nd_handler_t *h, struct sockaddr_in6 *ad } } else rdnss_addr = (struct in6_addr *)pinfo; - + if (conf_dnssl) { dnsslinfo = (struct nd_opt_dnssl_info_local *)rdnss_addr; memset(dnsslinfo, 0, sizeof(*dnsslinfo)); @@ -190,7 +199,7 @@ static void send_ra_timer(struct triton_timer_t *t) addr.sin6_family = AF_INET6; addr.sin6_addr.s6_addr32[0] = htonl(0xff020000); addr.sin6_addr.s6_addr32[3] = htonl(0x1); - addr.sin6_scope_id = h->ses->ifindex; + addr.sin6_scope_id = h->ses->ifindex; if (h->ra_sent == conf_init_ra) { h->timer.period = conf_MaxRtrAdvInterval * 1000; @@ -261,7 +270,7 @@ static int ipv6_nd_start(struct ap_session *ses) struct ipv6_nd_handler_t *h; sock = 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; @@ -283,7 +292,7 @@ static int ipv6_nd_start(struct ap_session *ses) 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))) { log_ppp_error("ipv6_nd: setsockopt(IPV6_MULTICAST_HOPS): %s\n", strerror(errno)); goto out_err; @@ -372,14 +381,14 @@ static void ev_ses_finishing(struct ap_session *ses) if (!h) return; - + if (h->timer.tpd) triton_timer_del(&h->timer); triton_md_unregister_handler(&h->hnd, 1); list_del(&h->pd.entry); - + _free(h); } @@ -393,19 +402,19 @@ static void add_dnssl(const char *val) n++; else n += 2; - + if (n > 255) { log_error("dnsv6: dnssl '%s' is too long\n", val); return; } - + if (!conf_dnssl) conf_dnssl = _malloc(n); else conf_dnssl = _realloc(conf_dnssl, conf_dnssl_size + n); - + buf = conf_dnssl + conf_dnssl_size; - + while (1) { ptr = strchr(val, '.'); if (!ptr) @@ -423,7 +432,7 @@ static void add_dnssl(const char *val) break; } } - + conf_dnssl_size += n; } @@ -431,12 +440,12 @@ static void load_dns(void) { struct conf_sect_t *s = conf_get_section("ipv6-dns"); struct conf_option_t *opt; - + if (!s) return; - + conf_dns_count = 0; - + if (conf_dnssl) _free(conf_dnssl); conf_dnssl = NULL; @@ -447,7 +456,7 @@ static void load_dns(void) add_dnssl(opt->val); continue; } - + if (!strcmp(opt->name, "lifetime")) { conf_rdnss_lifetime = atoi(opt->val); continue; @@ -473,10 +482,10 @@ static void load_config(void) opt = conf_get_opt("ipv6-nd", "MaxRtrAdvInterval"); if (opt) conf_MaxRtrAdvInterval = atoi(opt); - + conf_MinRtrAdvInterval = 0.33 * conf_MaxRtrAdvInterval; conf_AdvDefaultLifetime = 3 * conf_MaxRtrAdvInterval; - + conf_AdvManagedFlag = triton_module_loaded("ipv6_dhcp"); conf_AdvOtherConfigFlag = triton_module_loaded("ipv6_dhcp"); conf_AdvPrefixAutonomousFlag = !conf_AdvManagedFlag; @@ -532,7 +541,7 @@ static void load_config(void) opt = conf_get_opt("ipv6-nd", "AdvAutonomousFlag"); if (opt) conf_AdvPrefixAutonomousFlag = atoi(opt); - + load_dns(); } @@ -541,7 +550,7 @@ static void init(void) buf_pool = mempool_create(BUF_SIZE); load_config(); - + triton_event_register_handler(EV_CONFIG_RELOAD, (triton_event_func)load_config); triton_event_register_handler(EV_SES_STARTED, (triton_event_func)ev_ses_started); triton_event_register_handler(EV_SES_FINISHING, (triton_event_func)ev_ses_finishing); diff --git a/accel-pppd/libnetlink/iputils.c b/accel-pppd/libnetlink/iputils.c index fb85973..480f028 100644 --- a/accel-pppd/libnetlink/iputils.c +++ b/accel-pppd/libnetlink/iputils.c @@ -39,7 +39,7 @@ static void open_rth(void) if (!rth) return; - + memset(rth, 0, sizeof(*rth)); if (rtnl_open(rth, 0)) { @@ -78,7 +78,7 @@ static int store_nlmsg(const struct sockaddr_nl *who, struct nlmsghdr *n, void * 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); @@ -127,12 +127,12 @@ int __export iplink_get_stats(int ifindex, struct rtnl_link_stats *stats) if (!rth) open_rth(); - + if (!rth) return -1; memset(&req, 0, sizeof(req) - 4096); - + 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; @@ -158,10 +158,10 @@ int __export iplink_get_stats(int ifindex, struct rtnl_link_stats *stats) memcpy(stats, RTA_DATA(tb[IFLA_STATS]), sizeof(*stats)); else return -1; - + return 0; } - + int __export iplink_vlan_add(const char *ifname, int ifindex, int vid) { struct iplink_req { @@ -173,20 +173,20 @@ int __export iplink_vlan_add(const char *ifname, int ifindex, int vid) if (!rth) open_rth(); - + if (!rth) return -1; memset(&req, 0, sizeof(req) - 4096); - + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL; req.n.nlmsg_type = RTM_NEWLINK; req.i.ifi_family = AF_UNSPEC; - + addattr_l(&req.n, 4096, IFLA_LINK, &ifindex, 4); addattr_l(&req.n, 4096, IFLA_IFNAME, ifname, strlen(ifname)); - + linkinfo = NLMSG_TAIL(&req.n); addattr_l(&req.n, 4096, IFLA_LINKINFO, NULL, 0); addattr_l(&req.n, 4096, IFLA_INFO_KIND, "vlan", 4); @@ -195,12 +195,12 @@ int __export iplink_vlan_add(const char *ifname, int ifindex, int vid) addattr_l(&req.n, 4096, IFLA_INFO_DATA, NULL, 0); addattr_l(&req.n, 4096, IFLA_VLAN_ID, &vid, 2); data->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)data; - + 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; - + return 0; } @@ -215,18 +215,18 @@ int __export iplink_vlan_del(int ifindex) if (!rth) open_rth(); - + if (!rth) return -1; memset(&req, 0, sizeof(req) - 4096); - + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; req.n.nlmsg_type = RTM_DELLINK; req.i.ifi_family = AF_UNSPEC; req.i.ifi_index = ifindex; - + linkinfo = NLMSG_TAIL(&req.n); addattr_l(&req.n, 4096, IFLA_LINKINFO, NULL, 0); addattr_l(&req.n, 4096, IFLA_INFO_KIND, "vlan", 4); @@ -234,12 +234,12 @@ int __export iplink_vlan_del(int ifindex) /*data = NLMSG_TAIL(&req.n); addattr_l(&req.n, 4096, IFLA_VLAN_ID, &vid, 2); data->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)data;*/ - + 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; - + return 0; } @@ -253,12 +253,12 @@ int __export ipaddr_add(int ifindex, in_addr_t addr, int mask) if (!rth) open_rth(); - + if (!rth) return -1; memset(&req, 0, sizeof(req) - 4096); - + 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; @@ -270,7 +270,7 @@ int __export ipaddr_add(int ifindex, in_addr_t addr, int mask) if (rtnl_talk(rth, &req.n, 0, 0, NULL, NULL, NULL, 0) < 0) return -1; - + return 0; } @@ -284,12 +284,12 @@ int __export ipaddr_del(int ifindex, in_addr_t addr, int mask) if (!rth) open_rth(); - + if (!rth) return -1; memset(&req, 0, sizeof(req) - 4096); - + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)); req.n.nlmsg_flags = NLM_F_REQUEST; req.n.nlmsg_type = RTM_DELADDR; @@ -301,7 +301,7 @@ int __export ipaddr_del(int ifindex, in_addr_t addr, int mask) if (rtnl_talk(rth, &req.n, 0, 0, NULL, NULL, NULL, 0) < 0) return -1; - + return 0; } @@ -315,12 +315,12 @@ int __export iproute_add(int ifindex, in_addr_t src, in_addr_t dst, in_addr_t gw if (!rth) open_rth(); - + if (!rth) return -1; memset(&req, 0, sizeof(req) - 4096); - + 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; @@ -341,7 +341,7 @@ int __export iproute_add(int ifindex, in_addr_t src, in_addr_t dst, in_addr_t gw if (rtnl_talk(rth, &req.n, 0, 0, NULL, NULL, NULL, 0) < 0) return -1; - + return 0; } @@ -355,12 +355,12 @@ int __export iproute_del(int ifindex, in_addr_t dst, int proto) if (!rth) open_rth(); - + if (!rth) return -1; memset(&req, 0, sizeof(req) - 4096); - + 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; @@ -376,7 +376,7 @@ int __export iproute_del(int ifindex, in_addr_t dst, int proto) if (rtnl_talk(rth, &req.n, 0, 0, NULL, NULL, NULL, 0) < 0) return -1; - + return 0; } @@ -390,12 +390,12 @@ int __export ip6route_add(int ifindex, struct in6_addr *dst, int pref_len, int p if (!rth) open_rth(); - + if (!rth) return -1; memset(&req, 0, sizeof(req) - 4096); - + 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; @@ -411,11 +411,43 @@ int __export ip6route_add(int ifindex, struct in6_addr *dst, int pref_len, int p if (rtnl_talk(rth, &req.n, 0, 0, NULL, NULL, NULL, 0) < 0) return -1; - + return 0; } +int __export ip6addr_add(int ifindex, struct in6_addr *addr, int prefix_len) +{ + struct ipaddr_req { + struct nlmsghdr n; + struct ifaddrmsg i; + char buf[4096]; + } req; + + if (!rth) + open_rth(); + + if (!rth) + return -1; + + memset(&req, 0, sizeof(req) - 4096); + + 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_INET6; + req.i.ifa_index = ifindex; + req.i.ifa_prefixlen = prefix_len; + req.i.ifa_flags = IFA_F_NODAD; + + 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; + + return 0; +} + in_addr_t __export iproute_get(in_addr_t dst, in_addr_t *gw) { struct ipaddr_req { @@ -433,12 +465,12 @@ in_addr_t __export iproute_get(in_addr_t dst, in_addr_t *gw) if (!rth) open_rth(); - + if (!rth) return -1; memset(&req, 0, sizeof(req) - 4096); - + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); req.n.nlmsg_flags = NLM_F_REQUEST; req.n.nlmsg_type = RTM_GETROUTE; @@ -460,7 +492,7 @@ in_addr_t __export iproute_get(in_addr_t dst, in_addr_t *gw) r = NLMSG_DATA(&req.n); len = req.n.nlmsg_len; - + if (req.n.nlmsg_type != RTM_NEWROUTE) { log_error("failed to detect route to server (wrong netlink message type)"); goto out; @@ -473,7 +505,7 @@ in_addr_t __export iproute_get(in_addr_t dst, in_addr_t *gw) } parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len); - + if (tb[RTA_PREFSRC]) res = *(uint32_t *)RTA_DATA(tb[RTA_PREFSRC]); @@ -494,12 +526,12 @@ int __export iprule_add(uint32_t addr, int table) if (!rth) open_rth(); - + if (!rth) return -1; memset(&req, 0, sizeof(req) - 4096); - + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); req.n.nlmsg_flags = NLM_F_REQUEST; req.n.nlmsg_type = RTM_NEWRULE; @@ -516,7 +548,7 @@ int __export iprule_add(uint32_t addr, int table) if (rtnl_talk(rth, &req.n, 0, 0, NULL, NULL, NULL, 0) < 0) return -1; - + return 0; } @@ -530,12 +562,12 @@ int __export iprule_del(uint32_t addr, int table) if (!rth) open_rth(); - + if (!rth) return -1; memset(&req, 0, sizeof(req) - 4096); - + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); req.n.nlmsg_flags = NLM_F_REQUEST; req.n.nlmsg_type = RTM_DELRULE; @@ -552,7 +584,7 @@ int __export iprule_del(uint32_t addr, int table) if (rtnl_talk(rth, &req.n, 0, 0, NULL, NULL, NULL, 0) < 0) return -1; - + return 0; } diff --git a/accel-pppd/libnetlink/iputils.h b/accel-pppd/libnetlink/iputils.h index b9a6488..6097627 100644 --- a/accel-pppd/libnetlink/iputils.h +++ b/accel-pppd/libnetlink/iputils.h @@ -19,6 +19,7 @@ int iproute_del(int ifindex, in_addr_t dst, int proto); in_addr_t iproute_get(in_addr_t dst, in_addr_t *gw); int ip6route_add(int ifindex, struct in6_addr *dst, int prefix_len, int proto); +int ip6addr_add(int ifindex, struct in6_addr *addr, int prefix_len); int iprule_add(uint32_t addr, int table); int iprule_del(uint32_t addr, int table); |