1 /* 2 * Copyright (c) 1989, 1993, 1995 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 /* 35 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 36 * Portions Copyright (c) 1996-1999 by Internet Software Consortium. 37 * 38 * Permission to use, copy, modify, and distribute this software for any 39 * purpose with or without fee is hereby granted, provided that the above 40 * copyright notice and this permission notice appear in all copies. 41 * 42 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 43 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 44 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 45 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 46 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 47 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 48 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 49 */ 50 51 #include "port_before.h" 52 53 #include <sys/types.h> 54 #include <sys/socket.h> 55 #include <netinet/in.h> 56 #include <arpa/nameser.h> 57 #include <resolv.h> 58 59 #ifdef IRS_LCL_SV_DB 60 #include <db.h> 61 #endif 62 #include <errno.h> 63 #include <fcntl.h> 64 #include <limits.h> 65 #include <stdio.h> 66 #include <string.h> 67 #include <stdlib.h> 68 69 #include <irs.h> 70 #include <isc/memcluster.h> 71 72 #include "port_after.h" 73 74 #include "irs_p.h" 75 #include "lcl_p.h" 76 77 #ifdef SPRINTF_CHAR 78 # define SPRINTF(x) strlen(sprintf/**/x) 79 #else 80 # define SPRINTF(x) ((size_t)sprintf x) 81 #endif 82 83 /* Types */ 84 85 struct pvt { 86 #ifdef IRS_LCL_SV_DB 87 DB * dbh; 88 int dbf; 89 #endif 90 struct lcl_sv sv; 91 }; 92 93 /* Forward */ 94 95 static void sv_close(struct irs_sv*); 96 static struct servent * sv_next(struct irs_sv *); 97 static struct servent * sv_byname(struct irs_sv *, const char *, 98 const char *); 99 static struct servent * sv_byport(struct irs_sv *, int, const char *); 100 static void sv_rewind(struct irs_sv *); 101 static void sv_minimize(struct irs_sv *); 102 /*global*/ struct servent * irs_lclsv_fnxt(struct lcl_sv *); 103 #ifdef IRS_LCL_SV_DB 104 static struct servent * sv_db_rec(struct lcl_sv *, DBT *, DBT *); 105 #endif 106 107 /* Portability */ 108 109 #ifndef SEEK_SET 110 # define SEEK_SET 0 111 #endif 112 113 /* Public */ 114 115 struct irs_sv * 116 irs_lcl_sv(struct irs_acc *this) { 117 struct irs_sv *sv; 118 struct pvt *pvt; 119 120 UNUSED(this); 121 122 if ((sv = memget(sizeof *sv)) == NULL) { 123 errno = ENOMEM; 124 return (NULL); 125 } 126 memset(sv, 0x5e, sizeof *sv); 127 if ((pvt = memget(sizeof *pvt)) == NULL) { 128 memput(sv, sizeof *sv); 129 errno = ENOMEM; 130 return (NULL); 131 } 132 memset(pvt, 0, sizeof *pvt); 133 sv->private = pvt; 134 sv->close = sv_close; 135 sv->next = sv_next; 136 sv->byname = sv_byname; 137 sv->byport = sv_byport; 138 sv->rewind = sv_rewind; 139 sv->minimize = sv_minimize; 140 sv->res_get = NULL; 141 sv->res_set = NULL; 142 #ifdef IRS_LCL_SV_DB 143 pvt->dbf = R_FIRST; 144 #endif 145 return (sv); 146 } 147 148 /* Methods */ 149 150 static void 151 sv_close(struct irs_sv *this) { 152 struct pvt *pvt = (struct pvt *)this->private; 153 154 #ifdef IRS_LCL_SV_DB 155 if (pvt->dbh != NULL) 156 (*pvt->dbh->close)(pvt->dbh); 157 #endif 158 if (pvt->sv.fp) 159 fclose(pvt->sv.fp); 160 memput(pvt, sizeof *pvt); 161 memput(this, sizeof *this); 162 } 163 164 static struct servent * 165 sv_byname(struct irs_sv *this, const char *name, const char *proto) { 166 #ifdef IRS_LCL_SV_DB 167 struct pvt *pvt = (struct pvt *)this->private; 168 #endif 169 struct servent *p; 170 char **cp; 171 172 sv_rewind(this); 173 #ifdef IRS_LCL_SV_DB 174 if (pvt->dbh != NULL) { 175 DBT key, data; 176 177 /* Note that (sizeof "/") == 2. */ 178 if ((strlen(name) + sizeof "/" + proto ? strlen(proto) : 0) 179 > sizeof pvt->sv.line) 180 goto try_local; 181 key.data = pvt->sv.line; 182 key.size = SPRINTF((pvt->sv.line, "%s/%s", name, 183 proto ? proto : "")) + 1; 184 if (proto != NULL) { 185 if ((*pvt->dbh->get)(pvt->dbh, &key, &data, 0) != 0) 186 return (NULL); 187 } else if ((*pvt->dbh->seq)(pvt->dbh, &key, &data, R_CURSOR) 188 != 0) 189 return (NULL); 190 return (sv_db_rec(&pvt->sv, &key, &data)); 191 } 192 try_local: 193 #endif 194 195 while ((p = sv_next(this))) { 196 if (strcmp(name, p->s_name) == 0) 197 goto gotname; 198 for (cp = p->s_aliases; *cp; cp++) 199 if (strcmp(name, *cp) == 0) 200 goto gotname; 201 continue; 202 gotname: 203 if (proto == NULL || strcmp(p->s_proto, proto) == 0) 204 break; 205 } 206 return (p); 207 } 208 209 static struct servent * 210 sv_byport(struct irs_sv *this, int port, const char *proto) { 211 #ifdef IRS_LCL_SV_DB 212 struct pvt *pvt = (struct pvt *)this->private; 213 #endif 214 struct servent *p; 215 216 sv_rewind(this); 217 #ifdef IRS_LCL_SV_DB 218 if (pvt->dbh != NULL) { 219 DBT key, data; 220 u_short *ports; 221 222 ports = (u_short *)pvt->sv.line; 223 ports[0] = 0; 224 ports[1] = port; 225 key.data = ports; 226 key.size = sizeof(u_short) * 2; 227 if (proto && *proto) { 228 strncpy((char *)ports + key.size, proto, 229 BUFSIZ - key.size); 230 key.size += strlen((char *)ports + key.size) + 1; 231 if ((*pvt->dbh->get)(pvt->dbh, &key, &data, 0) != 0) 232 return (NULL); 233 } else { 234 if ((*pvt->dbh->seq)(pvt->dbh, &key, &data, R_CURSOR) 235 != 0) 236 return (NULL); 237 } 238 return (sv_db_rec(&pvt->sv, &key, &data)); 239 } 240 #endif 241 while ((p = sv_next(this))) { 242 if (p->s_port != port) 243 continue; 244 if (proto == NULL || strcmp(p->s_proto, proto) == 0) 245 break; 246 } 247 return (p); 248 } 249 250 static void 251 sv_rewind(struct irs_sv *this) { 252 struct pvt *pvt = (struct pvt *)this->private; 253 254 if (pvt->sv.fp) { 255 if (fseek(pvt->sv.fp, 0L, SEEK_SET) == 0) 256 return; 257 (void)fclose(pvt->sv.fp); 258 pvt->sv.fp = NULL; 259 } 260 #ifdef IRS_LCL_SV_DB 261 pvt->dbf = R_FIRST; 262 if (pvt->dbh != NULL) 263 return; 264 pvt->dbh = dbopen(_PATH_SERVICES_DB, O_RDONLY,O_RDONLY,DB_BTREE, NULL); 265 if (pvt->dbh != NULL) { 266 if (fcntl((*pvt->dbh->fd)(pvt->dbh), F_SETFD, 1) < 0) { 267 (*pvt->dbh->close)(pvt->dbh); 268 pvt->dbh = NULL; 269 } 270 return; 271 } 272 #endif 273 if ((pvt->sv.fp = fopen(_PATH_SERVICES, "r")) == NULL) 274 return; 275 if (fcntl(fileno(pvt->sv.fp), F_SETFD, 1) < 0) { 276 (void)fclose(pvt->sv.fp); 277 pvt->sv.fp = NULL; 278 } 279 } 280 281 static struct servent * 282 sv_next(struct irs_sv *this) { 283 struct pvt *pvt = (struct pvt *)this->private; 284 285 #ifdef IRS_LCL_SV_DB 286 if (pvt->dbh == NULL && pvt->sv.fp == NULL) 287 #else 288 if (pvt->sv.fp == NULL) 289 #endif 290 sv_rewind(this); 291 292 #ifdef IRS_LCL_SV_DB 293 if (pvt->dbh != NULL) { 294 DBT key, data; 295 296 while ((*pvt->dbh->seq)(pvt->dbh, &key, &data, pvt->dbf) == 0){ 297 pvt->dbf = R_NEXT; 298 if (((char *)key.data)[0]) 299 continue; 300 return (sv_db_rec(&pvt->sv, &key, &data)); 301 } 302 } 303 #endif 304 305 if (pvt->sv.fp == NULL) 306 return (NULL); 307 return (irs_lclsv_fnxt(&pvt->sv)); 308 } 309 310 static void 311 sv_minimize(struct irs_sv *this) { 312 struct pvt *pvt = (struct pvt *)this->private; 313 314 #ifdef IRS_LCL_SV_DB 315 if (pvt->dbh != NULL) { 316 (*pvt->dbh->close)(pvt->dbh); 317 pvt->dbh = NULL; 318 } 319 #endif 320 if (pvt->sv.fp != NULL) { 321 (void)fclose(pvt->sv.fp); 322 pvt->sv.fp = NULL; 323 } 324 } 325 326 /* Quasipublic. */ 327 328 struct servent * 329 irs_lclsv_fnxt(struct lcl_sv *sv) { 330 char *p, *cp, **q; 331 332 again: 333 if ((p = fgets(sv->line, BUFSIZ, sv->fp)) == NULL) 334 return (NULL); 335 if (*p == '#') 336 goto again; 337 sv->serv.s_name = p; 338 while (*p && *p != '\n' && *p != ' ' && *p != '\t' && *p != '#') 339 ++p; 340 if (*p == '\0' || *p == '#' || *p == '\n') 341 goto again; 342 *p++ = '\0'; 343 while (*p == ' ' || *p == '\t') 344 p++; 345 if (*p == '\0' || *p == '#' || *p == '\n') 346 goto again; 347 sv->serv.s_port = htons((u_short)strtol(p, &cp, 10)); 348 if (cp == p || (*cp != '/' && *cp != ',')) 349 goto again; 350 p = cp + 1; 351 sv->serv.s_proto = p; 352 353 q = sv->serv.s_aliases = sv->serv_aliases; 354 355 while (*p && *p != '\n' && *p != ' ' && *p != '\t' && *p != '#') 356 ++p; 357 358 while (*p == ' ' || *p == '\t') { 359 *p++ = '\0'; 360 while (*p == ' ' || *p == '\t') 361 ++p; 362 if (*p == '\0' || *p == '#' || *p == '\n') 363 break; 364 if (q < &sv->serv_aliases[IRS_SV_MAXALIASES - 1]) 365 *q++ = p; 366 while (*p && *p != '\n' && *p != ' ' && *p != '\t' && *p != '#') 367 ++p; 368 } 369 370 *p = '\0'; 371 *q = NULL; 372 return (&sv->serv); 373 } 374 375 /* Private. */ 376 377 #ifdef IRS_LCL_SV_DB 378 static struct servent * 379 sv_db_rec(struct lcl_sv *sv, DBT *key, DBT *data) { 380 char *p, **q; 381 int n; 382 383 p = data->data; 384 p[data->size - 1] = '\0'; /*%< should be, but we depend on it */ 385 if (((char *)key->data)[0] == '\0') { 386 if (key->size < sizeof(u_short)*2 || data->size < 2) 387 return (NULL); 388 sv->serv.s_port = ((u_short *)key->data)[1]; 389 n = strlen(p) + 1; 390 if ((size_t)n > sizeof(sv->line)) { 391 n = sizeof(sv->line); 392 } 393 memcpy(sv->line, p, n); 394 sv->serv.s_name = sv->line; 395 if ((sv->serv.s_proto = strchr(sv->line, '/')) != NULL) 396 *(sv->serv.s_proto)++ = '\0'; 397 p += n; 398 data->size -= n; 399 } else { 400 if (data->size < sizeof(u_short) + 1) 401 return (NULL); 402 if (key->size > sizeof(sv->line)) 403 key->size = sizeof(sv->line); 404 ((char *)key->data)[key->size - 1] = '\0'; 405 memcpy(sv->line, key->data, key->size); 406 sv->serv.s_name = sv->line; 407 if ((sv->serv.s_proto = strchr(sv->line, '/')) != NULL) 408 *(sv->serv.s_proto)++ = '\0'; 409 sv->serv.s_port = *(u_short *)data->data; 410 p += sizeof(u_short); 411 data->size -= sizeof(u_short); 412 } 413 q = sv->serv.s_aliases = sv->serv_aliases; 414 while (data->size > 0 && q < &sv->serv_aliases[IRS_SV_MAXALIASES - 1]) { 415 416 *q++ = p; 417 n = strlen(p) + 1; 418 data->size -= n; 419 p += n; 420 } 421 *q = NULL; 422 return (&sv->serv); 423 } 424 #endif 425 426 /*! \file */ 427