1c501d73cSMariusz Zaborski /*- 228b6f7c8SMariusz Zaborski * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 328b6f7c8SMariusz Zaborski * 4c501d73cSMariusz Zaborski * Copyright (c) 2012-2013 The FreeBSD Foundation 5c501d73cSMariusz Zaborski * All rights reserved. 6c501d73cSMariusz Zaborski * 7c501d73cSMariusz Zaborski * This software was developed by Pawel Jakub Dawidek under sponsorship from 8c501d73cSMariusz Zaborski * the FreeBSD Foundation. 9c501d73cSMariusz Zaborski * 10c501d73cSMariusz Zaborski * Redistribution and use in source and binary forms, with or without 11c501d73cSMariusz Zaborski * modification, are permitted provided that the following conditions 12c501d73cSMariusz Zaborski * are met: 13c501d73cSMariusz Zaborski * 1. Redistributions of source code must retain the above copyright 14c501d73cSMariusz Zaborski * notice, this list of conditions and the following disclaimer. 15c501d73cSMariusz Zaborski * 2. Redistributions in binary form must reproduce the above copyright 16c501d73cSMariusz Zaborski * notice, this list of conditions and the following disclaimer in the 17c501d73cSMariusz Zaborski * documentation and/or other materials provided with the distribution. 18c501d73cSMariusz Zaborski * 19c501d73cSMariusz Zaborski * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 20c501d73cSMariusz Zaborski * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21c501d73cSMariusz Zaborski * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22c501d73cSMariusz Zaborski * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 23c501d73cSMariusz Zaborski * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24c501d73cSMariusz Zaborski * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25c501d73cSMariusz Zaborski * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26c501d73cSMariusz Zaborski * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27c501d73cSMariusz Zaborski * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28c501d73cSMariusz Zaborski * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29c501d73cSMariusz Zaborski * SUCH DAMAGE. 30c501d73cSMariusz Zaborski */ 31c501d73cSMariusz Zaborski 32c501d73cSMariusz Zaborski #include <sys/cdefs.h> 33c501d73cSMariusz Zaborski __FBSDID("$FreeBSD$"); 34c501d73cSMariusz Zaborski 35c501d73cSMariusz Zaborski #include <sys/dnv.h> 36c501d73cSMariusz Zaborski #include <sys/nv.h> 37c501d73cSMariusz Zaborski #include <netinet/in.h> 38c501d73cSMariusz Zaborski 39c501d73cSMariusz Zaborski #include <assert.h> 40c501d73cSMariusz Zaborski #include <errno.h> 41c501d73cSMariusz Zaborski #include <netdb.h> 42c501d73cSMariusz Zaborski #include <stdlib.h> 43c501d73cSMariusz Zaborski #include <string.h> 44c501d73cSMariusz Zaborski #include <unistd.h> 45c501d73cSMariusz Zaborski 46c501d73cSMariusz Zaborski #include <libcasper.h> 47c501d73cSMariusz Zaborski #include <libcasper_service.h> 48c501d73cSMariusz Zaborski 49c501d73cSMariusz Zaborski #include "cap_dns.h" 50c501d73cSMariusz Zaborski 51c501d73cSMariusz Zaborski static struct hostent hent; 52c501d73cSMariusz Zaborski 53c501d73cSMariusz Zaborski static void 54c501d73cSMariusz Zaborski hostent_free(struct hostent *hp) 55c501d73cSMariusz Zaborski { 56c501d73cSMariusz Zaborski unsigned int ii; 57c501d73cSMariusz Zaborski 58c501d73cSMariusz Zaborski free(hp->h_name); 59c501d73cSMariusz Zaborski hp->h_name = NULL; 60c501d73cSMariusz Zaborski if (hp->h_aliases != NULL) { 61c501d73cSMariusz Zaborski for (ii = 0; hp->h_aliases[ii] != NULL; ii++) 62c501d73cSMariusz Zaborski free(hp->h_aliases[ii]); 63c501d73cSMariusz Zaborski free(hp->h_aliases); 64c501d73cSMariusz Zaborski hp->h_aliases = NULL; 65c501d73cSMariusz Zaborski } 66c501d73cSMariusz Zaborski if (hp->h_addr_list != NULL) { 67c501d73cSMariusz Zaborski for (ii = 0; hp->h_addr_list[ii] != NULL; ii++) 68c501d73cSMariusz Zaborski free(hp->h_addr_list[ii]); 69c501d73cSMariusz Zaborski free(hp->h_addr_list); 70c501d73cSMariusz Zaborski hp->h_addr_list = NULL; 71c501d73cSMariusz Zaborski } 72c501d73cSMariusz Zaborski } 73c501d73cSMariusz Zaborski 74c501d73cSMariusz Zaborski static struct hostent * 75c501d73cSMariusz Zaborski hostent_unpack(const nvlist_t *nvl, struct hostent *hp) 76c501d73cSMariusz Zaborski { 77c501d73cSMariusz Zaborski unsigned int ii, nitems; 78c501d73cSMariusz Zaborski char nvlname[64]; 79c501d73cSMariusz Zaborski int n; 80c501d73cSMariusz Zaborski 81c501d73cSMariusz Zaborski hostent_free(hp); 82c501d73cSMariusz Zaborski 83c501d73cSMariusz Zaborski hp->h_name = strdup(nvlist_get_string(nvl, "name")); 84c501d73cSMariusz Zaborski if (hp->h_name == NULL) 85c501d73cSMariusz Zaborski goto fail; 86c501d73cSMariusz Zaborski hp->h_addrtype = (int)nvlist_get_number(nvl, "addrtype"); 87c501d73cSMariusz Zaborski hp->h_length = (int)nvlist_get_number(nvl, "length"); 88c501d73cSMariusz Zaborski 89c501d73cSMariusz Zaborski nitems = (unsigned int)nvlist_get_number(nvl, "naliases"); 90c501d73cSMariusz Zaborski hp->h_aliases = calloc(sizeof(hp->h_aliases[0]), nitems + 1); 91c501d73cSMariusz Zaborski if (hp->h_aliases == NULL) 92c501d73cSMariusz Zaborski goto fail; 93c501d73cSMariusz Zaborski for (ii = 0; ii < nitems; ii++) { 94c501d73cSMariusz Zaborski n = snprintf(nvlname, sizeof(nvlname), "alias%u", ii); 95c501d73cSMariusz Zaborski assert(n > 0 && n < (int)sizeof(nvlname)); 96c501d73cSMariusz Zaborski hp->h_aliases[ii] = 97c501d73cSMariusz Zaborski strdup(nvlist_get_string(nvl, nvlname)); 98c501d73cSMariusz Zaborski if (hp->h_aliases[ii] == NULL) 99c501d73cSMariusz Zaborski goto fail; 100c501d73cSMariusz Zaborski } 101c501d73cSMariusz Zaborski hp->h_aliases[ii] = NULL; 102c501d73cSMariusz Zaborski 103c501d73cSMariusz Zaborski nitems = (unsigned int)nvlist_get_number(nvl, "naddrs"); 104c501d73cSMariusz Zaborski hp->h_addr_list = calloc(sizeof(hp->h_addr_list[0]), nitems + 1); 105c501d73cSMariusz Zaborski if (hp->h_addr_list == NULL) 106c501d73cSMariusz Zaborski goto fail; 107c501d73cSMariusz Zaborski for (ii = 0; ii < nitems; ii++) { 108c501d73cSMariusz Zaborski hp->h_addr_list[ii] = malloc(hp->h_length); 109c501d73cSMariusz Zaborski if (hp->h_addr_list[ii] == NULL) 110c501d73cSMariusz Zaborski goto fail; 111c501d73cSMariusz Zaborski n = snprintf(nvlname, sizeof(nvlname), "addr%u", ii); 112c501d73cSMariusz Zaborski assert(n > 0 && n < (int)sizeof(nvlname)); 113c501d73cSMariusz Zaborski bcopy(nvlist_get_binary(nvl, nvlname, NULL), 114c501d73cSMariusz Zaborski hp->h_addr_list[ii], hp->h_length); 115c501d73cSMariusz Zaborski } 116c501d73cSMariusz Zaborski hp->h_addr_list[ii] = NULL; 117c501d73cSMariusz Zaborski 118c501d73cSMariusz Zaborski return (hp); 119c501d73cSMariusz Zaborski fail: 120c501d73cSMariusz Zaborski hostent_free(hp); 121c501d73cSMariusz Zaborski h_errno = NO_RECOVERY; 122c501d73cSMariusz Zaborski return (NULL); 123c501d73cSMariusz Zaborski } 124c501d73cSMariusz Zaborski 125c501d73cSMariusz Zaborski struct hostent * 126c501d73cSMariusz Zaborski cap_gethostbyname(cap_channel_t *chan, const char *name) 127c501d73cSMariusz Zaborski { 128c501d73cSMariusz Zaborski 129c501d73cSMariusz Zaborski return (cap_gethostbyname2(chan, name, AF_INET)); 130c501d73cSMariusz Zaborski } 131c501d73cSMariusz Zaborski 132c501d73cSMariusz Zaborski struct hostent * 133c501d73cSMariusz Zaborski cap_gethostbyname2(cap_channel_t *chan, const char *name, int type) 134c501d73cSMariusz Zaborski { 135c501d73cSMariusz Zaborski struct hostent *hp; 136c501d73cSMariusz Zaborski nvlist_t *nvl; 137c501d73cSMariusz Zaborski 138c501d73cSMariusz Zaborski nvl = nvlist_create(0); 139c501d73cSMariusz Zaborski nvlist_add_string(nvl, "cmd", "gethostbyname"); 140c501d73cSMariusz Zaborski nvlist_add_number(nvl, "family", (uint64_t)type); 141c501d73cSMariusz Zaborski nvlist_add_string(nvl, "name", name); 1424fc0a279SMariusz Zaborski nvl = cap_xfer_nvlist(chan, nvl); 143c501d73cSMariusz Zaborski if (nvl == NULL) { 144c501d73cSMariusz Zaborski h_errno = NO_RECOVERY; 145c501d73cSMariusz Zaborski return (NULL); 146c501d73cSMariusz Zaborski } 147c501d73cSMariusz Zaborski if (nvlist_get_number(nvl, "error") != 0) { 148c501d73cSMariusz Zaborski h_errno = (int)nvlist_get_number(nvl, "error"); 149c501d73cSMariusz Zaborski nvlist_destroy(nvl); 150c501d73cSMariusz Zaborski return (NULL); 151c501d73cSMariusz Zaborski } 152c501d73cSMariusz Zaborski 153c501d73cSMariusz Zaborski hp = hostent_unpack(nvl, &hent); 154c501d73cSMariusz Zaborski nvlist_destroy(nvl); 155c501d73cSMariusz Zaborski return (hp); 156c501d73cSMariusz Zaborski } 157c501d73cSMariusz Zaborski 158c501d73cSMariusz Zaborski struct hostent * 159c501d73cSMariusz Zaborski cap_gethostbyaddr(cap_channel_t *chan, const void *addr, socklen_t len, 160c501d73cSMariusz Zaborski int type) 161c501d73cSMariusz Zaborski { 162c501d73cSMariusz Zaborski struct hostent *hp; 163c501d73cSMariusz Zaborski nvlist_t *nvl; 164c501d73cSMariusz Zaborski 165c501d73cSMariusz Zaborski nvl = nvlist_create(0); 166c501d73cSMariusz Zaborski nvlist_add_string(nvl, "cmd", "gethostbyaddr"); 167c501d73cSMariusz Zaborski nvlist_add_binary(nvl, "addr", addr, (size_t)len); 168c501d73cSMariusz Zaborski nvlist_add_number(nvl, "family", (uint64_t)type); 1694fc0a279SMariusz Zaborski nvl = cap_xfer_nvlist(chan, nvl); 170c501d73cSMariusz Zaborski if (nvl == NULL) { 171c501d73cSMariusz Zaborski h_errno = NO_RECOVERY; 172c501d73cSMariusz Zaborski return (NULL); 173c501d73cSMariusz Zaborski } 174c501d73cSMariusz Zaborski if (nvlist_get_number(nvl, "error") != 0) { 175c501d73cSMariusz Zaborski h_errno = (int)nvlist_get_number(nvl, "error"); 176c501d73cSMariusz Zaborski nvlist_destroy(nvl); 177c501d73cSMariusz Zaborski return (NULL); 178c501d73cSMariusz Zaborski } 179c501d73cSMariusz Zaborski hp = hostent_unpack(nvl, &hent); 180c501d73cSMariusz Zaborski nvlist_destroy(nvl); 181c501d73cSMariusz Zaborski return (hp); 182c501d73cSMariusz Zaborski } 183c501d73cSMariusz Zaborski 184c501d73cSMariusz Zaborski static struct addrinfo * 185c501d73cSMariusz Zaborski addrinfo_unpack(const nvlist_t *nvl) 186c501d73cSMariusz Zaborski { 187c501d73cSMariusz Zaborski struct addrinfo *ai; 188c501d73cSMariusz Zaborski const void *addr; 189c501d73cSMariusz Zaborski size_t addrlen; 190c501d73cSMariusz Zaborski const char *canonname; 191c501d73cSMariusz Zaborski 192c501d73cSMariusz Zaborski addr = nvlist_get_binary(nvl, "ai_addr", &addrlen); 193c501d73cSMariusz Zaborski ai = malloc(sizeof(*ai) + addrlen); 194c501d73cSMariusz Zaborski if (ai == NULL) 195c501d73cSMariusz Zaborski return (NULL); 196c501d73cSMariusz Zaborski ai->ai_flags = (int)nvlist_get_number(nvl, "ai_flags"); 197c501d73cSMariusz Zaborski ai->ai_family = (int)nvlist_get_number(nvl, "ai_family"); 198c501d73cSMariusz Zaborski ai->ai_socktype = (int)nvlist_get_number(nvl, "ai_socktype"); 199c501d73cSMariusz Zaborski ai->ai_protocol = (int)nvlist_get_number(nvl, "ai_protocol"); 200c501d73cSMariusz Zaborski ai->ai_addrlen = (socklen_t)addrlen; 201c501d73cSMariusz Zaborski canonname = dnvlist_get_string(nvl, "ai_canonname", NULL); 202c501d73cSMariusz Zaborski if (canonname != NULL) { 203c501d73cSMariusz Zaborski ai->ai_canonname = strdup(canonname); 204c501d73cSMariusz Zaborski if (ai->ai_canonname == NULL) { 205c501d73cSMariusz Zaborski free(ai); 206c501d73cSMariusz Zaborski return (NULL); 207c501d73cSMariusz Zaborski } 208c501d73cSMariusz Zaborski } else { 209c501d73cSMariusz Zaborski ai->ai_canonname = NULL; 210c501d73cSMariusz Zaborski } 211c501d73cSMariusz Zaborski ai->ai_addr = (void *)(ai + 1); 212c501d73cSMariusz Zaborski bcopy(addr, ai->ai_addr, addrlen); 213c501d73cSMariusz Zaborski ai->ai_next = NULL; 214c501d73cSMariusz Zaborski 215c501d73cSMariusz Zaborski return (ai); 216c501d73cSMariusz Zaborski } 217c501d73cSMariusz Zaborski 218c501d73cSMariusz Zaborski int 219c501d73cSMariusz Zaborski cap_getaddrinfo(cap_channel_t *chan, const char *hostname, const char *servname, 220c501d73cSMariusz Zaborski const struct addrinfo *hints, struct addrinfo **res) 221c501d73cSMariusz Zaborski { 222c501d73cSMariusz Zaborski struct addrinfo *firstai, *prevai, *curai; 223c501d73cSMariusz Zaborski unsigned int ii; 224c501d73cSMariusz Zaborski const nvlist_t *nvlai; 225c501d73cSMariusz Zaborski char nvlname[64]; 226c501d73cSMariusz Zaborski nvlist_t *nvl; 227c501d73cSMariusz Zaborski int error, n; 228c501d73cSMariusz Zaborski 229c501d73cSMariusz Zaborski nvl = nvlist_create(0); 230c501d73cSMariusz Zaborski nvlist_add_string(nvl, "cmd", "getaddrinfo"); 231c501d73cSMariusz Zaborski if (hostname != NULL) 232c501d73cSMariusz Zaborski nvlist_add_string(nvl, "hostname", hostname); 233c501d73cSMariusz Zaborski if (servname != NULL) 234c501d73cSMariusz Zaborski nvlist_add_string(nvl, "servname", servname); 235c501d73cSMariusz Zaborski if (hints != NULL) { 236c501d73cSMariusz Zaborski nvlist_add_number(nvl, "hints.ai_flags", 237c501d73cSMariusz Zaborski (uint64_t)hints->ai_flags); 238c501d73cSMariusz Zaborski nvlist_add_number(nvl, "hints.ai_family", 239c501d73cSMariusz Zaborski (uint64_t)hints->ai_family); 240c501d73cSMariusz Zaborski nvlist_add_number(nvl, "hints.ai_socktype", 241c501d73cSMariusz Zaborski (uint64_t)hints->ai_socktype); 242c501d73cSMariusz Zaborski nvlist_add_number(nvl, "hints.ai_protocol", 243c501d73cSMariusz Zaborski (uint64_t)hints->ai_protocol); 244c501d73cSMariusz Zaborski } 2454fc0a279SMariusz Zaborski nvl = cap_xfer_nvlist(chan, nvl); 246c501d73cSMariusz Zaborski if (nvl == NULL) 247c501d73cSMariusz Zaborski return (EAI_MEMORY); 248c501d73cSMariusz Zaborski if (nvlist_get_number(nvl, "error") != 0) { 249c501d73cSMariusz Zaborski error = (int)nvlist_get_number(nvl, "error"); 250c501d73cSMariusz Zaborski nvlist_destroy(nvl); 251c501d73cSMariusz Zaborski return (error); 252c501d73cSMariusz Zaborski } 253c501d73cSMariusz Zaborski 254c501d73cSMariusz Zaborski nvlai = NULL; 255c501d73cSMariusz Zaborski firstai = prevai = curai = NULL; 256c501d73cSMariusz Zaborski for (ii = 0; ; ii++) { 257c501d73cSMariusz Zaborski n = snprintf(nvlname, sizeof(nvlname), "res%u", ii); 258c501d73cSMariusz Zaborski assert(n > 0 && n < (int)sizeof(nvlname)); 259c501d73cSMariusz Zaborski if (!nvlist_exists_nvlist(nvl, nvlname)) 260c501d73cSMariusz Zaborski break; 261c501d73cSMariusz Zaborski nvlai = nvlist_get_nvlist(nvl, nvlname); 262c501d73cSMariusz Zaborski curai = addrinfo_unpack(nvlai); 263c501d73cSMariusz Zaborski if (curai == NULL) 264c501d73cSMariusz Zaborski break; 265c501d73cSMariusz Zaborski if (prevai != NULL) 266c501d73cSMariusz Zaborski prevai->ai_next = curai; 267c501d73cSMariusz Zaborski else if (firstai == NULL) 268c501d73cSMariusz Zaborski firstai = curai; 269c501d73cSMariusz Zaborski prevai = curai; 270c501d73cSMariusz Zaborski } 271c501d73cSMariusz Zaborski nvlist_destroy(nvl); 272c501d73cSMariusz Zaborski if (curai == NULL && nvlai != NULL) { 273c501d73cSMariusz Zaborski if (firstai == NULL) 274c501d73cSMariusz Zaborski freeaddrinfo(firstai); 275c501d73cSMariusz Zaborski return (EAI_MEMORY); 276c501d73cSMariusz Zaborski } 277c501d73cSMariusz Zaborski 278c501d73cSMariusz Zaborski *res = firstai; 279c501d73cSMariusz Zaborski return (0); 280c501d73cSMariusz Zaborski } 281c501d73cSMariusz Zaborski 282c501d73cSMariusz Zaborski int 283c501d73cSMariusz Zaborski cap_getnameinfo(cap_channel_t *chan, const struct sockaddr *sa, socklen_t salen, 284c501d73cSMariusz Zaborski char *host, size_t hostlen, char *serv, size_t servlen, int flags) 285c501d73cSMariusz Zaborski { 286c501d73cSMariusz Zaborski nvlist_t *nvl; 287c501d73cSMariusz Zaborski int error; 288c501d73cSMariusz Zaborski 289c501d73cSMariusz Zaborski nvl = nvlist_create(0); 290c501d73cSMariusz Zaborski nvlist_add_string(nvl, "cmd", "getnameinfo"); 291c501d73cSMariusz Zaborski nvlist_add_number(nvl, "hostlen", (uint64_t)hostlen); 292c501d73cSMariusz Zaborski nvlist_add_number(nvl, "servlen", (uint64_t)servlen); 293c501d73cSMariusz Zaborski nvlist_add_binary(nvl, "sa", sa, (size_t)salen); 294c501d73cSMariusz Zaborski nvlist_add_number(nvl, "flags", (uint64_t)flags); 2954fc0a279SMariusz Zaborski nvl = cap_xfer_nvlist(chan, nvl); 296c501d73cSMariusz Zaborski if (nvl == NULL) 297c501d73cSMariusz Zaborski return (EAI_MEMORY); 298c501d73cSMariusz Zaborski if (nvlist_get_number(nvl, "error") != 0) { 299c501d73cSMariusz Zaborski error = (int)nvlist_get_number(nvl, "error"); 300c501d73cSMariusz Zaborski nvlist_destroy(nvl); 301c501d73cSMariusz Zaborski return (error); 302c501d73cSMariusz Zaborski } 303c501d73cSMariusz Zaborski 304c501d73cSMariusz Zaborski if (host != NULL && nvlist_exists_string(nvl, "host")) 305c501d73cSMariusz Zaborski strlcpy(host, nvlist_get_string(nvl, "host"), hostlen + 1); 306c501d73cSMariusz Zaborski if (serv != NULL && nvlist_exists_string(nvl, "serv")) 307c501d73cSMariusz Zaborski strlcpy(serv, nvlist_get_string(nvl, "serv"), servlen + 1); 308c501d73cSMariusz Zaborski nvlist_destroy(nvl); 309c501d73cSMariusz Zaborski return (0); 310c501d73cSMariusz Zaborski } 311c501d73cSMariusz Zaborski 312c501d73cSMariusz Zaborski static void 313c501d73cSMariusz Zaborski limit_remove(nvlist_t *limits, const char *prefix) 314c501d73cSMariusz Zaborski { 315c501d73cSMariusz Zaborski const char *name; 316c501d73cSMariusz Zaborski size_t prefixlen; 317c501d73cSMariusz Zaborski void *cookie; 318c501d73cSMariusz Zaborski 319c501d73cSMariusz Zaborski prefixlen = strlen(prefix); 320c501d73cSMariusz Zaborski again: 321c501d73cSMariusz Zaborski cookie = NULL; 322c501d73cSMariusz Zaborski while ((name = nvlist_next(limits, NULL, &cookie)) != NULL) { 323c501d73cSMariusz Zaborski if (strncmp(name, prefix, prefixlen) == 0) { 324c501d73cSMariusz Zaborski nvlist_free(limits, name); 325c501d73cSMariusz Zaborski goto again; 326c501d73cSMariusz Zaborski } 327c501d73cSMariusz Zaborski } 328c501d73cSMariusz Zaborski } 329c501d73cSMariusz Zaborski 330c501d73cSMariusz Zaborski int 331c501d73cSMariusz Zaborski cap_dns_type_limit(cap_channel_t *chan, const char * const *types, 332c501d73cSMariusz Zaborski size_t ntypes) 333c501d73cSMariusz Zaborski { 334c501d73cSMariusz Zaborski nvlist_t *limits; 335c501d73cSMariusz Zaborski unsigned int i; 336c501d73cSMariusz Zaborski char nvlname[64]; 337c501d73cSMariusz Zaborski int n; 338c501d73cSMariusz Zaborski 339c501d73cSMariusz Zaborski if (cap_limit_get(chan, &limits) < 0) 340c501d73cSMariusz Zaborski return (-1); 341c501d73cSMariusz Zaborski if (limits == NULL) 342c501d73cSMariusz Zaborski limits = nvlist_create(0); 343c501d73cSMariusz Zaborski else 344c501d73cSMariusz Zaborski limit_remove(limits, "type"); 345c501d73cSMariusz Zaborski for (i = 0; i < ntypes; i++) { 346c501d73cSMariusz Zaborski n = snprintf(nvlname, sizeof(nvlname), "type%u", i); 347c501d73cSMariusz Zaborski assert(n > 0 && n < (int)sizeof(nvlname)); 348c501d73cSMariusz Zaborski nvlist_add_string(limits, nvlname, types[i]); 349c501d73cSMariusz Zaborski } 350c501d73cSMariusz Zaborski return (cap_limit_set(chan, limits)); 351c501d73cSMariusz Zaborski } 352c501d73cSMariusz Zaborski 353c501d73cSMariusz Zaborski int 354c501d73cSMariusz Zaborski cap_dns_family_limit(cap_channel_t *chan, const int *families, 355c501d73cSMariusz Zaborski size_t nfamilies) 356c501d73cSMariusz Zaborski { 357c501d73cSMariusz Zaborski nvlist_t *limits; 358c501d73cSMariusz Zaborski unsigned int i; 359c501d73cSMariusz Zaborski char nvlname[64]; 360c501d73cSMariusz Zaborski int n; 361c501d73cSMariusz Zaborski 362c501d73cSMariusz Zaborski if (cap_limit_get(chan, &limits) < 0) 363c501d73cSMariusz Zaborski return (-1); 364c501d73cSMariusz Zaborski if (limits == NULL) 365c501d73cSMariusz Zaborski limits = nvlist_create(0); 366c501d73cSMariusz Zaborski else 367c501d73cSMariusz Zaborski limit_remove(limits, "family"); 368c501d73cSMariusz Zaborski for (i = 0; i < nfamilies; i++) { 369c501d73cSMariusz Zaborski n = snprintf(nvlname, sizeof(nvlname), "family%u", i); 370c501d73cSMariusz Zaborski assert(n > 0 && n < (int)sizeof(nvlname)); 371c501d73cSMariusz Zaborski nvlist_add_number(limits, nvlname, (uint64_t)families[i]); 372c501d73cSMariusz Zaborski } 373c501d73cSMariusz Zaborski return (cap_limit_set(chan, limits)); 374c501d73cSMariusz Zaborski } 375c501d73cSMariusz Zaborski 376c501d73cSMariusz Zaborski /* 377c501d73cSMariusz Zaborski * Service functions. 378c501d73cSMariusz Zaborski */ 379c501d73cSMariusz Zaborski static bool 380c501d73cSMariusz Zaborski dns_allowed_type(const nvlist_t *limits, const char *type) 381c501d73cSMariusz Zaborski { 382c501d73cSMariusz Zaborski const char *name; 383c501d73cSMariusz Zaborski bool notypes; 384c501d73cSMariusz Zaborski void *cookie; 385c501d73cSMariusz Zaborski 386c501d73cSMariusz Zaborski if (limits == NULL) 387c501d73cSMariusz Zaborski return (true); 388c501d73cSMariusz Zaborski 389c501d73cSMariusz Zaborski notypes = true; 390c501d73cSMariusz Zaborski cookie = NULL; 391c501d73cSMariusz Zaborski while ((name = nvlist_next(limits, NULL, &cookie)) != NULL) { 392c501d73cSMariusz Zaborski if (strncmp(name, "type", sizeof("type") - 1) != 0) 393c501d73cSMariusz Zaborski continue; 394c501d73cSMariusz Zaborski notypes = false; 395c501d73cSMariusz Zaborski if (strcmp(nvlist_get_string(limits, name), type) == 0) 396c501d73cSMariusz Zaborski return (true); 397c501d73cSMariusz Zaborski } 398c501d73cSMariusz Zaborski 399c501d73cSMariusz Zaborski /* If there are no types at all, allow any type. */ 400c501d73cSMariusz Zaborski if (notypes) 401c501d73cSMariusz Zaborski return (true); 402c501d73cSMariusz Zaborski 403c501d73cSMariusz Zaborski return (false); 404c501d73cSMariusz Zaborski } 405c501d73cSMariusz Zaborski 406c501d73cSMariusz Zaborski static bool 407c501d73cSMariusz Zaborski dns_allowed_family(const nvlist_t *limits, int family) 408c501d73cSMariusz Zaborski { 409c501d73cSMariusz Zaborski const char *name; 410c501d73cSMariusz Zaborski bool nofamilies; 411c501d73cSMariusz Zaborski void *cookie; 412c501d73cSMariusz Zaborski 413c501d73cSMariusz Zaborski if (limits == NULL) 414c501d73cSMariusz Zaborski return (true); 415c501d73cSMariusz Zaborski 416c501d73cSMariusz Zaborski nofamilies = true; 417c501d73cSMariusz Zaborski cookie = NULL; 418c501d73cSMariusz Zaborski while ((name = nvlist_next(limits, NULL, &cookie)) != NULL) { 419c501d73cSMariusz Zaborski if (strncmp(name, "family", sizeof("family") - 1) != 0) 420c501d73cSMariusz Zaborski continue; 421c501d73cSMariusz Zaborski nofamilies = false; 422c501d73cSMariusz Zaborski if (family == AF_UNSPEC) 423c501d73cSMariusz Zaborski continue; 424c501d73cSMariusz Zaborski if (nvlist_get_number(limits, name) == (uint64_t)family) 425c501d73cSMariusz Zaborski return (true); 426c501d73cSMariusz Zaborski } 427c501d73cSMariusz Zaborski 428c501d73cSMariusz Zaborski /* If there are no families at all, allow any family. */ 429c501d73cSMariusz Zaborski if (nofamilies) 430c501d73cSMariusz Zaborski return (true); 431c501d73cSMariusz Zaborski 432c501d73cSMariusz Zaborski return (false); 433c501d73cSMariusz Zaborski } 434c501d73cSMariusz Zaborski 435c501d73cSMariusz Zaborski static void 436c501d73cSMariusz Zaborski hostent_pack(const struct hostent *hp, nvlist_t *nvl) 437c501d73cSMariusz Zaborski { 438c501d73cSMariusz Zaborski unsigned int ii; 439c501d73cSMariusz Zaborski char nvlname[64]; 440c501d73cSMariusz Zaborski int n; 441c501d73cSMariusz Zaborski 442c501d73cSMariusz Zaborski nvlist_add_string(nvl, "name", hp->h_name); 443c501d73cSMariusz Zaborski nvlist_add_number(nvl, "addrtype", (uint64_t)hp->h_addrtype); 444c501d73cSMariusz Zaborski nvlist_add_number(nvl, "length", (uint64_t)hp->h_length); 445c501d73cSMariusz Zaborski 446c501d73cSMariusz Zaborski if (hp->h_aliases == NULL) { 447c501d73cSMariusz Zaborski nvlist_add_number(nvl, "naliases", 0); 448c501d73cSMariusz Zaborski } else { 449c501d73cSMariusz Zaborski for (ii = 0; hp->h_aliases[ii] != NULL; ii++) { 450c501d73cSMariusz Zaborski n = snprintf(nvlname, sizeof(nvlname), "alias%u", ii); 451c501d73cSMariusz Zaborski assert(n > 0 && n < (int)sizeof(nvlname)); 452c501d73cSMariusz Zaborski nvlist_add_string(nvl, nvlname, hp->h_aliases[ii]); 453c501d73cSMariusz Zaborski } 454c501d73cSMariusz Zaborski nvlist_add_number(nvl, "naliases", (uint64_t)ii); 455c501d73cSMariusz Zaborski } 456c501d73cSMariusz Zaborski 457c501d73cSMariusz Zaborski if (hp->h_addr_list == NULL) { 458c501d73cSMariusz Zaborski nvlist_add_number(nvl, "naddrs", 0); 459c501d73cSMariusz Zaborski } else { 460c501d73cSMariusz Zaborski for (ii = 0; hp->h_addr_list[ii] != NULL; ii++) { 461c501d73cSMariusz Zaborski n = snprintf(nvlname, sizeof(nvlname), "addr%u", ii); 462c501d73cSMariusz Zaborski assert(n > 0 && n < (int)sizeof(nvlname)); 463c501d73cSMariusz Zaborski nvlist_add_binary(nvl, nvlname, hp->h_addr_list[ii], 464c501d73cSMariusz Zaborski (size_t)hp->h_length); 465c501d73cSMariusz Zaborski } 466c501d73cSMariusz Zaborski nvlist_add_number(nvl, "naddrs", (uint64_t)ii); 467c501d73cSMariusz Zaborski } 468c501d73cSMariusz Zaborski } 469c501d73cSMariusz Zaborski 470c501d73cSMariusz Zaborski static int 471c501d73cSMariusz Zaborski dns_gethostbyname(const nvlist_t *limits, const nvlist_t *nvlin, 472c501d73cSMariusz Zaborski nvlist_t *nvlout) 473c501d73cSMariusz Zaborski { 474c501d73cSMariusz Zaborski struct hostent *hp; 475c501d73cSMariusz Zaborski int family; 476c501d73cSMariusz Zaborski 477*2863fd2fSMariusz Zaborski if (!dns_allowed_type(limits, "NAME2ADDR") && 478*2863fd2fSMariusz Zaborski !dns_allowed_type(limits, "NAME")) 479c501d73cSMariusz Zaborski return (NO_RECOVERY); 480c501d73cSMariusz Zaborski 481c501d73cSMariusz Zaborski family = (int)nvlist_get_number(nvlin, "family"); 482c501d73cSMariusz Zaborski 483c501d73cSMariusz Zaborski if (!dns_allowed_family(limits, family)) 484c501d73cSMariusz Zaborski return (NO_RECOVERY); 485c501d73cSMariusz Zaborski 486c501d73cSMariusz Zaborski hp = gethostbyname2(nvlist_get_string(nvlin, "name"), family); 487c501d73cSMariusz Zaborski if (hp == NULL) 488c501d73cSMariusz Zaborski return (h_errno); 489c501d73cSMariusz Zaborski hostent_pack(hp, nvlout); 490c501d73cSMariusz Zaborski return (0); 491c501d73cSMariusz Zaborski } 492c501d73cSMariusz Zaborski 493c501d73cSMariusz Zaborski static int 494c501d73cSMariusz Zaborski dns_gethostbyaddr(const nvlist_t *limits, const nvlist_t *nvlin, 495c501d73cSMariusz Zaborski nvlist_t *nvlout) 496c501d73cSMariusz Zaborski { 497c501d73cSMariusz Zaborski struct hostent *hp; 498c501d73cSMariusz Zaborski const void *addr; 499c501d73cSMariusz Zaborski size_t addrsize; 500c501d73cSMariusz Zaborski int family; 501c501d73cSMariusz Zaborski 502*2863fd2fSMariusz Zaborski if (!dns_allowed_type(limits, "ADDR2NAME") && 503*2863fd2fSMariusz Zaborski !dns_allowed_type(limits, "ADDR")) 504c501d73cSMariusz Zaborski return (NO_RECOVERY); 505c501d73cSMariusz Zaborski 506c501d73cSMariusz Zaborski family = (int)nvlist_get_number(nvlin, "family"); 507c501d73cSMariusz Zaborski 508c501d73cSMariusz Zaborski if (!dns_allowed_family(limits, family)) 509c501d73cSMariusz Zaborski return (NO_RECOVERY); 510c501d73cSMariusz Zaborski 511c501d73cSMariusz Zaborski addr = nvlist_get_binary(nvlin, "addr", &addrsize); 512c501d73cSMariusz Zaborski hp = gethostbyaddr(addr, (socklen_t)addrsize, family); 513c501d73cSMariusz Zaborski if (hp == NULL) 514c501d73cSMariusz Zaborski return (h_errno); 515c501d73cSMariusz Zaborski hostent_pack(hp, nvlout); 516c501d73cSMariusz Zaborski return (0); 517c501d73cSMariusz Zaborski } 518c501d73cSMariusz Zaborski 519c501d73cSMariusz Zaborski static int 520c501d73cSMariusz Zaborski dns_getnameinfo(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout) 521c501d73cSMariusz Zaborski { 522c501d73cSMariusz Zaborski struct sockaddr_storage sast; 523c501d73cSMariusz Zaborski const void *sabin; 524c501d73cSMariusz Zaborski char *host, *serv; 525c501d73cSMariusz Zaborski size_t sabinsize, hostlen, servlen; 526c501d73cSMariusz Zaborski socklen_t salen; 527c501d73cSMariusz Zaborski int error, flags; 528c501d73cSMariusz Zaborski 529*2863fd2fSMariusz Zaborski if (!dns_allowed_type(limits, "ADDR2NAME") && 530*2863fd2fSMariusz Zaborski !dns_allowed_type(limits, "ADDR")) 531c501d73cSMariusz Zaborski return (NO_RECOVERY); 532c501d73cSMariusz Zaborski 533c501d73cSMariusz Zaborski error = 0; 534c501d73cSMariusz Zaborski host = serv = NULL; 535c501d73cSMariusz Zaborski memset(&sast, 0, sizeof(sast)); 536c501d73cSMariusz Zaborski 537c501d73cSMariusz Zaborski hostlen = (size_t)nvlist_get_number(nvlin, "hostlen"); 538c501d73cSMariusz Zaborski servlen = (size_t)nvlist_get_number(nvlin, "servlen"); 539c501d73cSMariusz Zaborski 540c501d73cSMariusz Zaborski if (hostlen > 0) { 541c501d73cSMariusz Zaborski host = calloc(1, hostlen + 1); 542c501d73cSMariusz Zaborski if (host == NULL) { 543c501d73cSMariusz Zaborski error = EAI_MEMORY; 544c501d73cSMariusz Zaborski goto out; 545c501d73cSMariusz Zaborski } 546c501d73cSMariusz Zaborski } 547c501d73cSMariusz Zaborski if (servlen > 0) { 548c501d73cSMariusz Zaborski serv = calloc(1, servlen + 1); 549c501d73cSMariusz Zaborski if (serv == NULL) { 550c501d73cSMariusz Zaborski error = EAI_MEMORY; 551c501d73cSMariusz Zaborski goto out; 552c501d73cSMariusz Zaborski } 553c501d73cSMariusz Zaborski } 554c501d73cSMariusz Zaborski 555c501d73cSMariusz Zaborski sabin = nvlist_get_binary(nvlin, "sa", &sabinsize); 556c501d73cSMariusz Zaborski if (sabinsize > sizeof(sast)) { 557c501d73cSMariusz Zaborski error = EAI_FAIL; 558c501d73cSMariusz Zaborski goto out; 559c501d73cSMariusz Zaborski } 560c501d73cSMariusz Zaborski 561c501d73cSMariusz Zaborski memcpy(&sast, sabin, sabinsize); 562c501d73cSMariusz Zaborski salen = (socklen_t)sabinsize; 563c501d73cSMariusz Zaborski 564c501d73cSMariusz Zaborski if ((sast.ss_family != AF_INET || 565c501d73cSMariusz Zaborski salen != sizeof(struct sockaddr_in)) && 566c501d73cSMariusz Zaborski (sast.ss_family != AF_INET6 || 567c501d73cSMariusz Zaborski salen != sizeof(struct sockaddr_in6))) { 568c501d73cSMariusz Zaborski error = EAI_FAIL; 569c501d73cSMariusz Zaborski goto out; 570c501d73cSMariusz Zaborski } 571c501d73cSMariusz Zaborski 572c501d73cSMariusz Zaborski if (!dns_allowed_family(limits, (int)sast.ss_family)) { 573c501d73cSMariusz Zaborski error = NO_RECOVERY; 574c501d73cSMariusz Zaborski goto out; 575c501d73cSMariusz Zaborski } 576c501d73cSMariusz Zaborski 577c501d73cSMariusz Zaborski flags = (int)nvlist_get_number(nvlin, "flags"); 578c501d73cSMariusz Zaborski 579c501d73cSMariusz Zaborski error = getnameinfo((struct sockaddr *)&sast, salen, host, hostlen, 580c501d73cSMariusz Zaborski serv, servlen, flags); 581c501d73cSMariusz Zaborski if (error != 0) 582c501d73cSMariusz Zaborski goto out; 583c501d73cSMariusz Zaborski 584c501d73cSMariusz Zaborski if (host != NULL) 585c501d73cSMariusz Zaborski nvlist_move_string(nvlout, "host", host); 586c501d73cSMariusz Zaborski if (serv != NULL) 587c501d73cSMariusz Zaborski nvlist_move_string(nvlout, "serv", serv); 588c501d73cSMariusz Zaborski out: 589c501d73cSMariusz Zaborski if (error != 0) { 590c501d73cSMariusz Zaborski free(host); 591c501d73cSMariusz Zaborski free(serv); 592c501d73cSMariusz Zaborski } 593c501d73cSMariusz Zaborski return (error); 594c501d73cSMariusz Zaborski } 595c501d73cSMariusz Zaborski 596c501d73cSMariusz Zaborski static nvlist_t * 597c501d73cSMariusz Zaborski addrinfo_pack(const struct addrinfo *ai) 598c501d73cSMariusz Zaborski { 599c501d73cSMariusz Zaborski nvlist_t *nvl; 600c501d73cSMariusz Zaborski 601c501d73cSMariusz Zaborski nvl = nvlist_create(0); 602c501d73cSMariusz Zaborski nvlist_add_number(nvl, "ai_flags", (uint64_t)ai->ai_flags); 603c501d73cSMariusz Zaborski nvlist_add_number(nvl, "ai_family", (uint64_t)ai->ai_family); 604c501d73cSMariusz Zaborski nvlist_add_number(nvl, "ai_socktype", (uint64_t)ai->ai_socktype); 605c501d73cSMariusz Zaborski nvlist_add_number(nvl, "ai_protocol", (uint64_t)ai->ai_protocol); 606c501d73cSMariusz Zaborski nvlist_add_binary(nvl, "ai_addr", ai->ai_addr, (size_t)ai->ai_addrlen); 607c501d73cSMariusz Zaborski if (ai->ai_canonname != NULL) 608c501d73cSMariusz Zaborski nvlist_add_string(nvl, "ai_canonname", ai->ai_canonname); 609c501d73cSMariusz Zaborski 610c501d73cSMariusz Zaborski return (nvl); 611c501d73cSMariusz Zaborski } 612c501d73cSMariusz Zaborski 613c501d73cSMariusz Zaborski static int 614c501d73cSMariusz Zaborski dns_getaddrinfo(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout) 615c501d73cSMariusz Zaborski { 616c501d73cSMariusz Zaborski struct addrinfo hints, *hintsp, *res, *cur; 617c501d73cSMariusz Zaborski const char *hostname, *servname; 618c501d73cSMariusz Zaborski char nvlname[64]; 619c501d73cSMariusz Zaborski nvlist_t *elem; 620c501d73cSMariusz Zaborski unsigned int ii; 621c501d73cSMariusz Zaborski int error, family, n; 622c501d73cSMariusz Zaborski 623*2863fd2fSMariusz Zaborski if (!dns_allowed_type(limits, "NAME2ADDR") && 624*2863fd2fSMariusz Zaborski !dns_allowed_type(limits, "NAME")) 625c501d73cSMariusz Zaborski return (NO_RECOVERY); 626c501d73cSMariusz Zaborski 627c501d73cSMariusz Zaborski hostname = dnvlist_get_string(nvlin, "hostname", NULL); 628c501d73cSMariusz Zaborski servname = dnvlist_get_string(nvlin, "servname", NULL); 629c501d73cSMariusz Zaborski if (nvlist_exists_number(nvlin, "hints.ai_flags")) { 630c501d73cSMariusz Zaborski hints.ai_flags = (int)nvlist_get_number(nvlin, 631c501d73cSMariusz Zaborski "hints.ai_flags"); 632c501d73cSMariusz Zaborski hints.ai_family = (int)nvlist_get_number(nvlin, 633c501d73cSMariusz Zaborski "hints.ai_family"); 634c501d73cSMariusz Zaborski hints.ai_socktype = (int)nvlist_get_number(nvlin, 635c501d73cSMariusz Zaborski "hints.ai_socktype"); 636c501d73cSMariusz Zaborski hints.ai_protocol = (int)nvlist_get_number(nvlin, 637c501d73cSMariusz Zaborski "hints.ai_protocol"); 638c501d73cSMariusz Zaborski hints.ai_addrlen = 0; 639c501d73cSMariusz Zaborski hints.ai_addr = NULL; 640c501d73cSMariusz Zaborski hints.ai_canonname = NULL; 6417f6a709bSMariusz Zaborski hints.ai_next = NULL; 642c501d73cSMariusz Zaborski hintsp = &hints; 643c501d73cSMariusz Zaborski family = hints.ai_family; 644c501d73cSMariusz Zaborski } else { 645c501d73cSMariusz Zaborski hintsp = NULL; 646c501d73cSMariusz Zaborski family = AF_UNSPEC; 647c501d73cSMariusz Zaborski } 648c501d73cSMariusz Zaborski 649c501d73cSMariusz Zaborski if (!dns_allowed_family(limits, family)) 650c501d73cSMariusz Zaborski return (NO_RECOVERY); 651c501d73cSMariusz Zaborski 652c501d73cSMariusz Zaborski error = getaddrinfo(hostname, servname, hintsp, &res); 653c501d73cSMariusz Zaborski if (error != 0) 654c501d73cSMariusz Zaborski goto out; 655c501d73cSMariusz Zaborski 656c501d73cSMariusz Zaborski for (cur = res, ii = 0; cur != NULL; cur = cur->ai_next, ii++) { 657c501d73cSMariusz Zaborski elem = addrinfo_pack(cur); 658c501d73cSMariusz Zaborski n = snprintf(nvlname, sizeof(nvlname), "res%u", ii); 659c501d73cSMariusz Zaborski assert(n > 0 && n < (int)sizeof(nvlname)); 660c501d73cSMariusz Zaborski nvlist_move_nvlist(nvlout, nvlname, elem); 661c501d73cSMariusz Zaborski } 662c501d73cSMariusz Zaborski 663c501d73cSMariusz Zaborski freeaddrinfo(res); 664c501d73cSMariusz Zaborski error = 0; 665c501d73cSMariusz Zaborski out: 666c501d73cSMariusz Zaborski return (error); 667c501d73cSMariusz Zaborski } 668c501d73cSMariusz Zaborski 669c501d73cSMariusz Zaborski static bool 670c501d73cSMariusz Zaborski limit_has_entry(const nvlist_t *limits, const char *prefix) 671c501d73cSMariusz Zaborski { 672c501d73cSMariusz Zaborski const char *name; 673c501d73cSMariusz Zaborski size_t prefixlen; 674c501d73cSMariusz Zaborski void *cookie; 675c501d73cSMariusz Zaborski 676c501d73cSMariusz Zaborski if (limits == NULL) 677c501d73cSMariusz Zaborski return (false); 678c501d73cSMariusz Zaborski 679c501d73cSMariusz Zaborski prefixlen = strlen(prefix); 680c501d73cSMariusz Zaborski 681c501d73cSMariusz Zaborski cookie = NULL; 682c501d73cSMariusz Zaborski while ((name = nvlist_next(limits, NULL, &cookie)) != NULL) { 683c501d73cSMariusz Zaborski if (strncmp(name, prefix, prefixlen) == 0) 684c501d73cSMariusz Zaborski return (true); 685c501d73cSMariusz Zaborski } 686c501d73cSMariusz Zaborski 687c501d73cSMariusz Zaborski return (false); 688c501d73cSMariusz Zaborski } 689c501d73cSMariusz Zaborski 690c501d73cSMariusz Zaborski static int 691c501d73cSMariusz Zaborski dns_limit(const nvlist_t *oldlimits, const nvlist_t *newlimits) 692c501d73cSMariusz Zaborski { 693c501d73cSMariusz Zaborski const char *name; 694c501d73cSMariusz Zaborski void *cookie; 695c501d73cSMariusz Zaborski int nvtype; 696c501d73cSMariusz Zaborski bool hastype, hasfamily; 697c501d73cSMariusz Zaborski 698c501d73cSMariusz Zaborski hastype = false; 699c501d73cSMariusz Zaborski hasfamily = false; 700c501d73cSMariusz Zaborski 701c501d73cSMariusz Zaborski cookie = NULL; 702c501d73cSMariusz Zaborski while ((name = nvlist_next(newlimits, &nvtype, &cookie)) != NULL) { 703c501d73cSMariusz Zaborski if (nvtype == NV_TYPE_STRING) { 704c501d73cSMariusz Zaborski const char *type; 705c501d73cSMariusz Zaborski 706c501d73cSMariusz Zaborski if (strncmp(name, "type", sizeof("type") - 1) != 0) 707c501d73cSMariusz Zaborski return (EINVAL); 708c501d73cSMariusz Zaborski type = nvlist_get_string(newlimits, name); 709752d135eSMariusz Zaborski if (strcmp(type, "ADDR2NAME") != 0 && 710*2863fd2fSMariusz Zaborski strcmp(type, "NAME2ADDR") != 0 && 711*2863fd2fSMariusz Zaborski strcmp(type, "ADDR") != 0 && 712*2863fd2fSMariusz Zaborski strcmp(type, "NAME") != 0) { 713c501d73cSMariusz Zaborski return (EINVAL); 714c501d73cSMariusz Zaborski } 715c501d73cSMariusz Zaborski if (!dns_allowed_type(oldlimits, type)) 716c501d73cSMariusz Zaborski return (ENOTCAPABLE); 717c501d73cSMariusz Zaborski hastype = true; 718c501d73cSMariusz Zaborski } else if (nvtype == NV_TYPE_NUMBER) { 719c501d73cSMariusz Zaborski int family; 720c501d73cSMariusz Zaborski 721c501d73cSMariusz Zaborski if (strncmp(name, "family", sizeof("family") - 1) != 0) 722c501d73cSMariusz Zaborski return (EINVAL); 723c501d73cSMariusz Zaborski family = (int)nvlist_get_number(newlimits, name); 724c501d73cSMariusz Zaborski if (!dns_allowed_family(oldlimits, family)) 725c501d73cSMariusz Zaborski return (ENOTCAPABLE); 726c501d73cSMariusz Zaborski hasfamily = true; 727c501d73cSMariusz Zaborski } else { 728c501d73cSMariusz Zaborski return (EINVAL); 729c501d73cSMariusz Zaborski } 730c501d73cSMariusz Zaborski } 731c501d73cSMariusz Zaborski 732c501d73cSMariusz Zaborski /* 733c501d73cSMariusz Zaborski * If the new limit doesn't mention type or family we have to 734c501d73cSMariusz Zaborski * check if the current limit does have those. Missing type or 735c501d73cSMariusz Zaborski * family in the limit means that all types or families are 736c501d73cSMariusz Zaborski * allowed. 737c501d73cSMariusz Zaborski */ 738c501d73cSMariusz Zaborski if (!hastype) { 739c501d73cSMariusz Zaborski if (limit_has_entry(oldlimits, "type")) 740c501d73cSMariusz Zaborski return (ENOTCAPABLE); 741c501d73cSMariusz Zaborski } 742c501d73cSMariusz Zaborski if (!hasfamily) { 743c501d73cSMariusz Zaborski if (limit_has_entry(oldlimits, "family")) 744c501d73cSMariusz Zaborski return (ENOTCAPABLE); 745c501d73cSMariusz Zaborski } 746c501d73cSMariusz Zaborski 747c501d73cSMariusz Zaborski return (0); 748c501d73cSMariusz Zaborski } 749c501d73cSMariusz Zaborski 750c501d73cSMariusz Zaborski static int 751c501d73cSMariusz Zaborski dns_command(const char *cmd, const nvlist_t *limits, nvlist_t *nvlin, 752c501d73cSMariusz Zaborski nvlist_t *nvlout) 753c501d73cSMariusz Zaborski { 754c501d73cSMariusz Zaborski int error; 755c501d73cSMariusz Zaborski 756c501d73cSMariusz Zaborski if (strcmp(cmd, "gethostbyname") == 0) 757c501d73cSMariusz Zaborski error = dns_gethostbyname(limits, nvlin, nvlout); 758c501d73cSMariusz Zaborski else if (strcmp(cmd, "gethostbyaddr") == 0) 759c501d73cSMariusz Zaborski error = dns_gethostbyaddr(limits, nvlin, nvlout); 760c501d73cSMariusz Zaborski else if (strcmp(cmd, "getnameinfo") == 0) 761c501d73cSMariusz Zaborski error = dns_getnameinfo(limits, nvlin, nvlout); 762c501d73cSMariusz Zaborski else if (strcmp(cmd, "getaddrinfo") == 0) 763c501d73cSMariusz Zaborski error = dns_getaddrinfo(limits, nvlin, nvlout); 764c501d73cSMariusz Zaborski else 765c501d73cSMariusz Zaborski error = NO_RECOVERY; 766c501d73cSMariusz Zaborski 767c501d73cSMariusz Zaborski return (error); 768c501d73cSMariusz Zaborski } 769c501d73cSMariusz Zaborski 770920be817SMariusz Zaborski CREATE_SERVICE("system.dns", dns_limit, dns_command, 0); 771