1 /* 2 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 3 * Portions Copyright (c) 1996,1998 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 #include "port_before.h" 19 20 #include <syslog.h> 21 #include <sys/types.h> 22 #include <sys/socket.h> 23 24 #ifdef IRS_LCL_SV_DB 25 #include <db.h> 26 #endif 27 #include <errno.h> 28 #include <fcntl.h> 29 #include <limits.h> 30 #include <stdio.h> 31 #include <string.h> 32 #include <stdlib.h> 33 #include <syslog.h> 34 35 #include <irs.h> 36 #include <irp.h> 37 #include <isc/irpmarshall.h> 38 #include <isc/memcluster.h> 39 40 #include "irs_p.h" 41 #include "lcl_p.h" 42 #include "irp_p.h" 43 44 #include "port_after.h" 45 46 /* Types */ 47 48 struct pvt { 49 struct irp_p *girpdata; 50 int warned; 51 struct servent service; 52 }; 53 54 /* Forward */ 55 56 static void sv_close(struct irs_sv*); 57 static struct servent * sv_next(struct irs_sv *); 58 static struct servent * sv_byname(struct irs_sv *, const char *, 59 const char *); 60 static struct servent * sv_byport(struct irs_sv *, int, const char *); 61 static void sv_rewind(struct irs_sv *); 62 static void sv_minimize(struct irs_sv *); 63 64 static void free_service(struct servent *sv); 65 66 67 68 /* Public */ 69 70 /*% 71 * struct irs_sv * irs_irp_sv(struct irs_acc *this) 72 * 73 */ 74 75 struct irs_sv * 76 irs_irp_sv(struct irs_acc *this) { 77 struct irs_sv *sv; 78 struct pvt *pvt; 79 80 if ((sv = memget(sizeof *sv)) == NULL) { 81 errno = ENOMEM; 82 return (NULL); 83 } 84 memset(sv, 0x0, sizeof *sv); 85 86 if ((pvt = memget(sizeof *pvt)) == NULL) { 87 memput(sv, sizeof *sv); 88 errno = ENOMEM; 89 return (NULL); 90 } 91 memset(pvt, 0, sizeof *pvt); 92 pvt->girpdata = this->private; 93 94 sv->private = pvt; 95 sv->close = sv_close; 96 sv->next = sv_next; 97 sv->byname = sv_byname; 98 sv->byport = sv_byport; 99 sv->rewind = sv_rewind; 100 sv->minimize = sv_minimize; 101 102 return (sv); 103 } 104 105 /* Methods */ 106 107 /*% 108 * void sv_close(struct irs_sv *this) 109 * 110 */ 111 112 static void 113 sv_close(struct irs_sv *this) { 114 struct pvt *pvt = (struct pvt *)this->private; 115 116 sv_minimize(this); 117 118 free_service(&pvt->service); 119 120 memput(pvt, sizeof *pvt); 121 memput(this, sizeof *this); 122 } 123 124 /*% 125 * Fills the cache if necessary and returns the next item from it. 126 * 127 */ 128 129 static struct servent * 130 sv_next(struct irs_sv *this) { 131 struct pvt *pvt = (struct pvt *)this->private; 132 struct servent *sv = &pvt->service; 133 char *body; 134 size_t bodylen; 135 int code; 136 char text[256]; 137 138 if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { 139 return (NULL); 140 } 141 142 if (irs_irp_send_command(pvt->girpdata, "getservent") != 0) { 143 return (NULL); 144 } 145 146 if (irs_irp_get_full_response(pvt->girpdata, &code, 147 text, sizeof text, 148 &body, &bodylen) != 0) { 149 return (NULL); 150 } 151 152 if (code == IRPD_GETSERVICE_OK) { 153 free_service(sv); 154 if (irp_unmarshall_sv(sv, body) != 0) { 155 sv = NULL; 156 } 157 } else { 158 sv = NULL; 159 } 160 161 if (body != NULL) { 162 memput(body, bodylen); 163 } 164 165 return (sv); 166 } 167 168 /*% 169 * struct servent * sv_byname(struct irs_sv *this, const char *name, 170 * const char *proto) 171 * 172 */ 173 174 static struct servent * 175 sv_byname(struct irs_sv *this, const char *name, const char *proto) { 176 struct pvt *pvt = (struct pvt *)this->private; 177 struct servent *sv = &pvt->service; 178 char *body; 179 char text[256]; 180 size_t bodylen; 181 int code; 182 183 if (sv->s_name != NULL && 184 strcmp(name, sv->s_name) == 0 && 185 strcasecmp(proto, sv->s_proto) == 0) { 186 return (sv); 187 } 188 189 if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { 190 return (NULL); 191 } 192 193 if (irs_irp_send_command(pvt->girpdata, "getservbyname %s %s", 194 name, proto) != 0) 195 return (NULL); 196 197 if (irs_irp_get_full_response(pvt->girpdata, &code, 198 text, sizeof text, 199 &body, &bodylen) != 0) { 200 return (NULL); 201 } 202 203 if (code == IRPD_GETSERVICE_OK) { 204 free_service(sv); 205 if (irp_unmarshall_sv(sv, body) != 0) { 206 sv = NULL; 207 } 208 } else { 209 sv = NULL; 210 } 211 212 if (body != NULL) { 213 memput(body, bodylen); 214 } 215 216 return (sv); 217 } 218 219 /*% 220 * struct servent * sv_byport(struct irs_sv *this, int port, 221 * const char *proto) 222 * 223 */ 224 225 static struct servent * 226 sv_byport(struct irs_sv *this, int port, const char *proto) { 227 struct pvt *pvt = (struct pvt *)this->private; 228 struct servent *sv = &pvt->service; 229 char *body; 230 size_t bodylen; 231 char text[256]; 232 int code; 233 234 if (sv->s_name != NULL && 235 port == sv->s_port && 236 strcasecmp(proto, sv->s_proto) == 0) { 237 return (sv); 238 } 239 240 if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { 241 return (NULL); 242 } 243 244 if (irs_irp_send_command(pvt->girpdata, "getservbyport %d %s", 245 ntohs((short)port), proto) != 0) { 246 return (NULL); 247 } 248 249 if (irs_irp_get_full_response(pvt->girpdata, &code, 250 text, sizeof text, 251 &body, &bodylen) != 0) { 252 return (NULL); 253 } 254 255 if (code == IRPD_GETSERVICE_OK) { 256 free_service(sv); 257 if (irp_unmarshall_sv(sv, body) != 0) { 258 sv = NULL; 259 } 260 } else { 261 sv = NULL; 262 } 263 264 if (body != NULL) { 265 memput(body, bodylen); 266 } 267 268 return (sv); 269 } 270 271 /*% 272 * void sv_rewind(struct irs_sv *this) 273 * 274 */ 275 276 static void 277 sv_rewind(struct irs_sv *this) { 278 struct pvt *pvt = (struct pvt *)this->private; 279 char text[256]; 280 int code; 281 282 if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { 283 return; 284 } 285 286 if (irs_irp_send_command(pvt->girpdata, "setservent") != 0) { 287 return; 288 } 289 290 code = irs_irp_read_response(pvt->girpdata, text, sizeof text); 291 if (code != IRPD_GETSERVICE_SETOK) { 292 if (irp_log_errors) { 293 syslog(LOG_WARNING, "setservent failed: %s", text); 294 } 295 } 296 297 return; 298 } 299 300 /*% 301 * void sv_minimize(struct irs_sv *this) 302 * 303 */ 304 305 static void 306 sv_minimize(struct irs_sv *this) { 307 struct pvt *pvt = (struct pvt *)this->private; 308 309 irs_irp_disconnect(pvt->girpdata); 310 } 311 312 313 314 315 316 317 static void 318 free_service(struct servent *sv) { 319 char **p; 320 321 if (sv == NULL) { 322 return; 323 } 324 325 if (sv->s_name != NULL) { 326 free(sv->s_name); 327 } 328 329 for (p = sv->s_aliases ; p != NULL && *p != NULL ; p++) { 330 free(*p); 331 } 332 333 if (sv->s_proto != NULL) { 334 free(sv->s_proto); 335 } 336 } 337 338 339 340 /*! \file */ 341