From b8fbb02240da7ce471f5b62fdb46c581d94b5335 Mon Sep 17 00:00:00 2001 From: Niklas Date: Fri, 7 Oct 2011 14:10:55 +0200 Subject: adding files of the renamed directory --- NetworkDiscovery/networkmanager.cpp | 497 ++++++++++++++++++++++++++++++++++++ 1 file changed, 497 insertions(+) create mode 100644 NetworkDiscovery/networkmanager.cpp (limited to 'NetworkDiscovery/networkmanager.cpp') diff --git a/NetworkDiscovery/networkmanager.cpp b/NetworkDiscovery/networkmanager.cpp new file mode 100644 index 0000000..da5f045 --- /dev/null +++ b/NetworkDiscovery/networkmanager.cpp @@ -0,0 +1,497 @@ +/* + * networkmanager.cpp + * + * Created on: Sep 5, 2011 + * Author: niklas + */ + +#include "networkmanager.h" + +NetworkManager::NetworkManager() { + // TODO Auto-generated constructor stub + _tag = "[nd:NetworkManager]"; +} + + + +NetworkManager::~NetworkManager() { + // TODO Auto-generated destructor stub +} + + + +/** + * This method adds /replaces the default route. + * This method adds /replaces the default route. + * To keep it modular, it is possible + * to specify an ip address family. + * + * @param ifName + * the interface name + * + * @param gateway + * the gateway address (e.g: 192.168.0.254) + * @param mss + * the mss. + * @param af + * specify the family type of the ip address. + * possible values are: AF_INET for an IPv4 address + * AF_INET6 for an IPv6 address + * + + * @return + * return -1 if an error happened. + * return 0 if everything was ok. + */ +int NetworkManager::replaceDefaultRoute(QString ifname, QString gateway, + int mss, int af) { + struct nl_cache *cache; + struct nl_handle* rtsock; + struct nl_addr * gw; + struct rtnl_route * route; + int retval, iface_idx; + + QByteArray ba_ifn = ifname.toAscii(); + char * ifn = ba_ifn.data(); + + QByteArray ba_gw = gateway.toAscii(); + char * gwaddr = ba_gw.data(); + + qDebug() << _tag << "---doRoute() gwaddr" << gwaddr; + + if (!(gw = nl_addr_parse(gwaddr, af))) { + qDebug() << _tag << "Invalid router address given:" << gwaddr; + return -1; + } + + rtsock = nl_handle_alloc(); + nl_connect(rtsock, NETLINK_ROUTE); + + if ((cache = rtnl_link_alloc_cache(rtsock)) == NULL) { + qDebug() << _tag << "error with link cache alloc \n"; + } + + iface_idx = rtnl_link_name2i(cache, ifn); + + route = rtnl_route_alloc(); + rtnl_route_set_scope(route, RT_SCOPE_UNIVERSE); + rtnl_route_set_gateway(route, gw); + rtnl_route_set_oif(route, iface_idx); + + if (mss > 0) { + rtnl_route_set_metric(route, RTAX_ADVMSS, mss); + } + + retval = rtnl_route_add(rtsock, route, NLM_F_REPLACE); + qDebug() << _tag << "return value:" << retval << ":" << strerror(-retval); + + rtnl_route_put(route); + nl_addr_put(gw); + nl_handle_destroy(rtsock); + + return retval; +} + + + +/** + * The method brings an interface up. + * + * @param ifname + * the name of the interface + * + * @return + * 0 -> success + * -1 -> error + */ +int NetworkManager::bringInterfaceUP(QString ifname) { + return bringInterfaceUpDown(ifname, true); +} + + + +/** + * The method brings an interface down. + * + * @param ifname + * the name of the interface + * + * @return + * 0 -> success + * -1 -> error + */ +int NetworkManager::bringInterfaceDown(QString ifname) { + return bringInterfaceUpDown(ifname, false); +} + + + +/** + * This method brings an interface up or down. + * + * @param ifname + * is a string which contains the interface name which is going down or up. + * + * @param up + * is a bool. true means. we bring the interface up. + * false meand. we bring the interface down. + * @return + * 0 if everything is ok + * else an error + */ +int NetworkManager::bringInterfaceUpDown(QString ifname, bool up) { + struct nl_cache *cache; + struct nl_handle* rtsock; + struct rtnl_link* request = NULL; + struct rtnl_link* old = NULL; + int retval; + + QByteArray ba_ifn = ifname.toAscii(); + char * ifn = ba_ifn.data(); + + if (!(request = rtnl_link_alloc())) { + qDebug() << _tag << "error. couldn't allocate a rtnl link"; + return -1; + } + + rtsock = nl_handle_alloc(); + nl_connect(rtsock, NETLINK_ROUTE); + + if (up) { + rtnl_link_set_flags(request, IFF_UP); + } else { + rtnl_link_unset_flags(request, IFF_UP); + } + + if ((cache = rtnl_link_alloc_cache(rtsock)) == NULL) { + qDebug() << _tag << "error with link cache alloc "; + } + + old = rtnl_link_get_by_name(cache, ifn); + if (old) { + qDebug() << _tag << "change link"; + retval = rtnl_link_change(rtsock, old, request, 0); + } else { + qDebug() << _tag << "change failed"; + retval = -1; + qDebug() << _tag << "return value:" << retval << ":" << strerror(-retval); + } + + rtnl_link_put(old); + rtnl_link_put(request); + nl_handle_destroy(rtsock); + + return retval; +} + + + +/** + * This method is used when the manual configuration is needed. + * + * This method is used when the manual configuration is needed. + * First we bring up the interface. Than we configure the interface with + * our manual entered configuration dates. + * After that we replace the old default route with the new and + * write a resolv.conf. + * + * @param ifname + * name of the interface which we are about to configure. + * + * @param ipAddress + * the new IP-Address. + * + * @param netmask + * the netmask of the IP-Address. + * + * @param broadcast + * the broadcast address. + * @param gateway + * the gateway address. + * @param metric + * do not exactly know why we need this. in most cases this should be 0. + * @param af + * the address type. Either AF_INET for IPv4 or AF_INET6 for IPv6. + * @param pathToResolvConf + * the path to the resolf.conf file. in most cases "/etc/". + * @param nameServer + * the name server addresses. + */ +int NetworkManager::ip4_setManualConfiguration(QString ifname, QString ipAddress, QString netmask, + QString broadcast, QString gateway, int metric, int af, QString pathToResolvConf, QList nameServer) { + + //bring the interface up + bringInterfaceUP(ifname); + //set configuration + ip4_configureInterface(ifname, ipAddress, broadcast, netmask,af); + //set default route + replaceDefaultRoute(ifname, gateway, metric, af); + //write resolv.conf + writeResolvConf(pathToResolvConf, ifname, nameServer); + return 0; +} + + + +int NetworkManager::ip4_configureInterface(QString ifname, QString ipAddress, + QString broadcast, QString netmask, int af) { + + struct nl_cache *cache; + struct nl_handle* rtsock; + struct nl_addr * local; + struct rtnl_addr * addr = NULL; + int retval = 0; + int iface_idx, err, prefixLength; + + QByteArray ba_ifn = ifname.trimmed().toAscii(); + char * ifn = ba_ifn.data(); + + QByteArray ba_ip = ipAddress.trimmed().toAscii(); + char * ipaddr = ba_ip.data(); + + QByteArray ba_bc = broadcast.trimmed().toAscii(); + char * bcaddr = ba_bc.data(); + + 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, ifn); + + if (!(addr = rtnl_addr_alloc())) { + qDebug() << _tag << "error with addr alloc"; + return -1; + } + + local = nl_addr_parse(ipaddr, af); + err = rtnl_addr_set_local(addr, local); + nl_addr_put(local); + if (err != 0) { + qDebug() << _tag << "error with set local addr"; + } + + prefixLength = ip4_netmaskToPrefix(ipAddress,netmask); + qDebug() << _tag << "prefix length:" << prefixLength; + rtnl_addr_set_prefixlen(addr, prefixLength); + + local = nl_addr_parse(bcaddr, af); + err = rtnl_addr_set_broadcast(addr, local); + nl_addr_put(local); + if (err != 0) { + qDebug() << _tag << "error with set broadcast addr"; + } + + rtnl_addr_set_ifindex(addr, iface_idx); + + + retval = sync_address(ifn, iface_idx, af, addr); + if(retval < 0) { + qDebug() << _tag << "error in sync_address"; + } + rtnl_addr_put(addr); + + return retval; +} + + + +/** + * This Method returns the length of the IP-Address netmask prefix. + * + * @param ipAddr + * the IP-address + * + * @param netmask + * the netmask of the IP-address. + * @return + * the length of the IP-Address netmask prefix + */ +int NetworkManager::ip4_netmaskToPrefix(QString ipAddr, QString netmask) { + int retval = -1; + QNetworkAddressEntry nae; + + if (netmask == "") { + qDebug() << _tag << "error: netmask is empty"; + return retval; + } + nae.setIp(QHostAddress(ipAddr)); + nae.setNetmask(QHostAddress(netmask.trimmed())); + retval = nae.prefixLength(); + + return retval; +} + + + +/** + * delete all addresses of this interface but not the one we just set + * + * @return + * -1 if something went wrong. else 0 + */ +int NetworkManager::sync_address(const char *iface, int ifindex, int family, + struct rtnl_addr *addr) { + + struct nl_handle *nlh; + struct nl_cache *addr_cache; + struct rtnl_addr *filter_addr, *match_addr; + struct nl_object *match; + struct nl_addr *nladdr; + int err; + char buf[INET6_ADDRSTRLEN + 1]; + + nlh = nl_handle_alloc(); + nl_connect(nlh, NETLINK_ROUTE); + + if (!nlh) + return -1; + + addr_cache = rtnl_addr_alloc_cache(nlh); + + if (!addr_cache) + return -1; + + filter_addr = rtnl_addr_alloc(); + if (!filter_addr) { + nl_cache_free(addr_cache); + return -1; + } + rtnl_addr_set_ifindex(filter_addr, ifindex); + if (family) + rtnl_addr_set_family(filter_addr, family); + + //nm_log_dbg (log_domain, "(%s): syncing addresses (family %d)", iface, family); + + /* Walk through the cache, comparing the addresses already on + * the interface to the addresses in addrs. + */ + for (match = nl_cache_get_first(addr_cache); match; match + = nl_cache_get_next(match)) { + int buf_valid = -1; + match_addr = (struct rtnl_addr *) match; + + /* Skip addresses not on our interface */ + if (!nl_object_match_filter(match, (struct nl_object *) filter_addr)) + continue; + + if (addr) { + if (addr && nl_object_identical(match, (struct nl_object *) addr)) { + continue; + } + } + + nladdr = rtnl_addr_get_local(match_addr); + + /* Don't delete IPv6 link-local addresses; they don't belong to NM */ + if (rtnl_addr_get_family(match_addr) == AF_INET6) { + struct in6_addr *tmp; + + if (rtnl_addr_get_scope(match_addr) == RT_SCOPE_LINK) { + //nm_log_dbg (log_domain, "(%s): ignoring IPv6 link-local address", iface); + continue; + } + + tmp = (in6_addr*) nl_addr_get_binary_addr(nladdr); + if (inet_ntop(AF_INET6, tmp, buf, sizeof(buf))) + buf_valid = 0; + } else if (rtnl_addr_get_family(match_addr) == AF_INET) { + struct in_addr *tmp; + + tmp = (in_addr *) nl_addr_get_binary_addr(nladdr); + if (inet_ntop(AF_INET, tmp, buf, sizeof(buf))) + buf_valid = 0; + } + + if (buf_valid == 0) { + //nm_log_dbg (log_domain, "(%s): removing address '%s/%d'", + // iface, buf, nl_addr_get_prefixlen (nladdr)); + } + + /* Otherwise, match_addr should be removed from the interface. */ + err = rtnl_addr_delete(nlh, match_addr, 0); + if (err < 0) { + //nm_log_err (log_domain, "(%s): error %d returned from rtnl_addr_delete(): %s", + // iface, err, nl_geterror ()); + qDebug() << _tag << "error with delete addr"; + } + } + + rtnl_addr_put(filter_addr); + nl_cache_free(addr_cache); + + /* Now add the remaining new addresses */ + if (!addr) + return -1; + + struct in6_addr *in6tmp; + struct in_addr *in4tmp; + int buf_valid = -1; + + nladdr = rtnl_addr_get_local(addr); + if (rtnl_addr_get_family(addr) == AF_INET6) { + in6tmp = (in6_addr*) nl_addr_get_binary_addr(nladdr); + if (inet_ntop(AF_INET6, in6tmp, buf, sizeof(buf))) + buf_valid = 0; + } else if (rtnl_addr_get_family(addr) == AF_INET) { + in4tmp = (in_addr*) nl_addr_get_binary_addr(nladdr); + if (inet_ntop(AF_INET, in4tmp, buf, sizeof(buf))) + buf_valid = 0; + } + + if (buf_valid == 0) { + //nm_log_dbg (log_domain, "(%s): adding address '%s/%d'", + //iface, buf, nl_addr_get_prefixlen (nladdr)); + qDebug() << _tag << "buf valid adding addr"; + } + + err = rtnl_addr_add(nlh, addr, 0); + if (err < 0) { + //nm_log_err (log_domain, + // "(%s): error %d returned from rtnl_addr_add():\n%s", + // iface, err, nl_geterror ()); + qDebug() << _tag << "error with add addr"<< strerror(-err); + } + + rtnl_addr_put(addr); + + return err; +} + + + +/** + * This method writes a resolv.conf file. + * + * @param path + * path to the resolv.conf file. (in most cases: /etc/) + * @param ifname + * name of the interface + * @param + * addresses of the nameserver + * + * @return + * return 0 if success + * else -1 + */ +int NetworkManager::writeResolvConf(QString path, QString ifname, QList nameServer){ + + QFile file(path + "resolv.conf"); + if(!file.open(QIODevice::WriteOnly | QIODevice::Text)) { + qDebug() << _tag << "error couldn't open file:" << path; + return -1; + } + QTextStream out(&file); + out << "# Generated by networkdiscovery manual configuration for interface " + ifname +"\n"; + foreach(QString ns, nameServer ) { + out << "nameserver " + ns +"\n"; + } + + file.close(); + + return 0; +} + -- cgit v1.2.3-55-g7522