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