1/* 2 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 3 * Copyright (c) 1996,1999 by Internet Software Consortium. 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 15 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18#if defined(LIBC_SCCS) && !defined(lint) 19static const char rcsid[] = "$Id: nis_sv.c,v 1.4 2005/04/27 04:56:34 sra Exp $"; 20#endif /* LIBC_SCCS and not lint */ 21 22/* Imports */ 23 24#include "port_before.h" 25 26#ifndef WANT_IRS_NIS 27static int __bind_irs_nis_unneeded; 28#else 29 30#include <sys/types.h> 31#include <netinet/in.h> 32#include <arpa/nameser.h> 33#include <resolv.h> 34#include <sys/socket.h> 35#ifdef T_NULL 36#undef T_NULL /* Silence re-definition warning of T_NULL. */ 37#endif 38#include <rpc/rpc.h> 39#include <rpc/xdr.h> 40#include <rpcsvc/yp_prot.h> 41#include <rpcsvc/ypclnt.h> 42 43#include <ctype.h> 44#include <errno.h> 45#include <stdio.h> 46#include <stdlib.h> 47#include <string.h> 48 49#include <isc/memcluster.h> 50#include <irs.h> 51 52#include "port_after.h" 53 54#include "irs_p.h" 55#include "nis_p.h" 56 57/* Definitions */ 58 59struct pvt { 60 int needrewind; 61 char * nis_domain; 62 char * curkey_data; 63 int curkey_len; 64 char * curval_data; 65 int curval_len; 66 char line[BUFSIZ+1]; 67 struct servent serv; 68 char * svbuf; 69}; 70 71enum do_what { do_none = 0x0, do_key = 0x1, do_val = 0x2, do_all = 0x3 }; 72 73static /*const*/ char services_byname[] = "services.byname"; 74 75/* Forward */ 76 77static void sv_close(struct irs_sv*); 78static struct servent * sv_next(struct irs_sv *); 79static struct servent * sv_byname(struct irs_sv *, const char *, 80 const char *); 81static struct servent * sv_byport(struct irs_sv *, int, const char *); 82static void sv_rewind(struct irs_sv *); 83static void sv_minimize(struct irs_sv *); 84 85static struct servent * makeservent(struct irs_sv *this); 86static void nisfree(struct pvt *, enum do_what); 87 88/* Public */ 89 90struct irs_sv * 91irs_nis_sv(struct irs_acc *this) { 92 struct irs_sv *sv; 93 struct pvt *pvt; 94 95 if (!(sv = memget(sizeof *sv))) { 96 errno = ENOMEM; 97 return (NULL); 98 } 99 memset(sv, 0x5e, sizeof *sv); 100 if (!(pvt = memget(sizeof *pvt))) { 101 memput(sv, sizeof *sv); 102 errno = ENOMEM; 103 return (NULL); 104 } 105 memset(pvt, 0, sizeof *pvt); 106 pvt->needrewind = 1; 107 pvt->nis_domain = ((struct nis_p *)this->private)->domain; 108 sv->private = pvt; 109 sv->close = sv_close; 110 sv->next = sv_next; 111 sv->byname = sv_byname; 112 sv->byport = sv_byport; 113 sv->rewind = sv_rewind; 114 sv->minimize = sv_minimize; 115 sv->res_get = NULL; 116 sv->res_set = NULL; 117 return (sv); 118} 119 120/* Methods */ 121 122static void 123sv_close(struct irs_sv *this) { 124 struct pvt *pvt = (struct pvt *)this->private; 125 126 nisfree(pvt, do_all); 127 if (pvt->serv.s_aliases) 128 free(pvt->serv.s_aliases); 129 if (pvt->svbuf) 130 free(pvt->svbuf); 131 memput(pvt, sizeof *pvt); 132 memput(this, sizeof *this); 133} 134 135static struct servent * 136sv_byname(struct irs_sv *this, const char *name, const char *proto) { 137 struct servent *serv; 138 char **sap; 139 140 sv_rewind(this); 141 while ((serv = sv_next(this)) != NULL) { 142 if (proto != NULL && strcmp(proto, serv->s_proto)) 143 continue; 144 if (!strcmp(name, serv->s_name)) 145 break; 146 for (sap = serv->s_aliases; sap && *sap; sap++) 147 if (!strcmp(name, *sap)) 148 break; 149 } 150 return (serv); 151} 152 153static struct servent * 154sv_byport(struct irs_sv *this, int port, const char *proto) { 155 struct servent *serv; 156 157 sv_rewind(this); 158 while ((serv = sv_next(this)) != NULL) { 159 if (proto != NULL && strcmp(proto, serv->s_proto)) 160 continue; 161 if (serv->s_port == port) 162 break; 163 } 164 return (serv); 165} 166 167static void 168sv_rewind(struct irs_sv *this) { 169 struct pvt *pvt = (struct pvt *)this->private; 170 171 pvt->needrewind = 1; 172} 173 174static struct servent * 175sv_next(struct irs_sv *this) { 176 struct pvt *pvt = (struct pvt *)this->private; 177 struct servent *rval; 178 int r; 179 180 do { 181 if (pvt->needrewind) { 182 nisfree(pvt, do_all); 183 r = yp_first(pvt->nis_domain, services_byname, 184 &pvt->curkey_data, &pvt->curkey_len, 185 &pvt->curval_data, &pvt->curval_len); 186 pvt->needrewind = 0; 187 } else { 188 char *newkey_data; 189 int newkey_len; 190 191 nisfree(pvt, do_val); 192 r = yp_next(pvt->nis_domain, services_byname, 193 pvt->curkey_data, pvt->curkey_len, 194 &newkey_data, &newkey_len, 195 &pvt->curval_data, &pvt->curval_len); 196 nisfree(pvt, do_key); 197 pvt->curkey_data = newkey_data; 198 pvt->curkey_len = newkey_len; 199 } 200 if (r != 0) { 201 errno = ENOENT; 202 return (NULL); 203 } 204 rval = makeservent(this); 205 } while (rval == NULL); 206 return (rval); 207} 208 209static void 210sv_minimize(struct irs_sv *this) { 211 UNUSED(this); 212 /* NOOP */ 213} 214 215/* Private */ 216 217static struct servent * 218makeservent(struct irs_sv *this) { 219 struct pvt *pvt = (struct pvt *)this->private; 220 static const char spaces[] = " \t"; 221 char *p, **t; 222 int n, m; 223 224 if (pvt->svbuf) 225 free(pvt->svbuf); 226 pvt->svbuf = pvt->curval_data; 227 pvt->curval_data = NULL; 228 229 if (pvt->serv.s_aliases) { 230 free(pvt->serv.s_aliases); 231 pvt->serv.s_aliases = NULL; 232 } 233 234 if ((p = strpbrk(pvt->svbuf, "#\n"))) 235 *p = '\0'; 236 237 p = pvt->svbuf; 238 239 pvt->serv.s_name = p; 240 p += strcspn(p, spaces); 241 if (!*p) 242 goto cleanup; 243 *p++ = '\0'; 244 p += strspn(p, spaces); 245 246 pvt->serv.s_port = htons((u_short) atoi(p)); 247 pvt->serv.s_proto = NULL; 248 249 while (*p && !isspace((unsigned char)*p)) 250 if (*p++ == '/') 251 pvt->serv.s_proto = p; 252 if (!pvt->serv.s_proto) 253 goto cleanup; 254 if (*p) { 255 *p++ = '\0'; 256 p += strspn(p, spaces); 257 } 258 259 n = m = 0; 260 while (*p) { 261 if ((n + 1) >= m || !pvt->serv.s_aliases) { 262 m += 10; 263 t = realloc(pvt->serv.s_aliases, m * sizeof(char *)); 264 if (!t) { 265 errno = ENOMEM; 266 goto cleanup; 267 } 268 pvt->serv.s_aliases = t; 269 } 270 pvt->serv.s_aliases[n++] = p; 271 p += strcspn(p, spaces); 272 if (!*p) 273 break; 274 *p++ = '\0'; 275 p += strspn(p, spaces); 276 } 277 if (!pvt->serv.s_aliases) 278 pvt->serv.s_aliases = malloc(sizeof(char *)); 279 if (!pvt->serv.s_aliases) 280 goto cleanup; 281 pvt->serv.s_aliases[n] = NULL; 282 return (&pvt->serv); 283 284 cleanup: 285 if (pvt->serv.s_aliases) { 286 free(pvt->serv.s_aliases); 287 pvt->serv.s_aliases = NULL; 288 } 289 if (pvt->svbuf) { 290 free(pvt->svbuf); 291 pvt->svbuf = NULL; 292 } 293 return (NULL); 294} 295 296static void 297nisfree(struct pvt *pvt, enum do_what do_what) { 298 if ((do_what & do_key) && pvt->curkey_data) { 299 free(pvt->curkey_data); 300 pvt->curkey_data = NULL; 301 } 302 if ((do_what & do_val) && pvt->curval_data) { 303 free(pvt->curval_data); 304 pvt->curval_data = NULL; 305 } 306} 307 308#endif /*WANT_IRS_NIS*/ 309 310/*! \file */ 311