readfile.c revision 1.6 1 1.1 gwr /************************************************************************
2 1.1 gwr Copyright 1988, 1991 by Carnegie Mellon University
3 1.1 gwr
4 1.1 gwr All Rights Reserved
5 1.1 gwr
6 1.1 gwr Permission to use, copy, modify, and distribute this software and its
7 1.1 gwr documentation for any purpose and without fee is hereby granted, provided
8 1.1 gwr that the above copyright notice appear in all copies and that both that
9 1.1 gwr copyright notice and this permission notice appear in supporting
10 1.1 gwr documentation, and that the name of Carnegie Mellon University not be used
11 1.1 gwr in advertising or publicity pertaining to distribution of the software
12 1.1 gwr without specific, written prior permission.
13 1.1 gwr
14 1.1 gwr CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
15 1.1 gwr SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
16 1.1 gwr IN NO EVENT SHALL CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
17 1.1 gwr DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
18 1.1 gwr PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
19 1.1 gwr ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
20 1.1 gwr SOFTWARE.
21 1.1 gwr ************************************************************************/
22 1.1 gwr
23 1.5 lukem #include <sys/cdefs.h>
24 1.1 gwr #ifndef lint
25 1.6 kleink __RCSID("$NetBSD: readfile.c,v 1.6 1998/04/02 11:55:52 kleink Exp $");
26 1.1 gwr #endif
27 1.1 gwr
28 1.1 gwr
29 1.1 gwr /*
30 1.1 gwr * bootpd configuration file reading code.
31 1.1 gwr *
32 1.1 gwr * The routines in this file deal with reading, interpreting, and storing
33 1.1 gwr * the information found in the bootpd configuration file (usually
34 1.1 gwr * /etc/bootptab).
35 1.1 gwr */
36 1.1 gwr
37 1.1 gwr
38 1.1 gwr #include <sys/errno.h>
39 1.1 gwr #include <sys/types.h>
40 1.1 gwr #include <sys/stat.h>
41 1.1 gwr #include <sys/file.h>
42 1.1 gwr #include <sys/time.h>
43 1.1 gwr #include <netinet/in.h>
44 1.1 gwr
45 1.1 gwr #include <stdlib.h>
46 1.1 gwr #include <stdio.h>
47 1.1 gwr #include <string.h>
48 1.6 kleink #include <time.h>
49 1.1 gwr #include <ctype.h>
50 1.1 gwr #include <assert.h>
51 1.1 gwr #include <syslog.h>
52 1.1 gwr
53 1.1 gwr #ifndef USE_BFUNCS
54 1.1 gwr #include <memory.h>
55 1.1 gwr /* Yes, memcpy is OK here (no overlapped copies). */
56 1.1 gwr #define bcopy(a,b,c) memcpy(b,a,c)
57 1.1 gwr #define bzero(p,l) memset(p,0,l)
58 1.1 gwr #define bcmp(a,b,c) memcmp(a,b,c)
59 1.1 gwr #endif
60 1.1 gwr
61 1.1 gwr #include "bootp.h"
62 1.1 gwr #include "hash.h"
63 1.1 gwr #include "hwaddr.h"
64 1.1 gwr #include "lookup.h"
65 1.1 gwr #include "readfile.h"
66 1.1 gwr #include "report.h"
67 1.1 gwr #include "tzone.h"
68 1.1 gwr #include "bootpd.h"
69 1.1 gwr
70 1.1 gwr #define HASHTABLESIZE 257 /* Hash table size (prime) */
71 1.1 gwr
72 1.1 gwr /* Non-standard hardware address type (see bootp.h) */
73 1.1 gwr #define HTYPE_DIRECT 0
74 1.1 gwr
75 1.1 gwr /* Error codes returned by eval_symbol: */
76 1.1 gwr #define SUCCESS 0
77 1.1 gwr #define E_END_OF_ENTRY (-1)
78 1.1 gwr #define E_SYNTAX_ERROR (-2)
79 1.1 gwr #define E_UNKNOWN_SYMBOL (-3)
80 1.1 gwr #define E_BAD_IPADDR (-4)
81 1.1 gwr #define E_BAD_HWADDR (-5)
82 1.1 gwr #define E_BAD_LONGWORD (-6)
83 1.1 gwr #define E_BAD_HWATYPE (-7)
84 1.1 gwr #define E_BAD_PATHNAME (-8)
85 1.2 gwr #define E_BAD_VALUE (-9)
86 1.1 gwr
87 1.1 gwr /* Tag idendities. */
88 1.1 gwr #define SYM_NULL 0
89 1.1 gwr #define SYM_BOOTFILE 1
90 1.1 gwr #define SYM_COOKIE_SERVER 2
91 1.1 gwr #define SYM_DOMAIN_SERVER 3
92 1.1 gwr #define SYM_GATEWAY 4
93 1.1 gwr #define SYM_HWADDR 5
94 1.1 gwr #define SYM_HOMEDIR 6
95 1.1 gwr #define SYM_HTYPE 7
96 1.1 gwr #define SYM_IMPRESS_SERVER 8
97 1.1 gwr #define SYM_IPADDR 9
98 1.1 gwr #define SYM_LOG_SERVER 10
99 1.1 gwr #define SYM_LPR_SERVER 11
100 1.1 gwr #define SYM_NAME_SERVER 12
101 1.1 gwr #define SYM_RLP_SERVER 13
102 1.1 gwr #define SYM_SUBNET_MASK 14
103 1.1 gwr #define SYM_TIME_OFFSET 15
104 1.1 gwr #define SYM_TIME_SERVER 16
105 1.1 gwr #define SYM_VENDOR_MAGIC 17
106 1.1 gwr #define SYM_SIMILAR_ENTRY 18
107 1.1 gwr #define SYM_NAME_SWITCH 19
108 1.1 gwr #define SYM_BOOTSIZE 20
109 1.1 gwr #define SYM_BOOT_SERVER 22
110 1.1 gwr #define SYM_TFTPDIR 23
111 1.1 gwr #define SYM_DUMP_FILE 24
112 1.1 gwr #define SYM_DOMAIN_NAME 25
113 1.1 gwr #define SYM_SWAP_SERVER 26
114 1.1 gwr #define SYM_ROOT_PATH 27
115 1.1 gwr #define SYM_EXTEN_FILE 28
116 1.1 gwr #define SYM_REPLY_ADDR 29
117 1.1 gwr #define SYM_NIS_DOMAIN 30 /* RFC 1533 */
118 1.1 gwr #define SYM_NIS_SERVER 31 /* RFC 1533 */
119 1.1 gwr #define SYM_NTP_SERVER 32 /* RFC 1533 */
120 1.1 gwr #define SYM_EXEC_FILE 33 /* YORK_EX_OPTION */
121 1.2 gwr #define SYM_MSG_SIZE 34
122 1.2 gwr #define SYM_MIN_WAIT 35
123 1.1 gwr /* XXX - Add new tags here */
124 1.1 gwr
125 1.2 gwr #define OP_ADDITION 1 /* Operations on tags */
126 1.1 gwr #define OP_DELETION 2
127 1.1 gwr #define OP_BOOLEAN 3
128 1.1 gwr
129 1.2 gwr #define MAXINADDRS 16 /* Max size of an IP address list */
130 1.2 gwr #define MAXBUFLEN 256 /* Max temp buffer space */
131 1.1 gwr #define MAXENTRYLEN 2048 /* Max size of an entire entry */
132 1.1 gwr
133 1.1 gwr
135 1.1 gwr
136 1.1 gwr /*
137 1.1 gwr * Structure used to map a configuration-file symbol (such as "ds") to a
138 1.1 gwr * unique integer.
139 1.1 gwr */
140 1.1 gwr
141 1.1 gwr struct symbolmap {
142 1.1 gwr char *symbol;
143 1.1 gwr int symbolcode;
144 1.1 gwr };
145 1.1 gwr
146 1.1 gwr
147 1.1 gwr struct htypename {
148 1.1 gwr char *name;
149 1.1 gwr byte htype;
150 1.1 gwr };
151 1.1 gwr
152 1.1 gwr
153 1.1 gwr PRIVATE int nhosts; /* Number of hosts (/w hw or IP address) */
154 1.1 gwr PRIVATE int nentries; /* Total number of entries */
155 1.1 gwr PRIVATE int32 modtime = 0; /* Last modification time of bootptab */
156 1.1 gwr PRIVATE char *current_hostname; /* Name of the current entry. */
157 1.1 gwr PRIVATE char current_tagname[8];
158 1.1 gwr
159 1.1 gwr /*
160 1.1 gwr * List of symbolic names used in the bootptab file. The order and actual
161 1.1 gwr * values of the symbol codes (SYM_. . .) are unimportant, but they must
162 1.1 gwr * all be unique.
163 1.1 gwr */
164 1.1 gwr
165 1.1 gwr PRIVATE struct symbolmap symbol_list[] = {
166 1.1 gwr {"bf", SYM_BOOTFILE},
167 1.1 gwr {"bs", SYM_BOOTSIZE},
168 1.1 gwr {"cs", SYM_COOKIE_SERVER},
169 1.1 gwr {"df", SYM_DUMP_FILE},
170 1.1 gwr {"dn", SYM_DOMAIN_NAME},
171 1.1 gwr {"ds", SYM_DOMAIN_SERVER},
172 1.1 gwr {"ef", SYM_EXTEN_FILE},
173 1.1 gwr {"ex", SYM_EXEC_FILE}, /* YORK_EX_OPTION */
174 1.1 gwr {"gw", SYM_GATEWAY},
175 1.1 gwr {"ha", SYM_HWADDR},
176 1.1 gwr {"hd", SYM_HOMEDIR},
177 1.1 gwr {"hn", SYM_NAME_SWITCH},
178 1.1 gwr {"ht", SYM_HTYPE},
179 1.1 gwr {"im", SYM_IMPRESS_SERVER},
180 1.1 gwr {"ip", SYM_IPADDR},
181 1.1 gwr {"lg", SYM_LOG_SERVER},
182 1.2 gwr {"lp", SYM_LPR_SERVER},
183 1.2 gwr {"ms", SYM_MSG_SIZE},
184 1.1 gwr {"mw", SYM_MIN_WAIT},
185 1.1 gwr {"ns", SYM_NAME_SERVER},
186 1.1 gwr {"nt", SYM_NTP_SERVER},
187 1.1 gwr {"ra", SYM_REPLY_ADDR},
188 1.1 gwr {"rl", SYM_RLP_SERVER},
189 1.1 gwr {"rp", SYM_ROOT_PATH},
190 1.1 gwr {"sa", SYM_BOOT_SERVER},
191 1.1 gwr {"sm", SYM_SUBNET_MASK},
192 1.1 gwr {"sw", SYM_SWAP_SERVER},
193 1.1 gwr {"tc", SYM_SIMILAR_ENTRY},
194 1.1 gwr {"td", SYM_TFTPDIR},
195 1.1 gwr {"to", SYM_TIME_OFFSET},
196 1.1 gwr {"ts", SYM_TIME_SERVER},
197 1.1 gwr {"vm", SYM_VENDOR_MAGIC},
198 1.1 gwr {"yd", SYM_NIS_DOMAIN},
199 1.1 gwr {"ys", SYM_NIS_SERVER},
200 1.1 gwr /* XXX - Add new tags here */
201 1.1 gwr };
202 1.1 gwr
203 1.1 gwr
204 1.1 gwr /*
205 1.1 gwr * List of symbolic names for hardware types. Name translates into
206 1.1 gwr * hardware type code listed with it. Names must begin with a letter
207 1.1 gwr * and must be all lowercase. This is searched linearly, so put
208 1.1 gwr * commonly-used entries near the beginning.
209 1.1 gwr */
210 1.1 gwr
211 1.1 gwr PRIVATE struct htypename htnamemap[] = {
212 1.1 gwr {"ethernet", HTYPE_ETHERNET},
213 1.1 gwr {"ethernet3", HTYPE_EXP_ETHERNET},
214 1.1 gwr {"ether", HTYPE_ETHERNET},
215 1.1 gwr {"ether3", HTYPE_EXP_ETHERNET},
216 1.1 gwr {"ieee802", HTYPE_IEEE802},
217 1.1 gwr {"tr", HTYPE_IEEE802},
218 1.1 gwr {"token-ring", HTYPE_IEEE802},
219 1.1 gwr {"pronet", HTYPE_PRONET},
220 1.1 gwr {"chaos", HTYPE_CHAOS},
221 1.1 gwr {"arcnet", HTYPE_ARCNET},
222 1.1 gwr {"ax.25", HTYPE_AX25},
223 1.1 gwr {"direct", HTYPE_DIRECT},
224 1.1 gwr {"serial", HTYPE_DIRECT},
225 1.1 gwr {"slip", HTYPE_DIRECT},
226 1.1 gwr {"ppp", HTYPE_DIRECT}
227 1.1 gwr };
228 1.1 gwr
229 1.1 gwr
230 1.1 gwr
231 1.1 gwr /*
232 1.1 gwr * Externals and forward declarations.
233 1.1 gwr */
234 1.1 gwr
235 1.1 gwr #ifdef __STDC__
236 1.1 gwr #define P(args) args
237 1.1 gwr #else
238 1.1 gwr #define P(args) ()
239 1.1 gwr #endif
240 1.1 gwr
241 1.1 gwr boolean nmcmp P((hash_datum *, hash_datum *));
242 1.1 gwr
243 1.1 gwr PRIVATE void
244 1.1 gwr adjust P((char **));
245 1.1 gwr PRIVATE void
246 1.1 gwr del_string P((struct shared_string *));
247 1.1 gwr PRIVATE void
248 1.1 gwr del_bindata P((struct shared_bindata *));
249 1.1 gwr PRIVATE void
250 1.1 gwr del_iplist P((struct in_addr_list *));
251 1.1 gwr PRIVATE void
252 1.1 gwr eat_whitespace P((char **));
253 1.1 gwr PRIVATE int
254 1.1 gwr eval_symbol P((char **, struct host *));
255 1.1 gwr PRIVATE void
256 1.1 gwr fill_defaults P((struct host *, char **));
257 1.1 gwr PRIVATE void
258 1.1 gwr free_host P((hash_datum *));
259 1.1 gwr PRIVATE struct in_addr_list *
260 1.1 gwr get_addresses P((char **));
261 1.1 gwr PRIVATE struct shared_string *
262 1.1 gwr get_shared_string P((char **));
263 1.1 gwr PRIVATE char *
264 1.1 gwr get_string P((char **, char *, u_int *));
265 1.1 gwr PRIVATE u_int32
266 1.1 gwr get_u_long P((char **));
267 1.1 gwr PRIVATE boolean
268 1.1 gwr goodname P((char *));
269 1.1 gwr PRIVATE boolean
270 1.1 gwr hwinscmp P((hash_datum *, hash_datum *));
271 1.1 gwr PRIVATE int
272 1.1 gwr interp_byte P((char **, byte *));
273 1.1 gwr PRIVATE void
274 1.1 gwr makelower P((char *));
275 1.1 gwr PRIVATE boolean
276 1.1 gwr nullcmp P((hash_datum *, hash_datum *));
277 1.1 gwr PRIVATE int
278 1.1 gwr process_entry P((struct host *, char *));
279 1.1 gwr PRIVATE int
280 1.1 gwr process_generic P((char **, struct shared_bindata **, u_int));
281 1.1 gwr PRIVATE byte *
282 1.1 gwr prs_haddr P((char **, u_int));
283 1.1 gwr PRIVATE int
284 1.1 gwr prs_inetaddr P((char **, u_int32 *));
285 1.1 gwr PRIVATE void
286 1.1 gwr read_entry P((FILE *, char *, u_int *));
287 1.1 gwr PRIVATE char *
288 1.1 gwr smalloc P((u_int));
289 1.1 gwr
290 1.1 gwr #undef P
291 1.1 gwr
292 1.1 gwr
294 1.1 gwr /*
295 1.1 gwr * Vendor magic cookies for CMU and RFC1048
296 1.1 gwr */
297 1.1 gwr u_char vm_cmu[4] = VM_CMU;
298 1.1 gwr u_char vm_rfc1048[4] = VM_RFC1048;
299 1.1 gwr
300 1.1 gwr /*
301 1.1 gwr * Main hash tables
302 1.1 gwr */
303 1.1 gwr hash_tbl *hwhashtable;
304 1.1 gwr hash_tbl *iphashtable;
305 1.1 gwr hash_tbl *nmhashtable;
306 1.1 gwr
307 1.1 gwr /*
308 1.1 gwr * Allocate hash tables for hardware address, ip address, and hostname
309 1.1 gwr * (shared by bootpd and bootpef)
310 1.1 gwr */
311 1.1 gwr void
312 1.1 gwr rdtab_init()
313 1.1 gwr {
314 1.1 gwr hwhashtable = hash_Init(HASHTABLESIZE);
315 1.1 gwr iphashtable = hash_Init(HASHTABLESIZE);
316 1.1 gwr nmhashtable = hash_Init(HASHTABLESIZE);
317 1.1 gwr if (!(hwhashtable && iphashtable && nmhashtable)) {
318 1.1 gwr report(LOG_ERR, "Unable to allocate hash tables.");
319 1.1 gwr exit(1);
320 1.1 gwr }
321 1.1 gwr }
322 1.1 gwr
323 1.1 gwr
325 1.1 gwr /*
326 1.1 gwr * Read bootptab database file. Avoid rereading the file if the
327 1.1 gwr * write date hasn't changed since the last time we read it.
328 1.1 gwr */
329 1.1 gwr
330 1.1 gwr void
331 1.1 gwr readtab(force)
332 1.1 gwr int force;
333 1.1 gwr {
334 1.1 gwr struct host *hp;
335 1.1 gwr FILE *fp;
336 1.1 gwr struct stat st;
337 1.1 gwr unsigned hashcode, buflen;
338 1.1 gwr static char buffer[MAXENTRYLEN];
339 1.1 gwr
340 1.1 gwr /*
341 1.1 gwr * Check the last modification time.
342 1.1 gwr */
343 1.1 gwr if (stat(bootptab, &st) < 0) {
344 1.1 gwr report(LOG_ERR, "stat on \"%s\": %s",
345 1.1 gwr bootptab, get_errmsg());
346 1.1 gwr return;
347 1.1 gwr }
348 1.1 gwr #ifdef DEBUG
349 1.1 gwr if (debug > 3) {
350 1.1 gwr char timestr[28];
351 1.1 gwr strcpy(timestr, ctime(&(st.st_mtime)));
352 1.1 gwr /* zap the newline */
353 1.1 gwr timestr[24] = '\0';
354 1.1 gwr report(LOG_INFO, "bootptab mtime: %s",
355 1.1 gwr timestr);
356 1.1 gwr }
357 1.1 gwr #endif
358 1.1 gwr if ((force == 0) &&
359 1.1 gwr (st.st_mtime == modtime) &&
360 1.1 gwr st.st_nlink) {
361 1.1 gwr /*
362 1.1 gwr * hasn't been modified or deleted yet.
363 1.1 gwr */
364 1.1 gwr return;
365 1.1 gwr }
366 1.1 gwr if (debug)
367 1.1 gwr report(LOG_INFO, "reading %s\"%s\"",
368 1.1 gwr (modtime != 0L) ? "new " : "",
369 1.1 gwr bootptab);
370 1.1 gwr
371 1.1 gwr /*
372 1.1 gwr * Open bootptab file.
373 1.1 gwr */
374 1.1 gwr if ((fp = fopen(bootptab, "r")) == NULL) {
375 1.1 gwr report(LOG_ERR, "error opening \"%s\": %s", bootptab, get_errmsg());
376 1.1 gwr return;
377 1.1 gwr }
378 1.1 gwr /*
379 1.1 gwr * Record file modification time.
380 1.1 gwr */
381 1.1 gwr if (fstat(fileno(fp), &st) < 0) {
382 1.1 gwr report(LOG_ERR, "fstat: %s", get_errmsg());
383 1.1 gwr fclose(fp);
384 1.1 gwr return;
385 1.1 gwr }
386 1.1 gwr modtime = st.st_mtime;
387 1.1 gwr
388 1.1 gwr /*
389 1.1 gwr * Entirely erase all hash tables.
390 1.1 gwr */
391 1.1 gwr hash_Reset(hwhashtable, free_host);
392 1.1 gwr hash_Reset(iphashtable, free_host);
393 1.1 gwr hash_Reset(nmhashtable, free_host);
394 1.1 gwr
395 1.1 gwr nhosts = 0;
396 1.1 gwr nentries = 0;
397 1.1 gwr while (TRUE) {
398 1.1 gwr buflen = sizeof(buffer);
399 1.1 gwr read_entry(fp, buffer, &buflen);
400 1.1 gwr if (buflen == 0) { /* More entries? */
401 1.1 gwr break;
402 1.1 gwr }
403 1.1 gwr hp = (struct host *) smalloc(sizeof(struct host));
404 1.1 gwr bzero((char *) hp, sizeof(*hp));
405 1.1 gwr /* the link count it zero */
406 1.1 gwr
407 1.1 gwr /*
408 1.1 gwr * Get individual info
409 1.1 gwr */
410 1.1 gwr if (process_entry(hp, buffer) < 0) {
411 1.1 gwr hp->linkcount = 1;
412 1.1 gwr free_host((hash_datum *) hp);
413 1.1 gwr continue;
414 1.1 gwr }
415 1.1 gwr /*
416 1.1 gwr * If this is not a dummy entry, and the IP or HW
417 1.1 gwr * address is not yet set, try to get them here.
418 1.1 gwr * Dummy entries have . as first char of name.
419 1.1 gwr */
420 1.1 gwr if (goodname(hp->hostname->string)) {
421 1.1 gwr char *hn = hp->hostname->string;
422 1.1 gwr u_int32 value;
423 1.1 gwr if (hp->flags.iaddr == 0) {
424 1.1 gwr if (lookup_ipa(hn, &value)) {
425 1.1 gwr report(LOG_ERR, "can not get IP addr for %s", hn);
426 1.1 gwr report(LOG_ERR, "(dummy names should start with '.')");
427 1.1 gwr } else {
428 1.1 gwr hp->iaddr.s_addr = value;
429 1.1 gwr hp->flags.iaddr = TRUE;
430 1.1 gwr }
431 1.1 gwr }
432 1.1 gwr /* Set default subnet mask. */
433 1.1 gwr if (hp->flags.subnet_mask == 0) {
434 1.1 gwr if (lookup_netmask(hp->iaddr.s_addr, &value)) {
435 1.1 gwr report(LOG_ERR, "can not get netmask for %s", hn);
436 1.1 gwr } else {
437 1.1 gwr hp->subnet_mask.s_addr = value;
438 1.1 gwr hp->flags.subnet_mask = TRUE;
439 1.1 gwr }
440 1.1 gwr }
441 1.1 gwr }
442 1.1 gwr if (hp->flags.iaddr) {
443 1.1 gwr nhosts++;
444 1.1 gwr }
445 1.1 gwr /* Register by HW addr if known. */
446 1.1 gwr if (hp->flags.htype && hp->flags.haddr) {
447 1.1 gwr /* We will either insert it or free it. */
448 1.1 gwr hp->linkcount++;
449 1.1 gwr hashcode = hash_HashFunction(hp->haddr, haddrlength(hp->htype));
450 1.3 gwr if (hash_Insert(hwhashtable, hashcode, hwinscmp, hp, hp) < 0) {
451 1.1 gwr report(LOG_NOTICE, "duplicate %s address: %s",
452 1.1 gwr netname(hp->htype),
453 1.1 gwr haddrtoa(hp->haddr, haddrlength(hp->htype)));
454 1.1 gwr free_host((hash_datum *) hp);
455 1.1 gwr continue;
456 1.1 gwr }
457 1.1 gwr }
458 1.1 gwr /* Register by IP addr if known. */
459 1.1 gwr if (hp->flags.iaddr) {
460 1.1 gwr hashcode = hash_HashFunction((u_char *) & (hp->iaddr.s_addr), 4);
461 1.1 gwr if (hash_Insert(iphashtable, hashcode, nullcmp, hp, hp) < 0) {
462 1.1 gwr report(LOG_ERR,
463 1.1 gwr "hash_Insert() failed on IP address insertion");
464 1.1 gwr } else {
465 1.1 gwr /* Just inserted the host struct in a new hash list. */
466 1.1 gwr hp->linkcount++;
467 1.1 gwr }
468 1.1 gwr }
469 1.1 gwr /* Register by Name (always known) */
470 1.1 gwr hashcode = hash_HashFunction((u_char *) hp->hostname->string,
471 1.1 gwr strlen(hp->hostname->string));
472 1.1 gwr if (hash_Insert(nmhashtable, hashcode, nullcmp,
473 1.1 gwr hp->hostname->string, hp) < 0) {
474 1.1 gwr report(LOG_ERR,
475 1.1 gwr "hash_Insert() failed on insertion of hostname: \"%s\"",
476 1.1 gwr hp->hostname->string);
477 1.1 gwr } else {
478 1.1 gwr /* Just inserted the host struct in a new hash list. */
479 1.1 gwr hp->linkcount++;
480 1.1 gwr }
481 1.1 gwr
482 1.1 gwr nentries++;
483 1.1 gwr }
484 1.1 gwr
485 1.1 gwr fclose(fp);
486 1.1 gwr if (debug)
487 1.1 gwr report(LOG_INFO, "read %d entries (%d hosts) from \"%s\"",
488 1.1 gwr nentries, nhosts, bootptab);
489 1.1 gwr return;
490 1.1 gwr }
491 1.1 gwr
492 1.1 gwr
494 1.1 gwr
495 1.1 gwr /*
496 1.1 gwr * Read an entire host entry from the file pointed to by "fp" and insert it
497 1.1 gwr * into the memory pointed to by "buffer". Leading whitespace and comments
498 1.1 gwr * starting with "#" are ignored (removed). Backslashes (\) always quote
499 1.1 gwr * the next character except that newlines preceeded by a backslash cause
500 1.1 gwr * line-continuation onto the next line. The entry is terminated by a
501 1.1 gwr * newline character which is not preceeded by a backslash. Sequences
502 1.1 gwr * surrounded by double quotes are taken literally (including newlines, but
503 1.1 gwr * not backslashes).
504 1.1 gwr *
505 1.1 gwr * The "bufsiz" parameter points to an unsigned int which specifies the
506 1.1 gwr * maximum permitted buffer size. Upon return, this value will be replaced
507 1.1 gwr * with the actual length of the entry (not including the null terminator).
508 1.1 gwr *
509 1.1 gwr * This code is a little scary. . . . I don't like using gotos in C
510 1.1 gwr * either, but I first wrote this as an FSM diagram and gotos seemed like
511 1.1 gwr * the easiest way to implement it. Maybe later I'll clean it up.
512 1.1 gwr */
513 1.1 gwr
514 1.1 gwr PRIVATE void
515 1.1 gwr read_entry(fp, buffer, bufsiz)
516 1.1 gwr FILE *fp;
517 1.1 gwr char *buffer;
518 1.1 gwr unsigned *bufsiz;
519 1.1 gwr {
520 1.1 gwr int c, length;
521 1.1 gwr
522 1.1 gwr length = 0;
523 1.1 gwr
524 1.1 gwr /*
525 1.1 gwr * Eat whitespace, blank lines, and comment lines.
526 1.1 gwr */
527 1.1 gwr top:
528 1.1 gwr c = fgetc(fp);
529 1.1 gwr if (c < 0) {
530 1.1 gwr goto done; /* Exit if end-of-file */
531 1.1 gwr }
532 1.1 gwr if (isspace(c)) {
533 1.1 gwr goto top; /* Skip over whitespace */
534 1.1 gwr }
535 1.1 gwr if (c == '#') {
536 1.1 gwr while (TRUE) { /* Eat comments after # */
537 1.1 gwr c = fgetc(fp);
538 1.1 gwr if (c < 0) {
539 1.1 gwr goto done; /* Exit if end-of-file */
540 1.1 gwr }
541 1.1 gwr if (c == '\n') {
542 1.1 gwr goto top; /* Try to read the next line */
543 1.1 gwr }
544 1.1 gwr }
545 1.1 gwr }
546 1.1 gwr ungetc(c, fp); /* Other character, push it back to reprocess it */
547 1.1 gwr
548 1.1 gwr
549 1.1 gwr /*
550 1.1 gwr * Now we're actually reading a data entry. Get each character and
551 1.1 gwr * assemble it into the data buffer, processing special characters like
552 1.1 gwr * double quotes (") and backslashes (\).
553 1.1 gwr */
554 1.1 gwr
555 1.1 gwr mainloop:
556 1.1 gwr c = fgetc(fp);
557 1.1 gwr switch (c) {
558 1.1 gwr case EOF:
559 1.1 gwr case '\n':
560 1.1 gwr goto done; /* Exit on EOF or newline */
561 1.1 gwr case '\\':
562 1.1 gwr c = fgetc(fp); /* Backslash, read a new character */
563 1.1 gwr if (c < 0) {
564 1.1 gwr goto done; /* Exit on EOF */
565 1.1 gwr }
566 1.1 gwr *buffer++ = c; /* Store the literal character */
567 1.1 gwr length++;
568 1.1 gwr if (length < *bufsiz - 1) {
569 1.1 gwr goto mainloop;
570 1.1 gwr } else {
571 1.1 gwr goto done;
572 1.1 gwr }
573 1.1 gwr case '"':
574 1.1 gwr *buffer++ = '"'; /* Store double-quote */
575 1.1 gwr length++;
576 1.1 gwr if (length >= *bufsiz - 1) {
577 1.1 gwr goto done;
578 1.1 gwr }
579 1.1 gwr while (TRUE) { /* Special quote processing loop */
580 1.1 gwr c = fgetc(fp);
581 1.1 gwr switch (c) {
582 1.1 gwr case EOF:
583 1.1 gwr goto done; /* Exit on EOF . . . */
584 1.1 gwr case '"':
585 1.1 gwr *buffer++ = '"';/* Store matching quote */
586 1.1 gwr length++;
587 1.1 gwr if (length < *bufsiz - 1) {
588 1.1 gwr goto mainloop; /* And continue main loop */
589 1.1 gwr } else {
590 1.1 gwr goto done;
591 1.1 gwr }
592 1.1 gwr case '\\':
593 1.1 gwr if ((c = fgetc(fp)) < 0) { /* Backslash */
594 1.1 gwr goto done; /* EOF. . . .*/
595 1.1 gwr } /* else fall through */
596 1.1 gwr default:
597 1.1 gwr *buffer++ = c; /* Other character, store it */
598 1.1 gwr length++;
599 1.1 gwr if (length >= *bufsiz - 1) {
600 1.1 gwr goto done;
601 1.1 gwr }
602 1.1 gwr }
603 1.1 gwr }
604 1.1 gwr case ':':
605 1.1 gwr *buffer++ = c; /* Store colons */
606 1.1 gwr length++;
607 1.1 gwr if (length >= *bufsiz - 1) {
608 1.1 gwr goto done;
609 1.1 gwr }
610 1.1 gwr do { /* But remove whitespace after them */
611 1.1 gwr c = fgetc(fp);
612 1.1 gwr if ((c < 0) || (c == '\n')) {
613 1.1 gwr goto done;
614 1.1 gwr }
615 1.1 gwr } while (isspace(c)); /* Skip whitespace */
616 1.1 gwr
617 1.1 gwr if (c == '\\') { /* Backslash quotes next character */
618 1.1 gwr c = fgetc(fp);
619 1.1 gwr if (c < 0) {
620 1.1 gwr goto done;
621 1.1 gwr }
622 1.1 gwr if (c == '\n') {
623 1.1 gwr goto top; /* Backslash-newline continuation */
624 1.1 gwr }
625 1.1 gwr }
626 1.1 gwr /* fall through if "other" character */
627 1.1 gwr default:
628 1.1 gwr *buffer++ = c; /* Store other characters */
629 1.1 gwr length++;
630 1.1 gwr if (length >= *bufsiz - 1) {
631 1.1 gwr goto done;
632 1.1 gwr }
633 1.1 gwr }
634 1.1 gwr goto mainloop; /* Keep going */
635 1.1 gwr
636 1.1 gwr done:
637 1.1 gwr *buffer = '\0'; /* Terminate string */
638 1.1 gwr *bufsiz = length; /* Tell the caller its length */
639 1.1 gwr }
640 1.1 gwr
641 1.1 gwr
643 1.1 gwr
644 1.1 gwr /*
645 1.1 gwr * Parse out all the various tags and parameters in the host entry pointed
646 1.1 gwr * to by "src". Stuff all the data into the appropriate fields of the
647 1.1 gwr * host structure pointed to by "host". If there is any problem with the
648 1.1 gwr * entry, an error message is reported via report(), no further processing
649 1.1 gwr * is done, and -1 is returned. Successful calls return 0.
650 1.1 gwr *
651 1.1 gwr * (Some errors probably shouldn't be so completely fatal. . . .)
652 1.1 gwr */
653 1.1 gwr
654 1.1 gwr PRIVATE int
655 1.1 gwr process_entry(host, src)
656 1.1 gwr struct host *host;
657 1.1 gwr char *src;
658 1.1 gwr {
659 1.1 gwr int retval;
660 1.1 gwr char *msg;
661 1.1 gwr
662 1.1 gwr if (!host || *src == '\0') {
663 1.1 gwr return -1;
664 1.1 gwr }
665 1.1 gwr host->hostname = get_shared_string(&src);
666 1.1 gwr #if 0
667 1.1 gwr /* Be more liberal for the benefit of dummy tag names. */
668 1.1 gwr if (!goodname(host->hostname->string)) {
669 1.1 gwr report(LOG_ERR, "bad hostname: \"%s\"", host->hostname->string);
670 1.1 gwr del_string(host->hostname);
671 1.1 gwr return -1;
672 1.1 gwr }
673 1.1 gwr #endif
674 1.1 gwr current_hostname = host->hostname->string;
675 1.1 gwr adjust(&src);
676 1.1 gwr while (TRUE) {
677 1.1 gwr retval = eval_symbol(&src, host);
678 1.1 gwr if (retval == SUCCESS) {
679 1.1 gwr adjust(&src);
680 1.1 gwr continue;
681 1.1 gwr }
682 1.1 gwr if (retval == E_END_OF_ENTRY) {
683 1.1 gwr /* The default subnet mask is set in readtab() */
684 1.1 gwr return 0;
685 1.1 gwr }
686 1.1 gwr /* Some kind of error. */
687 1.1 gwr switch (retval) {
688 1.1 gwr case E_SYNTAX_ERROR:
689 1.1 gwr msg = "bad syntax";
690 1.1 gwr break;
691 1.1 gwr case E_UNKNOWN_SYMBOL:
692 1.1 gwr msg = "unknown symbol";
693 1.1 gwr break;
694 1.1 gwr case E_BAD_IPADDR:
695 1.1 gwr msg = "bad INET address";
696 1.1 gwr break;
697 1.1 gwr case E_BAD_HWADDR:
698 1.1 gwr msg = "bad hardware address";
699 1.1 gwr break;
700 1.1 gwr case E_BAD_LONGWORD:
701 1.1 gwr msg = "bad longword value";
702 1.1 gwr break;
703 1.2 gwr case E_BAD_HWATYPE:
704 1.2 gwr msg = "bad HW address type";
705 1.1 gwr break;
706 1.1 gwr case E_BAD_PATHNAME:
707 1.1 gwr msg = "bad pathname (need leading '/')";
708 1.1 gwr case E_BAD_VALUE:
709 1.1 gwr msg = "bad value";
710 1.1 gwr default:
711 1.1 gwr msg = "unkown error";
712 1.1 gwr break;
713 1.1 gwr } /* switch */
714 1.1 gwr report(LOG_ERR, "in entry named \"%s\", symbol \"%s\": %s",
715 1.1 gwr current_hostname, current_tagname, msg);
716 1.1 gwr return -1;
717 1.1 gwr }
718 1.1 gwr }
719 1.1 gwr
720 1.1 gwr
722 1.1 gwr /*
723 1.1 gwr * Macros for use in the function below:
724 1.1 gwr */
725 1.1 gwr
726 1.1 gwr /* Parse one INET address stored directly in MEMBER. */
727 1.1 gwr #define PARSE_IA1(MEMBER) do \
728 1.1 gwr { \
729 1.1 gwr if (optype == OP_BOOLEAN) \
730 1.1 gwr return E_SYNTAX_ERROR; \
731 1.1 gwr hp->flags.MEMBER = FALSE; \
732 1.1 gwr if (optype == OP_ADDITION) { \
733 1.1 gwr if (prs_inetaddr(symbol, &value) < 0) \
734 1.1 gwr return E_BAD_IPADDR; \
735 1.1 gwr hp->MEMBER.s_addr = value; \
736 1.1 gwr hp->flags.MEMBER = TRUE; \
737 1.1 gwr } \
738 1.1 gwr } while (0)
739 1.1 gwr
740 1.1 gwr /* Parse a list of INET addresses pointed to by MEMBER */
741 1.1 gwr #define PARSE_IAL(MEMBER) do \
742 1.1 gwr { \
743 1.1 gwr if (optype == OP_BOOLEAN) \
744 1.1 gwr return E_SYNTAX_ERROR; \
745 1.1 gwr if (hp->flags.MEMBER) { \
746 1.1 gwr hp->flags.MEMBER = FALSE; \
747 1.1 gwr assert(hp->MEMBER); \
748 1.1 gwr del_iplist(hp->MEMBER); \
749 1.1 gwr hp->MEMBER = NULL; \
750 1.1 gwr } \
751 1.1 gwr if (optype == OP_ADDITION) { \
752 1.1 gwr hp->MEMBER = get_addresses(symbol); \
753 1.1 gwr if (hp->MEMBER == NULL) \
754 1.1 gwr return E_SYNTAX_ERROR; \
755 1.1 gwr hp->flags.MEMBER = TRUE; \
756 1.1 gwr } \
757 1.1 gwr } while (0)
758 1.1 gwr
759 1.1 gwr /* Parse a shared string pointed to by MEMBER */
760 1.1 gwr #define PARSE_STR(MEMBER) do \
761 1.1 gwr { \
762 1.1 gwr if (optype == OP_BOOLEAN) \
763 1.1 gwr return E_SYNTAX_ERROR; \
764 1.1 gwr if (hp->flags.MEMBER) { \
765 1.1 gwr hp->flags.MEMBER = FALSE; \
766 1.1 gwr assert(hp->MEMBER); \
767 1.1 gwr del_string(hp->MEMBER); \
768 1.1 gwr hp->MEMBER = NULL; \
769 1.1 gwr } \
770 1.1 gwr if (optype == OP_ADDITION) { \
771 1.1 gwr hp->MEMBER = get_shared_string(symbol); \
772 1.2 gwr if (hp->MEMBER == NULL) \
773 1.2 gwr return E_SYNTAX_ERROR; \
774 1.2 gwr hp->flags.MEMBER = TRUE; \
775 1.2 gwr } \
776 1.2 gwr } while (0)
777 1.2 gwr
778 1.2 gwr /* Parse an integer value for MEMBER */
779 1.2 gwr #define PARSE_INT(MEMBER) do \
780 1.2 gwr { \
781 1.2 gwr if (optype == OP_BOOLEAN) \
782 1.2 gwr return E_SYNTAX_ERROR; \
783 1.2 gwr hp->flags.MEMBER = FALSE; \
784 1.2 gwr if (optype == OP_ADDITION) { \
785 1.1 gwr value = get_u_long(symbol); \
786 1.1 gwr hp->MEMBER = value; \
787 1.1 gwr hp->flags.MEMBER = TRUE; \
788 1.1 gwr } \
789 1.1 gwr } while (0)
790 1.1 gwr
791 1.1 gwr /*
792 1.1 gwr * Evaluate the two-character tag symbol pointed to by "symbol" and place
793 1.1 gwr * the data in the structure pointed to by "hp". The pointer pointed to
794 1.1 gwr * by "symbol" is updated to point past the source string (but may not
795 1.1 gwr * point to the next tag entry).
796 1.1 gwr *
797 1.1 gwr * Obviously, this need a few more comments. . . .
798 1.1 gwr */
799 1.1 gwr PRIVATE int
800 1.1 gwr eval_symbol(symbol, hp)
801 1.1 gwr char **symbol;
802 1.1 gwr struct host *hp;
803 1.1 gwr {
804 1.1 gwr char tmpstr[MAXSTRINGLEN];
805 1.1 gwr byte *tmphaddr;
806 1.1 gwr struct symbolmap *symbolptr;
807 1.1 gwr u_int32 value;
808 1.1 gwr int32 timeoff;
809 1.1 gwr int i, numsymbols;
810 1.1 gwr unsigned len;
811 1.1 gwr int optype; /* Indicates boolean, addition, or deletion */
812 1.1 gwr
813 1.1 gwr eat_whitespace(symbol);
814 1.1 gwr
815 1.1 gwr /* Make sure this is set before returning. */
816 1.1 gwr current_tagname[0] = (*symbol)[0];
817 1.1 gwr current_tagname[1] = (*symbol)[1];
818 1.1 gwr current_tagname[2] = 0;
819 1.1 gwr
820 1.1 gwr if ((*symbol)[0] == '\0') {
821 1.1 gwr return E_END_OF_ENTRY;
822 1.1 gwr }
823 1.1 gwr if ((*symbol)[0] == ':') {
824 1.1 gwr return SUCCESS;
825 1.1 gwr }
826 1.1 gwr if ((*symbol)[0] == 'T') { /* generic symbol */
827 1.1 gwr (*symbol)++;
828 1.1 gwr value = get_u_long(symbol);
829 1.1 gwr sprintf(current_tagname, "T%d", value);
830 1.1 gwr eat_whitespace(symbol);
831 1.1 gwr if ((*symbol)[0] != '=') {
832 1.1 gwr return E_SYNTAX_ERROR;
833 1.1 gwr }
834 1.1 gwr (*symbol)++;
835 1.1 gwr if (!(hp->generic)) {
836 1.1 gwr hp->generic = (struct shared_bindata *)
837 1.1 gwr smalloc(sizeof(struct shared_bindata));
838 1.1 gwr }
839 1.1 gwr if (process_generic(symbol, &(hp->generic), (byte) (value & 0xFF)))
840 1.1 gwr return E_SYNTAX_ERROR;
841 1.1 gwr hp->flags.generic = TRUE;
842 1.1 gwr return SUCCESS;
843 1.1 gwr }
844 1.1 gwr /*
845 1.1 gwr * Determine the type of operation to be done on this symbol
846 1.1 gwr */
847 1.1 gwr switch ((*symbol)[2]) {
848 1.1 gwr case '=':
849 1.1 gwr optype = OP_ADDITION;
850 1.1 gwr break;
851 1.1 gwr case '@':
852 1.1 gwr optype = OP_DELETION;
853 1.1 gwr break;
854 1.1 gwr case ':':
855 1.1 gwr case '\0':
856 1.1 gwr optype = OP_BOOLEAN;
857 1.1 gwr break;
858 1.1 gwr default:
859 1.1 gwr return E_SYNTAX_ERROR;
860 1.1 gwr }
861 1.1 gwr
862 1.1 gwr symbolptr = symbol_list;
863 1.1 gwr numsymbols = sizeof(symbol_list) / sizeof(struct symbolmap);
864 1.1 gwr for (i = 0; i < numsymbols; i++) {
865 1.1 gwr if (((symbolptr->symbol)[0] == (*symbol)[0]) &&
866 1.1 gwr ((symbolptr->symbol)[1] == (*symbol)[1])) {
867 1.1 gwr break;
868 1.1 gwr }
869 1.1 gwr symbolptr++;
870 1.1 gwr }
871 1.1 gwr if (i >= numsymbols) {
872 1.1 gwr return E_UNKNOWN_SYMBOL;
873 1.1 gwr }
874 1.1 gwr /*
875 1.1 gwr * Skip past the = or @ character (to point to the data) if this
876 1.1 gwr * isn't a boolean operation. For boolean operations, just skip
877 1.1 gwr * over the two-character tag symbol (and nothing else. . . .).
878 1.1 gwr */
879 1.1 gwr (*symbol) += (optype == OP_BOOLEAN) ? 2 : 3;
880 1.1 gwr
881 1.1 gwr eat_whitespace(symbol);
882 1.1 gwr
883 1.1 gwr /* The cases below are in order by symbolcode value. */
884 1.1 gwr switch (symbolptr->symbolcode) {
885 1.1 gwr
886 1.1 gwr case SYM_BOOTFILE:
887 1.1 gwr PARSE_STR(bootfile);
888 1.1 gwr break;
889 1.1 gwr
890 1.1 gwr case SYM_COOKIE_SERVER:
891 1.1 gwr PARSE_IAL(cookie_server);
892 1.1 gwr break;
893 1.1 gwr
894 1.1 gwr case SYM_DOMAIN_SERVER:
895 1.1 gwr PARSE_IAL(domain_server);
896 1.1 gwr break;
897 1.1 gwr
898 1.1 gwr case SYM_GATEWAY:
899 1.1 gwr PARSE_IAL(gateway);
900 1.1 gwr break;
901 1.1 gwr
902 1.1 gwr case SYM_HWADDR:
903 1.1 gwr if (optype == OP_BOOLEAN)
904 1.1 gwr return E_SYNTAX_ERROR;
905 1.1 gwr hp->flags.haddr = FALSE;
906 1.1 gwr if (optype == OP_ADDITION) {
907 1.1 gwr /* Default the HW type to Ethernet */
908 1.1 gwr if (hp->flags.htype == 0) {
909 1.1 gwr hp->flags.htype = TRUE;
910 1.1 gwr hp->htype = HTYPE_ETHERNET;
911 1.1 gwr }
912 1.1 gwr tmphaddr = prs_haddr(symbol, hp->htype);
913 1.1 gwr if (!tmphaddr)
914 1.1 gwr return E_BAD_HWADDR;
915 1.1 gwr bcopy(tmphaddr, hp->haddr, haddrlength(hp->htype));
916 1.1 gwr hp->flags.haddr = TRUE;
917 1.1 gwr }
918 1.1 gwr break;
919 1.1 gwr
920 1.1 gwr case SYM_HOMEDIR:
921 1.1 gwr PARSE_STR(homedir);
922 1.1 gwr break;
923 1.1 gwr
924 1.1 gwr case SYM_HTYPE:
925 1.1 gwr if (optype == OP_BOOLEAN)
926 1.1 gwr return E_SYNTAX_ERROR;
927 1.1 gwr hp->flags.htype = FALSE;
928 1.1 gwr if (optype == OP_ADDITION) {
929 1.1 gwr value = 0L; /* Assume an illegal value */
930 1.1 gwr eat_whitespace(symbol);
931 1.1 gwr if (isdigit(**symbol)) {
932 1.1 gwr value = get_u_long(symbol);
933 1.1 gwr } else {
934 1.1 gwr len = sizeof(tmpstr);
935 1.1 gwr (void) get_string(symbol, tmpstr, &len);
936 1.1 gwr makelower(tmpstr);
937 1.1 gwr numsymbols = sizeof(htnamemap) /
938 1.1 gwr sizeof(struct htypename);
939 1.1 gwr for (i = 0; i < numsymbols; i++) {
940 1.1 gwr if (!strcmp(htnamemap[i].name, tmpstr)) {
941 1.1 gwr break;
942 1.1 gwr }
943 1.1 gwr }
944 1.1 gwr if (i < numsymbols) {
945 1.1 gwr value = htnamemap[i].htype;
946 1.1 gwr }
947 1.1 gwr }
948 1.1 gwr if (value >= hwinfocnt) {
949 1.1 gwr return E_BAD_HWATYPE;
950 1.1 gwr }
951 1.1 gwr hp->htype = (byte) (value & 0xFF);
952 1.1 gwr hp->flags.htype = TRUE;
953 1.1 gwr }
954 1.1 gwr break;
955 1.1 gwr
956 1.1 gwr case SYM_IMPRESS_SERVER:
957 1.1 gwr PARSE_IAL(impress_server);
958 1.1 gwr break;
959 1.1 gwr
960 1.1 gwr case SYM_IPADDR:
961 1.1 gwr PARSE_IA1(iaddr);
962 1.1 gwr break;
963 1.1 gwr
964 1.1 gwr case SYM_LOG_SERVER:
965 1.1 gwr PARSE_IAL(log_server);
966 1.1 gwr break;
967 1.1 gwr
968 1.1 gwr case SYM_LPR_SERVER:
969 1.1 gwr PARSE_IAL(lpr_server);
970 1.1 gwr break;
971 1.1 gwr
972 1.1 gwr case SYM_NAME_SERVER:
973 1.1 gwr PARSE_IAL(name_server);
974 1.1 gwr break;
975 1.1 gwr
976 1.1 gwr case SYM_RLP_SERVER:
977 1.1 gwr PARSE_IAL(rlp_server);
978 1.1 gwr break;
979 1.1 gwr
980 1.1 gwr case SYM_SUBNET_MASK:
981 1.1 gwr PARSE_IA1(subnet_mask);
982 1.1 gwr break;
983 1.1 gwr
984 1.1 gwr case SYM_TIME_OFFSET:
985 1.1 gwr if (optype == OP_BOOLEAN)
986 1.1 gwr return E_SYNTAX_ERROR;
987 1.1 gwr hp->flags.time_offset = FALSE;
988 1.1 gwr if (optype == OP_ADDITION) {
989 1.1 gwr len = sizeof(tmpstr);
990 1.1 gwr (void) get_string(symbol, tmpstr, &len);
991 1.1 gwr if (!strncmp(tmpstr, "auto", 4)) {
992 1.1 gwr hp->time_offset = secondswest;
993 1.1 gwr } else {
994 1.1 gwr if (sscanf(tmpstr, "%d", &timeoff) != 1)
995 1.1 gwr return E_BAD_LONGWORD;
996 1.1 gwr hp->time_offset = timeoff;
997 1.1 gwr }
998 1.1 gwr hp->flags.time_offset = TRUE;
999 1.1 gwr }
1000 1.1 gwr break;
1001 1.1 gwr
1002 1.1 gwr case SYM_TIME_SERVER:
1003 1.1 gwr PARSE_IAL(time_server);
1004 1.1 gwr break;
1005 1.1 gwr
1006 1.1 gwr case SYM_VENDOR_MAGIC:
1007 1.1 gwr if (optype == OP_BOOLEAN)
1008 1.1 gwr return E_SYNTAX_ERROR;
1009 1.1 gwr hp->flags.vm_cookie = FALSE;
1010 1.1 gwr if (optype == OP_ADDITION) {
1011 1.1 gwr if (strncmp(*symbol, "auto", 4)) {
1012 1.1 gwr /* The string is not "auto" */
1013 1.1 gwr if (!strncmp(*symbol, "rfc", 3)) {
1014 1.1 gwr bcopy(vm_rfc1048, hp->vm_cookie, 4);
1015 1.1 gwr } else if (!strncmp(*symbol, "cmu", 3)) {
1016 1.1 gwr bcopy(vm_cmu, hp->vm_cookie, 4);
1017 1.1 gwr } else {
1018 1.1 gwr if (!isdigit(**symbol))
1019 1.1 gwr return E_BAD_IPADDR;
1020 1.1 gwr if (prs_inetaddr(symbol, &value) < 0)
1021 1.1 gwr return E_BAD_IPADDR;
1022 1.1 gwr bcopy(&value, hp->vm_cookie, 4);
1023 1.1 gwr }
1024 1.1 gwr hp->flags.vm_cookie = TRUE;
1025 1.1 gwr }
1026 1.1 gwr }
1027 1.1 gwr break;
1028 1.1 gwr
1029 1.1 gwr case SYM_SIMILAR_ENTRY:
1030 1.1 gwr switch (optype) {
1031 1.1 gwr case OP_ADDITION:
1032 1.1 gwr fill_defaults(hp, symbol);
1033 1.1 gwr break;
1034 1.1 gwr default:
1035 1.1 gwr return E_SYNTAX_ERROR;
1036 1.1 gwr }
1037 1.1 gwr break;
1038 1.1 gwr
1039 1.1 gwr case SYM_NAME_SWITCH:
1040 1.1 gwr switch (optype) {
1041 1.1 gwr case OP_ADDITION:
1042 1.1 gwr return E_SYNTAX_ERROR;
1043 1.1 gwr case OP_DELETION:
1044 1.1 gwr hp->flags.send_name = FALSE;
1045 1.1 gwr hp->flags.name_switch = FALSE;
1046 1.1 gwr break;
1047 1.1 gwr case OP_BOOLEAN:
1048 1.1 gwr hp->flags.send_name = TRUE;
1049 1.1 gwr hp->flags.name_switch = TRUE;
1050 1.1 gwr break;
1051 1.1 gwr }
1052 1.1 gwr break;
1053 1.1 gwr
1054 1.1 gwr case SYM_BOOTSIZE:
1055 1.1 gwr switch (optype) {
1056 1.1 gwr case OP_ADDITION:
1057 1.1 gwr if (!strncmp(*symbol, "auto", 4)) {
1058 1.1 gwr hp->flags.bootsize = TRUE;
1059 1.1 gwr hp->flags.bootsize_auto = TRUE;
1060 1.1 gwr } else {
1061 1.1 gwr hp->bootsize = (unsigned int) get_u_long(symbol);
1062 1.1 gwr hp->flags.bootsize = TRUE;
1063 1.1 gwr hp->flags.bootsize_auto = FALSE;
1064 1.1 gwr }
1065 1.1 gwr break;
1066 1.1 gwr case OP_DELETION:
1067 1.1 gwr hp->flags.bootsize = FALSE;
1068 1.1 gwr break;
1069 1.1 gwr case OP_BOOLEAN:
1070 1.1 gwr hp->flags.bootsize = TRUE;
1071 1.1 gwr hp->flags.bootsize_auto = TRUE;
1072 1.1 gwr break;
1073 1.1 gwr }
1074 1.1 gwr break;
1075 1.1 gwr
1076 1.1 gwr case SYM_BOOT_SERVER:
1077 1.1 gwr PARSE_IA1(bootserver);
1078 1.1 gwr break;
1079 1.1 gwr
1080 1.1 gwr case SYM_TFTPDIR:
1081 1.1 gwr PARSE_STR(tftpdir);
1082 1.1 gwr if ((hp->tftpdir != NULL) &&
1083 1.1 gwr (hp->tftpdir->string[0] != '/'))
1084 1.1 gwr return E_BAD_PATHNAME;
1085 1.1 gwr break;
1086 1.1 gwr
1087 1.1 gwr case SYM_DUMP_FILE:
1088 1.1 gwr PARSE_STR(dump_file);
1089 1.1 gwr break;
1090 1.1 gwr
1091 1.1 gwr case SYM_DOMAIN_NAME:
1092 1.1 gwr PARSE_STR(domain_name);
1093 1.1 gwr break;
1094 1.1 gwr
1095 1.1 gwr case SYM_SWAP_SERVER:
1096 1.1 gwr PARSE_IA1(swap_server);
1097 1.1 gwr break;
1098 1.1 gwr
1099 1.1 gwr case SYM_ROOT_PATH:
1100 1.1 gwr PARSE_STR(root_path);
1101 1.1 gwr break;
1102 1.1 gwr
1103 1.1 gwr case SYM_EXTEN_FILE:
1104 1.1 gwr PARSE_STR(exten_file);
1105 1.1 gwr break;
1106 1.1 gwr
1107 1.1 gwr case SYM_REPLY_ADDR:
1108 1.1 gwr PARSE_IA1(reply_addr);
1109 1.1 gwr break;
1110 1.1 gwr
1111 1.1 gwr case SYM_NIS_DOMAIN:
1112 1.1 gwr PARSE_STR(nis_domain);
1113 1.1 gwr break;
1114 1.1 gwr
1115 1.1 gwr case SYM_NIS_SERVER:
1116 1.1 gwr PARSE_IAL(nis_server);
1117 1.1 gwr break;
1118 1.1 gwr
1119 1.1 gwr case SYM_NTP_SERVER:
1120 1.1 gwr PARSE_IAL(ntp_server);
1121 1.1 gwr break;
1122 1.1 gwr
1123 1.2 gwr #ifdef YORK_EX_OPTION
1124 1.2 gwr case SYM_EXEC_FILE:
1125 1.2 gwr PARSE_STR(exec_file);
1126 1.2 gwr break;
1127 1.2 gwr #endif
1128 1.2 gwr
1129 1.2 gwr case SYM_MSG_SIZE:
1130 1.2 gwr PARSE_INT(msg_size);
1131 1.2 gwr if (hp->msg_size < BP_MINPKTSZ ||
1132 1.2 gwr hp->msg_size > MAX_MSG_SIZE)
1133 1.2 gwr return E_BAD_VALUE;
1134 1.2 gwr break;
1135 1.2 gwr
1136 1.1 gwr case SYM_MIN_WAIT:
1137 1.1 gwr PARSE_INT(min_wait);
1138 1.1 gwr if (hp->min_wait < 0)
1139 1.1 gwr return E_BAD_VALUE;
1140 1.1 gwr break;
1141 1.1 gwr
1142 1.1 gwr /* XXX - Add new tags here */
1143 1.1 gwr
1144 1.1 gwr default:
1145 1.1 gwr return E_UNKNOWN_SYMBOL;
1146 1.1 gwr
1147 1.1 gwr } /* switch symbolcode */
1148 1.1 gwr
1149 1.1 gwr return SUCCESS;
1150 1.1 gwr }
1151 1.1 gwr #undef PARSE_IA1
1152 1.1 gwr #undef PARSE_IAL
1153 1.1 gwr #undef PARSE_STR
1154 1.1 gwr
1155 1.1 gwr
1157 1.1 gwr
1158 1.1 gwr
1159 1.1 gwr /*
1160 1.1 gwr * Read a string from the buffer indirectly pointed to through "src" and
1161 1.1 gwr * move it into the buffer pointed to by "dest". A pointer to the maximum
1162 1.1 gwr * allowable length of the string (including null-terminator) is passed as
1163 1.1 gwr * "length". The actual length of the string which was read is returned in
1164 1.1 gwr * the unsigned integer pointed to by "length". This value is the same as
1165 1.1 gwr * that which would be returned by applying the strlen() function on the
1166 1.1 gwr * destination string (i.e the terminating null is not counted as a
1167 1.1 gwr * character). Trailing whitespace is removed from the string. For
1168 1.1 gwr * convenience, the function returns the new value of "dest".
1169 1.1 gwr *
1170 1.1 gwr * The string is read until the maximum number of characters, an unquoted
1171 1.1 gwr * colon (:), or a null character is read. The return string in "dest" is
1172 1.1 gwr * null-terminated.
1173 1.1 gwr */
1174 1.1 gwr
1175 1.1 gwr PRIVATE char *
1176 1.1 gwr get_string(src, dest, length)
1177 1.1 gwr char **src, *dest;
1178 1.1 gwr unsigned *length;
1179 1.1 gwr {
1180 1.1 gwr int n, len, quoteflag;
1181 1.1 gwr
1182 1.1 gwr quoteflag = FALSE;
1183 1.1 gwr n = 0;
1184 1.1 gwr len = *length - 1;
1185 1.1 gwr while ((n < len) && (**src)) {
1186 1.1 gwr if (!quoteflag && (**src == ':')) {
1187 1.1 gwr break;
1188 1.1 gwr }
1189 1.1 gwr if (**src == '"') {
1190 1.1 gwr (*src)++;
1191 1.1 gwr quoteflag = !quoteflag;
1192 1.1 gwr continue;
1193 1.1 gwr }
1194 1.1 gwr if (**src == '\\') {
1195 1.1 gwr (*src)++;
1196 1.1 gwr if (!**src) {
1197 1.1 gwr break;
1198 1.1 gwr }
1199 1.1 gwr }
1200 1.1 gwr *dest++ = *(*src)++;
1201 1.1 gwr n++;
1202 1.1 gwr }
1203 1.1 gwr
1204 1.1 gwr /*
1205 1.1 gwr * Remove that troublesome trailing whitespace. . .
1206 1.1 gwr */
1207 1.1 gwr while ((n > 0) && isspace(dest[-1])) {
1208 1.1 gwr dest--;
1209 1.1 gwr n--;
1210 1.1 gwr }
1211 1.1 gwr
1212 1.1 gwr *dest = '\0';
1213 1.1 gwr *length = n;
1214 1.1 gwr return dest;
1215 1.1 gwr }
1216 1.1 gwr
1217 1.1 gwr
1219 1.1 gwr
1220 1.1 gwr /*
1221 1.1 gwr * Read the string indirectly pointed to by "src", update the caller's
1222 1.1 gwr * pointer, and return a pointer to a malloc'ed shared_string structure
1223 1.1 gwr * containing the string.
1224 1.1 gwr *
1225 1.1 gwr * The string is read using the same rules as get_string() above.
1226 1.1 gwr */
1227 1.1 gwr
1228 1.1 gwr PRIVATE struct shared_string *
1229 1.1 gwr get_shared_string(src)
1230 1.1 gwr char **src;
1231 1.1 gwr {
1232 1.1 gwr char retstring[MAXSTRINGLEN];
1233 1.1 gwr struct shared_string *s;
1234 1.1 gwr unsigned length;
1235 1.1 gwr
1236 1.1 gwr length = sizeof(retstring);
1237 1.1 gwr (void) get_string(src, retstring, &length);
1238 1.1 gwr
1239 1.1 gwr s = (struct shared_string *) smalloc(sizeof(struct shared_string)
1240 1.1 gwr + length);
1241 1.1 gwr s->linkcount = 1;
1242 1.1 gwr strcpy(s->string, retstring);
1243 1.1 gwr
1244 1.1 gwr return s;
1245 1.1 gwr }
1246 1.1 gwr
1247 1.1 gwr
1249 1.1 gwr
1250 1.1 gwr /*
1251 1.1 gwr * Load RFC1048 generic information directly into a memory buffer.
1252 1.1 gwr *
1253 1.1 gwr * "src" indirectly points to the ASCII representation of the generic data.
1254 1.1 gwr * "dest" points to a string structure which is updated to point to a new
1255 1.1 gwr * string with the new data appended to the old string. The old string is
1256 1.1 gwr * freed.
1257 1.1 gwr *
1258 1.1 gwr * The given tag value is inserted with the new data.
1259 1.1 gwr *
1260 1.1 gwr * The data may be represented as either a stream of hexadecimal numbers
1261 1.1 gwr * representing bytes (any or all bytes may optionally start with '0x' and
1262 1.1 gwr * be separated with periods ".") or as a quoted string of ASCII
1263 1.1 gwr * characters (the quotes are required).
1264 1.1 gwr */
1265 1.1 gwr
1266 1.1 gwr PRIVATE int
1267 1.1 gwr process_generic(src, dest, tagvalue)
1268 1.1 gwr char **src;
1269 1.1 gwr struct shared_bindata **dest;
1270 1.1 gwr u_int tagvalue;
1271 1.1 gwr {
1272 1.1 gwr byte tmpbuf[MAXBUFLEN];
1273 1.1 gwr byte *str;
1274 1.3 gwr struct shared_bindata *bdata;
1275 1.1 gwr u_int newlength, oldlength;
1276 1.1 gwr
1277 1.1 gwr str = tmpbuf;
1278 1.1 gwr *str++ = (tagvalue & 0xFF); /* Store tag value */
1279 1.1 gwr str++; /* Skip over length field */
1280 1.1 gwr if ((*src)[0] == '"') { /* ASCII data */
1281 1.1 gwr newlength = sizeof(tmpbuf) - 2; /* Set maximum allowed length */
1282 1.1 gwr (void) get_string(src, (char *) str, &newlength);
1283 1.1 gwr /* Do NOT include the terminating null. */
1284 1.1 gwr } else { /* Numeric data */
1285 1.1 gwr newlength = 0;
1286 1.1 gwr while (newlength < sizeof(tmpbuf) - 2) {
1287 1.1 gwr if (interp_byte(src, str++) < 0)
1288 1.1 gwr break;
1289 1.1 gwr newlength++;
1290 1.1 gwr if (**src == '.') {
1291 1.1 gwr (*src)++;
1292 1.1 gwr }
1293 1.1 gwr }
1294 1.1 gwr }
1295 1.1 gwr if ((*src)[0] != ':')
1296 1.1 gwr return -1;
1297 1.1 gwr
1298 1.1 gwr tmpbuf[1] = (newlength & 0xFF);
1299 1.1 gwr oldlength = ((*dest)->length);
1300 1.1 gwr bdata = (struct shared_bindata *) smalloc(sizeof(struct shared_bindata)
1301 1.1 gwr + oldlength + newlength + 1);
1302 1.1 gwr if (oldlength > 0) {
1303 1.1 gwr bcopy((*dest)->data, bdata->data, oldlength);
1304 1.1 gwr }
1305 1.1 gwr bcopy(tmpbuf, bdata->data + oldlength, newlength + 2);
1306 1.1 gwr bdata->length = oldlength + newlength + 2;
1307 1.1 gwr bdata->linkcount = 1;
1308 1.1 gwr if (*dest) {
1309 1.1 gwr del_bindata(*dest);
1310 1.1 gwr }
1311 1.1 gwr *dest = bdata;
1312 1.1 gwr return 0;
1313 1.1 gwr }
1314 1.1 gwr
1315 1.1 gwr
1317 1.1 gwr
1318 1.1 gwr /*
1319 1.1 gwr * Verify that the given string makes sense as a hostname (according to
1320 1.1 gwr * Appendix 1, page 29 of RFC882).
1321 1.1 gwr *
1322 1.1 gwr * Return TRUE for good names, FALSE otherwise.
1323 1.1 gwr */
1324 1.1 gwr
1325 1.1 gwr PRIVATE boolean
1326 1.1 gwr goodname(hostname)
1327 1.1 gwr register char *hostname;
1328 1.1 gwr {
1329 1.1 gwr do {
1330 1.1 gwr if (!isalpha(*hostname++)) { /* First character must be a letter */
1331 1.1 gwr return FALSE;
1332 1.1 gwr }
1333 1.1 gwr while (isalnum(*hostname) ||
1334 1.1 gwr (*hostname == '-') ||
1335 1.1 gwr (*hostname == '_') )
1336 1.1 gwr {
1337 1.1 gwr hostname++; /* Alphanumeric or a hyphen */
1338 1.1 gwr }
1339 1.1 gwr if (!isalnum(hostname[-1])) { /* Last must be alphanumeric */
1340 1.1 gwr return FALSE;
1341 1.1 gwr }
1342 1.1 gwr if (*hostname == '\0') {/* Done? */
1343 1.1 gwr return TRUE;
1344 1.1 gwr }
1345 1.1 gwr } while (*hostname++ == '.'); /* Dot, loop for next label */
1346 1.1 gwr
1347 1.1 gwr return FALSE; /* If it's not a dot, lose */
1348 1.1 gwr }
1349 1.1 gwr
1350 1.1 gwr
1352 1.1 gwr
1353 1.1 gwr /*
1354 1.1 gwr * Null compare function -- always returns FALSE so an element is always
1355 1.1 gwr * inserted into a hash table (i.e. there is never a collision with an
1356 1.1 gwr * existing element).
1357 1.1 gwr */
1358 1.1 gwr
1359 1.1 gwr PRIVATE boolean
1360 1.1 gwr nullcmp(d1, d2)
1361 1.1 gwr hash_datum *d1, *d2;
1362 1.1 gwr {
1363 1.1 gwr return FALSE;
1364 1.1 gwr }
1365 1.1 gwr
1366 1.1 gwr
1367 1.1 gwr /*
1368 1.1 gwr * Function for comparing a string with the hostname field of a host
1369 1.1 gwr * structure.
1370 1.1 gwr */
1371 1.1 gwr
1372 1.1 gwr boolean
1373 1.1 gwr nmcmp(d1, d2)
1374 1.1 gwr hash_datum *d1, *d2;
1375 1.1 gwr {
1376 1.1 gwr char *name = (char *) d1; /* XXX - OK? */
1377 1.1 gwr struct host *hp = (struct host *) d2;
1378 1.1 gwr
1379 1.1 gwr return !strcmp(name, hp->hostname->string);
1380 1.1 gwr }
1381 1.1 gwr
1382 1.1 gwr
1383 1.1 gwr /*
1384 1.1 gwr * Compare function to determine whether two hardware addresses are
1385 1.1 gwr * equivalent. Returns TRUE if "host1" and "host2" are equivalent, FALSE
1386 1.1 gwr * otherwise.
1387 1.1 gwr *
1388 1.1 gwr * If the hardware addresses of "host1" and "host2" are identical, but
1389 1.1 gwr * they are on different IP subnets, this function returns FALSE.
1390 1.1 gwr *
1391 1.1 gwr * This function is used when inserting elements into the hardware address
1392 1.1 gwr * hash table.
1393 1.1 gwr */
1394 1.1 gwr
1395 1.1 gwr PRIVATE boolean
1396 1.1 gwr hwinscmp(d1, d2)
1397 1.1 gwr hash_datum *d1, *d2;
1398 1.1 gwr {
1399 1.1 gwr struct host *host1 = (struct host *) d1;
1400 1.1 gwr struct host *host2 = (struct host *) d2;
1401 1.1 gwr
1402 1.1 gwr if (host1->htype != host2->htype) {
1403 1.1 gwr return FALSE;
1404 1.1 gwr }
1405 1.1 gwr if (bcmp(host1->haddr, host2->haddr, haddrlength(host1->htype))) {
1406 1.1 gwr return FALSE;
1407 1.1 gwr }
1408 1.1 gwr /* XXX - Is the subnet_mask field set yet? */
1409 1.1 gwr if ((host1->subnet_mask.s_addr) == (host2->subnet_mask.s_addr)) {
1410 1.1 gwr if (((host1->iaddr.s_addr) & (host1->subnet_mask.s_addr)) !=
1411 1.1 gwr ((host2->iaddr.s_addr) & (host2->subnet_mask.s_addr)))
1412 1.1 gwr {
1413 1.1 gwr return FALSE;
1414 1.1 gwr }
1415 1.1 gwr }
1416 1.1 gwr return TRUE;
1417 1.1 gwr }
1418 1.1 gwr
1419 1.1 gwr
1421 1.1 gwr /*
1422 1.1 gwr * Macros for use in the function below:
1423 1.1 gwr */
1424 1.1 gwr
1425 1.1 gwr #define DUP_COPY(MEMBER) do \
1426 1.1 gwr { \
1427 1.1 gwr if (!hp->flags.MEMBER) { \
1428 1.1 gwr if ((hp->flags.MEMBER = hp2->flags.MEMBER) != 0) { \
1429 1.1 gwr hp->MEMBER = hp2->MEMBER; \
1430 1.1 gwr } \
1431 1.1 gwr } \
1432 1.1 gwr } while (0)
1433 1.1 gwr
1434 1.1 gwr #define DUP_LINK(MEMBER) do \
1435 1.1 gwr { \
1436 1.1 gwr if (!hp->flags.MEMBER) { \
1437 1.1 gwr if ((hp->flags.MEMBER = hp2->flags.MEMBER) != 0) { \
1438 1.1 gwr assert(hp2->MEMBER); \
1439 1.1 gwr hp->MEMBER = hp2->MEMBER; \
1440 1.1 gwr (hp->MEMBER->linkcount)++; \
1441 1.1 gwr } \
1442 1.1 gwr } \
1443 1.1 gwr } while (0)
1444 1.1 gwr
1445 1.1 gwr /*
1446 1.1 gwr * Process the "similar entry" symbol.
1447 1.1 gwr *
1448 1.1 gwr * The host specified as the value of the "tc" symbol is used as a template
1449 1.1 gwr * for the current host entry. Symbol values not explicitly set in the
1450 1.1 gwr * current host entry are inferred from the template entry.
1451 1.1 gwr */
1452 1.1 gwr PRIVATE void
1453 1.1 gwr fill_defaults(hp, src)
1454 1.1 gwr struct host *hp;
1455 1.1 gwr char **src;
1456 1.1 gwr {
1457 1.1 gwr unsigned int tlen, hashcode;
1458 1.1 gwr struct host *hp2;
1459 1.1 gwr char tstring[MAXSTRINGLEN];
1460 1.1 gwr
1461 1.1 gwr tlen = sizeof(tstring);
1462 1.1 gwr (void) get_string(src, tstring, &tlen);
1463 1.1 gwr hashcode = hash_HashFunction((u_char *) tstring, tlen);
1464 1.1 gwr hp2 = (struct host *) hash_Lookup(nmhashtable, hashcode, nmcmp, tstring);
1465 1.1 gwr
1466 1.1 gwr if (hp2 == NULL) {
1467 1.1 gwr report(LOG_ERR, "can't find tc=\"%s\"", tstring);
1468 1.1 gwr return;
1469 1.1 gwr }
1470 1.1 gwr DUP_LINK(bootfile);
1471 1.1 gwr DUP_LINK(cookie_server);
1472 1.1 gwr DUP_LINK(domain_server);
1473 1.1 gwr DUP_LINK(gateway);
1474 1.1 gwr /* haddr not copied */
1475 1.1 gwr DUP_LINK(homedir);
1476 1.1 gwr DUP_COPY(htype);
1477 1.1 gwr
1478 1.1 gwr DUP_LINK(impress_server);
1479 1.1 gwr /* iaddr not copied */
1480 1.1 gwr DUP_LINK(log_server);
1481 1.1 gwr DUP_LINK(lpr_server);
1482 1.1 gwr DUP_LINK(name_server);
1483 1.1 gwr DUP_LINK(rlp_server);
1484 1.1 gwr
1485 1.1 gwr DUP_COPY(subnet_mask);
1486 1.1 gwr DUP_COPY(time_offset);
1487 1.1 gwr DUP_LINK(time_server);
1488 1.1 gwr
1489 1.1 gwr if (!hp->flags.vm_cookie) {
1490 1.1 gwr if ((hp->flags.vm_cookie = hp2->flags.vm_cookie)) {
1491 1.1 gwr bcopy(hp2->vm_cookie, hp->vm_cookie, 4);
1492 1.1 gwr }
1493 1.1 gwr }
1494 1.1 gwr if (!hp->flags.name_switch) {
1495 1.1 gwr if ((hp->flags.name_switch = hp2->flags.name_switch)) {
1496 1.1 gwr hp->flags.send_name = hp2->flags.send_name;
1497 1.1 gwr }
1498 1.1 gwr }
1499 1.1 gwr if (!hp->flags.bootsize) {
1500 1.1 gwr if ((hp->flags.bootsize = hp2->flags.bootsize)) {
1501 1.1 gwr hp->flags.bootsize_auto = hp2->flags.bootsize_auto;
1502 1.1 gwr hp->bootsize = hp2->bootsize;
1503 1.1 gwr }
1504 1.1 gwr }
1505 1.1 gwr DUP_COPY(bootserver);
1506 1.1 gwr
1507 1.1 gwr DUP_LINK(tftpdir);
1508 1.1 gwr DUP_LINK(dump_file);
1509 1.1 gwr DUP_LINK(domain_name);
1510 1.1 gwr
1511 1.1 gwr DUP_COPY(swap_server);
1512 1.2 gwr DUP_LINK(root_path);
1513 1.2 gwr DUP_LINK(exten_file);
1514 1.2 gwr
1515 1.1 gwr DUP_COPY(reply_addr);
1516 1.1 gwr
1517 1.1 gwr DUP_LINK(nis_domain);
1518 1.1 gwr DUP_LINK(nis_server);
1519 1.1 gwr DUP_LINK(ntp_server);
1520 1.1 gwr
1521 1.1 gwr #ifdef YORK_EX_OPTION
1522 1.1 gwr DUP_LINK(exec_file);
1523 1.1 gwr #endif
1524 1.1 gwr
1525 1.1 gwr DUP_COPY(msg_size);
1526 1.1 gwr DUP_COPY(min_wait);
1527 1.1 gwr
1528 1.1 gwr /* XXX - Add new tags here */
1529 1.1 gwr
1530 1.1 gwr DUP_LINK(generic);
1531 1.1 gwr
1532 1.1 gwr }
1533 1.1 gwr #undef DUP_COPY
1534 1.1 gwr #undef DUP_LINK
1535 1.1 gwr
1536 1.1 gwr
1538 1.1 gwr
1539 1.1 gwr /*
1540 1.1 gwr * This function adjusts the caller's pointer to point just past the
1541 1.1 gwr * first-encountered colon. If it runs into a null character, it leaves
1542 1.1 gwr * the pointer pointing to it.
1543 1.1 gwr */
1544 1.1 gwr
1545 1.1 gwr PRIVATE void
1546 1.1 gwr adjust(s)
1547 1.1 gwr char **s;
1548 1.1 gwr {
1549 1.1 gwr register char *t;
1550 1.1 gwr
1551 1.1 gwr t = *s;
1552 1.1 gwr while (*t && (*t != ':')) {
1553 1.1 gwr t++;
1554 1.1 gwr }
1555 1.1 gwr if (*t) {
1556 1.1 gwr t++;
1557 1.1 gwr }
1558 1.1 gwr *s = t;
1559 1.1 gwr }
1560 1.1 gwr
1561 1.1 gwr
1562 1.1 gwr
1563 1.1 gwr
1564 1.1 gwr /*
1565 1.1 gwr * This function adjusts the caller's pointer to point to the first
1566 1.1 gwr * non-whitespace character. If it runs into a null character, it leaves
1567 1.1 gwr * the pointer pointing to it.
1568 1.1 gwr */
1569 1.1 gwr
1570 1.1 gwr PRIVATE void
1571 1.1 gwr eat_whitespace(s)
1572 1.1 gwr char **s;
1573 1.1 gwr {
1574 1.1 gwr register char *t;
1575 1.1 gwr
1576 1.1 gwr t = *s;
1577 1.1 gwr while (*t && isspace(*t)) {
1578 1.1 gwr t++;
1579 1.1 gwr }
1580 1.1 gwr *s = t;
1581 1.1 gwr }
1582 1.1 gwr
1583 1.1 gwr
1584 1.1 gwr
1585 1.1 gwr /*
1586 1.1 gwr * This function converts the given string to all lowercase.
1587 1.1 gwr */
1588 1.1 gwr
1589 1.1 gwr PRIVATE void
1590 1.1 gwr makelower(s)
1591 1.1 gwr char *s;
1592 1.1 gwr {
1593 1.1 gwr while (*s) {
1594 1.1 gwr if (isupper(*s)) {
1595 1.1 gwr *s = tolower(*s);
1596 1.1 gwr }
1597 1.1 gwr s++;
1598 1.1 gwr }
1599 1.1 gwr }
1600 1.1 gwr
1601 1.1 gwr
1603 1.1 gwr
1604 1.1 gwr /*
1605 1.1 gwr *
1606 1.1 gwr * N O T E :
1607 1.1 gwr *
1608 1.1 gwr * In many of the functions which follow, a parameter such as "src" or
1609 1.1 gwr * "symbol" is passed as a pointer to a pointer to something. This is
1610 1.1 gwr * done for the purpose of letting the called function update the
1611 1.1 gwr * caller's copy of the parameter (i.e. to effect call-by-reference
1612 1.1 gwr * parameter passing). The value of the actual parameter is only used
1613 1.1 gwr * to locate the real parameter of interest and then update this indirect
1614 1.1 gwr * parameter.
1615 1.1 gwr *
1616 1.1 gwr * I'm sure somebody out there won't like this. . . .
1617 1.1 gwr * (Yea, because it usually makes code slower... -gwr)
1618 1.1 gwr *
1619 1.1 gwr */
1620 1.1 gwr
1621 1.1 gwr
1623 1.1 gwr
1624 1.1 gwr /*
1625 1.1 gwr * "src" points to a character pointer which points to an ASCII string of
1626 1.1 gwr * whitespace-separated IP addresses. A pointer to an in_addr_list
1627 1.1 gwr * structure containing the list of addresses is returned. NULL is
1628 1.1 gwr * returned if no addresses were found at all. The pointer pointed to by
1629 1.1 gwr * "src" is updated to point to the first non-address (illegal) character.
1630 1.1 gwr */
1631 1.1 gwr
1632 1.1 gwr PRIVATE struct in_addr_list *
1633 1.1 gwr get_addresses(src)
1634 1.1 gwr char **src;
1635 1.1 gwr {
1636 1.1 gwr struct in_addr tmpaddrlist[MAXINADDRS];
1637 1.1 gwr struct in_addr *address1, *address2;
1638 1.1 gwr struct in_addr_list *result;
1639 1.1 gwr unsigned addrcount, totalsize;
1640 1.1 gwr
1641 1.1 gwr address1 = tmpaddrlist;
1642 1.1 gwr for (addrcount = 0; addrcount < MAXINADDRS; addrcount++) {
1643 1.1 gwr while (isspace(**src) || (**src == ',')) {
1644 1.1 gwr (*src)++;
1645 1.1 gwr }
1646 1.1 gwr if (!**src) { /* Quit if nothing more */
1647 1.1 gwr break;
1648 1.1 gwr }
1649 1.1 gwr if (prs_inetaddr(src, &(address1->s_addr)) < 0) {
1650 1.1 gwr break;
1651 1.1 gwr }
1652 1.1 gwr address1++; /* Point to next address slot */
1653 1.1 gwr }
1654 1.1 gwr if (addrcount < 1) {
1655 1.1 gwr result = NULL;
1656 1.1 gwr } else {
1657 1.1 gwr totalsize = sizeof(struct in_addr_list)
1658 1.1 gwr + (addrcount - 1) * sizeof(struct in_addr);
1659 1.1 gwr result = (struct in_addr_list *) smalloc(totalsize);
1660 1.1 gwr result->linkcount = 1;
1661 1.1 gwr result->addrcount = addrcount;
1662 1.1 gwr address1 = tmpaddrlist;
1663 1.1 gwr address2 = result->addr;
1664 1.1 gwr for (; addrcount > 0; addrcount--) {
1665 1.1 gwr address2->s_addr = address1->s_addr;
1666 1.1 gwr address1++;
1667 1.1 gwr address2++;
1668 1.1 gwr }
1669 1.1 gwr }
1670 1.1 gwr return result;
1671 1.1 gwr }
1672 1.1 gwr
1673 1.1 gwr
1675 1.1 gwr
1676 1.1 gwr /*
1677 1.1 gwr * prs_inetaddr(src, result)
1678 1.1 gwr *
1679 1.1 gwr * "src" is a value-result parameter; the pointer it points to is updated
1680 1.1 gwr * to point to the next data position. "result" points to an unsigned long
1681 1.1 gwr * in which an address is returned.
1682 1.1 gwr *
1683 1.1 gwr * This function parses the IP address string in ASCII "dot notation" pointed
1684 1.1 gwr * to by (*src) and places the result (in network byte order) in the unsigned
1685 1.1 gwr * long pointed to by "result". For malformed addresses, -1 is returned,
1686 1.1 gwr * (*src) points to the first illegal character, and the unsigned long pointed
1687 1.1 gwr * to by "result" is unchanged. Successful calls return 0.
1688 1.1 gwr */
1689 1.1 gwr
1690 1.1 gwr PRIVATE int
1691 1.1 gwr prs_inetaddr(src, result)
1692 1.1 gwr char **src;
1693 1.1 gwr u_int32 *result;
1694 1.1 gwr {
1695 1.1 gwr char tmpstr[MAXSTRINGLEN];
1696 1.1 gwr register u_int32 value;
1697 1.1 gwr u_int32 parts[4], *pp;
1698 1.1 gwr int n;
1699 1.1 gwr char *s, *t;
1700 1.1 gwr
1701 1.1 gwr #if 1 /* XXX - experimental */
1702 1.1 gwr /* Leading alpha char causes IP addr lookup. */
1703 1.1 gwr if (isalpha(**src)) {
1704 1.1 gwr /* Lookup IP address. */
1705 1.1 gwr s = *src;
1706 1.1 gwr t = tmpstr;
1707 1.1 gwr while ((isalnum(*s) || (*s == '.') ||
1708 1.1 gwr (*s == '-') || (*s == '_') ) &&
1709 1.1 gwr (t < &tmpstr[MAXSTRINGLEN - 1]) )
1710 1.1 gwr *t++ = *s++;
1711 1.1 gwr *t = '\0';
1712 1.1 gwr *src = s;
1713 1.1 gwr
1714 1.1 gwr n = lookup_ipa(tmpstr, result);
1715 1.1 gwr if (n < 0)
1716 1.1 gwr report(LOG_ERR, "can not get IP addr for %s", tmpstr);
1717 1.1 gwr return n;
1718 1.1 gwr }
1719 1.1 gwr #endif
1720 1.1 gwr
1721 1.1 gwr /*
1722 1.1 gwr * Parse an address in Internet format:
1723 1.1 gwr * a.b.c.d
1724 1.1 gwr * a.b.c (with c treated as 16-bits)
1725 1.1 gwr * a.b (with b treated as 24 bits)
1726 1.1 gwr */
1727 1.1 gwr pp = parts;
1728 1.1 gwr loop:
1729 1.1 gwr /* If it's not a digit, return error. */
1730 1.1 gwr if (!isdigit(**src))
1731 1.1 gwr return -1;
1732 1.1 gwr *pp++ = get_u_long(src);
1733 1.1 gwr if (**src == '.') {
1734 1.1 gwr if (pp < (parts + 4)) {
1735 1.1 gwr (*src)++;
1736 1.1 gwr goto loop;
1737 1.1 gwr }
1738 1.1 gwr return (-1);
1739 1.1 gwr }
1740 1.1 gwr #if 0
1741 1.1 gwr /* This is handled by the caller. */
1742 1.1 gwr if (**src && !(isspace(**src) || (**src == ':'))) {
1743 1.1 gwr return (-1);
1744 1.1 gwr }
1745 1.1 gwr #endif
1746 1.1 gwr
1747 1.1 gwr /*
1748 1.1 gwr * Construct the address according to
1749 1.1 gwr * the number of parts specified.
1750 1.1 gwr */
1751 1.1 gwr n = pp - parts;
1752 1.1 gwr switch (n) {
1753 1.1 gwr case 1: /* a -- 32 bits */
1754 1.1 gwr value = parts[0];
1755 1.1 gwr break;
1756 1.1 gwr case 2: /* a.b -- 8.24 bits */
1757 1.1 gwr value = (parts[0] << 24) | (parts[1] & 0xFFFFFF);
1758 1.1 gwr break;
1759 1.1 gwr case 3: /* a.b.c -- 8.8.16 bits */
1760 1.1 gwr value = (parts[0] << 24) | ((parts[1] & 0xFF) << 16) |
1761 1.1 gwr (parts[2] & 0xFFFF);
1762 1.1 gwr break;
1763 1.1 gwr case 4: /* a.b.c.d -- 8.8.8.8 bits */
1764 1.1 gwr value = (parts[0] << 24) | ((parts[1] & 0xFF) << 16) |
1765 1.1 gwr ((parts[2] & 0xFF) << 8) | (parts[3] & 0xFF);
1766 1.1 gwr break;
1767 1.1 gwr default:
1768 1.1 gwr return (-1);
1769 1.1 gwr }
1770 1.1 gwr *result = htonl(value);
1771 1.1 gwr return (0);
1772 1.1 gwr }
1773 1.1 gwr
1774 1.1 gwr
1776 1.1 gwr
1777 1.1 gwr /*
1778 1.1 gwr * "src" points to a pointer which in turn points to a hexadecimal ASCII
1779 1.1 gwr * string. This string is interpreted as a hardware address and returned
1780 1.1 gwr * as a pointer to the actual hardware address, represented as an array of
1781 1.1 gwr * bytes.
1782 1.1 gwr *
1783 1.1 gwr * The ASCII string must have the proper number of digits for the specified
1784 1.1 gwr * hardware type (e.g. twelve digits for a 48-bit Ethernet address).
1785 1.1 gwr * Two-digit sequences (bytes) may be separated with periods (.) and/or
1786 1.1 gwr * prefixed with '0x' for readability, but this is not required.
1787 1.1 gwr *
1788 1.1 gwr * For bad addresses, the pointer which "src" points to is updated to point
1789 1.1 gwr * to the start of the first two-digit sequence which was bad, and the
1790 1.1 gwr * function returns a NULL pointer.
1791 1.1 gwr */
1792 1.1 gwr
1793 1.1 gwr PRIVATE byte *
1794 1.1 gwr prs_haddr(src, htype)
1795 1.1 gwr char **src;
1796 1.1 gwr u_int htype;
1797 1.1 gwr {
1798 1.1 gwr static byte haddr[MAXHADDRLEN];
1799 1.1 gwr byte *hap;
1800 1.1 gwr char tmpstr[MAXSTRINGLEN];
1801 1.1 gwr u_int tmplen;
1802 1.1 gwr unsigned hal;
1803 1.1 gwr char *p;
1804 1.1 gwr
1805 1.1 gwr hal = haddrlength(htype); /* Get length of this address type */
1806 1.1 gwr if (hal <= 0) {
1807 1.1 gwr report(LOG_ERR, "Invalid addr type for HW addr parse");
1808 1.1 gwr return NULL;
1809 1.1 gwr }
1810 1.3 gwr tmplen = sizeof(tmpstr);
1811 1.1 gwr get_string(src, tmpstr, &tmplen);
1812 1.1 gwr p = tmpstr;
1813 1.1 gwr
1814 1.1 gwr #if 1 /* XXX - experimental */
1815 1.1 gwr /* If it's a valid host name, try to lookup the HW address. */
1816 1.1 gwr if (goodname(p)) {
1817 1.1 gwr /* Lookup Hardware Address for hostname. */
1818 1.1 gwr if ((hap = lookup_hwa(p, htype)) != NULL)
1819 1.1 gwr return hap; /* success */
1820 1.1 gwr report(LOG_ERR, "Add 0x prefix if hex value starts with A-F");
1821 1.1 gwr /* OK, assume it must be numeric. */
1822 1.1 gwr }
1823 1.1 gwr #endif
1824 1.1 gwr
1825 1.1 gwr hap = haddr;
1826 1.1 gwr while (hap < haddr + hal) {
1827 1.1 gwr if ((*p == '.') || (*p == ':'))
1828 1.1 gwr p++;
1829 1.1 gwr if (interp_byte(&p, hap++) < 0) {
1830 1.1 gwr return NULL;
1831 1.1 gwr }
1832 1.1 gwr }
1833 1.1 gwr return haddr;
1834 1.1 gwr }
1835 1.1 gwr
1836 1.1 gwr
1838 1.1 gwr
1839 1.1 gwr /*
1840 1.1 gwr * "src" is a pointer to a character pointer which in turn points to a
1841 1.1 gwr * hexadecimal ASCII representation of a byte. This byte is read, the
1842 1.1 gwr * character pointer is updated, and the result is deposited into the
1843 1.1 gwr * byte pointed to by "retbyte".
1844 1.1 gwr *
1845 1.1 gwr * The usual '0x' notation is allowed but not required. The number must be
1846 1.1 gwr * a two digit hexadecimal number. If the number is invalid, "src" and
1847 1.1 gwr * "retbyte" are left untouched and -1 is returned as the function value.
1848 1.1 gwr * Successful calls return 0.
1849 1.1 gwr */
1850 1.1 gwr
1851 1.1 gwr PRIVATE int
1852 1.1 gwr interp_byte(src, retbyte)
1853 1.1 gwr char **src;
1854 1.1 gwr byte *retbyte;
1855 1.1 gwr {
1856 1.1 gwr int v;
1857 1.1 gwr
1858 1.1 gwr if ((*src)[0] == '0' &&
1859 1.1 gwr ((*src)[1] == 'x' ||
1860 1.1 gwr (*src)[1] == 'X')) {
1861 1.1 gwr (*src) += 2; /* allow 0x for hex, but don't require it */
1862 1.1 gwr }
1863 1.1 gwr if (!isxdigit((*src)[0]) || !isxdigit((*src)[1])) {
1864 1.1 gwr return -1;
1865 1.1 gwr }
1866 1.1 gwr if (sscanf(*src, "%2x", &v) != 1) {
1867 1.1 gwr return -1;
1868 1.1 gwr }
1869 1.1 gwr (*src) += 2;
1870 1.1 gwr *retbyte = (byte) (v & 0xFF);
1871 1.1 gwr return 0;
1872 1.1 gwr }
1873 1.1 gwr
1874 1.1 gwr
1876 1.1 gwr
1877 1.1 gwr /*
1878 1.1 gwr * The parameter "src" points to a character pointer which points to an
1879 1.1 gwr * ASCII string representation of an unsigned number. The number is
1880 1.1 gwr * returned as an unsigned long and the character pointer is updated to
1881 1.1 gwr * point to the first illegal character.
1882 1.1 gwr */
1883 1.1 gwr
1884 1.1 gwr PRIVATE u_int32
1885 1.1 gwr get_u_long(src)
1886 1.1 gwr char **src;
1887 1.1 gwr {
1888 1.1 gwr register u_int32 value, base;
1889 1.1 gwr char c;
1890 1.1 gwr
1891 1.1 gwr /*
1892 1.1 gwr * Collect number up to first illegal character. Values are specified
1893 1.1 gwr * as for C: 0x=hex, 0=octal, other=decimal.
1894 1.1 gwr */
1895 1.1 gwr value = 0;
1896 1.1 gwr base = 10;
1897 1.1 gwr if (**src == '0') {
1898 1.1 gwr base = 8;
1899 1.1 gwr (*src)++;
1900 1.1 gwr }
1901 1.1 gwr if (**src == 'x' || **src == 'X') {
1902 1.1 gwr base = 16;
1903 1.1 gwr (*src)++;
1904 1.1 gwr }
1905 1.1 gwr while ((c = **src)) {
1906 1.1 gwr if (isdigit(c)) {
1907 1.1 gwr value = (value * base) + (c - '0');
1908 1.1 gwr (*src)++;
1909 1.1 gwr continue;
1910 1.1 gwr }
1911 1.1 gwr if (base == 16 && isxdigit(c)) {
1912 1.1 gwr value = (value << 4) + ((c & ~32) + 10 - 'A');
1913 1.1 gwr (*src)++;
1914 1.1 gwr continue;
1915 1.1 gwr }
1916 1.1 gwr break;
1917 1.1 gwr }
1918 1.1 gwr return value;
1919 1.1 gwr }
1920 1.1 gwr
1921 1.1 gwr
1923 1.1 gwr
1924 1.1 gwr /*
1925 1.1 gwr * Routines for deletion of data associated with the main data structure.
1926 1.1 gwr */
1927 1.1 gwr
1928 1.1 gwr
1929 1.1 gwr /*
1930 1.1 gwr * Frees the entire host data structure given. Does nothing if the passed
1931 1.1 gwr * pointer is NULL.
1932 1.1 gwr */
1933 1.1 gwr
1934 1.1 gwr PRIVATE void
1935 1.1 gwr free_host(hmp)
1936 1.1 gwr hash_datum *hmp;
1937 1.1 gwr {
1938 1.1 gwr struct host *hostptr = (struct host *) hmp;
1939 1.1 gwr if (hostptr == NULL)
1940 1.1 gwr return;
1941 1.1 gwr assert(hostptr->linkcount > 0);
1942 1.1 gwr if (--(hostptr->linkcount))
1943 1.1 gwr return; /* Still has references */
1944 1.1 gwr del_iplist(hostptr->cookie_server);
1945 1.1 gwr del_iplist(hostptr->domain_server);
1946 1.1 gwr del_iplist(hostptr->gateway);
1947 1.1 gwr del_iplist(hostptr->impress_server);
1948 1.1 gwr del_iplist(hostptr->log_server);
1949 1.1 gwr del_iplist(hostptr->lpr_server);
1950 1.1 gwr del_iplist(hostptr->name_server);
1951 1.1 gwr del_iplist(hostptr->rlp_server);
1952 1.1 gwr del_iplist(hostptr->time_server);
1953 1.1 gwr del_iplist(hostptr->nis_server);
1954 1.1 gwr del_iplist(hostptr->ntp_server);
1955 1.1 gwr
1956 1.1 gwr /*
1957 1.1 gwr * XXX - Add new tags here
1958 1.1 gwr * (if the value is an IP list)
1959 1.1 gwr */
1960 1.1 gwr
1961 1.1 gwr del_string(hostptr->hostname);
1962 1.1 gwr del_string(hostptr->homedir);
1963 1.1 gwr del_string(hostptr->bootfile);
1964 1.1 gwr del_string(hostptr->tftpdir);
1965 1.1 gwr del_string(hostptr->root_path);
1966 1.1 gwr del_string(hostptr->domain_name);
1967 1.1 gwr del_string(hostptr->dump_file);
1968 1.1 gwr del_string(hostptr->exten_file);
1969 1.1 gwr del_string(hostptr->nis_domain);
1970 1.1 gwr
1971 1.1 gwr #ifdef YORK_EX_OPTION
1972 1.1 gwr del_string(hostptr->exec_file);
1973 1.1 gwr #endif
1974 1.1 gwr
1975 1.1 gwr /*
1976 1.1 gwr * XXX - Add new tags here
1977 1.1 gwr * (if it is a shared string)
1978 1.1 gwr */
1979 1.1 gwr
1980 1.1 gwr del_bindata(hostptr->generic);
1981 1.1 gwr free((char *) hostptr);
1982 1.1 gwr }
1983 1.1 gwr
1984 1.1 gwr
1986 1.1 gwr
1987 1.1 gwr /*
1988 1.1 gwr * Decrements the linkcount on the given IP address data structure. If the
1989 1.1 gwr * linkcount goes to zero, the memory associated with the data is freed.
1990 1.1 gwr */
1991 1.1 gwr
1992 1.1 gwr PRIVATE void
1993 1.1 gwr del_iplist(iplist)
1994 1.1 gwr struct in_addr_list *iplist;
1995 1.1 gwr {
1996 1.1 gwr if (iplist) {
1997 1.1 gwr if (!(--(iplist->linkcount))) {
1998 1.1 gwr free((char *) iplist);
1999 1.1 gwr }
2000 1.1 gwr }
2001 1.1 gwr }
2002 1.1 gwr
2003 1.1 gwr
2004 1.1 gwr
2005 1.1 gwr /*
2006 1.1 gwr * Decrements the linkcount on a string data structure. If the count
2007 1.1 gwr * goes to zero, the memory associated with the string is freed. Does
2008 1.1 gwr * nothing if the passed pointer is NULL.
2009 1.1 gwr */
2010 1.1 gwr
2011 1.1 gwr PRIVATE void
2012 1.1 gwr del_string(stringptr)
2013 1.1 gwr struct shared_string *stringptr;
2014 1.1 gwr {
2015 1.1 gwr if (stringptr) {
2016 1.1 gwr if (!(--(stringptr->linkcount))) {
2017 1.1 gwr free((char *) stringptr);
2018 1.1 gwr }
2019 1.1 gwr }
2020 1.1 gwr }
2021 1.1 gwr
2022 1.1 gwr
2023 1.1 gwr
2024 1.1 gwr /*
2025 1.1 gwr * Decrements the linkcount on a shared_bindata data structure. If the
2026 1.1 gwr * count goes to zero, the memory associated with the data is freed. Does
2027 1.1 gwr * nothing if the passed pointer is NULL.
2028 1.1 gwr */
2029 1.1 gwr
2030 1.1 gwr PRIVATE void
2031 1.1 gwr del_bindata(dataptr)
2032 1.1 gwr struct shared_bindata *dataptr;
2033 1.1 gwr {
2034 1.1 gwr if (dataptr) {
2035 1.1 gwr if (!(--(dataptr->linkcount))) {
2036 1.1 gwr free((char *) dataptr);
2037 1.1 gwr }
2038 1.1 gwr }
2039 1.1 gwr }
2040 1.1 gwr
2041 1.1 gwr
2043 1.1 gwr
2044 1.1 gwr
2045 1.1 gwr /* smalloc() -- safe malloc()
2046 1.1 gwr *
2047 1.1 gwr * Always returns a valid pointer (if it returns at all). The allocated
2048 1.1 gwr * memory is initialized to all zeros. If malloc() returns an error, a
2049 1.1 gwr * message is printed using the report() function and the program aborts
2050 1.1 gwr * with a status of 1.
2051 1.1 gwr */
2052 1.1 gwr
2053 1.1 gwr PRIVATE char *
2054 1.1 gwr smalloc(nbytes)
2055 1.1 gwr unsigned nbytes;
2056 1.1 gwr {
2057 1.1 gwr char *retvalue;
2058 1.1 gwr
2059 1.1 gwr retvalue = malloc(nbytes);
2060 1.1 gwr if (!retvalue) {
2061 1.1 gwr report(LOG_ERR, "malloc() failure -- exiting");
2062 1.1 gwr exit(1);
2063 1.1 gwr }
2064 1.1 gwr bzero(retvalue, nbytes);
2065 1.1 gwr return retvalue;
2066 1.1 gwr }
2067 1.1 gwr
2068 1.1 gwr
2070 1.1 gwr /*
2071 1.1 gwr * Compare function to determine whether two hardware addresses are
2072 1.1 gwr * equivalent. Returns TRUE if "host1" and "host2" are equivalent, FALSE
2073 1.1 gwr * otherwise.
2074 1.1 gwr *
2075 1.1 gwr * This function is used when retrieving elements from the hardware address
2076 1.1 gwr * hash table.
2077 1.1 gwr */
2078 1.1 gwr
2079 1.1 gwr boolean
2080 1.1 gwr hwlookcmp(d1, d2)
2081 1.1 gwr hash_datum *d1, *d2;
2082 1.1 gwr {
2083 1.1 gwr struct host *host1 = (struct host *) d1;
2084 1.1 gwr struct host *host2 = (struct host *) d2;
2085 1.1 gwr
2086 1.1 gwr if (host1->htype != host2->htype) {
2087 1.1 gwr return FALSE;
2088 1.1 gwr }
2089 1.1 gwr if (bcmp(host1->haddr, host2->haddr, haddrlength(host1->htype))) {
2090 1.1 gwr return FALSE;
2091 1.1 gwr }
2092 1.1 gwr return TRUE;
2093 1.1 gwr }
2094 1.1 gwr
2095 1.1 gwr
2096 1.1 gwr /*
2097 1.1 gwr * Compare function for doing IP address hash table lookup.
2098 */
2099
2100 boolean
2101 iplookcmp(d1, d2)
2102 hash_datum *d1, *d2;
2103 {
2104 struct host *host1 = (struct host *) d1;
2105 struct host *host2 = (struct host *) d2;
2106
2107 return (host1->iaddr.s_addr == host2->iaddr.s_addr);
2108 }
2109
2110 /*
2111 * Local Variables:
2112 * tab-width: 4
2113 * c-indent-level: 4
2114 * c-argdecl-indent: 4
2115 * c-continued-statement-offset: 4
2116 * c-continued-brace-offset: -4
2117 * c-label-offset: -4
2118 * c-brace-offset: 0
2119 * End:
2120 */
2121