From 91f8c9826f7c67c4e8e92d6f6460aa58622f2ee5 Mon Sep 17 00:00:00 2001 From: Niklas Date: Wed, 12 Oct 2011 17:05:12 +0200 Subject: small changes in the networkmanager. added some ipv6 methods for adding a route and a address to an interface --- NetworkDiscovery/networkmanager.cpp | 179 ++++++++++++++++++++++++++++++++++++ NetworkDiscovery/networkmanager.h | 11 +++ 2 files changed, 190 insertions(+) diff --git a/NetworkDiscovery/networkmanager.cpp b/NetworkDiscovery/networkmanager.cpp index da5f045..c40c83d 100644 --- a/NetworkDiscovery/networkmanager.cpp +++ b/NetworkDiscovery/networkmanager.cpp @@ -94,6 +94,108 @@ int NetworkManager::replaceDefaultRoute(QString ifname, QString gateway, +/**/ +int NetworkManager::ip6_addRoute(const char *iface, + const struct in6_addr *ip6_dest, int ip6_prefix, + const struct in6_addr *ip6_gateway, int metric, int mss) { + struct nl_cache *cache; + struct nl_handle *nlh; + struct rtnl_route *route; + struct nl_addr *dest_addr; + struct nl_addr *gw_addr = NULL; + int err, iface_idx; + + nlh = nl_handle_alloc(); + nl_connect(nlh, NETLINK_ROUTE); + + if ((cache = rtnl_link_alloc_cache(nlh)) == NULL) { + //qDebug() << _tag << "error with link cache alloc \n"; + printf("error with link cache alloc \n"); + } + + iface_idx = rtnl_link_name2i(cache, iface); + + route = rtnl_route_alloc(); + + /* Destination */ + dest_addr = nl_addr_build(AF_INET6, (struct in6_addr *) ip6_dest, + sizeof(*ip6_dest)); + nl_addr_set_prefixlen(dest_addr, (int) ip6_prefix); + + rtnl_route_set_dst(route, dest_addr); + nl_addr_put(dest_addr); + + /* Gateway */ + if (ip6_gateway && !IN6_IS_ADDR_UNSPECIFIED (ip6_gateway)) { + gw_addr = nl_addr_build(AF_INET6, (struct in6_addr *) ip6_gateway, + sizeof(*ip6_gateway)); + if (gw_addr) { + rtnl_route_set_gateway(route, gw_addr); + rtnl_route_set_scope(route, RT_SCOPE_UNIVERSE); + } else { + rtnl_route_put(route); + return -1; + } + } + + /* Metric */ + if (metric) + rtnl_route_set_prio(route, metric); + + /* Add the route */ + err = rtnl_route_add(nlh, route, 0); + if (err == -ESRCH && ip6_gateway) { + /* Gateway might be over a bridge; try adding a route to gateway first */ + struct rtnl_route *route2; + + route2 = create_route(iface_idx, mss); + if (route2) { + /* Add route to gateway over bridge */ + rtnl_route_set_dst(route2, gw_addr); + err = rtnl_route_add(nlh, route2, 0); + if (!err) { + /* Try adding the route again */ + err = rtnl_route_add(nlh, route, 0); + if (err) + rtnl_route_del(nlh, route2, 0); + } + rtnl_route_put(route2); + } + } + + if (gw_addr) + nl_addr_put(gw_addr); + + if (err) { + //nm_warning ("Failed to set IPv6 route on '%s': %s", iface, nl_geterror ()); + rtnl_route_put(route); + route = NULL; + } + + return 0; +} + + + +struct rtnl_route * NetworkManager::create_route (int iface_idx, int mss) +{ + struct rtnl_route *route; + + route = rtnl_route_alloc (); + if (route) { + rtnl_route_set_oif (route, iface_idx); + + if (mss && rtnl_route_set_metric (route, RTAX_ADVMSS, mss) < 0) { + //nm_warning ("Could not set mss"); + } + } else + //nm_warning ("Could not allocate route"); + + return route; +} + + + /** * The method brings an interface up. * @@ -327,6 +429,83 @@ int NetworkManager::ip4_netmaskToPrefix(QString ipAddr, QString netmask) { +int NetworkManager::ip6_addAddress(struct ip6_addr* ip6Addr, const char *iface) { + int num_addrs, i, iface_idx; + struct rtnl_addr* addr = NULL; + struct nl_cache *cache; + struct nl_handle* rtsock; + + rtsock = nl_handle_alloc(); + nl_connect(rtsock, NETLINK_ROUTE); + + if ((cache = rtnl_link_alloc_cache(rtsock)) == NULL) { + qDebug() << _tag << "error with link cache alloc"; + return -1; + } + + iface_idx = rtnl_link_name2i(cache, iface); + + addr = ip6AddrToRtnlAddr(ip6Addr); + if (!addr) { + //nm_warning("couldn't create rtnl address!\n"); + return -1; + } + rtnl_addr_set_ifindex(addr, iface_idx); + + return sync_address(iface, iface_idx, AF_INET6, addr); +} + + + +/**/ +struct rtnl_addr* NetworkManager::ip6AddrToRtnlAddr(struct ip6_addr* ip6Addr) { + struct rtnl_addr *addr; + bool success = true; + + if (!(addr = rtnl_addr_alloc())) + return NULL; + + success = (nlAddrToRtnlAddr(ip6Addr, addr) >= 0); + + if (!success) { + rtnl_addr_put(addr); + addr = NULL; + } + + return addr; +} + + + +/**/ +struct nl_addr* NetworkManager::ip6AddrToNlAddr(const struct ip6_addr *ip6Addr) { + struct nl_addr * nla = NULL; + + if (!(nla = nl_addr_alloc(sizeof(struct in6_addr)))) + return NULL; + nl_addr_set_family(nla, AF_INET6); + nl_addr_set_binary_addr(nla, (struct in6_addr *) ip6Addr, sizeof(struct in6_addr)); + + return nla; +} + + + +/**/ +int NetworkManager::nlAddrToRtnlAddr( + const struct ip6_addr* ip6Addr, struct rtnl_addr* addr) { + struct nl_addr * local = NULL; + int err = 0; + + local = ip6AddrToNlAddr(ip6Addr); + err = rtnl_addr_set_local(addr, local); + nl_addr_put(local); + + return -err; +} + + + /** * delete all addresses of this interface but not the one we just set * diff --git a/NetworkDiscovery/networkmanager.h b/NetworkDiscovery/networkmanager.h index 3fb1587..f332f9e 100644 --- a/NetworkDiscovery/networkmanager.h +++ b/NetworkDiscovery/networkmanager.h @@ -38,6 +38,12 @@ public: QString broadcast, QString gateway, int metric, int af, QString pathToResolvConf, QList nameServer); int ip4_configureInterface(QString ifname, QString ipAddress, QString broadcast, QString netmask, int af); + + int ip6_addRoute(const char *iface, + const struct in6_addr *ip6_dest, int ip6_prefix, + const struct in6_addr *ip6_gateway, int metric, int mss); + int ip6_addAddress(struct ip6_addr* ip6Addr, const char *iface); + int writeResolvConf(QString path, QString ifname, QList nameServer); private: @@ -48,6 +54,11 @@ private: int sync_address(const char *iface, int ifindex, int family, struct rtnl_addr *addr); + struct rtnl_route* create_route (int iface_idx, int mss); + struct nl_addr* ip6AddrToNlAddr (const struct ip6_addr* ip6Addr); + int nlAddrToRtnlAddr (const struct ip6_addr* ip6Addr, struct rtnl_addr* addr); + struct rtnl_addr* ip6AddrToRtnlAddr(struct ip6_addr* ip6Addr); + }; -- cgit v1.2.3-55-g7522