confip.c revision 10e6498d6d7b2cfd8d822788d817fc9a3e0b0c3a
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews/*
499b34cea04a46823d003d4c0520c8b03e8513cbBrian Wellington * Copyright (C) 1999, 2000 Internet Software Consortium.
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence *
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews * Permission to use, copy, modify, and distribute this software for any
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews * purpose with or without fee is hereby granted, provided that the above
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews * copyright notice and this permission notice appear in all copies.
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence *
15a44745412679c30a6d022733925af70a38b715David Lawrence * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
15a44745412679c30a6d022733925af70a38b715David Lawrence * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
15a44745412679c30a6d022733925af70a38b715David Lawrence * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
15a44745412679c30a6d022733925af70a38b715David Lawrence * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
15a44745412679c30a6d022733925af70a38b715David Lawrence * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
15a44745412679c30a6d022733925af70a38b715David Lawrence * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
15a44745412679c30a6d022733925af70a38b715David Lawrence * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
15a44745412679c30a6d022733925af70a38b715David Lawrence * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews */
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews
bddfe77128b0f16af263ff149db40f0d885f43d0Mark Andrews/* $Id: confip.c,v 1.38 2000/12/13 00:15:21 tale Exp $ */
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews
d0fe07af9cd5278b86bfba65c9a8391e007cd8c9Brian Wellington#include <config.h>
d0fe07af9cd5278b86bfba65c9a8391e007cd8c9Brian Wellington
d0fe07af9cd5278b86bfba65c9a8391e007cd8c9Brian Wellington
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews#include <isc/mem.h>
854d0238dbc2908490197984b3b9d558008a53dfMark Andrews#include <isc/string.h>
854d0238dbc2908490197984b3b9d558008a53dfMark Andrews#include <isc/util.h>
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff#include <dns/confip.h>
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff#include <dns/log.h>
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence/*
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews * Flag for dns_c_ipmatch_element.
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews */
ae114ded82e773a4d9058f833f964a17514712a8Brian Wellington#define DNS_C_IPMATCH_NEGATE 0x01 /* match means deny access */
ae114ded82e773a4d9058f833f964a17514712a8Brian Wellington
ae114ded82e773a4d9058f833f964a17514712a8Brian Wellington
c363150ad598e7a8ce03efe2776b8e6950f0de7bBrian Wellingtonstatic isc_result_t checkmask(isc_sockaddr_t *address, isc_uint32_t bits);
c363150ad598e7a8ce03efe2776b8e6950f0de7bBrian Wellingtonstatic isc_result_t bits2v6mask(struct in6_addr *addr, isc_uint32_t bits);
c363150ad598e7a8ce03efe2776b8e6950f0de7bBrian Wellington
bddfe77128b0f16af263ff149db40f0d885f43d0Mark Andrewsisc_result_t
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrewsdns_c_ipmatchelement_new(isc_mem_t *mem, dns_c_ipmatchelement_t **result) {
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews dns_c_ipmatchelement_t *ime ;
add4043305ca411202ed9cf1929a4179016515ceBrian Wellington
add4043305ca411202ed9cf1929a4179016515ceBrian Wellington REQUIRE(result != NULL);
9ac7076ebad044afb15e9e2687e3696868778538Mark Andrews
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews *result = NULL;
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews
add4043305ca411202ed9cf1929a4179016515ceBrian Wellington ime = isc_mem_get(mem, sizeof(*ime));
add4043305ca411202ed9cf1929a4179016515ceBrian Wellington if (ime == NULL) {
5dcb42f5bbd41da02a0b32a11a1912f7b90686a8Andreas Gustafsson return (ISC_R_NOMEMORY);
5dcb42f5bbd41da02a0b32a11a1912f7b90686a8Andreas Gustafsson }
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff ime->magic = DNS_C_IPMELEM_MAGIC;
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews ime->type = dns_c_ipmatch_none;
9ac7076ebad044afb15e9e2687e3696868778538Mark Andrews ime->flags = 0;
9ac7076ebad044afb15e9e2687e3696868778538Mark Andrews memset(&ime->u, 0x0, sizeof(ime->u));
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews ISC_LINK_INIT(ime, next);
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence *result = ime;
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews return (ISC_R_SUCCESS);
d0fe07af9cd5278b86bfba65c9a8391e007cd8c9Brian Wellington}
b589e90689c6e87bf9608424ca8d99571c18bc61Mark Andrews
d0fe07af9cd5278b86bfba65c9a8391e007cd8c9Brian Wellingtonisc_boolean_t
ae114ded82e773a4d9058f833f964a17514712a8Brian Wellingtondns_c_ipmatchelement_isneg(dns_c_ipmatchelement_t *elem) {
ae114ded82e773a4d9058f833f964a17514712a8Brian Wellington
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews REQUIRE(DNS_C_IPMELEM_VALID(elem));
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews return (ISC_TF((elem->flags & DNS_C_IPMATCH_NEGATE) ==
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff DNS_C_IPMATCH_NEGATE));
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews}
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrewsisc_result_t
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrewsdns_c_ipmatchelement_delete(isc_mem_t *mem, dns_c_ipmatchelement_t **ipme) {
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff dns_c_ipmatchelement_t *elem;
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence
ae114ded82e773a4d9058f833f964a17514712a8Brian Wellington REQUIRE(mem != NULL);
ae114ded82e773a4d9058f833f964a17514712a8Brian Wellington REQUIRE(ipme != NULL);
ae114ded82e773a4d9058f833f964a17514712a8Brian Wellington REQUIRE(*ipme != NULL);
c363150ad598e7a8ce03efe2776b8e6950f0de7bBrian Wellington
c363150ad598e7a8ce03efe2776b8e6950f0de7bBrian Wellington elem = *ipme;
c363150ad598e7a8ce03efe2776b8e6950f0de7bBrian Wellington
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews REQUIRE(DNS_C_IPMELEM_VALID(elem));
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews switch (elem->type) {
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff case dns_c_ipmatch_localhost:
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews case dns_c_ipmatch_localnets:
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews case dns_c_ipmatch_pattern:
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews /* nothing */
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff break;
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence
c363150ad598e7a8ce03efe2776b8e6950f0de7bBrian Wellington case dns_c_ipmatch_indirect:
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews INSIST(elem->u.indirect.list != NULL);
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews
b589e90689c6e87bf9608424ca8d99571c18bc61Mark Andrews if (elem->u.indirect.list != NULL)
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews dns_c_ipmatchlist_detach(&elem->u.indirect.list);
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews if (elem->u.indirect.refname.base != NULL) {
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews isc_mem_put(mem, elem->u.indirect.refname.base,
4529cdaedaf1a0a5f8ff89aeca510b7a4475446cBob Halley elem->u.indirect.refname.length);
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence }
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews break;
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence case dns_c_ipmatch_key:
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews isc_mem_free(mem, elem->u.key);
d981ca645597116d227a48bf37cc5edc061c854dBob Halley break;
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews
b589e90689c6e87bf9608424ca8d99571c18bc61Mark Andrews case dns_c_ipmatch_acl:
b589e90689c6e87bf9608424ca8d99571c18bc61Mark Andrews isc_mem_free(mem, elem->u.aclname);
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews break;
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews case dns_c_ipmatch_any:
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews /* nothing */
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews break;
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff case dns_c_ipmatch_none:
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG,
373ce67419680a398ba3dc51a14a486caaf0afb0Mark Andrews DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL,
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews "dns_ipmath_none element type");
d0fe07af9cd5278b86bfba65c9a8391e007cd8c9Brian Wellington return (ISC_R_FAILURE);
373ce67419680a398ba3dc51a14a486caaf0afb0Mark Andrews }
373ce67419680a398ba3dc51a14a486caaf0afb0Mark Andrews
373ce67419680a398ba3dc51a14a486caaf0afb0Mark Andrews elem->magic = 0;
373ce67419680a398ba3dc51a14a486caaf0afb0Mark Andrews isc_mem_put(mem, elem, sizeof(*elem));
ae114ded82e773a4d9058f833f964a17514712a8Brian Wellington
63cef8bde8b92aeb30ccdcf21d4e44c9be9cc6e3Andreas Gustafsson *ipme = NULL;
63cef8bde8b92aeb30ccdcf21d4e44c9be9cc6e3Andreas Gustafsson
373ce67419680a398ba3dc51a14a486caaf0afb0Mark Andrews return (ISC_R_SUCCESS);
373ce67419680a398ba3dc51a14a486caaf0afb0Mark Andrews}
373ce67419680a398ba3dc51a14a486caaf0afb0Mark Andrews
373ce67419680a398ba3dc51a14a486caaf0afb0Mark Andrewsisc_result_t
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrewsdns_c_ipmatchelement_copy(isc_mem_t *mem,
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews dns_c_ipmatchelement_t **dest,
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff dns_c_ipmatchelement_t *src)
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence{
9281e7aa775026dc47c01745fdcc438645146877Mark Andrews isc_result_t result;
9281e7aa775026dc47c01745fdcc438645146877Mark Andrews dns_c_ipmatchelement_t *newel;
9281e7aa775026dc47c01745fdcc438645146877Mark Andrews
82ca33427bdd4f3bc4ed3431e86bd810fe751674Andreas Gustafsson REQUIRE(mem != NULL);
9281e7aa775026dc47c01745fdcc438645146877Mark Andrews REQUIRE(dest != NULL);
b589e90689c6e87bf9608424ca8d99571c18bc61Mark Andrews REQUIRE(DNS_C_IPMELEM_VALID(src));
82ca33427bdd4f3bc4ed3431e86bd810fe751674Andreas Gustafsson
9281e7aa775026dc47c01745fdcc438645146877Mark Andrews result = dns_c_ipmatchelement_new(mem, &newel);
9281e7aa775026dc47c01745fdcc438645146877Mark Andrews if (result != ISC_R_SUCCESS) {
9281e7aa775026dc47c01745fdcc438645146877Mark Andrews return (result);
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews }
9281e7aa775026dc47c01745fdcc438645146877Mark Andrews
9281e7aa775026dc47c01745fdcc438645146877Mark Andrews newel->type = src->type;
9281e7aa775026dc47c01745fdcc438645146877Mark Andrews newel->flags = src->flags;
9281e7aa775026dc47c01745fdcc438645146877Mark Andrews
85bdc128fcda11c89ec1d76ea4221f4fa8e4fc24Mark Andrews switch(src->type) {
85bdc128fcda11c89ec1d76ea4221f4fa8e4fc24Mark Andrews case dns_c_ipmatch_pattern:
85bdc128fcda11c89ec1d76ea4221f4fa8e4fc24Mark Andrews newel->u.direct.address = src->u.direct.address;
85bdc128fcda11c89ec1d76ea4221f4fa8e4fc24Mark Andrews newel->u.direct.mask = src->u.direct.mask;
9281e7aa775026dc47c01745fdcc438645146877Mark Andrews break;
9281e7aa775026dc47c01745fdcc438645146877Mark Andrews
9281e7aa775026dc47c01745fdcc438645146877Mark Andrews case dns_c_ipmatch_indirect:
85bdc128fcda11c89ec1d76ea4221f4fa8e4fc24Mark Andrews result = dns_c_ipmatchlist_copy(mem,
85bdc128fcda11c89ec1d76ea4221f4fa8e4fc24Mark Andrews &newel->u.indirect.list,
85bdc128fcda11c89ec1d76ea4221f4fa8e4fc24Mark Andrews src->u.indirect.list);
9281e7aa775026dc47c01745fdcc438645146877Mark Andrews break;
9281e7aa775026dc47c01745fdcc438645146877Mark Andrews
9281e7aa775026dc47c01745fdcc438645146877Mark Andrews case dns_c_ipmatch_localhost:
9281e7aa775026dc47c01745fdcc438645146877Mark Andrews break;
9281e7aa775026dc47c01745fdcc438645146877Mark Andrews
9281e7aa775026dc47c01745fdcc438645146877Mark Andrews case dns_c_ipmatch_localnets:
9281e7aa775026dc47c01745fdcc438645146877Mark Andrews break;
9281e7aa775026dc47c01745fdcc438645146877Mark Andrews
1c3191528684f3dd93ebb122298c2f8ebfc6d397Mark Andrews case dns_c_ipmatch_key:
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews newel->u.key = isc_mem_strdup(mem, src->u.key);
4529cdaedaf1a0a5f8ff89aeca510b7a4475446cBob Halley break;
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence
9281e7aa775026dc47c01745fdcc438645146877Mark Andrews case dns_c_ipmatch_acl:
82ca33427bdd4f3bc4ed3431e86bd810fe751674Andreas Gustafsson newel->u.aclname = isc_mem_strdup(mem, src->u.aclname);
9281e7aa775026dc47c01745fdcc438645146877Mark Andrews break;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
9281e7aa775026dc47c01745fdcc438645146877Mark Andrews case dns_c_ipmatch_any:
9281e7aa775026dc47c01745fdcc438645146877Mark Andrews break;
9281e7aa775026dc47c01745fdcc438645146877Mark Andrews
9281e7aa775026dc47c01745fdcc438645146877Mark Andrews case dns_c_ipmatch_none:
9281e7aa775026dc47c01745fdcc438645146877Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG,
9281e7aa775026dc47c01745fdcc438645146877Mark Andrews DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL,
9281e7aa775026dc47c01745fdcc438645146877Mark Andrews "ipmatch 'none' element type");
9281e7aa775026dc47c01745fdcc438645146877Mark Andrews return (ISC_R_FAILURE);
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews }
d981ca645597116d227a48bf37cc5edc061c854dBob Halley
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff *dest = newel;
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence
82ca33427bdd4f3bc4ed3431e86bd810fe751674Andreas Gustafsson return (ISC_R_SUCCESS);
82ca33427bdd4f3bc4ed3431e86bd810fe751674Andreas Gustafsson}
82ca33427bdd4f3bc4ed3431e86bd810fe751674Andreas Gustafsson
c363150ad598e7a8ce03efe2776b8e6950f0de7bBrian Wellingtonisc_boolean_t
c363150ad598e7a8ce03efe2776b8e6950f0de7bBrian Wellingtondns_c_ipmatchelement_equal(dns_c_ipmatchelement_t *e1,
d981ca645597116d227a48bf37cc5edc061c854dBob Halley dns_c_ipmatchelement_t *e2)
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff{
d981ca645597116d227a48bf37cc5edc061c854dBob Halley REQUIRE(DNS_C_IPMELEM_VALID(e1));
d981ca645597116d227a48bf37cc5edc061c854dBob Halley REQUIRE(DNS_C_IPMELEM_VALID(e2));
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence if ((e1->type != e2->type) || (e1->flags != e2->flags))
e27a69f8bd9538e08f775265167ba6cc5f47c587Bob Halley return (ISC_FALSE);
e27a69f8bd9538e08f775265167ba6cc5f47c587Bob Halley
e27a69f8bd9538e08f775265167ba6cc5f47c587Bob Halley switch (e1->type) {
e27a69f8bd9538e08f775265167ba6cc5f47c587Bob Halley case dns_c_ipmatch_pattern:
e27a69f8bd9538e08f775265167ba6cc5f47c587Bob Halley if (e1->u.direct.mask != e2->u.direct.mask)
e27a69f8bd9538e08f775265167ba6cc5f47c587Bob Halley return (ISC_FALSE);
e27a69f8bd9538e08f775265167ba6cc5f47c587Bob Halley return (isc_sockaddr_equal(&e1->u.direct.address,
e27a69f8bd9538e08f775265167ba6cc5f47c587Bob Halley &e2->u.direct.address));
e27a69f8bd9538e08f775265167ba6cc5f47c587Bob Halley
854d0238dbc2908490197984b3b9d558008a53dfMark Andrews case dns_c_ipmatch_indirect:
return (dns_c_ipmatchlist_equal(e1->u.indirect.list,
e2->u.indirect.list));
case dns_c_ipmatch_localhost:
break;
case dns_c_ipmatch_localnets:
break;
case dns_c_ipmatch_key:
return (ISC_TF(strcmp(e1->u.key, e2->u.key) == 0));
case dns_c_ipmatch_acl:
return (ISC_TF(strcmp(e1->u.aclname, e2->u.aclname) == 0));
case dns_c_ipmatch_any:
break;
case dns_c_ipmatch_none:
break;
}
return (ISC_TRUE);
}
isc_result_t
dns_c_ipmatchlocalhost_new(isc_mem_t *mem, dns_c_ipmatchelement_t **result) {
dns_c_ipmatchelement_t *ime = NULL;
isc_result_t res;
REQUIRE(mem != NULL);
REQUIRE(result != NULL);
*result = NULL;
res = dns_c_ipmatchelement_new(mem, &ime);
if (res == ISC_R_SUCCESS) {
ime->type = dns_c_ipmatch_localhost;
}
*result = ime;
return (res);
}
isc_result_t
dns_c_ipmatchlocalnets_new(isc_mem_t *mem, dns_c_ipmatchelement_t **result) {
dns_c_ipmatchelement_t *ime = NULL;
isc_result_t res;
REQUIRE(mem != NULL);
REQUIRE(result != NULL);
*result = NULL;
res = dns_c_ipmatchelement_new(mem, &ime);
if (res == ISC_R_SUCCESS) {
ime->type = dns_c_ipmatch_localnets;
}
*result = ime;
return (res);
}
isc_result_t
dns_c_ipmatchany_new(isc_mem_t *mem, dns_c_ipmatchelement_t **result) {
dns_c_ipmatchelement_t *ime = NULL;
isc_result_t res;
REQUIRE(mem != NULL);
REQUIRE(result != NULL);
*result = NULL;
res = dns_c_ipmatchelement_new(mem, &ime);
if (res == ISC_R_SUCCESS) {
ime->type = dns_c_ipmatch_any;
}
*result = ime;
return (res);
}
isc_result_t
dns_c_ipmatchindirect_new(isc_mem_t *mem,
dns_c_ipmatchelement_t **result,
dns_c_ipmatchlist_t *iml,
const char *name)
{
dns_c_ipmatchelement_t *ime;
dns_c_ipmatchlist_t *iml_copy;
isc_result_t res;
REQUIRE(mem != NULL);
REQUIRE(result != NULL);
REQUIRE(DNS_C_IPMLIST_VALID(iml));
*result = NULL;
res = dns_c_ipmatchlist_copy(mem, &iml_copy, iml);
if (res != ISC_R_SUCCESS) {
return (res);
}
res = dns_c_ipmatchelement_new(mem, &ime);
if (res == ISC_R_SUCCESS) {
ime->type = dns_c_ipmatch_indirect;
ime->u.indirect.list = iml_copy;
if (name != NULL) {
ime->u.indirect.refname.length = strlen(name) + 1;
ime->u.indirect.refname.base =
isc_mem_get(mem,
ime->u.indirect.refname.length);
RUNTIME_CHECK(ime->u.indirect.refname.base != NULL);
strcpy(ime->u.indirect.refname.base, name);
}
} else {
dns_c_ipmatchlist_detach(&iml_copy);
}
*result = ime;
return (res);
}
isc_result_t
dns_c_ipmatchpattern_new(isc_mem_t *mem,
dns_c_ipmatchelement_t **result,
isc_sockaddr_t address,
isc_uint32_t maskbits)
{
dns_c_ipmatchelement_t *ime ;
isc_result_t res;
REQUIRE(result != NULL);
REQUIRE(mem != NULL);
*result = NULL;
res = checkmask(&address, maskbits);
if (res != ISC_R_SUCCESS) {
isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG,
DNS_LOGMODULE_CONFIG, ISC_LOG_ERROR,
"host portion of network address is not zero");
return (res);
}
res = dns_c_ipmatchelement_new(mem, &ime);
if (res != ISC_R_SUCCESS) {
return (res);
}
ime->type = dns_c_ipmatch_pattern;
ime->u.direct.address = address;
ime->u.direct.mask = maskbits;
*result = ime;
return (ISC_R_SUCCESS);
}
isc_result_t
dns_c_ipmatchkey_new(isc_mem_t *mem,
dns_c_ipmatchelement_t **result,
const char *key)
{
dns_c_ipmatchelement_t *ipme;
isc_result_t res;
REQUIRE(result != NULL);
REQUIRE(mem != NULL);
REQUIRE(key != NULL);
*result = NULL;
res = dns_c_ipmatchelement_new(mem, &ipme);
if (res != ISC_R_SUCCESS) {
return (res);
}
ipme->type = dns_c_ipmatch_key;
ipme->u.key = isc_mem_strdup(mem, key);
*result = ipme;
return (ISC_R_SUCCESS);
}
isc_result_t
dns_c_ipmatch_aclnew(isc_mem_t *mem,
dns_c_ipmatchelement_t **result,
const char *aclname)
{
dns_c_ipmatchelement_t *ipme;
isc_result_t res;
REQUIRE(result != NULL);
REQUIRE(mem != NULL);
REQUIRE(aclname != NULL);
REQUIRE(*aclname != '\0');
*result = NULL;
res = dns_c_ipmatchelement_new(mem, &ipme);
if (res != ISC_R_SUCCESS) {
return (res);
}
ipme->type = dns_c_ipmatch_acl;
ipme->u.aclname = isc_mem_strdup(mem, aclname);
*result = ipme;
return (ISC_R_SUCCESS);
}
isc_result_t
dns_c_ipmatch_negate(dns_c_ipmatchelement_t *ipe) {
REQUIRE(DNS_C_IPMELEM_VALID(ipe));
if ((ipe->flags & DNS_C_IPMATCH_NEGATE) == DNS_C_IPMATCH_NEGATE) {
ipe->flags &= ~DNS_C_IPMATCH_NEGATE;
} else {
ipe->flags |= DNS_C_IPMATCH_NEGATE;
}
return (ISC_R_SUCCESS);
}
isc_result_t
dns_c_ipmatchlist_new(isc_mem_t *mem, dns_c_ipmatchlist_t **ptr) {
dns_c_ipmatchlist_t *newlist;
REQUIRE(ptr != NULL);
REQUIRE(mem != NULL);
newlist = isc_mem_get(mem, sizeof(*newlist));
if (newlist == NULL) {
return (ISC_R_NOMEMORY);
}
newlist->magic = DNS_C_IPMLIST_MAGIC;
newlist->mem = mem;
newlist->refcount = 1;
ISC_LIST_INIT(newlist->elements);
*ptr = newlist;
return (ISC_R_SUCCESS);
}
isc_result_t
dns_c_ipmatchlist_detach(dns_c_ipmatchlist_t **ml) {
dns_c_ipmatchelement_t *ime;
dns_c_ipmatchelement_t *iptr;
dns_c_ipmatchlist_t *iml;
isc_mem_t *mem;
REQUIRE(ml != NULL);
REQUIRE(*ml != NULL);
iml = *ml;
*ml = NULL;
REQUIRE(DNS_C_IPMLIST_VALID(iml));
INSIST(iml->refcount > 0);
iml->refcount--;
if (iml->refcount > 0) {
return (ISC_R_SUCCESS);
}
mem = iml->mem;
INSIST(mem != NULL);
ime = ISC_LIST_HEAD(iml->elements);
while (ime != NULL) {
iptr = ISC_LIST_NEXT(ime, next);
dns_c_ipmatchelement_delete(mem, &ime);
ime = iptr;
}
isc_mem_put(mem, iml, sizeof(*iml));
return (ISC_R_SUCCESS);
}
void
dns_c_ipmatchlist_attach(dns_c_ipmatchlist_t *source,
dns_c_ipmatchlist_t **target)
{
REQUIRE(DNS_C_IPMLIST_VALID(source));
INSIST(source->refcount > 0);
source->refcount++;
*target = source;
}
isc_result_t
dns_c_ipmatchlist_empty(dns_c_ipmatchlist_t *ipml) {
dns_c_ipmatchelement_t *ime ;
dns_c_ipmatchelement_t *imptmp;
isc_result_t res = ISC_R_SUCCESS;
REQUIRE(DNS_C_IPMLIST_VALID(ipml));
ime = ISC_LIST_HEAD(ipml->elements);
while (ime != NULL) {
imptmp = ISC_LIST_NEXT(ime, next);
res = dns_c_ipmatchelement_delete(ipml->mem, &ime);
if (res != ISC_R_SUCCESS) {
break;
}
ime = imptmp;
}
return (res);
}
isc_result_t
dns_c_ipmatchlist_copy(isc_mem_t *mem,
dns_c_ipmatchlist_t **dest, dns_c_ipmatchlist_t *src)
{
dns_c_ipmatchelement_t *ime;
dns_c_ipmatchelement_t *ptr;
dns_c_ipmatchlist_t *newlist;
isc_result_t result;
REQUIRE(mem != NULL);
REQUIRE(dest != NULL);
REQUIRE(DNS_C_IPMLIST_VALID(src));
*dest = NULL;
result = dns_c_ipmatchlist_new(mem, &newlist);
if (result != ISC_R_SUCCESS) {
return (result);
}
ime = ISC_LIST_HEAD(src->elements);
while (ime != NULL) {
result = dns_c_ipmatchelement_copy(mem, &ptr, ime);
if (result != ISC_R_SUCCESS) {
dns_c_ipmatchlist_detach(&newlist);
return (result);
}
ISC_LIST_APPEND(newlist->elements, ptr, next);
ime = ISC_LIST_NEXT(ime, next);
}
*dest = newlist;
return (ISC_R_SUCCESS);
}
isc_boolean_t
dns_c_ipmatchlist_equal(dns_c_ipmatchlist_t *l1, dns_c_ipmatchlist_t *l2) {
dns_c_ipmatchelement_t *e1, *e2;
REQUIRE(l1 == NULL || DNS_C_IPMLIST_VALID(l1));
REQUIRE(l2 == NULL || DNS_C_IPMLIST_VALID(l2));
if (l1 == NULL && l2 == NULL)
return (ISC_TRUE);
if (l1 != NULL || l2 != NULL)
return (ISC_FALSE);
e1 = ISC_LIST_HEAD(l1->elements);
e2 = ISC_LIST_HEAD(l2->elements);
while (e1 != NULL && e2 != NULL) {
if (!dns_c_ipmatchelement_equal(e1, e2))
return (ISC_FALSE);
e1 = ISC_LIST_NEXT(e1, next);
e2 = ISC_LIST_NEXT(e2, next);
}
if (l1 != NULL || l2 != NULL)
return (ISC_FALSE);
return (ISC_TRUE);
}
isc_result_t
dns_c_ipmatchlist_append(dns_c_ipmatchlist_t *dest,
dns_c_ipmatchlist_t *src,
isc_boolean_t negate)
{
dns_c_ipmatchelement_t *ime;
dns_c_ipmatchelement_t *ime_copy;
isc_result_t result = ISC_R_SUCCESS;
REQUIRE(DNS_C_IPMLIST_VALID(dest));
REQUIRE(DNS_C_IPMLIST_VALID(src));
ime = ISC_LIST_HEAD(src->elements);
while (ime != NULL) {
result = dns_c_ipmatchelement_copy(dest->mem,
&ime_copy,
ime);
if (result != ISC_R_SUCCESS) {
break;
}
if (negate) {
dns_c_ipmatch_negate(ime_copy);
}
ISC_LIST_APPEND(dest->elements, ime_copy, next);
ime = ISC_LIST_NEXT(ime, next);
}
return (result);
}
isc_result_t
dns_c_ipmatchelement_print(FILE *fp, int indent, dns_c_ipmatchelement_t *ipme)
{
int bits;
REQUIRE(fp != NULL);
REQUIRE(DNS_C_IPMELEM_VALID(ipme));
if (dns_c_ipmatchelement_isneg(ipme) &&
ipme->type != dns_c_ipmatch_any) {
/* a '!any' element gets printed as 'none' */
fputc('!', fp);
} else {
fputc(' ', fp);
}
switch (ipme->type) {
case dns_c_ipmatch_pattern:
dns_c_print_ipaddr(fp, &ipme->u.direct.address);
bits = ipme->u.direct.mask;
if (bits > 0) {
isc_uint32_t fam =
ipme->u.direct.address.type.sa.sa_family;
if ((fam == AF_INET && bits < 32) ||
(fam == AF_INET6 && bits < 128)) {
fprintf(fp, "/%d", bits);
}
}
break;
case dns_c_ipmatch_indirect:
if (ipme->u.indirect.refname.base != NULL) {
fprintf(fp, "%s", ipme->u.indirect.refname.base);
} else {
dns_c_ipmatchlist_print(fp, indent,
ipme->u.indirect.list);
}
break;
case dns_c_ipmatch_key:
fprintf(fp, "key %s", ipme->u.key);
break;
case dns_c_ipmatch_localhost:
fprintf(fp, "localhost");
break;
case dns_c_ipmatch_localnets:
fprintf(fp, "localnets");
break;
case dns_c_ipmatch_any:
if (dns_c_ipmatchelement_isneg(ipme)) {
fprintf(fp, "none");
} else {
fprintf(fp, "any");
}
break;
case dns_c_ipmatch_none:
isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG,
DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL,
"dns_ipmatch_none element type");
return (ISC_R_FAILURE);
case dns_c_ipmatch_acl:
fprintf(fp, "%s", ipme->u.aclname);
break;
}
return (ISC_R_SUCCESS);
}
isc_result_t
dns_c_ipmatchlist_print(FILE *fp, int indent, dns_c_ipmatchlist_t *ml) {
dns_c_ipmatchelement_t *ipme ;
REQUIRE(DNS_C_IPMLIST_VALID(ml));
REQUIRE(fp != NULL);
/* no indent on first line. */
fprintf(fp, "{\n");
ipme = ISC_LIST_HEAD(ml->elements);
if (ipme == NULL) {
dns_c_printtabs(fp, indent);
fprintf(fp,
"/* this list intentionally left blank */\n");
} else {
while (ipme != NULL) {
dns_c_printtabs(fp, indent);
dns_c_ipmatchelement_print(fp, indent + 1, ipme);
fprintf(fp, ";\n");
ipme = ISC_LIST_NEXT(ipme, next);
}
}
dns_c_printtabs(fp, indent - 1);
fprintf(fp, "}");
return (ISC_R_SUCCESS);
}
isc_boolean_t
dns_c_ipmatchlist_walk(dns_c_ipmatchlist_t *list, dns_c_ipmlwalker func)
{
isc_boolean_t retval = ISC_TRUE;
dns_c_ipmatchelement_t *ipme ;
REQUIRE(DNS_C_IPMLIST_VALID(list));
ipme = ISC_LIST_HEAD(list->elements);
while (retval == ISC_TRUE && ipme != NULL) {
switch (ipme->type) {
case dns_c_ipmatch_pattern:
case dns_c_ipmatch_key:
case dns_c_ipmatch_localhost:
case dns_c_ipmatch_localnets:
case dns_c_ipmatch_any:
case dns_c_ipmatch_none:
retval = ISC_TF(retval && (*func)(ipme));
break;
case dns_c_ipmatch_indirect:
retval = ISC_TF(retval &&
dns_c_ipmatchlist_walk(ipme->
u.indirect.list,
func));
break;
default:
break;
}
ipme = ISC_LIST_NEXT(ipme, next);
}
return (retval);
}
isc_result_t
dns_c_iplist_new(isc_mem_t *mem, int length, dns_c_iplist_t **newlist) {
dns_c_iplist_t *list;
size_t bytes;
int i;
REQUIRE(mem != NULL);
REQUIRE(length > 0);
REQUIRE(newlist != NULL);
list = isc_mem_get(mem, sizeof(*list));
if (list == NULL) {
return (ISC_R_NOMEMORY);
}
bytes = sizeof(isc_sockaddr_t) * length;
list->ips = isc_mem_get(mem, bytes);
if (list->ips == NULL) {
isc_mem_put(mem, list, sizeof(*list));
return (ISC_R_NOMEMORY);
}
memset(list->ips, 0x0, bytes);
bytes = sizeof(dns_name_t *) * length;
list->keys = isc_mem_get(mem, bytes);
if (list->keys == NULL) {
isc_mem_put(mem, list->ips, sizeof(isc_sockaddr_t) * length);
isc_mem_put(mem, list, sizeof(*list));
return (ISC_R_NOMEMORY);
}
for (i = 0 ; i < length ; i++)
list->keys[i] = NULL;
list->magic = DNS_C_IPLIST_MAGIC;
list->size = length;
list->nextidx = 0;
list->mem = mem;
list->refcount = 1;
*newlist = list;
return (ISC_R_SUCCESS);
}
isc_result_t
dns_c_iplist_detach(dns_c_iplist_t **list) {
dns_c_iplist_t *l ;
unsigned int i;
REQUIRE(list != NULL);
REQUIRE(*list != NULL);
l = *list;
REQUIRE(DNS_C_IPLIST_VALID(l));
INSIST(l->refcount > 0);
l->refcount--;
if (l->refcount == 0) {
for (i = 0 ; i < l->size ; i++) {
if (l->keys[i] != NULL) {
dns_name_free(l->keys[i], l->mem);
isc_mem_put(l->mem, l->keys[i],
sizeof(dns_name_t));
l->keys[i] = NULL;
}
}
isc_mem_put(l->mem, l->keys, sizeof(dns_name_t *) * l->size);
isc_mem_put(l->mem, l->ips, sizeof(isc_sockaddr_t) * l->size);
isc_mem_put(l->mem, l, sizeof(*l));
}
*list = NULL;
return (ISC_R_SUCCESS);
}
isc_boolean_t
dns_c_iplist_haskeys(dns_c_iplist_t *list)
{
unsigned int i;
if (list->keys == NULL)
return (ISC_FALSE);
for (i = 0 ; i < list->nextidx ; i++) {
if (list->keys[i] != NULL)
return (ISC_TRUE);
}
return (ISC_FALSE);
}
void
dns_c_iplist_attach(dns_c_iplist_t *source, dns_c_iplist_t **target) {
REQUIRE(DNS_C_IPLIST_VALID(source));
INSIST(source->refcount > 0);
source->refcount++;
*target = source;
}
isc_result_t
dns_c_iplist_copy(isc_mem_t *mem, dns_c_iplist_t **dest, dns_c_iplist_t *src) {
dns_c_iplist_t *newl;
isc_result_t res;
isc_uint32_t i;
REQUIRE(dest != NULL);
REQUIRE(DNS_C_IPLIST_VALID(src));
res = dns_c_iplist_new(mem, src->size, &newl);
if (res != ISC_R_SUCCESS)
return (res);
for (i = 0 ; i < src->nextidx ; i++) {
newl->ips[i] = src->ips[i];
newl->keys[i] = NULL;
if (src->keys[i] != NULL) {
newl->keys[i] = isc_mem_get(mem, sizeof(dns_name_t));
if (newl->keys[i] == NULL) {
dns_c_iplist_detach(&newl);
return (ISC_R_NOMEMORY);
} else {
res = dns_name_dup(src->keys[i], mem,
newl->keys[i]);
if (res != ISC_R_SUCCESS) {
dns_c_iplist_detach(&newl);
return (res);
}
}
}
}
newl->nextidx = src->nextidx;
*dest = newl;
return (ISC_R_SUCCESS);
}
isc_boolean_t
dns_c_iplist_equal(dns_c_iplist_t *list1, dns_c_iplist_t *list2) {
isc_uint32_t i;
REQUIRE(DNS_C_IPLIST_VALID(list1));
REQUIRE(DNS_C_IPLIST_VALID(list2));
if (list1->nextidx != list2->nextidx)
return (ISC_FALSE);
for (i = 0 ; i < list1->nextidx ; i++) {
if (!isc_sockaddr_equal(&list1->ips[i], &list2->ips[i]))
return (ISC_FALSE);
if ((list1->keys[i] == NULL && list2->keys[i] != NULL) ||
(list1->keys[i] != NULL && list2->keys[i] == NULL))
return (ISC_FALSE);
if (list1->keys[i] != NULL &&
!dns_name_equal(list1->keys[i], list2->keys[i]))
return (ISC_FALSE);
}
return (ISC_TRUE);
}
void
dns_c_iplist_printfully(FILE *fp, int indent, isc_boolean_t porttoo,
dns_c_iplist_t *list)
{
isc_uint32_t i;
in_port_t port;
in_port_t tmpport;
isc_boolean_t athead = ISC_TRUE;
REQUIRE(DNS_C_IPLIST_VALID(list));
if (list->nextidx == 0) {
fputc('{', fp);
fputc('\n', fp);
dns_c_printtabs(fp, indent);
fprintf(fp, "/* no ip addresses defined */\n");
dns_c_printtabs(fp, indent - 1);
fputc('}', fp);
} else {
if (porttoo) {
port = isc_sockaddr_getport(&list->ips[0]);
for (i = 0 ; i < list->nextidx ; i++) {
tmpport = isc_sockaddr_getport(&list->ips[i]);
if (tmpport != port) {
athead = ISC_FALSE;
}
}
if (athead) {
fprintf(fp, "port %d ", port);
}
}
fputc('{', fp);
fputc('\n', fp);
for (i = 0 ; i < list->nextidx ; i++) {
dns_c_printtabs(fp, indent);
dns_c_print_ipaddr(fp, &list->ips[i]);
if (!athead) {
fprintf(fp, " port %d",
isc_sockaddr_getport(&list->ips[i]));
}
if (list->keys[i] != NULL) {
fprintf(fp, " key \"");
dns_name_print(list->keys[i], fp);
fprintf(fp, "\" ");
}
fprintf(fp, ";\n");
}
dns_c_printtabs(fp, indent - 1);
fputc('}', fp);
}
fputc('\n', fp);
}
void
dns_c_iplist_print(FILE *fp, int indent, dns_c_iplist_t *list) {
dns_c_iplist_printfully(fp, indent, ISC_FALSE, list);
}
isc_result_t
dns_c_iplist_append(dns_c_iplist_t *list, isc_sockaddr_t newaddr,
const char *key)
{
isc_uint32_t i;
isc_result_t res;
REQUIRE(DNS_C_IPLIST_VALID(list));
for (i = 0 ; i < list->nextidx ; i++) {
if (memcmp(&list->ips[i], &newaddr, sizeof(newaddr)) == 0) {
break;
}
}
if (i < list->nextidx)
return (ISC_R_FAILURE);
if (list->nextidx == list->size) {
isc_sockaddr_t *newlist;
dns_name_t **newkeys;
size_t newbytes;
size_t oldbytes = list->size * sizeof(list->ips[0]);
size_t newsize = list->size + 10;
newbytes = sizeof(list->ips[0]) * newsize;
newlist = isc_mem_get(list->mem, newbytes);
if (newlist == NULL)
return (ISC_R_NOMEMORY);
memset(newlist, 0x0, newbytes);
memcpy(newlist, list->ips, oldbytes);
isc_mem_put(list->mem, list->ips, oldbytes);
list->ips = newlist;
oldbytes = sizeof(dns_name_t *) * list->size;
newbytes = sizeof(dns_name_t *) * newsize;
newkeys = isc_mem_get(list->mem, newbytes);
if (newkeys == NULL)
return (ISC_R_NOMEMORY);
for (i = 0 ; i < list->size ; i++) {
newkeys[i] = list->keys[i];
list->keys[i] = NULL;
}
for (i = list->size ; i < newsize ; i++)
newkeys[i] = NULL;
isc_mem_put(list->mem, list->keys, oldbytes);
list->keys = newkeys;
i = list->size;
list->size = newsize;
}
list->ips[i] = newaddr;
list->nextidx++;
res = ISC_R_SUCCESS;
if (key != NULL) {
if (list->keys[i] != NULL) {
dns_name_free(list->keys[i], list->mem);
isc_mem_put(list->mem, list->keys,
sizeof(dns_name_t));
list->keys[i] = NULL;
}
res = dns_c_charptoname(list->mem, key, &list->keys[i]);
}
return (res);
}
isc_result_t
dns_c_iplist_remove(dns_c_iplist_t *list, isc_sockaddr_t newaddr) {
isc_uint32_t i;
REQUIRE(DNS_C_IPLIST_VALID(list));
for (i = 0 ; i < list->nextidx ; i++) {
if (memcmp(&list->ips[i], &newaddr, sizeof(newaddr)) == 0) {
break;
}
}
if (i == list->nextidx) {
return (ISC_R_FAILURE);
}
list->nextidx--;
if (list->keys[i] != NULL) {
dns_name_reset(list->keys[i]);
isc_mem_put(list->mem, list->keys[i], sizeof(dns_name_t));
}
for ( /* nothing */ ; i < list->nextidx ; i++) {
list->ips[i] = list->ips[i + 1];
list->keys[i] = list->keys[i + 1];
}
return (ISC_R_SUCCESS);
}
/*
* Check that the address given is a network address with the given number
* of high order bits.
*/
static isc_result_t
checkmask(isc_sockaddr_t *address, isc_uint32_t bits) {
if (bits > 0) {
if (address->type.sa.sa_family == AF_INET) {
isc_uint32_t mask;
if (bits > 32) {
return (ISC_R_FAILURE);
}
mask = ntohl(0xffffffffU << (32 - bits));
if ((mask & address->type.sin.sin_addr.s_addr) !=
address->type.sin.sin_addr.s_addr) {
return (ISC_R_FAILURE);
}
} else if (address->type.sa.sa_family == AF_INET6) {
struct in6_addr iaddr;
unsigned char *maskp;
unsigned char *addrp;
int i;
if (bits > 128) {
return (ISC_R_FAILURE);
}
if (bits2v6mask(&iaddr, bits) != ISC_R_SUCCESS) {
return (ISC_R_FAILURE);
}
addrp = (unsigned char *)&address->type.sin6.sin6_addr;
maskp = (unsigned char *)&iaddr;
for (i = 0 ; i < 16 ; i++) {
if ((addrp[i] & maskp[i]) != addrp[i]) {
return (ISC_R_FAILURE);
}
}
}
}
return (ISC_R_SUCCESS);
}
/*
* Create a 128 bits mask in network byte order in the the IPv6 address
* section of the sockaddr. The bits argument is the number of high bits
* that are to be set to 1.
*/
static isc_result_t
bits2v6mask(struct in6_addr *addr, isc_uint32_t bits) {
int i;
isc_uint32_t bitmask[4];
char addrbuff [ sizeof("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff") + 1 ];
INSIST(bits <= 128);
/* Break the 128 bits up into 32-bit sections */
bitmask[0] = bitmask[1] = bitmask[2] = bitmask[3] = 0U;
if (bits >= 32) {
bitmask[0] = 0xffffffffU;
} else if (bits > 0) {
bitmask[0] = 0xffffffffU << (32 - bits);
}
if (bits >= 64) {
bitmask[1] = 0xffffffffU;
} else if (bits > 32) {
bitmask[1] = 0xffffffffU << (64 - bits);
}
if (bits >= 96) {
bitmask[2] = 0xffffffffU;
bitmask[3] = 0xffffffffU << (128 - bits);
} else if (bits > 64) {
bitmask[2] = 0xffffffffU << (96 - bits);
}
memset(addr, 0x0, sizeof(*addr));
sprintf(addrbuff, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x",
(((bitmask[0] & 0xffff0000U) >> 16) & 0xffffU),
(bitmask[0] & 0xffff),
(((bitmask[1] & 0xffff0000U) >> 16) & 0xffffU),
(bitmask[1] & 0xffff),
(((bitmask[2] & 0xffff0000U) >> 16) & 0xffffU),
(bitmask[2] & 0xffff),
(((bitmask[3] & 0xffff0000U) >> 16) & 0xffffU),
(bitmask[3] & 0xffff));
i = inet_pton(AF_INET6, addrbuff, addr);
return (i == 1 ? ISC_R_SUCCESS : ISC_R_FAILURE);
}