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