1 /*- 2 * Copyright (c) 1994, Garrett Wollman 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 */ 25 26 #include <sys/cdefs.h> 27 __FBSDID("$FreeBSD$"); 28 29 #include "namespace.h" 30 #include "reentrant.h" 31 #include <sys/param.h> 32 #include <sys/socket.h> 33 #include <netinet/in.h> 34 #include <arpa/inet.h> 35 #include <netdb.h> 36 #include <stdio.h> 37 #include <ctype.h> 38 #include <stdlib.h> 39 #include <string.h> 40 #include <stdarg.h> 41 #include <nsswitch.h> 42 #include "un-namespace.h" 43 #include "netdb_private.h" 44 45 extern int _ht_getnetbyname(void *, void *, va_list); 46 extern int _dns_getnetbyname(void *, void *, va_list); 47 extern int _nis_getnetbyname(void *, void *, va_list); 48 extern int _ht_getnetbyaddr(void *, void *, va_list); 49 extern int _dns_getnetbyaddr(void *, void *, va_list); 50 extern int _nis_getnetbyaddr(void *, void *, va_list); 51 52 /* Network lookup order if nsswitch.conf is broken or nonexistant */ 53 static const ns_src default_src[] = { 54 { NSSRC_FILES, NS_SUCCESS }, 55 { NSSRC_DNS, NS_SUCCESS }, 56 { 0 } 57 }; 58 59 static struct netdata netdata; 60 static thread_key_t netdata_key; 61 static once_t netdata_init_once = ONCE_INITIALIZER; 62 static int netdata_thr_keycreated = 0; 63 64 static void 65 netdata_free(void *ptr) 66 { 67 struct netdata *nd = ptr; 68 69 if (nd == NULL) 70 return; 71 nd->data.stayopen = 0; 72 _endnethtent(&nd->data); 73 free(nd); 74 } 75 76 static void 77 netdata_keycreate(void) 78 { 79 netdata_thr_keycreated = 80 (thr_keycreate(&netdata_key, netdata_free) == 0); 81 } 82 83 struct netdata * 84 __netdata_init(void) 85 { 86 struct netdata *nd; 87 88 if (thr_main() != 0) 89 return &netdata; 90 if (thr_once(&netdata_init_once, netdata_keycreate) != 0 || 91 !netdata_thr_keycreated) 92 return NULL; 93 if ((nd = thr_getspecific(netdata_key)) != NULL) 94 return nd; 95 if ((nd = calloc(1, sizeof(*nd))) == NULL) 96 return NULL; 97 if (thr_setspecific(netdata_key, nd) == 0) 98 return nd; 99 free(nd); 100 return NULL; 101 } 102 103 int 104 getnetbyname_r(const char *name, struct netent *ne, struct netent_data *ned) 105 { 106 int rval; 107 108 109 static const ns_dtab dtab[] = { 110 NS_FILES_CB(_ht_getnetbyname, NULL) 111 { NSSRC_DNS, _dns_getnetbyname, NULL }, 112 NS_NIS_CB(_nis_getnetbyname, NULL) /* force -DHESIOD */ 113 { 0 } 114 }; 115 116 rval = _nsdispatch(NULL, dtab, NSDB_NETWORKS, "getnetbyname", 117 default_src, name, ne, ned); 118 119 return (rval == NS_SUCCESS) ? 0 : -1; 120 } 121 122 int 123 getnetbyaddr_r(uint32_t addr, int af, struct netent *ne, 124 struct netent_data *ned) 125 { 126 int rval; 127 128 static const ns_dtab dtab[] = { 129 NS_FILES_CB(_ht_getnetbyaddr, NULL) 130 { NSSRC_DNS, _dns_getnetbyaddr, NULL }, 131 NS_NIS_CB(_nis_getnetbyaddr, NULL) /* force -DHESIOD */ 132 { 0 } 133 }; 134 135 rval = _nsdispatch(NULL, dtab, NSDB_NETWORKS, "getnetbyaddr", 136 default_src, addr, af, ne, ned); 137 138 return (rval == NS_SUCCESS) ? 0 : -1; 139 } 140 141 void 142 setnetent_r(int stayopen, struct netent_data *ned) 143 { 144 _setnethtent(stayopen, ned); 145 _setnetdnsent(stayopen); 146 } 147 148 void 149 endnetent_r(struct netent_data *ned) 150 { 151 _endnethtent(ned); 152 _endnetdnsent(); 153 } 154 155 struct netent * 156 getnetbyname(const char *name) 157 { 158 struct netdata *nd; 159 160 if ((nd = __netdata_init()) == NULL) 161 return NULL; 162 if (getnetbyname_r(name, &nd->net, &nd->data) != 0) 163 return NULL; 164 return &nd->net; 165 } 166 167 struct netent * 168 #if __LONG_BIT == 64 169 getnetbyaddr(u_long addr, int af) /* ABI compatibility */ 170 #else 171 getnetbyaddr(uint32_t addr, int af) 172 #endif 173 { 174 struct netdata *nd; 175 176 if ((nd = __netdata_init()) == NULL) 177 return NULL; 178 if (getnetbyaddr_r((uint32_t)addr, af, &nd->net, &nd->data) != 0) 179 return NULL; 180 return &nd->net; 181 } 182 183 void 184 setnetent(int stayopen) 185 { 186 struct netdata *nd; 187 188 if ((nd = __netdata_init()) == NULL) 189 return; 190 setnetent_r(stayopen, &nd->data); 191 } 192 193 void 194 endnetent(void) 195 { 196 struct netdata *nd; 197 198 if ((nd = __netdata_init()) == NULL) 199 return; 200 endnetent_r(&nd->data); 201 } 202