1/* 2 * Copyright 2006-2009, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 6/* 7 * Copyright (c) 1989, 1993, 1995 8 * The Regents of the University of California. All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 */ 38 39/* 40 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 41 * Portions Copyright (c) 1996-1999 by Internet Software Consortium. 42 * 43 * Permission to use, copy, modify, and distribute this software for any 44 * purpose with or without fee is hereby granted, provided that the above 45 * copyright notice and this permission notice appear in all copies. 46 * 47 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 48 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 49 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 50 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 51 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 52 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 53 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 54 */ 55 56 57#include "port_before.h" 58 59extern "C" { 60// libbind's internal headers aren't C++ safe 61 62#include "irs_p.h" 63#include "lcl_p.h" 64 65#define private private_data 66#include <irs.h> 67#undef private 68 69#include <isc/memcluster.h> 70 71} 72 73#include <sys/types.h> 74#include <sys/socket.h> 75#include <netinet/in.h> 76#include <arpa/nameser.h> 77#include <resolv.h> 78 79#include "port_after.h" 80 81#include <errno.h> 82#include <fcntl.h> 83#include <limits.h> 84#include <stdio.h> 85#include <string.h> 86#include <stdlib.h> 87 88#include <FindDirectory.h> 89#include <fs_attr.h> 90#include <image.h> 91#include <TypeConstants.h> 92 93 94#define IRS_SV_MAXALIASES 35 95 96struct service_private { 97 FILE* file; 98 char line[BUFSIZ + 1]; 99 struct servent servent; 100 char* aliases[IRS_SV_MAXALIASES]; 101}; 102 103 104static status_t 105find_own_image(image_info* _info) 106{ 107 int32 cookie = 0; 108 image_info info; 109 while (get_next_image_info(B_CURRENT_TEAM, &cookie, &info) == B_OK) { 110 if (((addr_t)info.text <= (addr_t)find_own_image 111 && (addr_t)info.text + (size_t)info.text_size 112 > (addr_t)find_own_image)) { 113 // found us 114 *_info = info; 115 return B_OK; 116 } 117 } 118 119 return B_ENTRY_NOT_FOUND; 120} 121 122 123static char* 124get_next_line(struct service_private* service) 125{ 126 if (service->file == NULL) 127 return NULL; 128 return fgets(service->line, BUFSIZ, service->file); 129} 130 131 132// #pragma mark - 133 134 135static void 136sv_close(struct irs_sv *sv) 137{ 138 struct service_private *service = (struct service_private *)sv->private_data; 139 140 if (service->file) 141 fclose(service->file); 142 143 memput(service, sizeof *service); 144 memput(sv, sizeof *sv); 145} 146 147 148static void 149sv_rewind(struct irs_sv *sv) 150{ 151 struct service_private *service 152 = (struct service_private *)sv->private_data; 153 154 if (service->file) { 155 if (fseek(service->file, 0L, SEEK_SET) == 0) 156 return; 157 fclose(service->file); 158 service->file = NULL; 159 } 160 161 char path[PATH_MAX]; 162 if (find_directory(B_COMMON_DATA_DIRECTORY, -1, false, path, sizeof(path)) 163 == B_OK) { 164 strlcat(path, "/network/services", sizeof(path)); 165 166 if ((service->file = fopen(path, "r")) != NULL) { 167 if (fcntl(fileno(service->file), F_SETFD, FD_CLOEXEC) == 0) 168 return; 169 170 fclose(service->file); 171 service->file = NULL; 172 } 173 } 174 175 // opening the standard file has file has failed, use the attribute 176 177 // find our library image 178 image_info info; 179 if (find_own_image(&info) != B_OK) 180 return; 181 182 // open the library 183 int libraryFD = open(info.name, O_RDONLY); 184 if (libraryFD < 0) 185 return; 186 187 // open the attribute 188 int attrFD = fs_fopen_attr(libraryFD, "services", B_STRING_TYPE, O_RDONLY); 189 close(libraryFD); 190 if (attrFD < 0) 191 return; 192 193 // attach it to a FILE 194 service->file = fdopen(attrFD, "r"); 195 if (service->file == NULL) { 196 close(attrFD); 197 return; 198 } 199 200 if (fcntl(fileno(service->file), F_SETFD, FD_CLOEXEC) == 0) 201 return; 202 203 fclose(service->file); 204 service->file = NULL; 205} 206 207 208static struct servent * 209sv_next(struct irs_sv *sv) 210{ 211 struct service_private *service = (struct service_private *)sv->private_data; 212 char *p, *cp, **q; 213 214 if (service->file == NULL) 215 sv_rewind(sv); 216 217 if (service->file == NULL) 218 return NULL; 219 220again: 221 if ((p = get_next_line(service)) == NULL) 222 return NULL; 223 224 if (*p == '#') 225 goto again; 226 227 service->servent.s_name = p; 228 while (*p && *p != '\n' && *p != ' ' && *p != '\t' && *p != '#') 229 ++p; 230 if (*p == '\0' || *p == '#' || *p == '\n') 231 goto again; 232 *p++ = '\0'; 233 while (*p == ' ' || *p == '\t') 234 p++; 235 if (*p == '\0' || *p == '#' || *p == '\n') 236 goto again; 237 service->servent.s_port = htons((u_short)strtol(p, &cp, 10)); 238 if (cp == p || (*cp != '/' && *cp != ',')) 239 goto again; 240 p = cp + 1; 241 service->servent.s_proto = p; 242 243 q = service->servent.s_aliases = service->aliases; 244 245 while (*p && *p != '\n' && *p != ' ' && *p != '\t' && *p != '#') 246 ++p; 247 248 while (*p == ' ' || *p == '\t') { 249 *p++ = '\0'; 250 while (*p == ' ' || *p == '\t') 251 ++p; 252 if (*p == '\0' || *p == '#' || *p == '\n') 253 break; 254 if (q < &service->aliases[IRS_SV_MAXALIASES - 1]) 255 *q++ = p; 256 while (*p && *p != '\n' && *p != ' ' && *p != '\t' && *p != '#') 257 ++p; 258 } 259 260 *p = '\0'; 261 *q = NULL; 262 return &service->servent; 263} 264 265 266static struct servent * 267sv_byname(struct irs_sv *sv, const char *name, const char *protocol) 268{ 269 struct servent *servent; 270 271 sv_rewind(sv); 272 273 while ((servent = sv_next(sv))) { 274 char **alias; 275 276 if (!strcmp(name, servent->s_name)) 277 goto gotname; 278 for (alias = servent->s_aliases; *alias; alias++) { 279 if (!strcmp(name, *alias)) 280 goto gotname; 281 } 282 continue; 283gotname: 284 if (protocol == NULL || strcmp(servent->s_proto, protocol) == 0) 285 break; 286 } 287 return servent; 288} 289 290 291static struct servent * 292sv_byport(struct irs_sv *sv, int port, const char *protocol) 293{ 294 struct servent *servent; 295 296 sv_rewind(sv); 297 while ((servent = sv_next(sv))) { 298 if (servent->s_port != port) 299 continue; 300 if (protocol == NULL || strcmp(servent->s_proto, protocol) == 0) 301 break; 302 } 303 return servent; 304} 305 306 307static void 308sv_minimize(struct irs_sv *sv) 309{ 310 struct service_private *service = (struct service_private *)sv->private_data; 311 312 if (service->file != NULL) { 313 fclose(service->file); 314 service->file = NULL; 315 } 316} 317 318 319// #pragma mark - 320 321 322extern "C" struct irs_sv * 323irs_lcl_sv(struct irs_acc */*acc*/) 324{ 325 struct service_private *service; 326 struct irs_sv *sv; 327 328 if ((sv = (irs_sv *)memget(sizeof *sv)) == NULL) { 329 errno = ENOMEM; 330 return NULL; 331 } 332 if ((service = (service_private *)memget(sizeof *service)) == NULL) { 333 memput(sv, sizeof *sv); 334 errno = ENOMEM; 335 return NULL; 336 } 337 338 memset(service, 0, sizeof *service); 339 340 sv->private_data = service; 341 sv->close = sv_close; 342 sv->next = sv_next; 343 sv->byname = sv_byname; 344 sv->byport = sv_byport; 345 sv->rewind = sv_rewind; 346 sv->minimize = sv_minimize; 347 sv->res_get = NULL; 348 sv->res_set = NULL; 349 350 return sv; 351} 352