1 /************************************************************************
2 Copyright 1988, 1991 by Carnegie Mellon University
6 Permission to use, copy, modify, and distribute this software and its
7 documentation for any purpose and without fee is hereby granted, provided
8 that the above copyright notice appear in all copies and that both that
9 copyright notice and this permission notice appear in supporting
10 documentation, and that the name of Carnegie Mellon University not be used
11 in advertising or publicity pertaining to distribution of the software
12 without specific, written prior permission.
14 CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
15 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
16 IN NO EVENT SHALL CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
17 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
18 PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
19 ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
21 ************************************************************************/
23 #include <sys/cdefs.h>
25 __RCSID("$NetBSD: readfile.c,v 1.16 2008/05/02 19:22:10 xtraeme Exp $");
30 * bootpd configuration file reading code.
32 * The routines in this file deal with reading, interpreting, and storing
33 * the information found in the bootpd configuration file (usually
38 #include <sys/types.h>
42 #include <netinet/in.h>
63 #define HASHTABLESIZE 257 /* Hash table size (prime) */
65 /* Non-standard hardware address type (see bootp.h) */
66 #define HTYPE_DIRECT 0
68 /* Error codes returned by eval_symbol: */
70 #define E_END_OF_ENTRY (-1)
71 #define E_SYNTAX_ERROR (-2)
72 #define E_UNKNOWN_SYMBOL (-3)
73 #define E_BAD_IPADDR (-4)
74 #define E_BAD_HWADDR (-5)
75 #define E_BAD_LONGWORD (-6)
76 #define E_BAD_HWATYPE (-7)
77 #define E_BAD_PATHNAME (-8)
78 #define E_BAD_VALUE (-9)
82 #define SYM_BOOTFILE 1
83 #define SYM_COOKIE_SERVER 2
84 #define SYM_DOMAIN_SERVER 3
89 #define SYM_IMPRESS_SERVER 8
91 #define SYM_LOG_SERVER 10
92 #define SYM_LPR_SERVER 11
93 #define SYM_NAME_SERVER 12
94 #define SYM_RLP_SERVER 13
95 #define SYM_SUBNET_MASK 14
96 #define SYM_TIME_OFFSET 15
97 #define SYM_TIME_SERVER 16
98 #define SYM_VENDOR_MAGIC 17
99 #define SYM_SIMILAR_ENTRY 18
100 #define SYM_NAME_SWITCH 19
101 #define SYM_BOOTSIZE 20
102 #define SYM_BOOT_SERVER 22
103 #define SYM_TFTPDIR 23
104 #define SYM_DUMP_FILE 24
105 #define SYM_DOMAIN_NAME 25
106 #define SYM_SWAP_SERVER 26
107 #define SYM_ROOT_PATH 27
108 #define SYM_EXTEN_FILE 28
109 #define SYM_REPLY_ADDR 29
110 #define SYM_NIS_DOMAIN 30 /* RFC 1533 */
111 #define SYM_NIS_SERVER 31 /* RFC 1533 */
112 #define SYM_NTP_SERVER 32 /* RFC 1533 */
113 #define SYM_EXEC_FILE 33 /* YORK_EX_OPTION */
114 #define SYM_MSG_SIZE 34
115 #define SYM_MIN_WAIT 35
116 /* XXX - Add new tags here */
118 #define OP_ADDITION 1 /* Operations on tags */
119 #define OP_DELETION 2
122 #define MAXINADDRS 16 /* Max size of an IP address list */
123 #define MAXBUFLEN 256 /* Max temp buffer space */
124 #define MAXENTRYLEN 2048 /* Max size of an entire entry */
129 * Structure used to map a configuration-file symbol (such as "ds") to a
145 PRIVATE
int nhosts
; /* Number of hosts (/w hw or IP address) */
146 PRIVATE
int nentries
; /* Total number of entries */
147 PRIVATE int32 modtime
= 0; /* Last modification time of bootptab */
148 PRIVATE
char *current_hostname
; /* Name of the current entry. */
149 PRIVATE
char current_tagname
[8];
152 * List of symbolic names used in the bootptab file. The order and actual
153 * values of the symbol codes (SYM_. . .) are unimportant, but they must
157 PRIVATE
struct symbolmap symbol_list
[] = {
158 {"bf", SYM_BOOTFILE
},
159 {"bs", SYM_BOOTSIZE
},
160 {"cs", SYM_COOKIE_SERVER
},
161 {"df", SYM_DUMP_FILE
},
162 {"dn", SYM_DOMAIN_NAME
},
163 {"ds", SYM_DOMAIN_SERVER
},
164 {"ef", SYM_EXTEN_FILE
},
165 {"ex", SYM_EXEC_FILE
}, /* YORK_EX_OPTION */
169 {"hn", SYM_NAME_SWITCH
},
171 {"im", SYM_IMPRESS_SERVER
},
173 {"lg", SYM_LOG_SERVER
},
174 {"lp", SYM_LPR_SERVER
},
175 {"ms", SYM_MSG_SIZE
},
176 {"mw", SYM_MIN_WAIT
},
177 {"ns", SYM_NAME_SERVER
},
178 {"nt", SYM_NTP_SERVER
},
179 {"ra", SYM_REPLY_ADDR
},
180 {"rl", SYM_RLP_SERVER
},
181 {"rp", SYM_ROOT_PATH
},
182 {"sa", SYM_BOOT_SERVER
},
183 {"sm", SYM_SUBNET_MASK
},
184 {"sw", SYM_SWAP_SERVER
},
185 {"tc", SYM_SIMILAR_ENTRY
},
187 {"to", SYM_TIME_OFFSET
},
188 {"ts", SYM_TIME_SERVER
},
189 {"vm", SYM_VENDOR_MAGIC
},
190 {"yd", SYM_NIS_DOMAIN
},
191 {"ys", SYM_NIS_SERVER
},
192 /* XXX - Add new tags here */
197 * List of symbolic names for hardware types. Name translates into
198 * hardware type code listed with it. Names must begin with a letter
199 * and must be all lowercase. This is searched linearly, so put
200 * commonly-used entries near the beginning.
203 PRIVATE
struct htypename htnamemap
[] = {
204 {"ethernet", HTYPE_ETHERNET
},
205 {"ethernet3", HTYPE_EXP_ETHERNET
},
206 {"ether", HTYPE_ETHERNET
},
207 {"ether3", HTYPE_EXP_ETHERNET
},
208 {"ieee802", HTYPE_IEEE802
},
209 {"tr", HTYPE_IEEE802
},
210 {"token-ring", HTYPE_IEEE802
},
211 {"pronet", HTYPE_PRONET
},
212 {"chaos", HTYPE_CHAOS
},
213 {"arcnet", HTYPE_ARCNET
},
214 {"ax.25", HTYPE_AX25
},
215 {"direct", HTYPE_DIRECT
},
216 {"serial", HTYPE_DIRECT
},
217 {"slip", HTYPE_DIRECT
},
218 {"ppp", HTYPE_DIRECT
}
224 * Externals and forward declarations.
227 boolean
nmcmp(hash_datum
*, hash_datum
*);
232 del_string(struct shared_string
*);
234 del_bindata(struct shared_bindata
*);
236 del_iplist(struct in_addr_list
*);
238 eat_whitespace(char **);
240 eval_symbol(char **, struct host
*);
242 fill_defaults(struct host
*, char **);
244 free_host(hash_datum
*);
245 PRIVATE
struct in_addr_list
*
246 get_addresses(char **);
247 PRIVATE
struct shared_string
*
248 get_shared_string(char **);
250 get_string(char **, char *, u_int
*);
256 hwinscmp(hash_datum
*, hash_datum
*);
258 interp_byte(char **, byte
*);
262 nullcmp(hash_datum
*, hash_datum
*);
264 process_entry(struct host
*, char *);
266 process_generic(char **, struct shared_bindata
**, u_int
);
268 prs_haddr(char **, u_int
);
270 prs_inetaddr(char **, u_int32
*);
272 read_entry(FILE *, char *, u_int
*);
279 * Vendor magic cookies for CMU and RFC1048
281 u_char vm_cmu
[4] = VM_CMU
;
282 u_char vm_rfc1048
[4] = VM_RFC1048
;
287 hash_tbl
*hwhashtable
;
288 hash_tbl
*iphashtable
;
289 hash_tbl
*nmhashtable
;
292 * Allocate hash tables for hardware address, ip address, and hostname
293 * (shared by bootpd and bootpef)
298 hwhashtable
= hash_Init(HASHTABLESIZE
);
299 iphashtable
= hash_Init(HASHTABLESIZE
);
300 nmhashtable
= hash_Init(HASHTABLESIZE
);
301 if (!(hwhashtable
&& iphashtable
&& nmhashtable
)) {
302 report(LOG_ERR
, "Unable to allocate hash tables.");
309 * Read bootptab database file. Avoid rereading the file if the
310 * write date hasn't changed since the last time we read it.
319 unsigned hashcode
, buflen
;
320 static char buffer
[MAXENTRYLEN
];
323 * Check the last modification time.
325 if (stat(bootptab
, &st
) < 0) {
326 report(LOG_ERR
, "stat on \"%s\": %s",
327 bootptab
, get_errmsg());
333 strlcpy(timestr
, ctime(&(st
.st_mtime
)), sizeof(timestr
));
334 /* zap the newline */
336 report(LOG_INFO
, "bootptab mtime: %s",
341 (st
.st_mtime
== modtime
) &&
344 * hasn't been modified or deleted yet.
349 report(LOG_INFO
, "reading %s\"%s\"",
350 (modtime
!= 0L) ? "new " : "",
354 * Open bootptab file.
356 if ((fp
= fopen(bootptab
, "r")) == NULL
) {
357 report(LOG_ERR
, "error opening \"%s\": %s", bootptab
, get_errmsg());
361 * Record file modification time.
363 if (fstat(fileno(fp
), &st
) < 0) {
364 report(LOG_ERR
, "fstat: %s", get_errmsg());
368 modtime
= st
.st_mtime
;
371 * Entirely erase all hash tables.
373 hash_Reset(hwhashtable
, free_host
);
374 hash_Reset(iphashtable
, free_host
);
375 hash_Reset(nmhashtable
, free_host
);
380 buflen
= sizeof(buffer
);
381 read_entry(fp
, buffer
, &buflen
);
382 if (buflen
== 0) { /* More entries? */
385 hp
= (struct host
*) smalloc(sizeof(struct host
));
386 bzero((char *) hp
, sizeof(*hp
));
387 /* the link count it zero */
390 * Get individual info
392 if (process_entry(hp
, buffer
) < 0) {
394 free_host((hash_datum
*) hp
);
398 * If this is not a dummy entry, and the IP or HW
399 * address is not yet set, try to get them here.
400 * Dummy entries have . as first char of name.
402 if (goodname(hp
->hostname
->string
)) {
403 char *hn
= hp
->hostname
->string
;
405 if (hp
->flags
.iaddr
== 0) {
406 if (lookup_ipa(hn
, &value
)) {
407 report(LOG_ERR
, "can not get IP addr for %s", hn
);
408 report(LOG_ERR
, "(dummy names should start with '.')");
410 hp
->iaddr
.s_addr
= value
;
411 hp
->flags
.iaddr
= TRUE
;
414 /* Set default subnet mask. */
415 if (hp
->flags
.subnet_mask
== 0) {
416 if (lookup_netmask(hp
->iaddr
.s_addr
, &value
)) {
417 report(LOG_ERR
, "can not get netmask for %s", hn
);
419 hp
->subnet_mask
.s_addr
= value
;
420 hp
->flags
.subnet_mask
= TRUE
;
424 if (hp
->flags
.iaddr
) {
427 /* Register by HW addr if known. */
428 if (hp
->flags
.htype
&& hp
->flags
.haddr
) {
429 /* We will either insert it or free it. */
431 hashcode
= hash_HashFunction(hp
->haddr
, haddrlength(hp
->htype
));
432 if (hash_Insert(hwhashtable
, hashcode
, hwinscmp
, hp
, hp
) < 0) {
433 report(LOG_NOTICE
, "duplicate %s address: %s",
435 haddrtoa(hp
->haddr
, haddrlength(hp
->htype
)));
436 free_host((hash_datum
*) hp
);
440 /* Register by IP addr if known. */
441 if (hp
->flags
.iaddr
) {
442 hashcode
= hash_HashFunction((u_char
*) & (hp
->iaddr
.s_addr
), 4);
443 if (hash_Insert(iphashtable
, hashcode
, nullcmp
, hp
, hp
) < 0) {
445 "hash_Insert() failed on IP address insertion");
447 /* Just inserted the host struct in a new hash list. */
451 /* Register by Name (always known) */
452 hashcode
= hash_HashFunction((u_char
*) hp
->hostname
->string
,
453 strlen(hp
->hostname
->string
));
454 if (hash_Insert(nmhashtable
, hashcode
, nullcmp
,
455 hp
->hostname
->string
, hp
) < 0) {
457 "hash_Insert() failed on insertion of hostname: \"%s\"",
458 hp
->hostname
->string
);
460 /* Just inserted the host struct in a new hash list. */
469 report(LOG_INFO
, "read %d entries (%d hosts) from \"%s\"",
470 nentries
, nhosts
, bootptab
);
477 * Read an entire host entry from the file pointed to by "fp" and insert it
478 * into the memory pointed to by "buffer". Leading whitespace and comments
479 * starting with "#" are ignored (removed). Backslashes (\) always quote
480 * the next character except that newlines preceded by a backslash cause
481 * line-continuation onto the next line. The entry is terminated by a
482 * newline character which is not preceded by a backslash. Sequences
483 * surrounded by double quotes are taken literally (including newlines, but
486 * The "bufsiz" parameter points to an unsigned int which specifies the
487 * maximum permitted buffer size. Upon return, this value will be replaced
488 * with the actual length of the entry (not including the null terminator).
490 * This code is a little scary. . . . I don't like using gotos in C
491 * either, but I first wrote this as an FSM diagram and gotos seemed like
492 * the easiest way to implement it. Maybe later I'll clean it up.
496 read_entry(FILE *fp
, char *buffer
, unsigned int *bufsiz
)
504 * Eat whitespace, blank lines, and comment lines.
509 goto done
; /* Exit if end-of-file */
512 goto top
; /* Skip over whitespace */
515 while (TRUE
) { /* Eat comments after # */
518 goto done
; /* Exit if end-of-file */
521 goto top
; /* Try to read the next line */
525 ungetc(c
, fp
); /* Other character, push it back to reprocess it */
529 * Now we're actually reading a data entry. Get each character and
530 * assemble it into the data buffer, processing special characters like
531 * double quotes (") and backslashes (\).
539 goto done
; /* Exit on EOF or newline */
541 c
= fgetc(fp
); /* Backslash, read a new character */
543 goto done
; /* Exit on EOF */
545 *buffer
++ = c
; /* Store the literal character */
547 if (length
< *bufsiz
- 1) {
553 *buffer
++ = '"'; /* Store double-quote */
555 if (length
>= *bufsiz
- 1) {
558 while (TRUE
) { /* Special quote processing loop */
562 goto done
; /* Exit on EOF . . . */
564 *buffer
++ = '"';/* Store matching quote */
566 if (length
< *bufsiz
- 1) {
567 goto mainloop
; /* And continue main loop */
572 if ((c
= fgetc(fp
)) < 0) { /* Backslash */
573 goto done
; /* EOF. . . .*/
574 } /* else fall through */
576 *buffer
++ = c
; /* Other character, store it */
578 if (length
>= *bufsiz
- 1) {
584 *buffer
++ = c
; /* Store colons */
586 if (length
>= *bufsiz
- 1) {
589 do { /* But remove whitespace after them */
591 if ((c
< 0) || (c
== '\n')) {
594 } while (isspace(c
)); /* Skip whitespace */
596 if (c
== '\\') { /* Backslash quotes next character */
602 goto top
; /* Backslash-newline continuation */
605 /* fall through if "other" character */
607 *buffer
++ = c
; /* Store other characters */
609 if (length
>= *bufsiz
- 1) {
613 goto mainloop
; /* Keep going */
616 *buffer
= '\0'; /* Terminate string */
617 *bufsiz
= length
; /* Tell the caller its length */
623 * Parse out all the various tags and parameters in the host entry pointed
624 * to by "src". Stuff all the data into the appropriate fields of the
625 * host structure pointed to by "host". If there is any problem with the
626 * entry, an error message is reported via report(), no further processing
627 * is done, and -1 is returned. Successful calls return 0.
629 * (Some errors probably shouldn't be so completely fatal. . . .)
633 process_entry(struct host
*host
, char *src
)
638 if (!host
|| *src
== '\0') {
641 host
->hostname
= get_shared_string(&src
);
643 /* Be more liberal for the benefit of dummy tag names. */
644 if (!goodname(host
->hostname
->string
)) {
645 report(LOG_ERR
, "bad hostname: \"%s\"", host
->hostname
->string
);
646 del_string(host
->hostname
);
650 current_hostname
= host
->hostname
->string
;
653 retval
= eval_symbol(&src
, host
);
654 if (retval
== SUCCESS
) {
658 if (retval
== E_END_OF_ENTRY
) {
659 /* The default subnet mask is set in readtab() */
662 /* Some kind of error. */
667 case E_UNKNOWN_SYMBOL
:
668 msg
= "unknown symbol";
671 msg
= "bad INET address";
674 msg
= "bad hardware address";
677 msg
= "bad longword value";
680 msg
= "bad HW address type";
683 msg
= "bad pathname (need leading '/')";
687 msg
= "unknown error";
690 report(LOG_ERR
, "in entry named \"%s\", symbol \"%s\": %s",
691 current_hostname
, current_tagname
, msg
);
698 * Macros for use in the function below:
701 /* Parse one INET address stored directly in MEMBER. */
702 #define PARSE_IA1(MEMBER) do \
704 if (optype == OP_BOOLEAN) \
705 return E_SYNTAX_ERROR; \
706 hp->flags.MEMBER = FALSE; \
707 if (optype == OP_ADDITION) { \
708 if (prs_inetaddr(symbol, &value) < 0) \
709 return E_BAD_IPADDR; \
710 hp->MEMBER.s_addr = value; \
711 hp->flags.MEMBER = TRUE; \
715 /* Parse a list of INET addresses pointed to by MEMBER */
716 #define PARSE_IAL(MEMBER) do \
718 if (optype == OP_BOOLEAN) \
719 return E_SYNTAX_ERROR; \
720 if (hp->flags.MEMBER) { \
721 hp->flags.MEMBER = FALSE; \
722 assert(hp->MEMBER); \
723 del_iplist(hp->MEMBER); \
726 if (optype == OP_ADDITION) { \
727 hp->MEMBER = get_addresses(symbol); \
728 if (hp->MEMBER == NULL) \
729 return E_SYNTAX_ERROR; \
730 hp->flags.MEMBER = TRUE; \
734 /* Parse a shared string pointed to by MEMBER */
735 #define PARSE_STR(MEMBER) do \
737 if (optype == OP_BOOLEAN) \
738 return E_SYNTAX_ERROR; \
739 if (hp->flags.MEMBER) { \
740 hp->flags.MEMBER = FALSE; \
741 assert(hp->MEMBER); \
742 del_string(hp->MEMBER); \
745 if (optype == OP_ADDITION) { \
746 hp->MEMBER = get_shared_string(symbol); \
747 if (hp->MEMBER == NULL) \
748 return E_SYNTAX_ERROR; \
749 hp->flags.MEMBER = TRUE; \
753 /* Parse an integer value for MEMBER */
754 #define PARSE_INT(MEMBER) do \
756 if (optype == OP_BOOLEAN) \
757 return E_SYNTAX_ERROR; \
758 hp->flags.MEMBER = FALSE; \
759 if (optype == OP_ADDITION) { \
760 value = get_u_long(symbol); \
761 hp->MEMBER = value; \
762 hp->flags.MEMBER = TRUE; \
767 * Evaluate the two-character tag symbol pointed to by "symbol" and place
768 * the data in the structure pointed to by "hp". The pointer pointed to
769 * by "symbol" is updated to point past the source string (but may not
770 * point to the next tag entry).
772 * Obviously, this need a few more comments. . . .
775 eval_symbol(char **symbol
, struct host
*hp
)
777 char tmpstr
[MAXSTRINGLEN
];
779 struct symbolmap
*symbolptr
;
784 int optype
; /* Indicates boolean, addition, or deletion */
786 eat_whitespace(symbol
);
788 /* Make sure this is set before returning. */
789 current_tagname
[0] = (*symbol
)[0];
790 current_tagname
[1] = (*symbol
)[1];
791 current_tagname
[2] = 0;
793 if ((*symbol
)[0] == '\0') {
794 return E_END_OF_ENTRY
;
796 if ((*symbol
)[0] == ':') {
799 if ((*symbol
)[0] == 'T') { /* generic symbol */
801 value
= get_u_long(symbol
);
802 snprintf(current_tagname
, sizeof(current_tagname
),
804 eat_whitespace(symbol
);
805 if ((*symbol
)[0] != '=') {
806 return E_SYNTAX_ERROR
;
809 if (!(hp
->generic
)) {
810 hp
->generic
= (struct shared_bindata
*)
811 smalloc(sizeof(struct shared_bindata
));
813 if (process_generic(symbol
, &(hp
->generic
), (byte
) (value
& 0xFF)))
814 return E_SYNTAX_ERROR
;
815 hp
->flags
.generic
= TRUE
;
819 * Determine the type of operation to be done on this symbol
821 switch ((*symbol
)[2]) {
823 optype
= OP_ADDITION
;
826 optype
= OP_DELETION
;
833 return E_SYNTAX_ERROR
;
836 symbolptr
= symbol_list
;
837 numsymbols
= sizeof(symbol_list
) / sizeof(struct symbolmap
);
838 for (i
= 0; i
< numsymbols
; i
++) {
839 if (((symbolptr
->symbol
)[0] == (*symbol
)[0]) &&
840 ((symbolptr
->symbol
)[1] == (*symbol
)[1])) {
845 if (i
>= numsymbols
) {
846 return E_UNKNOWN_SYMBOL
;
849 * Skip past the = or @ character (to point to the data) if this
850 * isn't a boolean operation. For boolean operations, just skip
851 * over the two-character tag symbol (and nothing else. . . .).
853 (*symbol
) += (optype
== OP_BOOLEAN
) ? 2 : 3;
855 eat_whitespace(symbol
);
857 /* The cases below are in order by symbolcode value. */
858 switch (symbolptr
->symbolcode
) {
864 case SYM_COOKIE_SERVER
:
865 PARSE_IAL(cookie_server
);
868 case SYM_DOMAIN_SERVER
:
869 PARSE_IAL(domain_server
);
877 if (optype
== OP_BOOLEAN
)
878 return E_SYNTAX_ERROR
;
879 hp
->flags
.haddr
= FALSE
;
880 if (optype
== OP_ADDITION
) {
881 /* Default the HW type to Ethernet */
882 if (hp
->flags
.htype
== 0) {
883 hp
->flags
.htype
= TRUE
;
884 hp
->htype
= HTYPE_ETHERNET
;
886 tmphaddr
= prs_haddr(symbol
, hp
->htype
);
889 bcopy(tmphaddr
, hp
->haddr
, haddrlength(hp
->htype
));
890 hp
->flags
.haddr
= TRUE
;
899 if (optype
== OP_BOOLEAN
)
900 return E_SYNTAX_ERROR
;
901 hp
->flags
.htype
= FALSE
;
902 if (optype
== OP_ADDITION
) {
903 value
= 0L; /* Assume an illegal value */
904 eat_whitespace(symbol
);
905 if (isdigit((unsigned char)**symbol
)) {
906 value
= get_u_long(symbol
);
908 len
= sizeof(tmpstr
);
909 (void) get_string(symbol
, tmpstr
, &len
);
911 numsymbols
= sizeof(htnamemap
) /
912 sizeof(struct htypename
);
913 for (i
= 0; i
< numsymbols
; i
++) {
914 if (!strcmp(htnamemap
[i
].name
, tmpstr
)) {
918 if (i
< numsymbols
) {
919 value
= htnamemap
[i
].htype
;
922 if (value
>= hwinfocnt
) {
923 return E_BAD_HWATYPE
;
925 hp
->htype
= (byte
) (value
& 0xFF);
926 hp
->flags
.htype
= TRUE
;
930 case SYM_IMPRESS_SERVER
:
931 PARSE_IAL(impress_server
);
939 PARSE_IAL(log_server
);
943 PARSE_IAL(lpr_server
);
946 case SYM_NAME_SERVER
:
947 PARSE_IAL(name_server
);
951 PARSE_IAL(rlp_server
);
954 case SYM_SUBNET_MASK
:
955 PARSE_IA1(subnet_mask
);
958 case SYM_TIME_OFFSET
:
959 if (optype
== OP_BOOLEAN
)
960 return E_SYNTAX_ERROR
;
961 hp
->flags
.time_offset
= FALSE
;
962 if (optype
== OP_ADDITION
) {
963 len
= sizeof(tmpstr
);
964 (void) get_string(symbol
, tmpstr
, &len
);
965 if (!strncmp(tmpstr
, "auto", 4)) {
966 hp
->time_offset
= secondswest
;
968 if (sscanf(tmpstr
, "%d", <imeoff
) != 1)
969 return E_BAD_LONGWORD
;
970 hp
->time_offset
= ltimeoff
;
972 hp
->flags
.time_offset
= TRUE
;
976 case SYM_TIME_SERVER
:
977 PARSE_IAL(time_server
);
980 case SYM_VENDOR_MAGIC
:
981 if (optype
== OP_BOOLEAN
)
982 return E_SYNTAX_ERROR
;
983 hp
->flags
.vm_cookie
= FALSE
;
984 if (optype
== OP_ADDITION
) {
985 if (strncmp(*symbol
, "auto", 4)) {
986 /* The string is not "auto" */
987 if (!strncmp(*symbol
, "rfc", 3)) {
988 bcopy(vm_rfc1048
, hp
->vm_cookie
, 4);
989 } else if (!strncmp(*symbol
, "cmu", 3)) {
990 bcopy(vm_cmu
, hp
->vm_cookie
, 4);
992 if (!isdigit((unsigned char)**symbol
))
994 if (prs_inetaddr(symbol
, &value
) < 0)
996 bcopy(&value
, hp
->vm_cookie
, 4);
998 hp
->flags
.vm_cookie
= TRUE
;
1003 case SYM_SIMILAR_ENTRY
:
1006 fill_defaults(hp
, symbol
);
1009 return E_SYNTAX_ERROR
;
1013 case SYM_NAME_SWITCH
:
1016 return E_SYNTAX_ERROR
;
1018 hp
->flags
.send_name
= FALSE
;
1019 hp
->flags
.name_switch
= FALSE
;
1022 hp
->flags
.send_name
= TRUE
;
1023 hp
->flags
.name_switch
= TRUE
;
1031 if (!strncmp(*symbol
, "auto", 4)) {
1032 hp
->flags
.bootsize
= TRUE
;
1033 hp
->flags
.bootsize_auto
= TRUE
;
1035 hp
->bootsize
= (unsigned int) get_u_long(symbol
);
1036 hp
->flags
.bootsize
= TRUE
;
1037 hp
->flags
.bootsize_auto
= FALSE
;
1041 hp
->flags
.bootsize
= FALSE
;
1044 hp
->flags
.bootsize
= TRUE
;
1045 hp
->flags
.bootsize_auto
= TRUE
;
1050 case SYM_BOOT_SERVER
:
1051 PARSE_IA1(bootserver
);
1056 if ((hp
->tftpdir
!= NULL
) &&
1057 (hp
->tftpdir
->string
[0] != '/'))
1058 return E_BAD_PATHNAME
;
1062 PARSE_STR(dump_file
);
1065 case SYM_DOMAIN_NAME
:
1066 PARSE_STR(domain_name
);
1069 case SYM_SWAP_SERVER
:
1070 PARSE_IA1(swap_server
);
1074 PARSE_STR(root_path
);
1077 case SYM_EXTEN_FILE
:
1078 PARSE_STR(exten_file
);
1081 case SYM_REPLY_ADDR
:
1082 PARSE_IA1(reply_addr
);
1085 case SYM_NIS_DOMAIN
:
1086 PARSE_STR(nis_domain
);
1089 case SYM_NIS_SERVER
:
1090 PARSE_IAL(nis_server
);
1093 case SYM_NTP_SERVER
:
1094 PARSE_IAL(ntp_server
);
1097 #ifdef YORK_EX_OPTION
1099 PARSE_STR(exec_file
);
1104 PARSE_INT(msg_size
);
1105 if (hp
->msg_size
< BP_MINPKTSZ
||
1106 hp
->msg_size
> MAX_MSG_SIZE
)
1111 PARSE_INT(min_wait
);
1112 if (hp
->min_wait
== 0)
1116 /* XXX - Add new tags here */
1119 return E_UNKNOWN_SYMBOL
;
1121 } /* switch symbolcode */
1133 * Read a string from the buffer indirectly pointed to through "src" and
1134 * move it into the buffer pointed to by "dest". A pointer to the maximum
1135 * allowable length of the string (including null-terminator) is passed as
1136 * "length". The actual length of the string which was read is returned in
1137 * the unsigned integer pointed to by "length". This value is the same as
1138 * that which would be returned by applying the strlen() function on the
1139 * destination string (i.e the terminating null is not counted as a
1140 * character). Trailing whitespace is removed from the string. For
1141 * convenience, the function returns the new value of "dest".
1143 * The string is read until the maximum number of characters, an unquoted
1144 * colon (:), or a null character is read. The return string in "dest" is
1149 get_string(char **src
, char *dest
, unsigned int *length
)
1151 int n
, len
, quoteflag
;
1156 while ((n
< len
) && (**src
)) {
1157 if (!quoteflag
&& (**src
== ':')) {
1162 quoteflag
= !quoteflag
;
1165 if (**src
== '\\') {
1171 *dest
++ = *(*src
)++;
1176 * Remove that troublesome trailing whitespace. . .
1178 while ((n
> 0) && isspace((unsigned char)dest
[-1])) {
1191 * Read the string indirectly pointed to by "src", update the caller's
1192 * pointer, and return a pointer to a malloc'ed shared_string structure
1193 * containing the string.
1195 * The string is read using the same rules as get_string() above.
1198 PRIVATE
struct shared_string
*
1199 get_shared_string(char **src
)
1201 char retstring
[MAXSTRINGLEN
];
1202 struct shared_string
*s
;
1205 length
= sizeof(retstring
);
1206 (void) get_string(src
, retstring
, &length
);
1208 s
= (struct shared_string
*) smalloc(sizeof(struct shared_string
) +
1211 strlcpy(s
->string
, retstring
, sizeof(retstring
));
1219 * Load RFC1048 generic information directly into a memory buffer.
1221 * "src" indirectly points to the ASCII representation of the generic data.
1222 * "dest" points to a string structure which is updated to point to a new
1223 * string with the new data appended to the old string. The old string is
1226 * The given tag value is inserted with the new data.
1228 * The data may be represented as either a stream of hexadecimal numbers
1229 * representing bytes (any or all bytes may optionally start with '0x' and
1230 * be separated with periods ".") or as a quoted string of ASCII
1231 * characters (the quotes are required).
1235 process_generic(char **src
, struct shared_bindata
**dest
, u_int tagvalue
)
1237 byte tmpbuf
[MAXBUFLEN
];
1239 struct shared_bindata
*bdata
;
1240 u_int newlength
, oldlength
;
1243 *str
++ = (tagvalue
& 0xFF); /* Store tag value */
1244 str
++; /* Skip over length field */
1245 if ((*src
)[0] == '"') { /* ASCII data */
1246 newlength
= sizeof(tmpbuf
) - 2; /* Set maximum allowed length */
1247 (void) get_string(src
, (char *) str
, &newlength
);
1248 /* Do NOT include the terminating null. */
1249 } else { /* Numeric data */
1251 while (newlength
< sizeof(tmpbuf
) - 2) {
1252 if (interp_byte(src
, str
++) < 0)
1260 if ((*src
)[0] != ':')
1263 tmpbuf
[1] = (newlength
& 0xFF);
1264 oldlength
= ((*dest
)->length
);
1265 bdata
= (struct shared_bindata
*) smalloc(sizeof(struct shared_bindata
)
1266 + oldlength
+ newlength
+ 1);
1267 if (oldlength
> 0) {
1268 bcopy((*dest
)->data
, bdata
->data
, oldlength
);
1270 bcopy(tmpbuf
, bdata
->data
+ oldlength
, newlength
+ 2);
1271 bdata
->length
= oldlength
+ newlength
+ 2;
1272 bdata
->linkcount
= 1;
1281 * Verify that the given string makes sense as a hostname (according to
1282 * Appendix 1, page 29 of RFC882).
1284 * Return TRUE for good names, FALSE otherwise.
1288 goodname(char *hostname
)
1291 if (!isalpha((unsigned char)*hostname
++)) { /* First character must be a letter */
1294 while (isalnum((unsigned char)*hostname
) ||
1295 (*hostname
== '-') ||
1296 (*hostname
== '_') )
1298 hostname
++; /* Alphanumeric or a hyphen */
1300 if (!isalnum((unsigned char)hostname
[-1])) { /* Last must be alphanumeric */
1303 if (*hostname
== '\0') {/* Done? */
1306 } while (*hostname
++ == '.'); /* Dot, loop for next label */
1308 return FALSE
; /* If it's not a dot, lose */
1314 * Null compare function -- always returns FALSE so an element is always
1315 * inserted into a hash table (i.e. there is never a collision with an
1316 * existing element).
1320 nullcmp(hash_datum
*d1
, hash_datum
*d2
)
1327 * Function for comparing a string with the hostname field of a host
1332 nmcmp(hash_datum
*d1
, hash_datum
*d2
)
1334 char *name
= (char *) d1
; /* XXX - OK? */
1335 struct host
*hp
= (struct host
*) d2
;
1337 return !strcmp(name
, hp
->hostname
->string
);
1342 * Compare function to determine whether two hardware addresses are
1343 * equivalent. Returns TRUE if "host1" and "host2" are equivalent, FALSE
1346 * If the hardware addresses of "host1" and "host2" are identical, but
1347 * they are on different IP subnets, this function returns FALSE.
1349 * This function is used when inserting elements into the hardware address
1354 hwinscmp(hash_datum
*d1
, hash_datum
*d2
)
1356 struct host
*host1
= (struct host
*) d1
;
1357 struct host
*host2
= (struct host
*) d2
;
1359 if (host1
->htype
!= host2
->htype
) {
1362 if (bcmp(host1
->haddr
, host2
->haddr
, haddrlength(host1
->htype
))) {
1365 /* XXX - Is the subnet_mask field set yet? */
1366 if ((host1
->subnet_mask
.s_addr
) == (host2
->subnet_mask
.s_addr
)) {
1367 if (((host1
->iaddr
.s_addr
) & (host1
->subnet_mask
.s_addr
)) !=
1368 ((host2
->iaddr
.s_addr
) & (host2
->subnet_mask
.s_addr
)))
1378 * Macros for use in the function below:
1381 #define DUP_COPY(MEMBER) do \
1383 if (!hp->flags.MEMBER) { \
1384 if ((hp->flags.MEMBER = hp2->flags.MEMBER) != 0) { \
1385 hp->MEMBER = hp2->MEMBER; \
1390 #define DUP_LINK(MEMBER) do \
1392 if (!hp->flags.MEMBER) { \
1393 if ((hp->flags.MEMBER = hp2->flags.MEMBER) != 0) { \
1394 assert(hp2->MEMBER); \
1395 hp->MEMBER = hp2->MEMBER; \
1396 (hp->MEMBER->linkcount)++; \
1402 * Process the "similar entry" symbol.
1404 * The host specified as the value of the "tc" symbol is used as a template
1405 * for the current host entry. Symbol values not explicitly set in the
1406 * current host entry are inferred from the template entry.
1409 fill_defaults(struct host
*hp
, char **src
)
1411 unsigned int tlen
, hashcode
;
1413 char tstring
[MAXSTRINGLEN
];
1415 tlen
= sizeof(tstring
);
1416 (void) get_string(src
, tstring
, &tlen
);
1417 hashcode
= hash_HashFunction((u_char
*) tstring
, tlen
);
1418 hp2
= (struct host
*) hash_Lookup(nmhashtable
, hashcode
, nmcmp
, tstring
);
1421 report(LOG_ERR
, "can't find tc=\"%s\"", tstring
);
1425 DUP_LINK(cookie_server
);
1426 DUP_LINK(domain_server
);
1428 /* haddr not copied */
1432 DUP_LINK(impress_server
);
1433 /* iaddr not copied */
1434 DUP_LINK(log_server
);
1435 DUP_LINK(lpr_server
);
1436 DUP_LINK(name_server
);
1437 DUP_LINK(rlp_server
);
1439 DUP_COPY(subnet_mask
);
1440 DUP_COPY(time_offset
);
1441 DUP_LINK(time_server
);
1443 if (!hp
->flags
.vm_cookie
) {
1444 if ((hp
->flags
.vm_cookie
= hp2
->flags
.vm_cookie
)) {
1445 bcopy(hp2
->vm_cookie
, hp
->vm_cookie
, 4);
1448 if (!hp
->flags
.name_switch
) {
1449 if ((hp
->flags
.name_switch
= hp2
->flags
.name_switch
)) {
1450 hp
->flags
.send_name
= hp2
->flags
.send_name
;
1453 if (!hp
->flags
.bootsize
) {
1454 if ((hp
->flags
.bootsize
= hp2
->flags
.bootsize
)) {
1455 hp
->flags
.bootsize_auto
= hp2
->flags
.bootsize_auto
;
1456 hp
->bootsize
= hp2
->bootsize
;
1459 DUP_COPY(bootserver
);
1462 DUP_LINK(dump_file
);
1463 DUP_LINK(domain_name
);
1465 DUP_COPY(swap_server
);
1466 DUP_LINK(root_path
);
1467 DUP_LINK(exten_file
);
1469 DUP_COPY(reply_addr
);
1471 DUP_LINK(nis_domain
);
1472 DUP_LINK(nis_server
);
1473 DUP_LINK(ntp_server
);
1475 #ifdef YORK_EX_OPTION
1476 DUP_LINK(exec_file
);
1482 /* XXX - Add new tags here */
1493 * This function adjusts the caller's pointer to point just past the
1494 * first-encountered colon. If it runs into a null character, it leaves
1495 * the pointer pointing to it.
1504 while (*t
&& (*t
!= ':')) {
1517 * This function adjusts the caller's pointer to point to the first
1518 * non-whitespace character. If it runs into a null character, it leaves
1519 * the pointer pointing to it.
1523 eat_whitespace(char **s
)
1528 while (*t
&& isspace((unsigned char)*t
)) {
1537 * This function converts the given string to all lowercase.
1544 if (isupper((unsigned char)*s
)) {
1545 *s
= tolower((unsigned char)*s
);
1557 * In many of the functions which follow, a parameter such as "src" or
1558 * "symbol" is passed as a pointer to a pointer to something. This is
1559 * done for the purpose of letting the called function update the
1560 * caller's copy of the parameter (i.e. to effect call-by-reference
1561 * parameter passing). The value of the actual parameter is only used
1562 * to locate the real parameter of interest and then update this indirect
1565 * I'm sure somebody out there won't like this. . . .
1566 * (Yea, because it usually makes code slower... -gwr)
1573 * "src" points to a character pointer which points to an ASCII string of
1574 * whitespace-separated IP addresses. A pointer to an in_addr_list
1575 * structure containing the list of addresses is returned. NULL is
1576 * returned if no addresses were found at all. The pointer pointed to by
1577 * "src" is updated to point to the first non-address (illegal) character.
1580 PRIVATE
struct in_addr_list
*
1581 get_addresses(char **src
)
1583 struct in_addr tmpaddrlist
[MAXINADDRS
];
1584 struct in_addr
*address1
, *address2
;
1585 struct in_addr_list
*result
;
1586 unsigned addrcount
, totalsize
;
1588 address1
= tmpaddrlist
;
1589 for (addrcount
= 0; addrcount
< MAXINADDRS
; addrcount
++) {
1590 while (isspace((unsigned char)**src
) || (**src
== ',')) {
1593 if (!**src
) { /* Quit if nothing more */
1596 if (prs_inetaddr(src
, &(address1
->s_addr
)) < 0) {
1599 address1
++; /* Point to next address slot */
1601 if (addrcount
< 1) {
1604 totalsize
= sizeof(struct in_addr_list
)
1605 + (addrcount
- 1) * sizeof(struct in_addr
);
1606 result
= (struct in_addr_list
*) smalloc(totalsize
);
1607 result
->linkcount
= 1;
1608 result
->addrcount
= addrcount
;
1609 address1
= tmpaddrlist
;
1610 address2
= result
->addr
;
1611 for (; addrcount
> 0; addrcount
--) {
1612 address2
->s_addr
= address1
->s_addr
;
1623 * prs_inetaddr(src, result)
1625 * "src" is a value-result parameter; the pointer it points to is updated
1626 * to point to the next data position. "result" points to an unsigned long
1627 * in which an address is returned.
1629 * This function parses the IP address string in ASCII "dot notation" pointed
1630 * to by (*src) and places the result (in network byte order) in the unsigned
1631 * long pointed to by "result". For malformed addresses, -1 is returned,
1632 * (*src) points to the first illegal character, and the unsigned long pointed
1633 * to by "result" is unchanged. Successful calls return 0.
1637 prs_inetaddr(char **src
, u_int32
*result
)
1639 char tmpstr
[MAXSTRINGLEN
];
1641 u_int32 parts
[4], *pp
;
1645 #if 1 /* XXX - experimental */
1646 /* Leading alpha char causes IP addr lookup. */
1647 if (isalpha((unsigned char)**src
)) {
1648 /* Lookup IP address. */
1651 while ((isalnum((unsigned char)*s
) || (*s
== '.') ||
1652 (*s
== '-') || (*s
== '_') ) &&
1653 (t
< &tmpstr
[MAXSTRINGLEN
- 1]) )
1658 n
= lookup_ipa(tmpstr
, result
);
1660 report(LOG_ERR
, "can not get IP addr for %s", tmpstr
);
1666 * Parse an address in Internet format:
1668 * a.b.c (with c treated as 16-bits)
1669 * a.b (with b treated as 24 bits)
1673 /* If it's not a digit, return error. */
1674 if (!isdigit((unsigned char)**src
))
1676 *pp
++ = get_u_long(src
);
1678 if (pp
< (parts
+ 4)) {
1685 /* This is handled by the caller. */
1686 if (**src
&& !((unsigned char)isspace(**src
) || (**src
== ':'))) {
1692 * Construct the address according to
1693 * the number of parts specified.
1697 case 1: /* a -- 32 bits */
1700 case 2: /* a.b -- 8.24 bits */
1701 value
= (parts
[0] << 24) | (parts
[1] & 0xFFFFFF);
1703 case 3: /* a.b.c -- 8.8.16 bits */
1704 value
= (parts
[0] << 24) | ((parts
[1] & 0xFF) << 16) |
1705 (parts
[2] & 0xFFFF);
1707 case 4: /* a.b.c.d -- 8.8.8.8 bits */
1708 value
= (parts
[0] << 24) | ((parts
[1] & 0xFF) << 16) |
1709 ((parts
[2] & 0xFF) << 8) | (parts
[3] & 0xFF);
1714 *result
= htonl(value
);
1721 * "src" points to a pointer which in turn points to a hexadecimal ASCII
1722 * string. This string is interpreted as a hardware address and returned
1723 * as a pointer to the actual hardware address, represented as an array of
1726 * The ASCII string must have the proper number of digits for the specified
1727 * hardware type (e.g. twelve digits for a 48-bit Ethernet address).
1728 * Two-digit sequences (bytes) may be separated with periods (.) and/or
1729 * prefixed with '0x' for readability, but this is not required.
1731 * For bad addresses, the pointer which "src" points to is updated to point
1732 * to the start of the first two-digit sequence which was bad, and the
1733 * function returns a NULL pointer.
1737 prs_haddr(char **src
, u_int htype
)
1739 static byte haddr
[MAXHADDRLEN
];
1741 char tmpstr
[MAXSTRINGLEN
];
1746 hal
= haddrlength(htype
); /* Get length of this address type */
1748 report(LOG_ERR
, "Invalid addr type for HW addr parse");
1751 tmplen
= sizeof(tmpstr
);
1752 get_string(src
, tmpstr
, &tmplen
);
1755 #if 1 /* XXX - experimental */
1756 /* If it's a valid host name, try to lookup the HW address. */
1758 /* Lookup Hardware Address for hostname. */
1759 if ((hap
= lookup_hwa(p
, htype
)) != NULL
)
1760 return hap
; /* success */
1761 report(LOG_ERR
, "Add 0x prefix if hex value starts with A-F");
1762 /* OK, assume it must be numeric. */
1767 while (hap
< haddr
+ hal
) {
1768 if ((*p
== '.') || (*p
== ':'))
1770 if (interp_byte(&p
, hap
++) < 0) {
1780 * "src" is a pointer to a character pointer which in turn points to a
1781 * hexadecimal ASCII representation of a byte. This byte is read, the
1782 * character pointer is updated, and the result is deposited into the
1783 * byte pointed to by "retbyte".
1785 * The usual '0x' notation is allowed but not required. The number must be
1786 * a two digit hexadecimal number. If the number is invalid, "src" and
1787 * "retbyte" are left untouched and -1 is returned as the function value.
1788 * Successful calls return 0.
1792 interp_byte(char **src
, byte
*retbyte
)
1796 if ((*src
)[0] == '0' &&
1797 ((*src
)[1] == 'x' ||
1798 (*src
)[1] == 'X')) {
1799 (*src
) += 2; /* allow 0x for hex, but don't require it */
1801 if (!isxdigit((unsigned char)(*src
)[0]) || !isxdigit((unsigned char)(*src
)[1])) {
1804 if (sscanf(*src
, "%2x", &v
) != 1) {
1808 *retbyte
= (byte
) (v
& 0xFF);
1815 * The parameter "src" points to a character pointer which points to an
1816 * ASCII string representation of an unsigned number. The number is
1817 * returned as an unsigned long and the character pointer is updated to
1818 * point to the first illegal character.
1822 get_u_long(char **src
)
1824 u_int32 value
, base
;
1828 * Collect number up to first illegal character. Values are specified
1829 * as for C: 0x=hex, 0=octal, other=decimal.
1837 if (**src
== 'x' || **src
== 'X') {
1841 while ((c
= **src
)) {
1842 if (isdigit((unsigned char)c
)) {
1843 value
= (value
* base
) + (c
- '0');
1847 if (base
== 16 && isxdigit((unsigned char)c
)) {
1848 value
= (value
<< 4) + ((c
& ~32) + 10 - 'A');
1860 * Routines for deletion of data associated with the main data structure.
1865 * Frees the entire host data structure given. Does nothing if the passed
1870 free_host(hash_datum
*hmp
)
1872 struct host
*hostptr
= (struct host
*) hmp
;
1873 if (hostptr
== NULL
)
1875 assert(hostptr
->linkcount
> 0);
1876 if (--(hostptr
->linkcount
))
1877 return; /* Still has references */
1878 del_iplist(hostptr
->cookie_server
);
1879 del_iplist(hostptr
->domain_server
);
1880 del_iplist(hostptr
->gateway
);
1881 del_iplist(hostptr
->impress_server
);
1882 del_iplist(hostptr
->log_server
);
1883 del_iplist(hostptr
->lpr_server
);
1884 del_iplist(hostptr
->name_server
);
1885 del_iplist(hostptr
->rlp_server
);
1886 del_iplist(hostptr
->time_server
);
1887 del_iplist(hostptr
->nis_server
);
1888 del_iplist(hostptr
->ntp_server
);
1891 * XXX - Add new tags here
1892 * (if the value is an IP list)
1895 del_string(hostptr
->hostname
);
1896 del_string(hostptr
->homedir
);
1897 del_string(hostptr
->bootfile
);
1898 del_string(hostptr
->tftpdir
);
1899 del_string(hostptr
->root_path
);
1900 del_string(hostptr
->domain_name
);
1901 del_string(hostptr
->dump_file
);
1902 del_string(hostptr
->exten_file
);
1903 del_string(hostptr
->nis_domain
);
1905 #ifdef YORK_EX_OPTION
1906 del_string(hostptr
->exec_file
);
1910 * XXX - Add new tags here
1911 * (if it is a shared string)
1914 del_bindata(hostptr
->generic
);
1915 free((char *) hostptr
);
1921 * Decrements the linkcount on the given IP address data structure. If the
1922 * linkcount goes to zero, the memory associated with the data is freed.
1926 del_iplist(struct in_addr_list
*iplist
)
1929 if (!(--(iplist
->linkcount
))) {
1930 free((char *) iplist
);
1938 * Decrements the linkcount on a string data structure. If the count
1939 * goes to zero, the memory associated with the string is freed. Does
1940 * nothing if the passed pointer is NULL.
1944 del_string(struct shared_string
*stringptr
)
1947 if (!(--(stringptr
->linkcount
))) {
1948 free((char *) stringptr
);
1956 * Decrements the linkcount on a shared_bindata data structure. If the
1957 * count goes to zero, the memory associated with the data is freed. Does
1958 * nothing if the passed pointer is NULL.
1962 del_bindata(struct shared_bindata
*dataptr
)
1965 if (!(--(dataptr
->linkcount
))) {
1966 free((char *) dataptr
);
1974 /* smalloc() -- safe malloc()
1976 * Always returns a valid pointer (if it returns at all). The allocated
1977 * memory is initialized to all zeros. If malloc() returns an error, a
1978 * message is printed using the report() function and the program aborts
1979 * with a status of 1.
1983 smalloc(unsigned int nbytes
)
1987 retvalue
= malloc(nbytes
);
1989 report(LOG_ERR
, "malloc() failure -- exiting");
1992 bzero(retvalue
, nbytes
);
1998 * Compare function to determine whether two hardware addresses are
1999 * equivalent. Returns TRUE if "host1" and "host2" are equivalent, FALSE
2002 * This function is used when retrieving elements from the hardware address
2007 hwlookcmp(hash_datum
*d1
, hash_datum
*d2
)
2009 struct host
*host1
= (struct host
*) d1
;
2010 struct host
*host2
= (struct host
*) d2
;
2012 if (host1
->htype
!= host2
->htype
) {
2015 if (bcmp(host1
->haddr
, host2
->haddr
, haddrlength(host1
->htype
))) {
2023 * Compare function for doing IP address hash table lookup.
2027 iplookcmp(hash_datum
*d1
, hash_datum
*d2
)
2029 struct host
*host1
= (struct host
*) d1
;
2030 struct host
*host2
= (struct host
*) d2
;
2032 return (host1
->iaddr
.s_addr
== host2
->iaddr
.s_addr
);
2039 * c-argdecl-indent: 4
2040 * c-continued-statement-offset: 4
2041 * c-continued-brace-offset: -4
2042 * c-label-offset: -4