blob: cb316b87077589282b034200d781b179bebb6176 [file] [log] [blame]
/*
* Functions to generate various networks based on a CIDR
*/
#include "config.h"
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include "cidr.h"
#include "abstract_mem.h"
/* Get the CIDR's immediate supernet */
CIDR *cidr_net_supernet(const CIDR * addr)
{
int i, j;
int pflen;
CIDR *toret;
/* If it's already a /0 in its protocol, return nothing */
pflen = cidr_get_pflen(addr);
if (pflen == 0) {
errno = 0;
return (NULL);
}
toret = cidr_dup(addr);
if (toret == NULL)
return (NULL); /* Preserve errno */
/* Chop a bit off the netmask */
/* This gets the last network bit */
if (toret->proto == CIDR_IPV4)
pflen += 96;
pflen--;
i = pflen / 8;
j = 7 - (pflen % 8);
/* Make that bit a host bit */
(toret->mask)[i] &= ~(1 << j);
/*
* Now zero out the host bits in the addr. Do this manually instead
* of calling cidr_addr_network() to save some extra copies and
* allocationss and so forth.
*/
for ( /* i */ ; i <= 15; i++) {
for ( /* j */ ; j >= 0; j--)
(toret->addr)[i] &= ~(1 << j);
j = 7;
}
/* And send it back */
return (toret);
}
/* Get the CIDR's two children */
CIDR **cidr_net_subnets(const CIDR * addr)
{
int i, j;
int pflen;
CIDR **toret;
/* You can't split a host address! */
pflen = cidr_get_pflen(addr);
if ((addr->proto == CIDR_IPV4 && pflen == 32)
|| (addr->proto == CIDR_IPV6 && pflen == 128)) {
errno = 0;
return (NULL);
}
toret = gsh_calloc(2, sizeof(CIDR *));
/* Get a blank-ish slate for the first kid */
toret[0] = cidr_addr_network(addr);
if (toret[0] == NULL) {
gsh_free(toret);
return (NULL); /* Preserve errno */
}
/* Find its first host bit */
if (toret[0]->proto == CIDR_IPV4)
pflen += 96;
i = pflen / 8;
j = 7 - (pflen % 8);
/* Make it a network bit */
(toret[0])->mask[i] |= 1 << j;
/* Now dup the second kid off that */
toret[1] = cidr_dup(toret[0]);
if (toret[1] == NULL) {
cidr_free(toret[0]);
gsh_free(toret);
return (NULL); /* Preserve errno */
}
/* And set that first host bit */
(toret[1])->addr[i] |= 1 << j;
/* Return the pair */
return (toret);
}