struct rtnl_addr * nm_ip4_config_to_rtnl_addr (NMIP4Config *config, guint32 i, guint32 flags) { NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); NMIP4Address *config_addr; struct rtnl_addr *addr; gboolean success = TRUE; g_return_val_if_fail (NM_IS_IP4_CONFIG (config), NULL); config_addr = nm_ip4_config_get_address (config, i); g_return_val_if_fail (config_addr != NULL, NULL); if (!(addr = rtnl_addr_alloc())) return NULL; if (flags & NM_RTNL_ADDR_ADDR) success = (ip4_addr_to_rtnl_local (nm_ip4_address_get_address (config_addr), addr) >= 0); if (flags & NM_RTNL_ADDR_PTP_ADDR) success = (ip4_addr_to_rtnl_peer (priv->ptp_address, addr) >= 0); if (flags & NM_RTNL_ADDR_PREFIX) rtnl_addr_set_prefixlen (addr, nm_ip4_address_get_prefix (config_addr)); if (flags & NM_RTNL_ADDR_BROADCAST) { guint32 hostmask, network, bcast, netmask; netmask = nm_utils_ip4_prefix_to_netmask (nm_ip4_address_get_prefix (config_addr)); network = ntohl (nm_ip4_address_get_address (config_addr)) & ntohl (netmask); hostmask = ~ntohl (netmask); bcast = htonl (network | hostmask); success = (ip4_addr_to_rtnl_broadcast (bcast, addr) >= 0); } if (!success) { rtnl_addr_put (addr); addr = NULL; } return addr; }
int sysnet_interface_set_addr(VPNInterface *i) { int err; struct nl_cache *link_cache; struct nl_sock *sock; struct rtnl_addr *addr; struct rtnl_link *link; struct nl_addr *local_addr; sock = nl_socket_alloc(); nl_connect(sock, NETLINK_ROUTE); rtnl_link_alloc_cache(sock, AF_UNSPEC, &link_cache); addr = rtnl_addr_alloc(); link = rtnl_link_get_by_name(link_cache, i->name); local_addr = nl_addr_build(i->address.ip.family, &i->address.ip.ip4, sizeof(i->address.ip.ip4)); rtnl_addr_set_local(addr, local_addr); rtnl_addr_set_family(addr, i->address.ip.family); rtnl_addr_set_prefixlen(addr, i->address.prefix); rtnl_addr_set_link(addr, link); if ((err = rtnl_addr_add(sock, addr, 0)) < 0) { tox_trace(i->context->tox, "Unable to add address %s on %s: %s", ip_ntoa(&i->address.ip), rtnl_link_get_name(link), nl_geterror(err)); } else { tox_trace(i->context->tox, "Added address %s on \"%s\"", ip_ntoa(&i->address.ip), i->name); } rtnl_link_put(link); rtnl_addr_put(addr); nl_cache_free(link_cache); nl_addr_put(local_addr); nl_socket_free(sock); return err; }
int main(int argc, char *argv[]) { struct nl_sock *nl_sock; struct nl_cache *link_cache; int ifindex; int ret = 0; int err = 0; if (argc < 2) { printf("%s ip gw on/off tip\n", argv[0]); return -1; } //link if (err = rtnl_route_read_table_names(ROUTE_TABLE)) { printf("failed to read %s. err = %s\n", ROUTE_TABLE, nl_geterror(err)); return -1;; } nl_sock = nl_socket_alloc(); if (NULL == nl_sock) { printf("failed to alloc netlink handler.\n"); return -1; } if (err = nl_connect(nl_sock, NETLINK_ROUTE)) { printf("failed to connect NETLINK_ROUTE. err = %s\n", nl_geterror(err)); ret = -1; goto release_nl; } if (err = rtnl_link_alloc_cache(nl_sock, AF_INET, &link_cache)) { printf("failed to allocate link cache. err = %s\n", nl_geterror(err)); ret = -1; goto release_nl; } ifindex = rtnl_link_name2i(link_cache, NAME); if (0 == ifindex) { printf("%s - failed to find.\n", NAME); ret = -1; goto release_link_cache; } struct rtnl_link * link = rtnl_link_get(link_cache, ifindex); if (link == NULL) { printf("can't get link.\n"); ret = -1; goto release_link_cache; } //rtnl_link_get_by_name struct nl_addr *lladdr = rtnl_link_get_addr(link); if (NULL == lladdr || AF_LLC != nl_addr_get_family(lladdr)) { printf("failed to get MAC\n"); ret = -1; goto release_link; } uint8_t mac_address[ETHER_ADDR_LEN]; memcpy(mac_address, nl_addr_get_binary_addr(lladdr), ETHER_ADDR_LEN); printf("%02X:%02X:%02X:%02X:%02X:%02X\n", mac_address[0], mac_address[1], mac_address[2], mac_address[3], mac_address[4], mac_address[5]); //addr struct nl_cache * addr_cache; if (err = rtnl_addr_alloc_cache(nl_sock, &addr_cache)) { printf("fail to get addr_cache\n"); ret = -1; goto release_link; } struct rtnl_addr *addr = rtnl_addr_alloc(); rtnl_addr_set_ifindex(addr, ifindex); rtnl_addr_set_family(addr, AF_INET); int prefixlen = 16; nl_cache_foreach_filter(addr_cache, (struct nl_object *)addr, get_ip, &prefixlen); nl_cache_free(addr_cache); uint32_t ipaddr = inet_addr(argv[1]); struct nl_addr * local = nl_addr_build(AF_INET, &ipaddr, sizeof(ipaddr)); rtnl_addr_set_local(addr, local); rtnl_addr_set_ifindex(addr, ifindex); rtnl_addr_set_family(addr, AF_INET); rtnl_addr_set_prefixlen(addr, 32); if (!strcmp(argv[2], "on")) { if (err = rtnl_addr_add(nl_sock, addr, 0)) { printf("fail to add addr %s\n", nl_geterror(err)); ret = -1; goto release_addr; } } else { if (err = rtnl_addr_delete(nl_sock, addr, 0)) { printf("fail to del addr %s\n", nl_geterror(err)); ret = -1; goto release_addr; } } //neigh struct nl_cache * neigh_cache; if (err = rtnl_neigh_alloc_cache(nl_sock, &neigh_cache)) { printf("failed to allocate neighbor cache. err = %s\n", nl_geterror(err)); ret = -1; goto release_neigh_cache; } uint32_t gw = inet_addr(argv[3]); struct nl_addr * gw_addr = nl_addr_build(AF_INET, &gw, sizeof(gw)); struct rtnl_neigh * neigh = rtnl_neigh_get(neigh_cache, ifindex, gw_addr); if (neigh) { // It's optional struct nl_addr * lladdr = rtnl_neigh_get_lladdr(neigh); if (lladdr) { uint8_t mac_address[ETHER_ADDR_LEN]; memcpy(mac_address, nl_addr_get_binary_addr(lladdr), ETHER_ADDR_LEN); printf("gw %02X:%02X:%02X:%02X:%02X:%02X\n", mac_address[0], mac_address[1], mac_address[2], mac_address[3], mac_address[4], mac_address[5]); } } nl_addr_put(gw_addr); //route struct nl_cache *route_cache; if (err = rtnl_route_alloc_cache(nl_sock, AF_INET, 0, &route_cache)) { printf("failed to allocate route cache. err = %s\n", nl_geterror(err)); ret = -1; goto release_neigh_cache; } struct rtnl_route *route = rtnl_route_alloc(); struct nl_addr * taddr; err = nl_addr_parse(argv[4], AF_INET, &taddr); if (err) { printf("failed to get taddr. err = %s\n", nl_geterror(err)); ret = -1; goto release_route_cache; } nl_cache_foreach_filter(route_cache, OBJ_CAST(route), get_route, NULL); /* struct nl_sock *nl_fib_sock; nl_fib_sock = nl_socket_alloc(); if (err = nl_connect(nl_fib_sock, NETLINK_FIB_LOOKUP)) { printf("failed to connect NETLINK_ROUTE. err = %s\n", nl_geterror(err)); ret = -1; goto release_nl; } struct nl_dump_params params = { .dp_fd = stdout, .dp_type = NL_DUMP_DETAILS, }; struct nl_cache *route_cache = flnl_result_alloc_cache(); struct flnl_request *req = flnl_request_alloc(); struct nl_addr * taddr; err = nl_addr_parse(argv[4], AF_INET, &taddr); if (err) { printf("failed to get taddr. err = %s\n", nl_geterror(err)); ret = -1; goto release_route; } int table = RT_TABLE_UNSPEC, scope = RT_SCOPE_UNIVERSE; flnl_request_set_addr(req, taddr); flnl_request_set_table(req, table); flnl_request_set_scope(req, scope); err = flnl_lookup(nl_fib_sock, req, route_cache); if (err) { printf("failed to fib lookup. err = %s\n", nl_geterror(err)); ret = -1; goto release_route_addr; } nl_cache_dump(route_cache, ¶ms); release_route_addr: nl_addr_put(taddr); release_route: nl_cache_free(route_cache); nl_object_put(OBJ_CAST(req)); nl_close(nl_fib_sock); nl_socket_free(nl_fib_sock); */ release_route_cache: nl_cache_free(route_cache); release_neigh_cache: nl_cache_free(neigh_cache); release_addr: nl_addr_put(local); rtnl_addr_put(addr); release_link: rtnl_link_put(link); release_link_cache: nl_cache_free(link_cache); release_nl: nl_close(nl_sock); nl_socket_free(nl_sock); return ret; }
static int _set_ip(nozzle_t nozzle, int command, const char *ipaddr, const char *prefix, int secondary) { int fam; char *broadcast = NULL; int err = 0; #ifdef KNET_LINUX struct rtnl_addr *addr = NULL; struct nl_addr *local_addr = NULL; struct nl_addr *bcast_addr = NULL; struct nl_cache *cache = NULL; int ifindex; #endif #ifdef KNET_BSD char cmdline[4096]; char proto[6]; char *error_string = NULL; #endif if (!strchr(ipaddr, ':')) { fam = AF_INET; broadcast = generate_v4_broadcast(ipaddr, prefix); if (!broadcast) { errno = EINVAL; return -1; } } else { fam = AF_INET6; } #ifdef KNET_LINUX addr = rtnl_addr_alloc(); if (!addr) { errno = ENOMEM; return -1; } if (rtnl_link_alloc_cache(lib_cfg.nlsock, AF_UNSPEC, &cache) < 0) { errno = ENOMEM; err = -1; goto out; } ifindex = rtnl_link_name2i(cache, nozzle->name); if (ifindex == 0) { errno = ENOENT; err = -1; goto out; } rtnl_addr_set_ifindex(addr, ifindex); if (nl_addr_parse(ipaddr, fam, &local_addr) < 0) { errno = EINVAL; err = -1; goto out; } if (rtnl_addr_set_local(addr, local_addr) < 0) { errno = EINVAL; err = -1; goto out; } if (broadcast) { if (nl_addr_parse(broadcast, fam, &bcast_addr) < 0) { errno = EINVAL; err = -1; goto out; } if (rtnl_addr_set_broadcast(addr, bcast_addr) < 0) { errno = EINVAL; err = -1; goto out; } } rtnl_addr_set_prefixlen(addr, atoi(prefix)); if (command == IP_ADD) { if (rtnl_addr_add(lib_cfg.nlsock, addr, 0) < 0) { errno = EINVAL; err = -1; goto out; } } else { if (rtnl_addr_delete(lib_cfg.nlsock, addr, 0) < 0) { errno = EINVAL; err = -1; goto out; } } out: if (addr) { rtnl_addr_put(addr); } if (local_addr) { nl_addr_put(local_addr); } if (bcast_addr) { nl_addr_put(bcast_addr); } if (cache) { nl_cache_put(cache); } if (broadcast) { free(broadcast); } return err; #endif #ifdef KNET_BSD /* * TODO: port to use ioctl and such, drop shell forking here */ memset(cmdline, 0, sizeof(cmdline)); if (fam == AF_INET) { snprintf(proto, sizeof(proto), "inet"); } else { snprintf(proto, sizeof(proto), "inet6"); } if (command == IP_ADD) { snprintf(cmdline, sizeof(cmdline)-1, "ifconfig %s %s %s/%s", nozzle->name, proto, ipaddr, prefix); if (broadcast) { snprintf(cmdline + strlen(cmdline), sizeof(cmdline) - strlen(cmdline) -1, " broadcast %s", broadcast); } if ((secondary) && (fam == AF_INET)) { snprintf(cmdline + strlen(cmdline), sizeof(cmdline) - strlen(cmdline) -1, " alias"); } } else { snprintf(cmdline, sizeof(cmdline)-1, "ifconfig %s %s %s/%s delete", nozzle->name, proto, ipaddr, prefix); } if (broadcast) { free(broadcast); } /* * temporary workaround as we port libnozzle to BSD ioctl * for IP address management */ err = execute_bin_sh_command(cmdline, &error_string); if (error_string) { free(error_string); error_string = NULL; } return err; #endif }