/** * virNetDevIPRouteAdd: * @ifname: the interface name * @addr: the IP network address (IPv4 or IPv6) * @prefix: number of 1 bits in the netmask * @gateway: via address for route (same as @addr) * * Add a route for a network IP address to an interface. This function * *does not* remove any previously added IP static routes. * * Returns 0 in case of success or -1 in case of error. */ int virNetDevIPRouteAdd(const char *ifname, virSocketAddrPtr addr, unsigned int prefix, virSocketAddrPtr gateway, unsigned int metric) { int ret = -1; struct nl_msg *nlmsg = NULL; struct nlmsghdr *resp = NULL; unsigned int recvbuflen; unsigned int ifindex; struct rtmsg rtmsg; void *gatewayData = NULL; void *addrData = NULL; size_t addrDataLen; int errCode; virSocketAddr defaultAddr; virSocketAddrPtr actualAddr; char *toStr = NULL; char *viaStr = NULL; actualAddr = addr; /* If we have no valid network address, then use the default one */ if (!addr || !VIR_SOCKET_ADDR_VALID(addr)) { VIR_DEBUG("computing default address"); int family = VIR_SOCKET_ADDR_FAMILY(gateway); if (family == AF_INET) { if (virSocketAddrParseIPv4(&defaultAddr, VIR_SOCKET_ADDR_IPV4_ALL) < 0) goto cleanup; } else { if (virSocketAddrParseIPv6(&defaultAddr, VIR_SOCKET_ADDR_IPV6_ALL) < 0) goto cleanup; } actualAddr = &defaultAddr; } toStr = virSocketAddrFormat(actualAddr); viaStr = virSocketAddrFormat(gateway); VIR_DEBUG("Adding route %s/%d via %s", toStr, prefix, viaStr); if (virNetDevGetIPAddressBinary(actualAddr, &addrData, &addrDataLen) < 0 || virNetDevGetIPAddressBinary(gateway, &gatewayData, &addrDataLen) < 0) goto cleanup; /* Get the interface index */ if ((ifindex = if_nametoindex(ifname)) == 0) goto cleanup; if (!(nlmsg = nlmsg_alloc_simple(RTM_NEWROUTE, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL))) { virReportOOMError(); goto cleanup; } memset(&rtmsg, 0, sizeof(rtmsg)); rtmsg.rtm_family = VIR_SOCKET_ADDR_FAMILY(gateway); rtmsg.rtm_table = RT_TABLE_MAIN; rtmsg.rtm_scope = RT_SCOPE_UNIVERSE; rtmsg.rtm_protocol = RTPROT_BOOT; rtmsg.rtm_type = RTN_UNICAST; rtmsg.rtm_dst_len = prefix; if (nlmsg_append(nlmsg, &rtmsg, sizeof(rtmsg), NLMSG_ALIGNTO) < 0) goto buffer_too_small; if (prefix > 0 && nla_put(nlmsg, RTA_DST, addrDataLen, addrData) < 0) goto buffer_too_small; if (nla_put(nlmsg, RTA_GATEWAY, addrDataLen, gatewayData) < 0) goto buffer_too_small; if (nla_put_u32(nlmsg, RTA_OIF, ifindex) < 0) goto buffer_too_small; if (metric > 0 && nla_put_u32(nlmsg, RTA_PRIORITY, metric) < 0) goto buffer_too_small; if (virNetlinkCommand(nlmsg, &resp, &recvbuflen, 0, 0, NETLINK_ROUTE, 0) < 0) goto cleanup; if ((errCode = virNetlinkGetErrorCode(resp, recvbuflen)) < 0) { virReportSystemError(errCode, _("Error adding route to %s"), ifname); goto cleanup; } ret = 0; cleanup: VIR_FREE(toStr); VIR_FREE(viaStr); nlmsg_free(nlmsg); return ret; buffer_too_small: virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("allocated netlink buffer is too small")); goto cleanup; }
static int parallelsGetHostOnlyNetInfo(virNetworkDefPtr def, const char *name) { const char *tmp; virJSONValuePtr jobj = NULL, jobj2; int ret = -1; if (VIR_EXPAND_N(def->ips, def->nips, 1) < 0) { virReportOOMError(); goto cleanup; } jobj = parallelsParseOutput("prlsrvctl", "net", "info", "-j", name, NULL); if (!jobj) { parallelsParseError(); goto cleanup; } if (!(jobj2 = virJSONValueObjectGet(jobj, "Parallels adapter"))) { parallelsParseError(); goto cleanup; } if (!(def->ips[0].family = strdup("ipv4"))) { virReportOOMError(); goto cleanup; }; if (!(tmp = virJSONValueObjectGetString(jobj2, "IP address"))) { parallelsParseError(); goto cleanup; } if (virSocketAddrParseIPv4(&def->ips[0].address, tmp) < 0) { parallelsParseError(); goto cleanup; } if (!(tmp = virJSONValueObjectGetString(jobj2, "Subnet mask"))) { parallelsParseError(); goto cleanup; } if (virSocketAddrParseIPv4(&def->ips[0].netmask, tmp) < 0) { parallelsParseError(); goto cleanup; } if (!(jobj2 = virJSONValueObjectGet(jobj, "DHCPv4 server"))) { parallelsParseError(); goto cleanup; } if (VIR_EXPAND_N(def->ips[0].ranges, def->ips[0].nranges, 1) < 0) { virReportOOMError(); goto cleanup; } if (!(tmp = virJSONValueObjectGetString(jobj2, "IP scope start address"))) { parallelsParseError(); goto cleanup; } if (virSocketAddrParseIPv4(&def->ips[0].ranges[0].start, tmp) < 0) { parallelsParseError(); goto cleanup; } if (!(tmp = virJSONValueObjectGetString(jobj2, "IP scope end address"))) { parallelsParseError(); goto cleanup; } if (virSocketAddrParseIPv4(&def->ips[0].ranges[0].end, tmp) < 0) { parallelsParseError(); goto cleanup; } ret = 0; cleanup: virJSONValueFree(jobj); return ret; }