mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-12 13:17:58 +03:00
New virSocketAddr utility functions
virSocketPrefixToNetmask: Given a 'prefix', which is the number of 1 bits in a netmask, fill in a virSocketAddr object with a netmask as an IP address (IPv6 or IPv4). virSocketAddrMask: Mask off the host bits in one virSocketAddr according to the netmask in another virSocketAddr. virSocketAddrMaskByPrefix, Mask off the host bits in a virSocketAddr according to a prefix (number of 1 bits in netmask). VIR_SOCKET_FAMILY: return the family of a virSocketAddr
This commit is contained in:
parent
9a4af303fc
commit
1ab80f32dd
@ -559,6 +559,9 @@ virShrinkN;
|
||||
|
||||
# network.h
|
||||
virSocketAddrIsNetmask;
|
||||
virSocketAddrMask;
|
||||
virSocketAddrMaskByPrefix;
|
||||
virSocketAddrPrefixToNetmask;
|
||||
virSocketCheckNetmask;
|
||||
virSocketFormatAddr;
|
||||
virSocketFormatAddrFull;
|
||||
|
@ -287,6 +287,59 @@ int virSocketAddrIsNetmask(virSocketAddrPtr netmask) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* virSocketAddrMask:
|
||||
* @addr: address that needs to be masked
|
||||
* @netmask: the netmask address
|
||||
*
|
||||
* Mask off the host bits of @addr according to @netmask, turning it
|
||||
* into a network address.
|
||||
*
|
||||
* Returns 0 in case of success, or -1 on error.
|
||||
*/
|
||||
int
|
||||
virSocketAddrMask(virSocketAddrPtr addr, const virSocketAddrPtr netmask)
|
||||
{
|
||||
if (addr->data.stor.ss_family != netmask->data.stor.ss_family)
|
||||
return -1;
|
||||
|
||||
if (addr->data.stor.ss_family == AF_INET) {
|
||||
addr->data.inet4.sin_addr.s_addr
|
||||
&= netmask->data.inet4.sin_addr.s_addr;
|
||||
return 0;
|
||||
}
|
||||
if (addr->data.stor.ss_family == AF_INET6) {
|
||||
int ii;
|
||||
for (ii = 0; ii < 16; ii++)
|
||||
addr->data.inet6.sin6_addr.s6_addr[ii]
|
||||
&= netmask->data.inet6.sin6_addr.s6_addr[ii];
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* virSocketAddrMaskByPrefix:
|
||||
* @addr: address that needs to be masked
|
||||
* @prefix: prefix (# of 1 bits) of netmask to apply
|
||||
*
|
||||
* Mask off the host bits of @addr according to @prefix, turning it
|
||||
* into a network address.
|
||||
*
|
||||
* Returns 0 in case of success, or -1 on error.
|
||||
*/
|
||||
int
|
||||
virSocketAddrMaskByPrefix(virSocketAddrPtr addr, unsigned int prefix)
|
||||
{
|
||||
virSocketAddr netmask;
|
||||
|
||||
if (virSocketAddrPrefixToNetmask(prefix, &netmask,
|
||||
addr->data.stor.ss_family) < 0)
|
||||
return -1;
|
||||
|
||||
return virSocketAddrMask(addr, &netmask);
|
||||
}
|
||||
|
||||
/**
|
||||
* virSocketCheckNetmask:
|
||||
* @addr1: a first network address
|
||||
@ -486,3 +539,63 @@ int virSocketGetNumNetmaskBits(const virSocketAddrPtr netmask)
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* virSocketPrefixToNetmask:
|
||||
* @prefix: number of 1 bits to put in the netmask
|
||||
* @netmask: address to fill in with the desired netmask
|
||||
* @family: family of the address (AF_INET or AF_INET6 only)
|
||||
*
|
||||
* given @prefix and @family, fill in @netmask with a netmask
|
||||
* (eg 255.255.255.0).
|
||||
*
|
||||
* Returns 0 on success or -1 on error.
|
||||
*/
|
||||
|
||||
int
|
||||
virSocketAddrPrefixToNetmask(unsigned int prefix,
|
||||
virSocketAddrPtr netmask,
|
||||
int family)
|
||||
{
|
||||
int result = -1;
|
||||
|
||||
netmask->data.stor.ss_family = AF_UNSPEC; /* assume failure */
|
||||
|
||||
if (family == AF_INET) {
|
||||
int ip;
|
||||
|
||||
if (prefix > 32)
|
||||
goto error;
|
||||
|
||||
ip = prefix ? ~((1 << (32 - prefix)) - 1) : 0;
|
||||
netmask->data.inet4.sin_addr.s_addr = htonl(ip);
|
||||
netmask->data.stor.ss_family = AF_INET;
|
||||
result = 0;
|
||||
|
||||
} else if (family == AF_INET6) {
|
||||
int ii = 0;
|
||||
|
||||
if (prefix > 128)
|
||||
goto error;
|
||||
|
||||
while (prefix >= 8) {
|
||||
/* do as much as possible an entire byte at a time */
|
||||
netmask->data.inet6.sin6_addr.s6_addr[ii++] = 0xff;
|
||||
prefix -= 8;
|
||||
}
|
||||
if (prefix > 0) {
|
||||
/* final partial byte */
|
||||
netmask->data.inet6.sin6_addr.s6_addr[ii++]
|
||||
= ~((1 << (8 - prefix)) -1);
|
||||
}
|
||||
while (ii < 16) {
|
||||
/* zerofill remainder in case it wasn't initialized */
|
||||
netmask->data.inet6.sin6_addr.s6_addr[ii++] = 0;
|
||||
}
|
||||
netmask->data.stor.ss_family = AF_INET6;
|
||||
result = 0;
|
||||
}
|
||||
|
||||
error:
|
||||
return result;
|
||||
}
|
||||
|
@ -41,6 +41,9 @@ typedef struct {
|
||||
# define VIR_SOCKET_IS_FAMILY(s, f) \
|
||||
((s)->data.sa.sa_family == f)
|
||||
|
||||
# define VIR_SOCKET_FAMILY(s) \
|
||||
((s)->data.sa.sa_family)
|
||||
|
||||
typedef virSocketAddr *virSocketAddrPtr;
|
||||
|
||||
int virSocketParseAddr (const char *val,
|
||||
@ -70,7 +73,14 @@ int virSocketAddrIsNetmask(virSocketAddrPtr netmask);
|
||||
int virSocketCheckNetmask (virSocketAddrPtr addr1,
|
||||
virSocketAddrPtr addr2,
|
||||
virSocketAddrPtr netmask);
|
||||
int virSocketAddrMask (virSocketAddrPtr addr,
|
||||
const virSocketAddrPtr netmask);
|
||||
int virSocketAddrMaskByPrefix(virSocketAddrPtr addr,
|
||||
unsigned int prefix);
|
||||
|
||||
int virSocketGetNumNetmaskBits(const virSocketAddrPtr netmask);
|
||||
int virSocketAddrPrefixToNetmask(unsigned int prefix,
|
||||
virSocketAddrPtr netmask,
|
||||
int family);
|
||||
|
||||
#endif /* __VIR_NETWORK_H__ */
|
||||
|
Loading…
Reference in New Issue
Block a user