1 /* 2 * Copyright (c) 1999 by Sun Microsystems, Inc. 3 * All rights reserved. 4 */ 5 6 /* 7 * Portions Copyright (c) 1996,1998 by Internet Software Consortium. 8 * 9 * Permission to use, copy, modify, and distribute this software for any 10 * purpose with or without fee is hereby granted, provided that the above 11 * copyright notice and this permission notice appear in all copies. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS 14 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES 15 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE 16 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 17 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 18 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 19 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 20 * SOFTWARE. 21 */ 22 23 #pragma ident "%Z%%M% %I% %E% SMI" 24 25 #if defined(LIBC_SCCS) && !defined(lint) 26 static const char rcsid[] = "$Id: irp_sv.c,v 8.1 1999/01/18 07:46:54 vixie Exp $"; 27 #endif /* LIBC_SCCS and not lint */ 28 29 /* extern */ 30 31 #include "port_before.h" 32 33 #include <syslog.h> 34 #include <sys/types.h> 35 #include <sys/socket.h> 36 37 #ifdef IRS_LCL_SV_DB 38 #include <db.h> 39 #endif 40 #include <errno.h> 41 #include <fcntl.h> 42 #include <limits.h> 43 #include <stdio.h> 44 #include <string.h> 45 #include <stdlib.h> 46 #include <syslog.h> 47 48 #include <irs.h> 49 #include <irp.h> 50 #include <isc/irpmarshall.h> 51 #include <isc/memcluster.h> 52 53 #include "irs_p.h" 54 #include "lcl_p.h" 55 #include "irp_p.h" 56 57 #include "port_after.h" 58 59 /* Types */ 60 61 struct pvt { 62 struct irp_p *girpdata; 63 int warned; 64 struct servent service; 65 }; 66 67 /* Forward */ 68 69 static void sv_close(struct irs_sv*); 70 static struct servent * sv_next(struct irs_sv *); 71 static struct servent * sv_byname(struct irs_sv *, const char *, 72 const char *); 73 static struct servent * sv_byport(struct irs_sv *, int, const char *); 74 static void sv_rewind(struct irs_sv *); 75 static void sv_minimize(struct irs_sv *); 76 77 static void free_service(struct servent *sv); 78 79 80 81 /* Public */ 82 83 84 85 /* 86 * struct irs_sv * irs_irp_sv(struct irs_acc *this) 87 * 88 */ 89 90 struct irs_sv * 91 irs_irp_sv(struct irs_acc *this) { 92 struct irs_sv *sv; 93 struct pvt *pvt; 94 95 if ((sv = memget(sizeof *sv)) == NULL) { 96 errno = ENOMEM; 97 return (NULL); 98 } 99 memset(sv, 0x0, sizeof *sv); 100 101 if ((pvt = memget(sizeof *pvt)) == NULL) { 102 memput(sv, sizeof *sv); 103 errno = ENOMEM; 104 return (NULL); 105 } 106 memset(pvt, 0, sizeof *pvt); 107 pvt->girpdata = this->private; 108 109 sv->private = pvt; 110 sv->close = sv_close; 111 sv->next = sv_next; 112 sv->byname = sv_byname; 113 sv->byport = sv_byport; 114 sv->rewind = sv_rewind; 115 sv->minimize = sv_minimize; 116 117 return (sv); 118 } 119 120 /* Methods */ 121 122 123 124 /* 125 * void sv_close(struct irs_sv *this) 126 * 127 */ 128 129 static void 130 sv_close(struct irs_sv *this) { 131 struct pvt *pvt = (struct pvt *)this->private; 132 133 sv_minimize(this); 134 135 free_service(&pvt->service); 136 137 memput(pvt, sizeof *pvt); 138 memput(this, sizeof *this); 139 } 140 141 142 143 144 /* 145 * struct servent * sv_next(struct irs_sv *this) 146 * 147 * Notes: 148 * 149 * Fills the cache if necessary and returns the next item from it. 150 * 151 */ 152 153 static struct servent * 154 sv_next(struct irs_sv *this) { 155 struct pvt *pvt = (struct pvt *)this->private; 156 struct servent *sv = &pvt->service; 157 char *body; 158 size_t bodylen; 159 int code; 160 char text[256]; 161 162 if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { 163 return (NULL); 164 } 165 166 if (irs_irp_send_command(pvt->girpdata, "getservent") != 0) { 167 return (NULL); 168 } 169 170 if (irs_irp_get_full_response(pvt->girpdata, &code, 171 text, sizeof text, 172 &body, &bodylen) != 0) { 173 return (NULL); 174 } 175 176 if (code == IRPD_GETSERVICE_OK) { 177 free_service(sv); 178 if (irp_unmarshall_sv(sv, body) != 0) { 179 sv = NULL; 180 } 181 } else { 182 sv = NULL; 183 } 184 185 if (body != NULL) { 186 memput(body, bodylen); 187 } 188 189 return (sv); 190 } 191 192 193 194 195 /* 196 * struct servent * sv_byname(struct irs_sv *this, const char *name, 197 * const char *proto) 198 * 199 */ 200 201 static struct servent * 202 sv_byname(struct irs_sv *this, const char *name, const char *proto) { 203 struct pvt *pvt = (struct pvt *)this->private; 204 struct servent *sv = &pvt->service; 205 char *body; 206 char text[256]; 207 size_t bodylen; 208 int code; 209 210 if (sv->s_name != NULL && 211 strcmp(name, sv->s_name) == 0 && 212 strcasecmp(proto, sv->s_proto) == 0) { 213 return (sv); 214 } 215 216 if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { 217 return (NULL); 218 } 219 220 if (irs_irp_send_command(pvt->girpdata, "getservbyname %s %s", 221 name, proto) != 0) 222 return (NULL); 223 224 if (irs_irp_get_full_response(pvt->girpdata, &code, 225 text, sizeof text, 226 &body, &bodylen) != 0) { 227 return (NULL); 228 } 229 230 if (code == IRPD_GETSERVICE_OK) { 231 free_service(sv); 232 if (irp_unmarshall_sv(sv, body) != 0) { 233 sv = NULL; 234 } 235 } else { 236 sv = NULL; 237 } 238 239 if (body != NULL) { 240 memput(body, bodylen); 241 } 242 243 return (sv); 244 } 245 246 247 248 249 /* 250 * struct servent * sv_byport(struct irs_sv *this, int port, 251 * const char *proto) 252 * 253 */ 254 255 static struct servent * 256 sv_byport(struct irs_sv *this, int port, const char *proto) { 257 struct pvt *pvt = (struct pvt *)this->private; 258 struct servent *sv = &pvt->service; 259 char *body; 260 size_t bodylen; 261 char text[256]; 262 int code; 263 264 if (sv->s_name != NULL && 265 port == sv->s_port && 266 strcasecmp(proto, sv->s_proto) == 0) { 267 return (sv); 268 } 269 270 if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { 271 return (NULL); 272 } 273 274 if (irs_irp_send_command(pvt->girpdata, "getservbyport %d %s", 275 ntohs((short)port), proto) != 0) { 276 return (NULL); 277 } 278 279 if (irs_irp_get_full_response(pvt->girpdata, &code, 280 text, sizeof text, 281 &body, &bodylen) != 0) { 282 return (NULL); 283 } 284 285 if (code == IRPD_GETSERVICE_OK) { 286 free_service(sv); 287 if (irp_unmarshall_sv(sv, body) != 0) { 288 sv = NULL; 289 } 290 } else { 291 sv = NULL; 292 } 293 294 if (body != NULL) { 295 memput(body, bodylen); 296 } 297 298 return (sv); 299 } 300 301 302 303 304 305 /* 306 * void sv_rewind(struct irs_sv *this) 307 * 308 */ 309 310 static void 311 sv_rewind(struct irs_sv *this) { 312 struct pvt *pvt = (struct pvt *)this->private; 313 char text[256]; 314 int code; 315 316 if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { 317 return; 318 } 319 320 if (irs_irp_send_command(pvt->girpdata, "setservent") != 0) { 321 return; 322 } 323 324 code = irs_irp_read_response(pvt->girpdata, text, sizeof text); 325 if (code != IRPD_GETSERVICE_SETOK) { 326 if (irp_log_errors) { 327 syslog(LOG_WARNING, "setservent failed: %s", text); 328 } 329 } 330 331 return; 332 } 333 334 335 336 337 338 /* 339 * void sv_minimize(struct irs_sv *this) 340 * 341 */ 342 343 static void 344 sv_minimize(struct irs_sv *this) { 345 struct pvt *pvt = (struct pvt *)this->private; 346 347 irs_irp_disconnect(pvt->girpdata); 348 } 349 350 351 352 353 354 355 static void 356 free_service(struct servent *sv) { 357 char **p; 358 359 if (sv == NULL) { 360 return; 361 } 362 363 if (sv->s_name != NULL) { 364 free(sv->s_name); 365 } 366 367 for (p = sv->s_aliases ; p != NULL && *p != NULL ; p++) { 368 free(*p); 369 } 370 371 if (sv->s_proto != NULL) { 372 free(sv->s_proto); 373 } 374 } 375 376 377