mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-23 22:25:25 +00:00
Set of new network related utilities
* src/util/network.h src/util/network.c: utilities to parse network addresses, check netmask and compute ranges
This commit is contained in:
parent
d5fcd4f7a3
commit
24c8fc5dff
@ -55,6 +55,7 @@ UTIL_SOURCES = \
|
||||
util/memory.c util/memory.h \
|
||||
util/pci.c util/pci.h \
|
||||
util/hostusb.c util/hostusb.h \
|
||||
util/network.c util/network.h \
|
||||
util/qparams.c util/qparams.h \
|
||||
util/stats_linux.c util/stats_linux.h \
|
||||
util/storage_file.c util/storage_file.h \
|
||||
|
323
src/util/network.c
Normal file
323
src/util/network.c
Normal file
@ -0,0 +1,323 @@
|
||||
/*
|
||||
* network.c: network helper APIs for libvirt
|
||||
*
|
||||
* Copyright (C) 2009-2009 Red Hat, Inc.
|
||||
*
|
||||
* See COPYING.LIB for the License of this software
|
||||
*
|
||||
* Daniel Veillard <veillard@redhat.com>
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "memory.h"
|
||||
#include "network.h"
|
||||
|
||||
/*
|
||||
* Helpers to extract the IP arrays from the virSocketAddrPtr
|
||||
* That part is the less portable of the module
|
||||
*/
|
||||
typedef unsigned char virIPv4Addr[4];
|
||||
typedef virIPv4Addr *virIPv4AddrPtr;
|
||||
typedef unsigned short virIPv6Addr[8];
|
||||
typedef virIPv6Addr *virIPv6AddrPtr;
|
||||
|
||||
static int getIPv4Addr(virSocketAddrPtr addr, virIPv4AddrPtr tab) {
|
||||
unsigned long val;
|
||||
int i;
|
||||
|
||||
if ((addr == NULL) || (tab == NULL) || (addr->stor.ss_family != AF_INET))
|
||||
return(-1);
|
||||
|
||||
val = ntohl(addr->inet4.sin_addr.s_addr);
|
||||
|
||||
for (i = 0;i < 4;i++) {
|
||||
(*tab)[i] = val & 0xFF;
|
||||
val >>= 8;
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int getIPv6Addr(virSocketAddrPtr addr, virIPv6AddrPtr tab) {
|
||||
virIPv6AddrPtr val;
|
||||
int i;
|
||||
|
||||
if ((addr == NULL) || (tab == NULL) || (addr->stor.ss_family != AF_INET6))
|
||||
return(-1);
|
||||
|
||||
val = (virIPv6AddrPtr) &(addr->inet6.sin6_addr.__in6_u.__u6_addr16);
|
||||
|
||||
for (i = 0;i < 8;i++) {
|
||||
(*tab)[i] = ntohs((*val)[i]);
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* virSocketParseAddr:
|
||||
* @val: a numeric network address IPv4 or IPv6
|
||||
* @addr: where to store the return value.
|
||||
* @hint: optional hint to pass down to getaddrinfo
|
||||
*
|
||||
* Mostly a wrapper for getaddrinfo() extracting the address storage
|
||||
* from the numeric string like 1.2.3.4 or 2001:db8:85a3:0:0:8a2e:370:7334
|
||||
*
|
||||
* Returns the lenght of the network address or -1 in case of error.
|
||||
*/
|
||||
int
|
||||
virSocketParseAddr(const char *val, virSocketAddrPtr addr, int hint) {
|
||||
int len;
|
||||
struct addrinfo hints;
|
||||
struct addrinfo *res = NULL;
|
||||
|
||||
if ((val == NULL) || (addr == NULL))
|
||||
return(-1);
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_flags = AI_NUMERICHOST | hint;
|
||||
if ((getaddrinfo(val, NULL, &hints, &res) != 0) || (res == NULL)) {
|
||||
return(-1);
|
||||
}
|
||||
|
||||
len = res->ai_addrlen;
|
||||
memcpy(&addr->stor, res->ai_addr, len);
|
||||
|
||||
freeaddrinfo(res);
|
||||
return(len);
|
||||
}
|
||||
|
||||
/*
|
||||
* virSocketParseIpv4Addr:
|
||||
* @val: an IPv4 numeric address
|
||||
* @addr: the loacation to store the result
|
||||
*
|
||||
* Extract the address storage from an IPv4 numeric address
|
||||
*
|
||||
* Returns the lenght of the network address or -1 in case of error.
|
||||
*/
|
||||
int
|
||||
virSocketParseIpv4Addr(const char *val, virSocketAddrPtr addr) {
|
||||
return(virSocketParseAddr(val, addr, AF_INET));
|
||||
}
|
||||
|
||||
/*
|
||||
* virSocketParseIpv6Addr:
|
||||
* @val: an IPv6 numeric address
|
||||
* @addr: the loacation to store the result
|
||||
*
|
||||
* Extract the address storage from an IPv6 numeric address
|
||||
*
|
||||
* Returns the lenght of the network address or -1 in case of error.
|
||||
*/
|
||||
int
|
||||
virSocketParseIpv6Addr(const char *val, virSocketAddrPtr addr) {
|
||||
return(virSocketParseAddr(val, addr, AF_INET6));
|
||||
}
|
||||
|
||||
/**
|
||||
* virSocketAddrIsNetmask:
|
||||
* @netmask: the netmask address
|
||||
*
|
||||
* Check that @netmask is a proper network mask
|
||||
*
|
||||
* Returns 0 in case of success and -1 in case of error
|
||||
*/
|
||||
int virSocketAddrIsNetmask(virSocketAddrPtr netmask) {
|
||||
int i;
|
||||
|
||||
if (netmask == NULL)
|
||||
return(-1);
|
||||
|
||||
if (netmask->stor.ss_family == AF_INET) {
|
||||
virIPv4Addr tm;
|
||||
unsigned char tmp;
|
||||
int ok = 0;
|
||||
|
||||
if (getIPv4Addr(netmask, &tm) < 0)
|
||||
return(-1);
|
||||
|
||||
for (i = 0;i < 4;i++) {
|
||||
if (tm[i] != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i >= 4)
|
||||
return(0);
|
||||
|
||||
tmp = 0xFF;
|
||||
do {
|
||||
if (tm[i] == tmp) {
|
||||
ok = 1;
|
||||
break;
|
||||
}
|
||||
tmp <<= 1;
|
||||
} while (tmp != 0);
|
||||
if (ok == 0)
|
||||
return(-1);
|
||||
i++;
|
||||
|
||||
if (i >= 4)
|
||||
return(0);
|
||||
|
||||
for (;i < 4;i++) {
|
||||
if (tm[i] != 0xFF)
|
||||
return(-1);
|
||||
}
|
||||
} else if (netmask->stor.ss_family == AF_INET6) {
|
||||
virIPv6Addr tm;
|
||||
unsigned short tmp;
|
||||
int ok = 0;
|
||||
|
||||
/*
|
||||
* Hum, on IPv6 people use prefixes instead of netmask
|
||||
*/
|
||||
if (getIPv6Addr(netmask, &tm) < 0)
|
||||
return(-1);
|
||||
|
||||
for (i = 0;i < 8;i++) {
|
||||
if (tm[i] != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i >= 8)
|
||||
return(0);
|
||||
|
||||
tmp = 0xFFFF;
|
||||
do {
|
||||
if (tm[i] == tmp) {
|
||||
ok = 1;
|
||||
break;
|
||||
}
|
||||
tmp <<= 1;
|
||||
} while (tmp != 0);
|
||||
if (ok == 0)
|
||||
return(-1);
|
||||
i++;
|
||||
|
||||
if (i >= 8)
|
||||
return(0);
|
||||
|
||||
for (;i < 8;i++) {
|
||||
if (tm[i] != 0xFFFF)
|
||||
return(-1);
|
||||
}
|
||||
} else {
|
||||
return(-1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* virSocketCheckNetmask:
|
||||
* @addr1: a first network address
|
||||
* @addr2: a second network address
|
||||
* @netmask: the netmask address
|
||||
*
|
||||
* Check that @addr1 and @addr2 pertain to the same @netmask address
|
||||
* range and returns the size of the range
|
||||
*
|
||||
* Returns 1 in case of success and 0 in case of failure and
|
||||
* -1 in case of error
|
||||
*/
|
||||
int virSocketCheckNetmask(virSocketAddrPtr addr1, virSocketAddrPtr addr2,
|
||||
virSocketAddrPtr netmask) {
|
||||
int i;
|
||||
|
||||
if ((addr1 == NULL) || (addr2 == NULL) || (netmask == NULL))
|
||||
return(-1);
|
||||
if ((addr1->stor.ss_family != addr2->stor.ss_family) ||
|
||||
(addr1->stor.ss_family != netmask->stor.ss_family))
|
||||
return(-1);
|
||||
|
||||
if (virSocketAddrIsNetmask(netmask) != 0)
|
||||
return(-1);
|
||||
|
||||
if (addr1->stor.ss_family == AF_INET) {
|
||||
virIPv4Addr t1, t2, tm;
|
||||
|
||||
if ((getIPv4Addr(addr1, &t1) < 0) ||
|
||||
(getIPv4Addr(addr2, &t2) < 0) ||
|
||||
(getIPv4Addr(netmask, &tm) < 0))
|
||||
return(-1);
|
||||
|
||||
for (i = 0;i < 4;i++) {
|
||||
if ((t1[i] & tm[i]) != (t2[i] & tm[i]))
|
||||
return(0);
|
||||
}
|
||||
|
||||
} else if (addr1->stor.ss_family == AF_INET) {
|
||||
virIPv6Addr t1, t2, tm;
|
||||
|
||||
if ((getIPv6Addr(addr1, &t1) < 0) ||
|
||||
(getIPv6Addr(addr2, &t2) < 0) ||
|
||||
(getIPv6Addr(netmask, &tm) < 0))
|
||||
return(-1);
|
||||
|
||||
for (i = 0;i < 8;i++) {
|
||||
if ((t1[i] & tm[i]) != (t2[i] & tm[i]))
|
||||
return(0);
|
||||
}
|
||||
|
||||
} else {
|
||||
return(-1);
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* virSocketGetRange:
|
||||
* @start: start of an IP range
|
||||
* @end: end of an IP range
|
||||
*
|
||||
* Check the order of the 2 addresses and compute the range, this
|
||||
* will return 1 for identical addresses. Errors can come from incompatible
|
||||
* addresses type, excessive range (>= 2^^16) where the two addresses are
|
||||
* unrelated or inverted start and end.
|
||||
*
|
||||
* Returns the size of the range or -1 in case of failure
|
||||
*/
|
||||
int virSocketGetRange(virSocketAddrPtr start, virSocketAddrPtr end) {
|
||||
int ret = 0, i;
|
||||
|
||||
if ((start == NULL) || (end == NULL))
|
||||
return(-1);
|
||||
if (start->stor.ss_family != end->stor.ss_family)
|
||||
return(-1);
|
||||
|
||||
if (start->stor.ss_family == AF_INET) {
|
||||
virIPv4Addr t1, t2;
|
||||
|
||||
if ((getIPv4Addr(start, &t1) < 0) ||
|
||||
(getIPv4Addr(end, &t2) < 0))
|
||||
return(-1);
|
||||
|
||||
for (i = 0;i < 2;i++) {
|
||||
if (t1[i] != t2[i])
|
||||
return(-1);
|
||||
}
|
||||
ret = (t2[2] - t1[2]) * 256 + (t2[3] - t1[3]);
|
||||
if (ret < 0)
|
||||
return(-1);
|
||||
ret++;
|
||||
} else if (start->stor.ss_family == AF_INET6) {
|
||||
virIPv6Addr t1, t2;
|
||||
|
||||
if ((getIPv6Addr(start, &t1) < 0) ||
|
||||
(getIPv6Addr(end, &t2) < 0))
|
||||
return(-1);
|
||||
|
||||
for (i = 0;i < 7;i++) {
|
||||
if (t1[i] != t2[i])
|
||||
return(-1);
|
||||
}
|
||||
ret = t2[7] - t1[7];
|
||||
if (ret < 0)
|
||||
return(-1);
|
||||
ret++;
|
||||
} else {
|
||||
return(-1);
|
||||
}
|
||||
return(ret);
|
||||
}
|
49
src/util/network.h
Normal file
49
src/util/network.h
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* network.h: network helper APIs for libvirt
|
||||
*
|
||||
* Copyright (C) 2009-2009 Red Hat, Inc.
|
||||
*
|
||||
* See COPYING.LIB for the License of this software
|
||||
*
|
||||
* Daniel Veillard <veillard@redhat.com>
|
||||
*/
|
||||
|
||||
#ifndef __VIR_NETWORK_H__
|
||||
#define __VIR_NETWORK_H__
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
|
||||
typedef union {
|
||||
struct sockaddr_storage stor;
|
||||
struct sockaddr_in inet4;
|
||||
struct sockaddr_in6 inet6;
|
||||
} virSocketAddr;
|
||||
typedef virSocketAddr *virSocketAddrPtr;
|
||||
|
||||
int virSocketParseAddr (const char *val,
|
||||
virSocketAddrPtr addr,
|
||||
int hint);
|
||||
|
||||
int virSocketParseIpv4Addr(const char *val,
|
||||
virSocketAddrPtr addr);
|
||||
|
||||
int virSocketParseIpv6Addr(const char *val,
|
||||
virSocketAddrPtr addr);
|
||||
|
||||
int virSocketAddrInNetwork(virSocketAddrPtr addr1,
|
||||
virSocketAddrPtr addr2,
|
||||
virSocketAddrPtr netmask);
|
||||
|
||||
int virSocketGetRange (virSocketAddrPtr start,
|
||||
virSocketAddrPtr end);
|
||||
|
||||
int virSocketAddrIsNetmask(virSocketAddrPtr netmask);
|
||||
|
||||
int virSocketCheckNetmask (virSocketAddrPtr addr1,
|
||||
virSocketAddrPtr addr2,
|
||||
virSocketAddrPtr netmask);
|
||||
#endif /* __VIR_NETWORK_H__ */
|
Loading…
Reference in New Issue
Block a user