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