144099b7bSPaul Traina /************************************************************************
244099b7bSPaul Traina Copyright 1988, 1991 by Carnegie Mellon University
344099b7bSPaul Traina
444099b7bSPaul Traina All Rights Reserved
544099b7bSPaul Traina
644099b7bSPaul Traina Permission to use, copy, modify, and distribute this software and its
744099b7bSPaul Traina documentation for any purpose and without fee is hereby granted, provided
844099b7bSPaul Traina that the above copyright notice appear in all copies and that both that
944099b7bSPaul Traina copyright notice and this permission notice appear in supporting
1044099b7bSPaul Traina documentation, and that the name of Carnegie Mellon University not be used
1144099b7bSPaul Traina in advertising or publicity pertaining to distribution of the software
1244099b7bSPaul Traina without specific, written prior permission.
1344099b7bSPaul Traina
1444099b7bSPaul Traina CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
1544099b7bSPaul Traina SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
1644099b7bSPaul Traina IN NO EVENT SHALL CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
1744099b7bSPaul Traina DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
1844099b7bSPaul Traina PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
1944099b7bSPaul Traina ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
2044099b7bSPaul Traina SOFTWARE.
21148531efSWolfram Schneider
2244099b7bSPaul Traina ************************************************************************/
2344099b7bSPaul Traina
2444099b7bSPaul Traina /*
2544099b7bSPaul Traina * bootpd configuration file reading code.
2644099b7bSPaul Traina *
2744099b7bSPaul Traina * The routines in this file deal with reading, interpreting, and storing
2844099b7bSPaul Traina * the information found in the bootpd configuration file (usually
2944099b7bSPaul Traina * /etc/bootptab).
3044099b7bSPaul Traina */
3144099b7bSPaul Traina
3244099b7bSPaul Traina
3344099b7bSPaul Traina #include <sys/errno.h>
3444099b7bSPaul Traina #include <sys/types.h>
3544099b7bSPaul Traina #include <sys/stat.h>
3644099b7bSPaul Traina #include <sys/file.h>
3744099b7bSPaul Traina #include <sys/time.h>
3844099b7bSPaul Traina #include <netinet/in.h>
3944099b7bSPaul Traina
4044099b7bSPaul Traina #include <stdlib.h>
4144099b7bSPaul Traina #include <stdio.h>
4244099b7bSPaul Traina #include <string.h>
4344099b7bSPaul Traina #include <ctype.h>
4444099b7bSPaul Traina #include <assert.h>
4544099b7bSPaul Traina #include <syslog.h>
4644099b7bSPaul Traina
4744099b7bSPaul Traina #include "bootp.h"
4844099b7bSPaul Traina #include "hash.h"
4944099b7bSPaul Traina #include "hwaddr.h"
5044099b7bSPaul Traina #include "lookup.h"
5144099b7bSPaul Traina #include "readfile.h"
5244099b7bSPaul Traina #include "report.h"
5344099b7bSPaul Traina #include "tzone.h"
5444099b7bSPaul Traina #include "bootpd.h"
5544099b7bSPaul Traina
5644099b7bSPaul Traina #define HASHTABLESIZE 257 /* Hash table size (prime) */
5744099b7bSPaul Traina
5844099b7bSPaul Traina /* Non-standard hardware address type (see bootp.h) */
5944099b7bSPaul Traina #define HTYPE_DIRECT 0
6044099b7bSPaul Traina
6144099b7bSPaul Traina /* Error codes returned by eval_symbol: */
6244099b7bSPaul Traina #define SUCCESS 0
6344099b7bSPaul Traina #define E_END_OF_ENTRY (-1)
6444099b7bSPaul Traina #define E_SYNTAX_ERROR (-2)
6544099b7bSPaul Traina #define E_UNKNOWN_SYMBOL (-3)
6644099b7bSPaul Traina #define E_BAD_IPADDR (-4)
6744099b7bSPaul Traina #define E_BAD_HWADDR (-5)
6844099b7bSPaul Traina #define E_BAD_LONGWORD (-6)
6944099b7bSPaul Traina #define E_BAD_HWATYPE (-7)
7044099b7bSPaul Traina #define E_BAD_PATHNAME (-8)
7144099b7bSPaul Traina #define E_BAD_VALUE (-9)
7244099b7bSPaul Traina
7344099b7bSPaul Traina /* Tag idendities. */
7444099b7bSPaul Traina #define SYM_NULL 0
7544099b7bSPaul Traina #define SYM_BOOTFILE 1
7644099b7bSPaul Traina #define SYM_COOKIE_SERVER 2
7744099b7bSPaul Traina #define SYM_DOMAIN_SERVER 3
7844099b7bSPaul Traina #define SYM_GATEWAY 4
7944099b7bSPaul Traina #define SYM_HWADDR 5
8044099b7bSPaul Traina #define SYM_HOMEDIR 6
8144099b7bSPaul Traina #define SYM_HTYPE 7
8244099b7bSPaul Traina #define SYM_IMPRESS_SERVER 8
8344099b7bSPaul Traina #define SYM_IPADDR 9
8444099b7bSPaul Traina #define SYM_LOG_SERVER 10
8544099b7bSPaul Traina #define SYM_LPR_SERVER 11
8644099b7bSPaul Traina #define SYM_NAME_SERVER 12
8744099b7bSPaul Traina #define SYM_RLP_SERVER 13
8844099b7bSPaul Traina #define SYM_SUBNET_MASK 14
8944099b7bSPaul Traina #define SYM_TIME_OFFSET 15
9044099b7bSPaul Traina #define SYM_TIME_SERVER 16
9144099b7bSPaul Traina #define SYM_VENDOR_MAGIC 17
9244099b7bSPaul Traina #define SYM_SIMILAR_ENTRY 18
9344099b7bSPaul Traina #define SYM_NAME_SWITCH 19
9444099b7bSPaul Traina #define SYM_BOOTSIZE 20
9544099b7bSPaul Traina #define SYM_BOOT_SERVER 22
9644099b7bSPaul Traina #define SYM_TFTPDIR 23
9744099b7bSPaul Traina #define SYM_DUMP_FILE 24
9844099b7bSPaul Traina #define SYM_DOMAIN_NAME 25
9944099b7bSPaul Traina #define SYM_SWAP_SERVER 26
10044099b7bSPaul Traina #define SYM_ROOT_PATH 27
10144099b7bSPaul Traina #define SYM_EXTEN_FILE 28
10244099b7bSPaul Traina #define SYM_REPLY_ADDR 29
10344099b7bSPaul Traina #define SYM_NIS_DOMAIN 30 /* RFC 1533 */
10444099b7bSPaul Traina #define SYM_NIS_SERVER 31 /* RFC 1533 */
10544099b7bSPaul Traina #define SYM_NTP_SERVER 32 /* RFC 1533 */
10644099b7bSPaul Traina #define SYM_EXEC_FILE 33 /* YORK_EX_OPTION */
10744099b7bSPaul Traina #define SYM_MSG_SIZE 34
10844099b7bSPaul Traina #define SYM_MIN_WAIT 35
10944099b7bSPaul Traina /* XXX - Add new tags here */
11044099b7bSPaul Traina
11144099b7bSPaul Traina #define OP_ADDITION 1 /* Operations on tags */
11244099b7bSPaul Traina #define OP_DELETION 2
11344099b7bSPaul Traina #define OP_BOOLEAN 3
11444099b7bSPaul Traina
11544099b7bSPaul Traina #define MAXINADDRS 16 /* Max size of an IP address list */
11644099b7bSPaul Traina #define MAXBUFLEN 256 /* Max temp buffer space */
11744099b7bSPaul Traina #define MAXENTRYLEN 2048 /* Max size of an entire entry */
11844099b7bSPaul Traina
11944099b7bSPaul Traina
12044099b7bSPaul Traina
12144099b7bSPaul Traina /*
12244099b7bSPaul Traina * Structure used to map a configuration-file symbol (such as "ds") to a
12344099b7bSPaul Traina * unique integer.
12444099b7bSPaul Traina */
12544099b7bSPaul Traina
12644099b7bSPaul Traina struct symbolmap {
12744099b7bSPaul Traina char *symbol;
12844099b7bSPaul Traina int symbolcode;
12944099b7bSPaul Traina };
13044099b7bSPaul Traina
13144099b7bSPaul Traina
13244099b7bSPaul Traina struct htypename {
13344099b7bSPaul Traina char *name;
13444099b7bSPaul Traina byte htype;
13544099b7bSPaul Traina };
13644099b7bSPaul Traina
13744099b7bSPaul Traina
13844099b7bSPaul Traina PRIVATE int nhosts; /* Number of hosts (/w hw or IP address) */
13944099b7bSPaul Traina PRIVATE int nentries; /* Total number of entries */
14044099b7bSPaul Traina PRIVATE int32 modtime = 0; /* Last modification time of bootptab */
14144099b7bSPaul Traina PRIVATE char *current_hostname; /* Name of the current entry. */
14244099b7bSPaul Traina PRIVATE char current_tagname[8];
14344099b7bSPaul Traina
14444099b7bSPaul Traina /*
14544099b7bSPaul Traina * List of symbolic names used in the bootptab file. The order and actual
14644099b7bSPaul Traina * values of the symbol codes (SYM_. . .) are unimportant, but they must
14744099b7bSPaul Traina * all be unique.
14844099b7bSPaul Traina */
14944099b7bSPaul Traina
15044099b7bSPaul Traina PRIVATE struct symbolmap symbol_list[] = {
15144099b7bSPaul Traina {"bf", SYM_BOOTFILE},
15244099b7bSPaul Traina {"bs", SYM_BOOTSIZE},
15344099b7bSPaul Traina {"cs", SYM_COOKIE_SERVER},
15444099b7bSPaul Traina {"df", SYM_DUMP_FILE},
15544099b7bSPaul Traina {"dn", SYM_DOMAIN_NAME},
15644099b7bSPaul Traina {"ds", SYM_DOMAIN_SERVER},
15744099b7bSPaul Traina {"ef", SYM_EXTEN_FILE},
15844099b7bSPaul Traina {"ex", SYM_EXEC_FILE}, /* YORK_EX_OPTION */
15944099b7bSPaul Traina {"gw", SYM_GATEWAY},
16044099b7bSPaul Traina {"ha", SYM_HWADDR},
16144099b7bSPaul Traina {"hd", SYM_HOMEDIR},
16244099b7bSPaul Traina {"hn", SYM_NAME_SWITCH},
16344099b7bSPaul Traina {"ht", SYM_HTYPE},
16444099b7bSPaul Traina {"im", SYM_IMPRESS_SERVER},
16544099b7bSPaul Traina {"ip", SYM_IPADDR},
16644099b7bSPaul Traina {"lg", SYM_LOG_SERVER},
16744099b7bSPaul Traina {"lp", SYM_LPR_SERVER},
16844099b7bSPaul Traina {"ms", SYM_MSG_SIZE},
16944099b7bSPaul Traina {"mw", SYM_MIN_WAIT},
17044099b7bSPaul Traina {"ns", SYM_NAME_SERVER},
17144099b7bSPaul Traina {"nt", SYM_NTP_SERVER},
17244099b7bSPaul Traina {"ra", SYM_REPLY_ADDR},
17344099b7bSPaul Traina {"rl", SYM_RLP_SERVER},
17444099b7bSPaul Traina {"rp", SYM_ROOT_PATH},
17544099b7bSPaul Traina {"sa", SYM_BOOT_SERVER},
17644099b7bSPaul Traina {"sm", SYM_SUBNET_MASK},
17744099b7bSPaul Traina {"sw", SYM_SWAP_SERVER},
17844099b7bSPaul Traina {"tc", SYM_SIMILAR_ENTRY},
17944099b7bSPaul Traina {"td", SYM_TFTPDIR},
18044099b7bSPaul Traina {"to", SYM_TIME_OFFSET},
18144099b7bSPaul Traina {"ts", SYM_TIME_SERVER},
18244099b7bSPaul Traina {"vm", SYM_VENDOR_MAGIC},
18344099b7bSPaul Traina {"yd", SYM_NIS_DOMAIN},
18444099b7bSPaul Traina {"ys", SYM_NIS_SERVER},
18544099b7bSPaul Traina /* XXX - Add new tags here */
18644099b7bSPaul Traina };
18744099b7bSPaul Traina
18844099b7bSPaul Traina
18944099b7bSPaul Traina /*
19044099b7bSPaul Traina * List of symbolic names for hardware types. Name translates into
19144099b7bSPaul Traina * hardware type code listed with it. Names must begin with a letter
19244099b7bSPaul Traina * and must be all lowercase. This is searched linearly, so put
19344099b7bSPaul Traina * commonly-used entries near the beginning.
19444099b7bSPaul Traina */
19544099b7bSPaul Traina
19644099b7bSPaul Traina PRIVATE struct htypename htnamemap[] = {
19744099b7bSPaul Traina {"ethernet", HTYPE_ETHERNET},
19844099b7bSPaul Traina {"ethernet3", HTYPE_EXP_ETHERNET},
19944099b7bSPaul Traina {"ether", HTYPE_ETHERNET},
20044099b7bSPaul Traina {"ether3", HTYPE_EXP_ETHERNET},
20144099b7bSPaul Traina {"ieee802", HTYPE_IEEE802},
20244099b7bSPaul Traina {"tr", HTYPE_IEEE802},
20344099b7bSPaul Traina {"token-ring", HTYPE_IEEE802},
20444099b7bSPaul Traina {"pronet", HTYPE_PRONET},
20544099b7bSPaul Traina {"chaos", HTYPE_CHAOS},
20644099b7bSPaul Traina {"arcnet", HTYPE_ARCNET},
20744099b7bSPaul Traina {"ax.25", HTYPE_AX25},
20844099b7bSPaul Traina {"direct", HTYPE_DIRECT},
20944099b7bSPaul Traina {"serial", HTYPE_DIRECT},
21044099b7bSPaul Traina {"slip", HTYPE_DIRECT},
21144099b7bSPaul Traina {"ppp", HTYPE_DIRECT}
21244099b7bSPaul Traina };
21344099b7bSPaul Traina
21444099b7bSPaul Traina
21544099b7bSPaul Traina
21644099b7bSPaul Traina /*
21744099b7bSPaul Traina * Externals and forward declarations.
21844099b7bSPaul Traina */
21944099b7bSPaul Traina
220f19d047aSAlfred Perlstein boolean nmcmp(hash_datum *, hash_datum *);
22144099b7bSPaul Traina
22244099b7bSPaul Traina PRIVATE void
223f19d047aSAlfred Perlstein adjust(char **);
22444099b7bSPaul Traina PRIVATE void
225f19d047aSAlfred Perlstein del_string(struct shared_string *);
22644099b7bSPaul Traina PRIVATE void
227f19d047aSAlfred Perlstein del_bindata(struct shared_bindata *);
22844099b7bSPaul Traina PRIVATE void
229f19d047aSAlfred Perlstein del_iplist(struct in_addr_list *);
23044099b7bSPaul Traina PRIVATE void
231f19d047aSAlfred Perlstein eat_whitespace(char **);
23244099b7bSPaul Traina PRIVATE int
233f19d047aSAlfred Perlstein eval_symbol(char **, struct host *);
23444099b7bSPaul Traina PRIVATE void
235f19d047aSAlfred Perlstein fill_defaults(struct host *, char **);
23644099b7bSPaul Traina PRIVATE void
237f19d047aSAlfred Perlstein free_host(hash_datum *);
23844099b7bSPaul Traina PRIVATE struct in_addr_list *
239f19d047aSAlfred Perlstein get_addresses(char **);
24044099b7bSPaul Traina PRIVATE struct shared_string *
241f19d047aSAlfred Perlstein get_shared_string(char **);
24244099b7bSPaul Traina PRIVATE char *
243f19d047aSAlfred Perlstein get_string(char **, char *, u_int *);
24444099b7bSPaul Traina PRIVATE u_int32
245f19d047aSAlfred Perlstein get_u_long(char **);
24644099b7bSPaul Traina PRIVATE boolean
247f19d047aSAlfred Perlstein goodname(char *);
24844099b7bSPaul Traina PRIVATE boolean
249f19d047aSAlfred Perlstein hwinscmp(hash_datum *, hash_datum *);
25044099b7bSPaul Traina PRIVATE int
251f19d047aSAlfred Perlstein interp_byte(char **, byte *);
25244099b7bSPaul Traina PRIVATE void
253f19d047aSAlfred Perlstein makelower(char *);
25444099b7bSPaul Traina PRIVATE boolean
255f19d047aSAlfred Perlstein nullcmp(hash_datum *, hash_datum *);
25644099b7bSPaul Traina PRIVATE int
257f19d047aSAlfred Perlstein process_entry(struct host *, char *);
25844099b7bSPaul Traina PRIVATE int
259f19d047aSAlfred Perlstein process_generic(char **, struct shared_bindata **, u_int);
26044099b7bSPaul Traina PRIVATE byte *
261f19d047aSAlfred Perlstein prs_haddr(char **, u_int);
26244099b7bSPaul Traina PRIVATE int
263f19d047aSAlfred Perlstein prs_inetaddr(char **, u_int32 *);
26444099b7bSPaul Traina PRIVATE void
265f19d047aSAlfred Perlstein read_entry(FILE *, char *, u_int *);
26644099b7bSPaul Traina PRIVATE char *
267f19d047aSAlfred Perlstein smalloc(u_int);
26844099b7bSPaul Traina
26944099b7bSPaul Traina
27044099b7bSPaul Traina /*
27144099b7bSPaul Traina * Vendor magic cookies for CMU and RFC1048
27244099b7bSPaul Traina */
27344099b7bSPaul Traina u_char vm_cmu[4] = VM_CMU;
27444099b7bSPaul Traina u_char vm_rfc1048[4] = VM_RFC1048;
27544099b7bSPaul Traina
27644099b7bSPaul Traina /*
27744099b7bSPaul Traina * Main hash tables
27844099b7bSPaul Traina */
27944099b7bSPaul Traina hash_tbl *hwhashtable;
28044099b7bSPaul Traina hash_tbl *iphashtable;
28144099b7bSPaul Traina hash_tbl *nmhashtable;
28244099b7bSPaul Traina
28344099b7bSPaul Traina /*
28444099b7bSPaul Traina * Allocate hash tables for hardware address, ip address, and hostname
28544099b7bSPaul Traina * (shared by bootpd and bootpef)
28644099b7bSPaul Traina */
28744099b7bSPaul Traina void
rdtab_init(void)288*8b356c88SJohn Baldwin rdtab_init(void)
28944099b7bSPaul Traina {
29044099b7bSPaul Traina hwhashtable = hash_Init(HASHTABLESIZE);
29144099b7bSPaul Traina iphashtable = hash_Init(HASHTABLESIZE);
29244099b7bSPaul Traina nmhashtable = hash_Init(HASHTABLESIZE);
29344099b7bSPaul Traina if (!(hwhashtable && iphashtable && nmhashtable)) {
29444099b7bSPaul Traina report(LOG_ERR, "Unable to allocate hash tables.");
29544099b7bSPaul Traina exit(1);
29644099b7bSPaul Traina }
29744099b7bSPaul Traina }
29844099b7bSPaul Traina
29944099b7bSPaul Traina
30044099b7bSPaul Traina /*
30144099b7bSPaul Traina * Read bootptab database file. Avoid rereading the file if the
30244099b7bSPaul Traina * write date hasn't changed since the last time we read it.
30344099b7bSPaul Traina */
30444099b7bSPaul Traina
30544099b7bSPaul Traina void
readtab(int force)306*8b356c88SJohn Baldwin readtab(int force)
30744099b7bSPaul Traina {
30844099b7bSPaul Traina struct host *hp;
30944099b7bSPaul Traina FILE *fp;
31044099b7bSPaul Traina struct stat st;
31144099b7bSPaul Traina unsigned hashcode, buflen;
31244099b7bSPaul Traina static char buffer[MAXENTRYLEN];
31344099b7bSPaul Traina
31444099b7bSPaul Traina /*
31544099b7bSPaul Traina * Check the last modification time.
31644099b7bSPaul Traina */
31744099b7bSPaul Traina if (stat(bootptab, &st) < 0) {
31844099b7bSPaul Traina report(LOG_ERR, "stat on \"%s\": %s",
31944099b7bSPaul Traina bootptab, get_errmsg());
32044099b7bSPaul Traina return;
32144099b7bSPaul Traina }
32244099b7bSPaul Traina #ifdef DEBUG
32344099b7bSPaul Traina if (debug > 3) {
32444099b7bSPaul Traina char timestr[28];
32544099b7bSPaul Traina strcpy(timestr, ctime(&(st.st_mtime)));
32644099b7bSPaul Traina /* zap the newline */
32744099b7bSPaul Traina timestr[24] = '\0';
32844099b7bSPaul Traina report(LOG_INFO, "bootptab mtime: %s",
32944099b7bSPaul Traina timestr);
33044099b7bSPaul Traina }
33144099b7bSPaul Traina #endif
33244099b7bSPaul Traina if ((force == 0) &&
33344099b7bSPaul Traina (st.st_mtime == modtime) &&
33444099b7bSPaul Traina st.st_nlink) {
33544099b7bSPaul Traina /*
33644099b7bSPaul Traina * hasn't been modified or deleted yet.
33744099b7bSPaul Traina */
33844099b7bSPaul Traina return;
33944099b7bSPaul Traina }
34044099b7bSPaul Traina if (debug)
34144099b7bSPaul Traina report(LOG_INFO, "reading %s\"%s\"",
34244099b7bSPaul Traina (modtime != 0L) ? "new " : "",
34344099b7bSPaul Traina bootptab);
34444099b7bSPaul Traina
34544099b7bSPaul Traina /*
34644099b7bSPaul Traina * Open bootptab file.
34744099b7bSPaul Traina */
34844099b7bSPaul Traina if ((fp = fopen(bootptab, "r")) == NULL) {
34944099b7bSPaul Traina report(LOG_ERR, "error opening \"%s\": %s", bootptab, get_errmsg());
35044099b7bSPaul Traina return;
35144099b7bSPaul Traina }
35244099b7bSPaul Traina /*
35344099b7bSPaul Traina * Record file modification time.
35444099b7bSPaul Traina */
35544099b7bSPaul Traina if (fstat(fileno(fp), &st) < 0) {
35644099b7bSPaul Traina report(LOG_ERR, "fstat: %s", get_errmsg());
35744099b7bSPaul Traina fclose(fp);
35844099b7bSPaul Traina return;
35944099b7bSPaul Traina }
36044099b7bSPaul Traina modtime = st.st_mtime;
36144099b7bSPaul Traina
36244099b7bSPaul Traina /*
36344099b7bSPaul Traina * Entirely erase all hash tables.
36444099b7bSPaul Traina */
36544099b7bSPaul Traina hash_Reset(hwhashtable, free_host);
36644099b7bSPaul Traina hash_Reset(iphashtable, free_host);
36744099b7bSPaul Traina hash_Reset(nmhashtable, free_host);
36844099b7bSPaul Traina
36944099b7bSPaul Traina nhosts = 0;
37044099b7bSPaul Traina nentries = 0;
37144099b7bSPaul Traina while (TRUE) {
37244099b7bSPaul Traina buflen = sizeof(buffer);
37344099b7bSPaul Traina read_entry(fp, buffer, &buflen);
37444099b7bSPaul Traina if (buflen == 0) { /* More entries? */
37544099b7bSPaul Traina break;
37644099b7bSPaul Traina }
37744099b7bSPaul Traina hp = (struct host *) smalloc(sizeof(struct host));
37844099b7bSPaul Traina bzero((char *) hp, sizeof(*hp));
37944099b7bSPaul Traina /* the link count it zero */
38044099b7bSPaul Traina
38144099b7bSPaul Traina /*
38244099b7bSPaul Traina * Get individual info
38344099b7bSPaul Traina */
38444099b7bSPaul Traina if (process_entry(hp, buffer) < 0) {
38544099b7bSPaul Traina hp->linkcount = 1;
38644099b7bSPaul Traina free_host((hash_datum *) hp);
38744099b7bSPaul Traina continue;
38844099b7bSPaul Traina }
38944099b7bSPaul Traina /*
39044099b7bSPaul Traina * If this is not a dummy entry, and the IP or HW
39144099b7bSPaul Traina * address is not yet set, try to get them here.
39244099b7bSPaul Traina * Dummy entries have . as first char of name.
39344099b7bSPaul Traina */
39444099b7bSPaul Traina if (goodname(hp->hostname->string)) {
39544099b7bSPaul Traina char *hn = hp->hostname->string;
39644099b7bSPaul Traina u_int32 value;
39744099b7bSPaul Traina if (hp->flags.iaddr == 0) {
39844099b7bSPaul Traina if (lookup_ipa(hn, &value)) {
39944099b7bSPaul Traina report(LOG_ERR, "can not get IP addr for %s", hn);
40044099b7bSPaul Traina report(LOG_ERR, "(dummy names should start with '.')");
40144099b7bSPaul Traina } else {
40244099b7bSPaul Traina hp->iaddr.s_addr = value;
40344099b7bSPaul Traina hp->flags.iaddr = TRUE;
40444099b7bSPaul Traina }
40544099b7bSPaul Traina }
40644099b7bSPaul Traina /* Set default subnet mask. */
40744099b7bSPaul Traina if (hp->flags.subnet_mask == 0) {
40844099b7bSPaul Traina if (lookup_netmask(hp->iaddr.s_addr, &value)) {
40944099b7bSPaul Traina report(LOG_ERR, "can not get netmask for %s", hn);
41044099b7bSPaul Traina } else {
41144099b7bSPaul Traina hp->subnet_mask.s_addr = value;
41244099b7bSPaul Traina hp->flags.subnet_mask = TRUE;
41344099b7bSPaul Traina }
41444099b7bSPaul Traina }
41544099b7bSPaul Traina }
41644099b7bSPaul Traina if (hp->flags.iaddr) {
41744099b7bSPaul Traina nhosts++;
41844099b7bSPaul Traina }
4199a9048e1SPedro F. Giffuni /* Register by HW addr if known. */
42044099b7bSPaul Traina if (hp->flags.htype && hp->flags.haddr) {
42144099b7bSPaul Traina /* We will either insert it or free it. */
42244099b7bSPaul Traina hp->linkcount++;
42344099b7bSPaul Traina hashcode = hash_HashFunction(hp->haddr, haddrlength(hp->htype));
42444099b7bSPaul Traina if (hash_Insert(hwhashtable, hashcode, hwinscmp, hp, hp) < 0) {
42544099b7bSPaul Traina report(LOG_NOTICE, "duplicate %s address: %s",
42644099b7bSPaul Traina netname(hp->htype),
427e08ac58bSPaul Traina haddrtoa(hp->haddr, haddrlength(hp->htype)));
42844099b7bSPaul Traina free_host((hash_datum *) hp);
42944099b7bSPaul Traina continue;
43044099b7bSPaul Traina }
43144099b7bSPaul Traina }
4329a9048e1SPedro F. Giffuni /* Register by IP addr if known. */
43344099b7bSPaul Traina if (hp->flags.iaddr) {
43444099b7bSPaul Traina hashcode = hash_HashFunction((u_char *) & (hp->iaddr.s_addr), 4);
43544099b7bSPaul Traina if (hash_Insert(iphashtable, hashcode, nullcmp, hp, hp) < 0) {
43644099b7bSPaul Traina report(LOG_ERR,
43744099b7bSPaul Traina "hash_Insert() failed on IP address insertion");
43844099b7bSPaul Traina } else {
43944099b7bSPaul Traina /* Just inserted the host struct in a new hash list. */
44044099b7bSPaul Traina hp->linkcount++;
44144099b7bSPaul Traina }
44244099b7bSPaul Traina }
4439a9048e1SPedro F. Giffuni /* Register by Name (always known) */
44444099b7bSPaul Traina hashcode = hash_HashFunction((u_char *) hp->hostname->string,
44544099b7bSPaul Traina strlen(hp->hostname->string));
44644099b7bSPaul Traina if (hash_Insert(nmhashtable, hashcode, nullcmp,
44744099b7bSPaul Traina hp->hostname->string, hp) < 0) {
44844099b7bSPaul Traina report(LOG_ERR,
44944099b7bSPaul Traina "hash_Insert() failed on insertion of hostname: \"%s\"",
45044099b7bSPaul Traina hp->hostname->string);
45144099b7bSPaul Traina } else {
45244099b7bSPaul Traina /* Just inserted the host struct in a new hash list. */
45344099b7bSPaul Traina hp->linkcount++;
45444099b7bSPaul Traina }
45544099b7bSPaul Traina
45644099b7bSPaul Traina nentries++;
45744099b7bSPaul Traina }
45844099b7bSPaul Traina
45944099b7bSPaul Traina fclose(fp);
46044099b7bSPaul Traina if (debug)
46144099b7bSPaul Traina report(LOG_INFO, "read %d entries (%d hosts) from \"%s\"",
46244099b7bSPaul Traina nentries, nhosts, bootptab);
46344099b7bSPaul Traina return;
46444099b7bSPaul Traina }
46544099b7bSPaul Traina
46644099b7bSPaul Traina
46744099b7bSPaul Traina
46844099b7bSPaul Traina /*
46944099b7bSPaul Traina * Read an entire host entry from the file pointed to by "fp" and insert it
47044099b7bSPaul Traina * into the memory pointed to by "buffer". Leading whitespace and comments
47144099b7bSPaul Traina * starting with "#" are ignored (removed). Backslashes (\) always quote
4727c637968SJeroen Ruigrok van der Werven * the next character except that newlines preceded by a backslash cause
47344099b7bSPaul Traina * line-continuation onto the next line. The entry is terminated by a
4747c637968SJeroen Ruigrok van der Werven * newline character which is not preceded by a backslash. Sequences
47544099b7bSPaul Traina * surrounded by double quotes are taken literally (including newlines, but
47644099b7bSPaul Traina * not backslashes).
47744099b7bSPaul Traina *
47844099b7bSPaul Traina * The "bufsiz" parameter points to an unsigned int which specifies the
47944099b7bSPaul Traina * maximum permitted buffer size. Upon return, this value will be replaced
48044099b7bSPaul Traina * with the actual length of the entry (not including the null terminator).
48144099b7bSPaul Traina *
48244099b7bSPaul Traina * This code is a little scary. . . . I don't like using gotos in C
48344099b7bSPaul Traina * either, but I first wrote this as an FSM diagram and gotos seemed like
48444099b7bSPaul Traina * the easiest way to implement it. Maybe later I'll clean it up.
48544099b7bSPaul Traina */
48644099b7bSPaul Traina
48744099b7bSPaul Traina PRIVATE void
read_entry(FILE * fp,char * buffer,unsigned * bufsiz)488*8b356c88SJohn Baldwin read_entry(FILE *fp, char *buffer, unsigned *bufsiz)
48944099b7bSPaul Traina {
49044099b7bSPaul Traina int c, length;
49144099b7bSPaul Traina
49244099b7bSPaul Traina length = 0;
49344099b7bSPaul Traina
49444099b7bSPaul Traina /*
49544099b7bSPaul Traina * Eat whitespace, blank lines, and comment lines.
49644099b7bSPaul Traina */
49744099b7bSPaul Traina top:
49844099b7bSPaul Traina c = fgetc(fp);
49944099b7bSPaul Traina if (c < 0) {
50044099b7bSPaul Traina goto done; /* Exit if end-of-file */
50144099b7bSPaul Traina }
50244099b7bSPaul Traina if (isspace(c)) {
50344099b7bSPaul Traina goto top; /* Skip over whitespace */
50444099b7bSPaul Traina }
50544099b7bSPaul Traina if (c == '#') {
50644099b7bSPaul Traina while (TRUE) { /* Eat comments after # */
50744099b7bSPaul Traina c = fgetc(fp);
50844099b7bSPaul Traina if (c < 0) {
50944099b7bSPaul Traina goto done; /* Exit if end-of-file */
51044099b7bSPaul Traina }
51144099b7bSPaul Traina if (c == '\n') {
51244099b7bSPaul Traina goto top; /* Try to read the next line */
51344099b7bSPaul Traina }
51444099b7bSPaul Traina }
51544099b7bSPaul Traina }
51644099b7bSPaul Traina ungetc(c, fp); /* Other character, push it back to reprocess it */
51744099b7bSPaul Traina
51844099b7bSPaul Traina
51944099b7bSPaul Traina /*
52044099b7bSPaul Traina * Now we're actually reading a data entry. Get each character and
52144099b7bSPaul Traina * assemble it into the data buffer, processing special characters like
52244099b7bSPaul Traina * double quotes (") and backslashes (\).
52344099b7bSPaul Traina */
52444099b7bSPaul Traina
52544099b7bSPaul Traina mainloop:
52644099b7bSPaul Traina c = fgetc(fp);
52744099b7bSPaul Traina switch (c) {
52844099b7bSPaul Traina case EOF:
52944099b7bSPaul Traina case '\n':
53044099b7bSPaul Traina goto done; /* Exit on EOF or newline */
53144099b7bSPaul Traina case '\\':
53244099b7bSPaul Traina c = fgetc(fp); /* Backslash, read a new character */
53344099b7bSPaul Traina if (c < 0) {
53444099b7bSPaul Traina goto done; /* Exit on EOF */
53544099b7bSPaul Traina }
53644099b7bSPaul Traina *buffer++ = c; /* Store the literal character */
53744099b7bSPaul Traina length++;
53844099b7bSPaul Traina if (length < *bufsiz - 1) {
53944099b7bSPaul Traina goto mainloop;
54044099b7bSPaul Traina } else {
54144099b7bSPaul Traina goto done;
54244099b7bSPaul Traina }
54344099b7bSPaul Traina case '"':
54444099b7bSPaul Traina *buffer++ = '"'; /* Store double-quote */
54544099b7bSPaul Traina length++;
54644099b7bSPaul Traina if (length >= *bufsiz - 1) {
54744099b7bSPaul Traina goto done;
54844099b7bSPaul Traina }
54944099b7bSPaul Traina while (TRUE) { /* Special quote processing loop */
55044099b7bSPaul Traina c = fgetc(fp);
55144099b7bSPaul Traina switch (c) {
55244099b7bSPaul Traina case EOF:
55344099b7bSPaul Traina goto done; /* Exit on EOF . . . */
55444099b7bSPaul Traina case '"':
55544099b7bSPaul Traina *buffer++ = '"';/* Store matching quote */
55644099b7bSPaul Traina length++;
55744099b7bSPaul Traina if (length < *bufsiz - 1) {
55844099b7bSPaul Traina goto mainloop; /* And continue main loop */
55944099b7bSPaul Traina } else {
56044099b7bSPaul Traina goto done;
56144099b7bSPaul Traina }
56244099b7bSPaul Traina case '\\':
56344099b7bSPaul Traina if ((c = fgetc(fp)) < 0) { /* Backslash */
56444099b7bSPaul Traina goto done; /* EOF. . . .*/
5657fed38d0SPhilippe Charnier }
5667fed38d0SPhilippe Charnier /* FALLTHROUGH */
56744099b7bSPaul Traina default:
56844099b7bSPaul Traina *buffer++ = c; /* Other character, store it */
56944099b7bSPaul Traina length++;
57044099b7bSPaul Traina if (length >= *bufsiz - 1) {
57144099b7bSPaul Traina goto done;
57244099b7bSPaul Traina }
57344099b7bSPaul Traina }
57444099b7bSPaul Traina }
57544099b7bSPaul Traina case ':':
57644099b7bSPaul Traina *buffer++ = c; /* Store colons */
57744099b7bSPaul Traina length++;
57844099b7bSPaul Traina if (length >= *bufsiz - 1) {
57944099b7bSPaul Traina goto done;
58044099b7bSPaul Traina }
58144099b7bSPaul Traina do { /* But remove whitespace after them */
58244099b7bSPaul Traina c = fgetc(fp);
58344099b7bSPaul Traina if ((c < 0) || (c == '\n')) {
58444099b7bSPaul Traina goto done;
58544099b7bSPaul Traina }
58644099b7bSPaul Traina } while (isspace(c)); /* Skip whitespace */
58744099b7bSPaul Traina
58844099b7bSPaul Traina if (c == '\\') { /* Backslash quotes next character */
58944099b7bSPaul Traina c = fgetc(fp);
59044099b7bSPaul Traina if (c < 0) {
59144099b7bSPaul Traina goto done;
59244099b7bSPaul Traina }
59344099b7bSPaul Traina if (c == '\n') {
59444099b7bSPaul Traina goto top; /* Backslash-newline continuation */
59544099b7bSPaul Traina }
59644099b7bSPaul Traina }
5977fed38d0SPhilippe Charnier /* FALLTHROUGH if "other" character */
59844099b7bSPaul Traina default:
59944099b7bSPaul Traina *buffer++ = c; /* Store other characters */
60044099b7bSPaul Traina length++;
60144099b7bSPaul Traina if (length >= *bufsiz - 1) {
60244099b7bSPaul Traina goto done;
60344099b7bSPaul Traina }
60444099b7bSPaul Traina }
60544099b7bSPaul Traina goto mainloop; /* Keep going */
60644099b7bSPaul Traina
60744099b7bSPaul Traina done:
60844099b7bSPaul Traina *buffer = '\0'; /* Terminate string */
60944099b7bSPaul Traina *bufsiz = length; /* Tell the caller its length */
61044099b7bSPaul Traina }
61144099b7bSPaul Traina
61244099b7bSPaul Traina
61344099b7bSPaul Traina
61444099b7bSPaul Traina /*
61544099b7bSPaul Traina * Parse out all the various tags and parameters in the host entry pointed
61644099b7bSPaul Traina * to by "src". Stuff all the data into the appropriate fields of the
61744099b7bSPaul Traina * host structure pointed to by "host". If there is any problem with the
61844099b7bSPaul Traina * entry, an error message is reported via report(), no further processing
61944099b7bSPaul Traina * is done, and -1 is returned. Successful calls return 0.
62044099b7bSPaul Traina *
62144099b7bSPaul Traina * (Some errors probably shouldn't be so completely fatal. . . .)
62244099b7bSPaul Traina */
62344099b7bSPaul Traina
62444099b7bSPaul Traina PRIVATE int
process_entry(struct host * host,char * src)625*8b356c88SJohn Baldwin process_entry(struct host *host, char *src)
62644099b7bSPaul Traina {
62744099b7bSPaul Traina int retval;
62844099b7bSPaul Traina char *msg;
62944099b7bSPaul Traina
63044099b7bSPaul Traina if (!host || *src == '\0') {
63144099b7bSPaul Traina return -1;
63244099b7bSPaul Traina }
63344099b7bSPaul Traina host->hostname = get_shared_string(&src);
63444099b7bSPaul Traina #if 0
63544099b7bSPaul Traina /* Be more liberal for the benefit of dummy tag names. */
63644099b7bSPaul Traina if (!goodname(host->hostname->string)) {
63744099b7bSPaul Traina report(LOG_ERR, "bad hostname: \"%s\"", host->hostname->string);
63844099b7bSPaul Traina del_string(host->hostname);
63944099b7bSPaul Traina return -1;
64044099b7bSPaul Traina }
64144099b7bSPaul Traina #endif
64244099b7bSPaul Traina current_hostname = host->hostname->string;
64344099b7bSPaul Traina adjust(&src);
64444099b7bSPaul Traina while (TRUE) {
64544099b7bSPaul Traina retval = eval_symbol(&src, host);
64644099b7bSPaul Traina if (retval == SUCCESS) {
64744099b7bSPaul Traina adjust(&src);
64844099b7bSPaul Traina continue;
64944099b7bSPaul Traina }
65044099b7bSPaul Traina if (retval == E_END_OF_ENTRY) {
65144099b7bSPaul Traina /* The default subnet mask is set in readtab() */
65244099b7bSPaul Traina return 0;
65344099b7bSPaul Traina }
65444099b7bSPaul Traina /* Some kind of error. */
65544099b7bSPaul Traina switch (retval) {
65644099b7bSPaul Traina case E_SYNTAX_ERROR:
65744099b7bSPaul Traina msg = "bad syntax";
65844099b7bSPaul Traina break;
65944099b7bSPaul Traina case E_UNKNOWN_SYMBOL:
66044099b7bSPaul Traina msg = "unknown symbol";
66144099b7bSPaul Traina break;
66244099b7bSPaul Traina case E_BAD_IPADDR:
66344099b7bSPaul Traina msg = "bad INET address";
66444099b7bSPaul Traina break;
66544099b7bSPaul Traina case E_BAD_HWADDR:
66644099b7bSPaul Traina msg = "bad hardware address";
66744099b7bSPaul Traina break;
66844099b7bSPaul Traina case E_BAD_LONGWORD:
66944099b7bSPaul Traina msg = "bad longword value";
67044099b7bSPaul Traina break;
67144099b7bSPaul Traina case E_BAD_HWATYPE:
67244099b7bSPaul Traina msg = "bad HW address type";
67344099b7bSPaul Traina break;
67444099b7bSPaul Traina case E_BAD_PATHNAME:
67544099b7bSPaul Traina msg = "bad pathname (need leading '/')";
676c2c0f195SIan Dowse break;
67744099b7bSPaul Traina case E_BAD_VALUE:
67844099b7bSPaul Traina msg = "bad value";
679c2c0f195SIan Dowse break;
68044099b7bSPaul Traina default:
681c2c0f195SIan Dowse msg = "unknown error";
68244099b7bSPaul Traina break;
68344099b7bSPaul Traina } /* switch */
68444099b7bSPaul Traina report(LOG_ERR, "in entry named \"%s\", symbol \"%s\": %s",
68544099b7bSPaul Traina current_hostname, current_tagname, msg);
68644099b7bSPaul Traina return -1;
68744099b7bSPaul Traina }
68844099b7bSPaul Traina }
68944099b7bSPaul Traina
69044099b7bSPaul Traina
69144099b7bSPaul Traina /*
69244099b7bSPaul Traina * Macros for use in the function below:
69344099b7bSPaul Traina */
69444099b7bSPaul Traina
69544099b7bSPaul Traina /* Parse one INET address stored directly in MEMBER. */
69644099b7bSPaul Traina #define PARSE_IA1(MEMBER) do \
69744099b7bSPaul Traina { \
69844099b7bSPaul Traina if (optype == OP_BOOLEAN) \
69944099b7bSPaul Traina return E_SYNTAX_ERROR; \
70044099b7bSPaul Traina hp->flags.MEMBER = FALSE; \
70144099b7bSPaul Traina if (optype == OP_ADDITION) { \
70244099b7bSPaul Traina if (prs_inetaddr(symbol, &value) < 0) \
70344099b7bSPaul Traina return E_BAD_IPADDR; \
70444099b7bSPaul Traina hp->MEMBER.s_addr = value; \
70544099b7bSPaul Traina hp->flags.MEMBER = TRUE; \
70644099b7bSPaul Traina } \
70744099b7bSPaul Traina } while (0)
70844099b7bSPaul Traina
70944099b7bSPaul Traina /* Parse a list of INET addresses pointed to by MEMBER */
71044099b7bSPaul Traina #define PARSE_IAL(MEMBER) do \
71144099b7bSPaul Traina { \
71244099b7bSPaul Traina if (optype == OP_BOOLEAN) \
71344099b7bSPaul Traina return E_SYNTAX_ERROR; \
71444099b7bSPaul Traina if (hp->flags.MEMBER) { \
71544099b7bSPaul Traina hp->flags.MEMBER = FALSE; \
71644099b7bSPaul Traina assert(hp->MEMBER); \
71744099b7bSPaul Traina del_iplist(hp->MEMBER); \
71844099b7bSPaul Traina hp->MEMBER = NULL; \
71944099b7bSPaul Traina } \
72044099b7bSPaul Traina if (optype == OP_ADDITION) { \
72144099b7bSPaul Traina hp->MEMBER = get_addresses(symbol); \
72244099b7bSPaul Traina if (hp->MEMBER == NULL) \
72344099b7bSPaul Traina return E_SYNTAX_ERROR; \
72444099b7bSPaul Traina hp->flags.MEMBER = TRUE; \
72544099b7bSPaul Traina } \
72644099b7bSPaul Traina } while (0)
72744099b7bSPaul Traina
72844099b7bSPaul Traina /* Parse a shared string pointed to by MEMBER */
72944099b7bSPaul Traina #define PARSE_STR(MEMBER) do \
73044099b7bSPaul Traina { \
73144099b7bSPaul Traina if (optype == OP_BOOLEAN) \
73244099b7bSPaul Traina return E_SYNTAX_ERROR; \
73344099b7bSPaul Traina if (hp->flags.MEMBER) { \
73444099b7bSPaul Traina hp->flags.MEMBER = FALSE; \
73544099b7bSPaul Traina assert(hp->MEMBER); \
73644099b7bSPaul Traina del_string(hp->MEMBER); \
73744099b7bSPaul Traina hp->MEMBER = NULL; \
73844099b7bSPaul Traina } \
73944099b7bSPaul Traina if (optype == OP_ADDITION) { \
74044099b7bSPaul Traina hp->MEMBER = get_shared_string(symbol); \
74144099b7bSPaul Traina if (hp->MEMBER == NULL) \
74244099b7bSPaul Traina return E_SYNTAX_ERROR; \
74344099b7bSPaul Traina hp->flags.MEMBER = TRUE; \
74444099b7bSPaul Traina } \
74544099b7bSPaul Traina } while (0)
74644099b7bSPaul Traina
747e08ac58bSPaul Traina /* Parse an unsigned integer value for MEMBER */
748e08ac58bSPaul Traina #define PARSE_UINT(MEMBER) do \
74944099b7bSPaul Traina { \
75044099b7bSPaul Traina if (optype == OP_BOOLEAN) \
75144099b7bSPaul Traina return E_SYNTAX_ERROR; \
75244099b7bSPaul Traina hp->flags.MEMBER = FALSE; \
75344099b7bSPaul Traina if (optype == OP_ADDITION) { \
75444099b7bSPaul Traina value = get_u_long(symbol); \
75544099b7bSPaul Traina hp->MEMBER = value; \
75644099b7bSPaul Traina hp->flags.MEMBER = TRUE; \
75744099b7bSPaul Traina } \
75844099b7bSPaul Traina } while (0)
75944099b7bSPaul Traina
76044099b7bSPaul Traina /*
76144099b7bSPaul Traina * Evaluate the two-character tag symbol pointed to by "symbol" and place
76244099b7bSPaul Traina * the data in the structure pointed to by "hp". The pointer pointed to
76344099b7bSPaul Traina * by "symbol" is updated to point past the source string (but may not
76444099b7bSPaul Traina * point to the next tag entry).
76544099b7bSPaul Traina *
76644099b7bSPaul Traina * Obviously, this need a few more comments. . . .
76744099b7bSPaul Traina */
76844099b7bSPaul Traina PRIVATE int
eval_symbol(char ** symbol,struct host * hp)769*8b356c88SJohn Baldwin eval_symbol(char **symbol, struct host *hp)
77044099b7bSPaul Traina {
77144099b7bSPaul Traina char tmpstr[MAXSTRINGLEN];
77244099b7bSPaul Traina byte *tmphaddr;
77344099b7bSPaul Traina struct symbolmap *symbolptr;
77444099b7bSPaul Traina u_int32 value;
77544099b7bSPaul Traina int32 timeoff;
77644099b7bSPaul Traina int i, numsymbols;
77744099b7bSPaul Traina unsigned len;
77844099b7bSPaul Traina int optype; /* Indicates boolean, addition, or deletion */
77944099b7bSPaul Traina
78044099b7bSPaul Traina eat_whitespace(symbol);
78144099b7bSPaul Traina
78244099b7bSPaul Traina /* Make sure this is set before returning. */
78344099b7bSPaul Traina current_tagname[0] = (*symbol)[0];
78444099b7bSPaul Traina current_tagname[1] = (*symbol)[1];
78544099b7bSPaul Traina current_tagname[2] = 0;
78644099b7bSPaul Traina
78744099b7bSPaul Traina if ((*symbol)[0] == '\0') {
78844099b7bSPaul Traina return E_END_OF_ENTRY;
78944099b7bSPaul Traina }
79044099b7bSPaul Traina if ((*symbol)[0] == ':') {
79144099b7bSPaul Traina return SUCCESS;
79244099b7bSPaul Traina }
79344099b7bSPaul Traina if ((*symbol)[0] == 'T') { /* generic symbol */
79444099b7bSPaul Traina (*symbol)++;
79544099b7bSPaul Traina value = get_u_long(symbol);
7969bc34f7cSWarner Losh snprintf(current_tagname, sizeof(current_tagname),
7979bc34f7cSWarner Losh "T%d", (int)value);
79844099b7bSPaul Traina eat_whitespace(symbol);
79944099b7bSPaul Traina if ((*symbol)[0] != '=') {
80044099b7bSPaul Traina return E_SYNTAX_ERROR;
80144099b7bSPaul Traina }
80244099b7bSPaul Traina (*symbol)++;
80344099b7bSPaul Traina if (!(hp->generic)) {
80444099b7bSPaul Traina hp->generic = (struct shared_bindata *)
80544099b7bSPaul Traina smalloc(sizeof(struct shared_bindata));
80644099b7bSPaul Traina }
80744099b7bSPaul Traina if (process_generic(symbol, &(hp->generic), (byte) (value & 0xFF)))
80844099b7bSPaul Traina return E_SYNTAX_ERROR;
80944099b7bSPaul Traina hp->flags.generic = TRUE;
81044099b7bSPaul Traina return SUCCESS;
81144099b7bSPaul Traina }
81244099b7bSPaul Traina /*
81344099b7bSPaul Traina * Determine the type of operation to be done on this symbol
81444099b7bSPaul Traina */
81544099b7bSPaul Traina switch ((*symbol)[2]) {
81644099b7bSPaul Traina case '=':
81744099b7bSPaul Traina optype = OP_ADDITION;
81844099b7bSPaul Traina break;
81944099b7bSPaul Traina case '@':
82044099b7bSPaul Traina optype = OP_DELETION;
82144099b7bSPaul Traina break;
82244099b7bSPaul Traina case ':':
82344099b7bSPaul Traina case '\0':
82444099b7bSPaul Traina optype = OP_BOOLEAN;
82544099b7bSPaul Traina break;
82644099b7bSPaul Traina default:
82744099b7bSPaul Traina return E_SYNTAX_ERROR;
82844099b7bSPaul Traina }
82944099b7bSPaul Traina
83044099b7bSPaul Traina symbolptr = symbol_list;
83144099b7bSPaul Traina numsymbols = sizeof(symbol_list) / sizeof(struct symbolmap);
83244099b7bSPaul Traina for (i = 0; i < numsymbols; i++) {
83344099b7bSPaul Traina if (((symbolptr->symbol)[0] == (*symbol)[0]) &&
83444099b7bSPaul Traina ((symbolptr->symbol)[1] == (*symbol)[1])) {
83544099b7bSPaul Traina break;
83644099b7bSPaul Traina }
83744099b7bSPaul Traina symbolptr++;
83844099b7bSPaul Traina }
83944099b7bSPaul Traina if (i >= numsymbols) {
84044099b7bSPaul Traina return E_UNKNOWN_SYMBOL;
84144099b7bSPaul Traina }
84244099b7bSPaul Traina /*
84344099b7bSPaul Traina * Skip past the = or @ character (to point to the data) if this
84444099b7bSPaul Traina * isn't a boolean operation. For boolean operations, just skip
84544099b7bSPaul Traina * over the two-character tag symbol (and nothing else. . . .).
84644099b7bSPaul Traina */
84744099b7bSPaul Traina (*symbol) += (optype == OP_BOOLEAN) ? 2 : 3;
84844099b7bSPaul Traina
84944099b7bSPaul Traina eat_whitespace(symbol);
85044099b7bSPaul Traina
85144099b7bSPaul Traina /* The cases below are in order by symbolcode value. */
85244099b7bSPaul Traina switch (symbolptr->symbolcode) {
85344099b7bSPaul Traina
85444099b7bSPaul Traina case SYM_BOOTFILE:
85544099b7bSPaul Traina PARSE_STR(bootfile);
85644099b7bSPaul Traina break;
85744099b7bSPaul Traina
85844099b7bSPaul Traina case SYM_COOKIE_SERVER:
85944099b7bSPaul Traina PARSE_IAL(cookie_server);
86044099b7bSPaul Traina break;
86144099b7bSPaul Traina
86244099b7bSPaul Traina case SYM_DOMAIN_SERVER:
86344099b7bSPaul Traina PARSE_IAL(domain_server);
86444099b7bSPaul Traina break;
86544099b7bSPaul Traina
86644099b7bSPaul Traina case SYM_GATEWAY:
86744099b7bSPaul Traina PARSE_IAL(gateway);
86844099b7bSPaul Traina break;
86944099b7bSPaul Traina
87044099b7bSPaul Traina case SYM_HWADDR:
87144099b7bSPaul Traina if (optype == OP_BOOLEAN)
87244099b7bSPaul Traina return E_SYNTAX_ERROR;
87344099b7bSPaul Traina hp->flags.haddr = FALSE;
87444099b7bSPaul Traina if (optype == OP_ADDITION) {
87544099b7bSPaul Traina /* Default the HW type to Ethernet */
87644099b7bSPaul Traina if (hp->flags.htype == 0) {
87744099b7bSPaul Traina hp->flags.htype = TRUE;
87844099b7bSPaul Traina hp->htype = HTYPE_ETHERNET;
87944099b7bSPaul Traina }
88044099b7bSPaul Traina tmphaddr = prs_haddr(symbol, hp->htype);
88144099b7bSPaul Traina if (!tmphaddr)
88244099b7bSPaul Traina return E_BAD_HWADDR;
88344099b7bSPaul Traina bcopy(tmphaddr, hp->haddr, haddrlength(hp->htype));
88444099b7bSPaul Traina hp->flags.haddr = TRUE;
88544099b7bSPaul Traina }
88644099b7bSPaul Traina break;
88744099b7bSPaul Traina
88844099b7bSPaul Traina case SYM_HOMEDIR:
88944099b7bSPaul Traina PARSE_STR(homedir);
89044099b7bSPaul Traina break;
89144099b7bSPaul Traina
89244099b7bSPaul Traina case SYM_HTYPE:
89344099b7bSPaul Traina if (optype == OP_BOOLEAN)
89444099b7bSPaul Traina return E_SYNTAX_ERROR;
89544099b7bSPaul Traina hp->flags.htype = FALSE;
89644099b7bSPaul Traina if (optype == OP_ADDITION) {
89744099b7bSPaul Traina value = 0L; /* Assume an illegal value */
89844099b7bSPaul Traina eat_whitespace(symbol);
89944099b7bSPaul Traina if (isdigit(**symbol)) {
90044099b7bSPaul Traina value = get_u_long(symbol);
90144099b7bSPaul Traina } else {
90244099b7bSPaul Traina len = sizeof(tmpstr);
90344099b7bSPaul Traina (void) get_string(symbol, tmpstr, &len);
90444099b7bSPaul Traina makelower(tmpstr);
90544099b7bSPaul Traina numsymbols = sizeof(htnamemap) /
90644099b7bSPaul Traina sizeof(struct htypename);
90744099b7bSPaul Traina for (i = 0; i < numsymbols; i++) {
90844099b7bSPaul Traina if (!strcmp(htnamemap[i].name, tmpstr)) {
90944099b7bSPaul Traina break;
91044099b7bSPaul Traina }
91144099b7bSPaul Traina }
91244099b7bSPaul Traina if (i < numsymbols) {
91344099b7bSPaul Traina value = htnamemap[i].htype;
91444099b7bSPaul Traina }
91544099b7bSPaul Traina }
91644099b7bSPaul Traina if (value >= hwinfocnt) {
91744099b7bSPaul Traina return E_BAD_HWATYPE;
91844099b7bSPaul Traina }
91944099b7bSPaul Traina hp->htype = (byte) (value & 0xFF);
92044099b7bSPaul Traina hp->flags.htype = TRUE;
92144099b7bSPaul Traina }
92244099b7bSPaul Traina break;
92344099b7bSPaul Traina
92444099b7bSPaul Traina case SYM_IMPRESS_SERVER:
92544099b7bSPaul Traina PARSE_IAL(impress_server);
92644099b7bSPaul Traina break;
92744099b7bSPaul Traina
92844099b7bSPaul Traina case SYM_IPADDR:
92944099b7bSPaul Traina PARSE_IA1(iaddr);
93044099b7bSPaul Traina break;
93144099b7bSPaul Traina
93244099b7bSPaul Traina case SYM_LOG_SERVER:
93344099b7bSPaul Traina PARSE_IAL(log_server);
93444099b7bSPaul Traina break;
93544099b7bSPaul Traina
93644099b7bSPaul Traina case SYM_LPR_SERVER:
93744099b7bSPaul Traina PARSE_IAL(lpr_server);
93844099b7bSPaul Traina break;
93944099b7bSPaul Traina
94044099b7bSPaul Traina case SYM_NAME_SERVER:
94144099b7bSPaul Traina PARSE_IAL(name_server);
94244099b7bSPaul Traina break;
94344099b7bSPaul Traina
94444099b7bSPaul Traina case SYM_RLP_SERVER:
94544099b7bSPaul Traina PARSE_IAL(rlp_server);
94644099b7bSPaul Traina break;
94744099b7bSPaul Traina
94844099b7bSPaul Traina case SYM_SUBNET_MASK:
94944099b7bSPaul Traina PARSE_IA1(subnet_mask);
95044099b7bSPaul Traina break;
95144099b7bSPaul Traina
95244099b7bSPaul Traina case SYM_TIME_OFFSET:
95344099b7bSPaul Traina if (optype == OP_BOOLEAN)
95444099b7bSPaul Traina return E_SYNTAX_ERROR;
95544099b7bSPaul Traina hp->flags.time_offset = FALSE;
95644099b7bSPaul Traina if (optype == OP_ADDITION) {
95744099b7bSPaul Traina len = sizeof(tmpstr);
95844099b7bSPaul Traina (void) get_string(symbol, tmpstr, &len);
95944099b7bSPaul Traina if (!strncmp(tmpstr, "auto", 4)) {
96044099b7bSPaul Traina hp->time_offset = secondswest;
96144099b7bSPaul Traina } else {
962e08ac58bSPaul Traina if (sscanf(tmpstr, "%d", (int*)&timeoff) != 1)
96344099b7bSPaul Traina return E_BAD_LONGWORD;
96444099b7bSPaul Traina hp->time_offset = timeoff;
96544099b7bSPaul Traina }
96644099b7bSPaul Traina hp->flags.time_offset = TRUE;
96744099b7bSPaul Traina }
96844099b7bSPaul Traina break;
96944099b7bSPaul Traina
97044099b7bSPaul Traina case SYM_TIME_SERVER:
97144099b7bSPaul Traina PARSE_IAL(time_server);
97244099b7bSPaul Traina break;
97344099b7bSPaul Traina
97444099b7bSPaul Traina case SYM_VENDOR_MAGIC:
97544099b7bSPaul Traina if (optype == OP_BOOLEAN)
97644099b7bSPaul Traina return E_SYNTAX_ERROR;
97744099b7bSPaul Traina hp->flags.vm_cookie = FALSE;
97844099b7bSPaul Traina if (optype == OP_ADDITION) {
97944099b7bSPaul Traina if (strncmp(*symbol, "auto", 4)) {
98044099b7bSPaul Traina /* The string is not "auto" */
98144099b7bSPaul Traina if (!strncmp(*symbol, "rfc", 3)) {
98244099b7bSPaul Traina bcopy(vm_rfc1048, hp->vm_cookie, 4);
98344099b7bSPaul Traina } else if (!strncmp(*symbol, "cmu", 3)) {
98444099b7bSPaul Traina bcopy(vm_cmu, hp->vm_cookie, 4);
98544099b7bSPaul Traina } else {
98644099b7bSPaul Traina if (!isdigit(**symbol))
98744099b7bSPaul Traina return E_BAD_IPADDR;
98844099b7bSPaul Traina if (prs_inetaddr(symbol, &value) < 0)
98944099b7bSPaul Traina return E_BAD_IPADDR;
99044099b7bSPaul Traina bcopy(&value, hp->vm_cookie, 4);
99144099b7bSPaul Traina }
99244099b7bSPaul Traina hp->flags.vm_cookie = TRUE;
99344099b7bSPaul Traina }
99444099b7bSPaul Traina }
99544099b7bSPaul Traina break;
99644099b7bSPaul Traina
99744099b7bSPaul Traina case SYM_SIMILAR_ENTRY:
99844099b7bSPaul Traina switch (optype) {
99944099b7bSPaul Traina case OP_ADDITION:
100044099b7bSPaul Traina fill_defaults(hp, symbol);
100144099b7bSPaul Traina break;
100244099b7bSPaul Traina default:
100344099b7bSPaul Traina return E_SYNTAX_ERROR;
100444099b7bSPaul Traina }
100544099b7bSPaul Traina break;
100644099b7bSPaul Traina
100744099b7bSPaul Traina case SYM_NAME_SWITCH:
100844099b7bSPaul Traina switch (optype) {
100944099b7bSPaul Traina case OP_ADDITION:
101044099b7bSPaul Traina return E_SYNTAX_ERROR;
101144099b7bSPaul Traina case OP_DELETION:
101244099b7bSPaul Traina hp->flags.send_name = FALSE;
101344099b7bSPaul Traina hp->flags.name_switch = FALSE;
101444099b7bSPaul Traina break;
101544099b7bSPaul Traina case OP_BOOLEAN:
101644099b7bSPaul Traina hp->flags.send_name = TRUE;
101744099b7bSPaul Traina hp->flags.name_switch = TRUE;
101844099b7bSPaul Traina break;
101944099b7bSPaul Traina }
102044099b7bSPaul Traina break;
102144099b7bSPaul Traina
102244099b7bSPaul Traina case SYM_BOOTSIZE:
102344099b7bSPaul Traina switch (optype) {
102444099b7bSPaul Traina case OP_ADDITION:
102544099b7bSPaul Traina if (!strncmp(*symbol, "auto", 4)) {
102644099b7bSPaul Traina hp->flags.bootsize = TRUE;
102744099b7bSPaul Traina hp->flags.bootsize_auto = TRUE;
102844099b7bSPaul Traina } else {
102944099b7bSPaul Traina hp->bootsize = (unsigned int) get_u_long(symbol);
103044099b7bSPaul Traina hp->flags.bootsize = TRUE;
103144099b7bSPaul Traina hp->flags.bootsize_auto = FALSE;
103244099b7bSPaul Traina }
103344099b7bSPaul Traina break;
103444099b7bSPaul Traina case OP_DELETION:
103544099b7bSPaul Traina hp->flags.bootsize = FALSE;
103644099b7bSPaul Traina break;
103744099b7bSPaul Traina case OP_BOOLEAN:
103844099b7bSPaul Traina hp->flags.bootsize = TRUE;
103944099b7bSPaul Traina hp->flags.bootsize_auto = TRUE;
104044099b7bSPaul Traina break;
104144099b7bSPaul Traina }
104244099b7bSPaul Traina break;
104344099b7bSPaul Traina
104444099b7bSPaul Traina case SYM_BOOT_SERVER:
104544099b7bSPaul Traina PARSE_IA1(bootserver);
104644099b7bSPaul Traina break;
104744099b7bSPaul Traina
104844099b7bSPaul Traina case SYM_TFTPDIR:
104944099b7bSPaul Traina PARSE_STR(tftpdir);
105044099b7bSPaul Traina if ((hp->tftpdir != NULL) &&
105144099b7bSPaul Traina (hp->tftpdir->string[0] != '/'))
105244099b7bSPaul Traina return E_BAD_PATHNAME;
105344099b7bSPaul Traina break;
105444099b7bSPaul Traina
105544099b7bSPaul Traina case SYM_DUMP_FILE:
105644099b7bSPaul Traina PARSE_STR(dump_file);
105744099b7bSPaul Traina break;
105844099b7bSPaul Traina
105944099b7bSPaul Traina case SYM_DOMAIN_NAME:
106044099b7bSPaul Traina PARSE_STR(domain_name);
106144099b7bSPaul Traina break;
106244099b7bSPaul Traina
106344099b7bSPaul Traina case SYM_SWAP_SERVER:
106444099b7bSPaul Traina PARSE_IA1(swap_server);
106544099b7bSPaul Traina break;
106644099b7bSPaul Traina
106744099b7bSPaul Traina case SYM_ROOT_PATH:
106844099b7bSPaul Traina PARSE_STR(root_path);
106944099b7bSPaul Traina break;
107044099b7bSPaul Traina
107144099b7bSPaul Traina case SYM_EXTEN_FILE:
107244099b7bSPaul Traina PARSE_STR(exten_file);
107344099b7bSPaul Traina break;
107444099b7bSPaul Traina
107544099b7bSPaul Traina case SYM_REPLY_ADDR:
107644099b7bSPaul Traina PARSE_IA1(reply_addr);
107744099b7bSPaul Traina break;
107844099b7bSPaul Traina
107944099b7bSPaul Traina case SYM_NIS_DOMAIN:
108044099b7bSPaul Traina PARSE_STR(nis_domain);
108144099b7bSPaul Traina break;
108244099b7bSPaul Traina
108344099b7bSPaul Traina case SYM_NIS_SERVER:
108444099b7bSPaul Traina PARSE_IAL(nis_server);
108544099b7bSPaul Traina break;
108644099b7bSPaul Traina
108744099b7bSPaul Traina case SYM_NTP_SERVER:
108844099b7bSPaul Traina PARSE_IAL(ntp_server);
108944099b7bSPaul Traina break;
109044099b7bSPaul Traina
109144099b7bSPaul Traina #ifdef YORK_EX_OPTION
109244099b7bSPaul Traina case SYM_EXEC_FILE:
109344099b7bSPaul Traina PARSE_STR(exec_file);
109444099b7bSPaul Traina break;
109544099b7bSPaul Traina #endif
109644099b7bSPaul Traina
109744099b7bSPaul Traina case SYM_MSG_SIZE:
1098e08ac58bSPaul Traina PARSE_UINT(msg_size);
109944099b7bSPaul Traina if (hp->msg_size < BP_MINPKTSZ ||
110044099b7bSPaul Traina hp->msg_size > MAX_MSG_SIZE)
110144099b7bSPaul Traina return E_BAD_VALUE;
110244099b7bSPaul Traina break;
110344099b7bSPaul Traina
110444099b7bSPaul Traina case SYM_MIN_WAIT:
1105e08ac58bSPaul Traina PARSE_UINT(min_wait);
110644099b7bSPaul Traina break;
110744099b7bSPaul Traina
110844099b7bSPaul Traina /* XXX - Add new tags here */
110944099b7bSPaul Traina
111044099b7bSPaul Traina default:
111144099b7bSPaul Traina return E_UNKNOWN_SYMBOL;
111244099b7bSPaul Traina
111344099b7bSPaul Traina } /* switch symbolcode */
111444099b7bSPaul Traina
111544099b7bSPaul Traina return SUCCESS;
111644099b7bSPaul Traina }
111744099b7bSPaul Traina #undef PARSE_IA1
111844099b7bSPaul Traina #undef PARSE_IAL
111944099b7bSPaul Traina #undef PARSE_STR
112044099b7bSPaul Traina
112144099b7bSPaul Traina
112244099b7bSPaul Traina
112344099b7bSPaul Traina
112444099b7bSPaul Traina /*
112544099b7bSPaul Traina * Read a string from the buffer indirectly pointed to through "src" and
112644099b7bSPaul Traina * move it into the buffer pointed to by "dest". A pointer to the maximum
112744099b7bSPaul Traina * allowable length of the string (including null-terminator) is passed as
112844099b7bSPaul Traina * "length". The actual length of the string which was read is returned in
112944099b7bSPaul Traina * the unsigned integer pointed to by "length". This value is the same as
113044099b7bSPaul Traina * that which would be returned by applying the strlen() function on the
113144099b7bSPaul Traina * destination string (i.e the terminating null is not counted as a
113244099b7bSPaul Traina * character). Trailing whitespace is removed from the string. For
113344099b7bSPaul Traina * convenience, the function returns the new value of "dest".
113444099b7bSPaul Traina *
113544099b7bSPaul Traina * The string is read until the maximum number of characters, an unquoted
113644099b7bSPaul Traina * colon (:), or a null character is read. The return string in "dest" is
113744099b7bSPaul Traina * null-terminated.
113844099b7bSPaul Traina */
113944099b7bSPaul Traina
114044099b7bSPaul Traina PRIVATE char *
get_string(char ** src,char * dest,unsigned * length)1141*8b356c88SJohn Baldwin get_string(char **src, char *dest, unsigned *length)
114244099b7bSPaul Traina {
114344099b7bSPaul Traina int n, len, quoteflag;
114444099b7bSPaul Traina
114544099b7bSPaul Traina quoteflag = FALSE;
114644099b7bSPaul Traina n = 0;
114744099b7bSPaul Traina len = *length - 1;
114844099b7bSPaul Traina while ((n < len) && (**src)) {
114944099b7bSPaul Traina if (!quoteflag && (**src == ':')) {
115044099b7bSPaul Traina break;
115144099b7bSPaul Traina }
115244099b7bSPaul Traina if (**src == '"') {
115344099b7bSPaul Traina (*src)++;
115444099b7bSPaul Traina quoteflag = !quoteflag;
115544099b7bSPaul Traina continue;
115644099b7bSPaul Traina }
115744099b7bSPaul Traina if (**src == '\\') {
115844099b7bSPaul Traina (*src)++;
115944099b7bSPaul Traina if (!**src) {
116044099b7bSPaul Traina break;
116144099b7bSPaul Traina }
116244099b7bSPaul Traina }
116344099b7bSPaul Traina *dest++ = *(*src)++;
116444099b7bSPaul Traina n++;
116544099b7bSPaul Traina }
116644099b7bSPaul Traina
116744099b7bSPaul Traina /*
116844099b7bSPaul Traina * Remove that troublesome trailing whitespace. . .
116944099b7bSPaul Traina */
117044099b7bSPaul Traina while ((n > 0) && isspace(dest[-1])) {
117144099b7bSPaul Traina dest--;
117244099b7bSPaul Traina n--;
117344099b7bSPaul Traina }
117444099b7bSPaul Traina
117544099b7bSPaul Traina *dest = '\0';
117644099b7bSPaul Traina *length = n;
117744099b7bSPaul Traina return dest;
117844099b7bSPaul Traina }
117944099b7bSPaul Traina
118044099b7bSPaul Traina
118144099b7bSPaul Traina
118244099b7bSPaul Traina /*
118344099b7bSPaul Traina * Read the string indirectly pointed to by "src", update the caller's
118444099b7bSPaul Traina * pointer, and return a pointer to a malloc'ed shared_string structure
118544099b7bSPaul Traina * containing the string.
118644099b7bSPaul Traina *
118744099b7bSPaul Traina * The string is read using the same rules as get_string() above.
118844099b7bSPaul Traina */
118944099b7bSPaul Traina
119044099b7bSPaul Traina PRIVATE struct shared_string *
get_shared_string(char ** src)1191*8b356c88SJohn Baldwin get_shared_string(char **src)
119244099b7bSPaul Traina {
119344099b7bSPaul Traina char retstring[MAXSTRINGLEN];
119444099b7bSPaul Traina struct shared_string *s;
119544099b7bSPaul Traina unsigned length;
119644099b7bSPaul Traina
119744099b7bSPaul Traina length = sizeof(retstring);
119844099b7bSPaul Traina (void) get_string(src, retstring, &length);
119944099b7bSPaul Traina
120044099b7bSPaul Traina s = (struct shared_string *) smalloc(sizeof(struct shared_string)
120144099b7bSPaul Traina + length);
120244099b7bSPaul Traina s->linkcount = 1;
120344099b7bSPaul Traina strcpy(s->string, retstring);
120444099b7bSPaul Traina
120544099b7bSPaul Traina return s;
120644099b7bSPaul Traina }
120744099b7bSPaul Traina
120844099b7bSPaul Traina
120944099b7bSPaul Traina
121044099b7bSPaul Traina /*
121144099b7bSPaul Traina * Load RFC1048 generic information directly into a memory buffer.
121244099b7bSPaul Traina *
121344099b7bSPaul Traina * "src" indirectly points to the ASCII representation of the generic data.
121444099b7bSPaul Traina * "dest" points to a string structure which is updated to point to a new
121544099b7bSPaul Traina * string with the new data appended to the old string. The old string is
121644099b7bSPaul Traina * freed.
121744099b7bSPaul Traina *
121844099b7bSPaul Traina * The given tag value is inserted with the new data.
121944099b7bSPaul Traina *
122044099b7bSPaul Traina * The data may be represented as either a stream of hexadecimal numbers
122144099b7bSPaul Traina * representing bytes (any or all bytes may optionally start with '0x' and
122244099b7bSPaul Traina * be separated with periods ".") or as a quoted string of ASCII
122344099b7bSPaul Traina * characters (the quotes are required).
122444099b7bSPaul Traina */
122544099b7bSPaul Traina
122644099b7bSPaul Traina PRIVATE int
process_generic(char ** src,struct shared_bindata ** dest,u_int tagvalue)1227*8b356c88SJohn Baldwin process_generic(char **src, struct shared_bindata **dest, u_int tagvalue)
122844099b7bSPaul Traina {
122944099b7bSPaul Traina byte tmpbuf[MAXBUFLEN];
123044099b7bSPaul Traina byte *str;
123144099b7bSPaul Traina struct shared_bindata *bdata;
123244099b7bSPaul Traina u_int newlength, oldlength;
123344099b7bSPaul Traina
123444099b7bSPaul Traina str = tmpbuf;
123544099b7bSPaul Traina *str++ = (tagvalue & 0xFF); /* Store tag value */
123644099b7bSPaul Traina str++; /* Skip over length field */
123744099b7bSPaul Traina if ((*src)[0] == '"') { /* ASCII data */
123844099b7bSPaul Traina newlength = sizeof(tmpbuf) - 2; /* Set maximum allowed length */
123944099b7bSPaul Traina (void) get_string(src, (char *) str, &newlength);
124044099b7bSPaul Traina newlength++; /* null terminator */
124144099b7bSPaul Traina } else { /* Numeric data */
124244099b7bSPaul Traina newlength = 0;
124344099b7bSPaul Traina while (newlength < sizeof(tmpbuf) - 2) {
124444099b7bSPaul Traina if (interp_byte(src, str++) < 0)
124544099b7bSPaul Traina break;
124644099b7bSPaul Traina newlength++;
124744099b7bSPaul Traina if (**src == '.') {
124844099b7bSPaul Traina (*src)++;
124944099b7bSPaul Traina }
125044099b7bSPaul Traina }
125144099b7bSPaul Traina }
125244099b7bSPaul Traina if ((*src)[0] != ':')
125344099b7bSPaul Traina return -1;
125444099b7bSPaul Traina
125544099b7bSPaul Traina tmpbuf[1] = (newlength & 0xFF);
125644099b7bSPaul Traina oldlength = ((*dest)->length);
125744099b7bSPaul Traina bdata = (struct shared_bindata *) smalloc(sizeof(struct shared_bindata)
125844099b7bSPaul Traina + oldlength + newlength + 1);
125944099b7bSPaul Traina if (oldlength > 0) {
126044099b7bSPaul Traina bcopy((*dest)->data, bdata->data, oldlength);
126144099b7bSPaul Traina }
126244099b7bSPaul Traina bcopy(tmpbuf, bdata->data + oldlength, newlength + 2);
126344099b7bSPaul Traina bdata->length = oldlength + newlength + 2;
126444099b7bSPaul Traina bdata->linkcount = 1;
126544099b7bSPaul Traina if (*dest) {
126644099b7bSPaul Traina del_bindata(*dest);
126744099b7bSPaul Traina }
126844099b7bSPaul Traina *dest = bdata;
126944099b7bSPaul Traina return 0;
127044099b7bSPaul Traina }
127144099b7bSPaul Traina
127244099b7bSPaul Traina
127344099b7bSPaul Traina
127444099b7bSPaul Traina /*
127544099b7bSPaul Traina * Verify that the given string makes sense as a hostname (according to
127644099b7bSPaul Traina * Appendix 1, page 29 of RFC882).
127744099b7bSPaul Traina *
127844099b7bSPaul Traina * Return TRUE for good names, FALSE otherwise.
127944099b7bSPaul Traina */
128044099b7bSPaul Traina
128144099b7bSPaul Traina PRIVATE boolean
goodname(char * hostname)1282*8b356c88SJohn Baldwin goodname(char *hostname)
128344099b7bSPaul Traina {
128444099b7bSPaul Traina do {
128544099b7bSPaul Traina if (!isalpha(*hostname++)) { /* First character must be a letter */
128644099b7bSPaul Traina return FALSE;
128744099b7bSPaul Traina }
128844099b7bSPaul Traina while (isalnum(*hostname) ||
128944099b7bSPaul Traina (*hostname == '-') ||
129044099b7bSPaul Traina (*hostname == '_') )
129144099b7bSPaul Traina {
129244099b7bSPaul Traina hostname++; /* Alphanumeric or a hyphen */
129344099b7bSPaul Traina }
129444099b7bSPaul Traina if (!isalnum(hostname[-1])) { /* Last must be alphanumeric */
129544099b7bSPaul Traina return FALSE;
129644099b7bSPaul Traina }
129744099b7bSPaul Traina if (*hostname == '\0') {/* Done? */
129844099b7bSPaul Traina return TRUE;
129944099b7bSPaul Traina }
130044099b7bSPaul Traina } while (*hostname++ == '.'); /* Dot, loop for next label */
130144099b7bSPaul Traina
130244099b7bSPaul Traina return FALSE; /* If it's not a dot, lose */
130344099b7bSPaul Traina }
130444099b7bSPaul Traina
130544099b7bSPaul Traina
130644099b7bSPaul Traina
130744099b7bSPaul Traina /*
130844099b7bSPaul Traina * Null compare function -- always returns FALSE so an element is always
130944099b7bSPaul Traina * inserted into a hash table (i.e. there is never a collision with an
131044099b7bSPaul Traina * existing element).
131144099b7bSPaul Traina */
131244099b7bSPaul Traina
131344099b7bSPaul Traina PRIVATE boolean
nullcmp(hash_datum * d1,hash_datum * d2)1314*8b356c88SJohn Baldwin nullcmp(hash_datum *d1, hash_datum *d2)
131544099b7bSPaul Traina {
131644099b7bSPaul Traina return FALSE;
131744099b7bSPaul Traina }
131844099b7bSPaul Traina
131944099b7bSPaul Traina
132044099b7bSPaul Traina /*
132144099b7bSPaul Traina * Function for comparing a string with the hostname field of a host
132244099b7bSPaul Traina * structure.
132344099b7bSPaul Traina */
132444099b7bSPaul Traina
132544099b7bSPaul Traina boolean
nmcmp(hash_datum * d1,hash_datum * d2)1326*8b356c88SJohn Baldwin nmcmp(hash_datum *d1, hash_datum *d2)
132744099b7bSPaul Traina {
132844099b7bSPaul Traina char *name = (char *) d1; /* XXX - OK? */
132944099b7bSPaul Traina struct host *hp = (struct host *) d2;
133044099b7bSPaul Traina
133144099b7bSPaul Traina return !strcmp(name, hp->hostname->string);
133244099b7bSPaul Traina }
133344099b7bSPaul Traina
133444099b7bSPaul Traina
133544099b7bSPaul Traina /*
133644099b7bSPaul Traina * Compare function to determine whether two hardware addresses are
133744099b7bSPaul Traina * equivalent. Returns TRUE if "host1" and "host2" are equivalent, FALSE
133844099b7bSPaul Traina * otherwise.
133944099b7bSPaul Traina *
134044099b7bSPaul Traina * If the hardware addresses of "host1" and "host2" are identical, but
134144099b7bSPaul Traina * they are on different IP subnets, this function returns FALSE.
134244099b7bSPaul Traina *
134344099b7bSPaul Traina * This function is used when inserting elements into the hardware address
134444099b7bSPaul Traina * hash table.
134544099b7bSPaul Traina */
134644099b7bSPaul Traina
134744099b7bSPaul Traina PRIVATE boolean
hwinscmp(hash_datum * d1,hash_datum * d2)1348*8b356c88SJohn Baldwin hwinscmp(hash_datum *d1, hash_datum *d2)
134944099b7bSPaul Traina {
135044099b7bSPaul Traina struct host *host1 = (struct host *) d1;
135144099b7bSPaul Traina struct host *host2 = (struct host *) d2;
135244099b7bSPaul Traina
135344099b7bSPaul Traina if (host1->htype != host2->htype) {
135444099b7bSPaul Traina return FALSE;
135544099b7bSPaul Traina }
135644099b7bSPaul Traina if (bcmp(host1->haddr, host2->haddr, haddrlength(host1->htype))) {
135744099b7bSPaul Traina return FALSE;
135844099b7bSPaul Traina }
135944099b7bSPaul Traina /* XXX - Is the subnet_mask field set yet? */
136044099b7bSPaul Traina if ((host1->subnet_mask.s_addr) == (host2->subnet_mask.s_addr)) {
136144099b7bSPaul Traina if (((host1->iaddr.s_addr) & (host1->subnet_mask.s_addr)) !=
136244099b7bSPaul Traina ((host2->iaddr.s_addr) & (host2->subnet_mask.s_addr)))
136344099b7bSPaul Traina {
136444099b7bSPaul Traina return FALSE;
136544099b7bSPaul Traina }
136644099b7bSPaul Traina }
136744099b7bSPaul Traina return TRUE;
136844099b7bSPaul Traina }
136944099b7bSPaul Traina
137044099b7bSPaul Traina
137144099b7bSPaul Traina /*
137244099b7bSPaul Traina * Macros for use in the function below:
137344099b7bSPaul Traina */
137444099b7bSPaul Traina
137544099b7bSPaul Traina #define DUP_COPY(MEMBER) do \
137644099b7bSPaul Traina { \
137744099b7bSPaul Traina if (!hp->flags.MEMBER) { \
137844099b7bSPaul Traina if ((hp->flags.MEMBER = hp2->flags.MEMBER) != 0) { \
137944099b7bSPaul Traina hp->MEMBER = hp2->MEMBER; \
138044099b7bSPaul Traina } \
138144099b7bSPaul Traina } \
138244099b7bSPaul Traina } while (0)
138344099b7bSPaul Traina
138444099b7bSPaul Traina #define DUP_LINK(MEMBER) do \
138544099b7bSPaul Traina { \
138644099b7bSPaul Traina if (!hp->flags.MEMBER) { \
138744099b7bSPaul Traina if ((hp->flags.MEMBER = hp2->flags.MEMBER) != 0) { \
138844099b7bSPaul Traina assert(hp2->MEMBER); \
138944099b7bSPaul Traina hp->MEMBER = hp2->MEMBER; \
139044099b7bSPaul Traina (hp->MEMBER->linkcount)++; \
139144099b7bSPaul Traina } \
139244099b7bSPaul Traina } \
139344099b7bSPaul Traina } while (0)
139444099b7bSPaul Traina
139544099b7bSPaul Traina /*
139644099b7bSPaul Traina * Process the "similar entry" symbol.
139744099b7bSPaul Traina *
139844099b7bSPaul Traina * The host specified as the value of the "tc" symbol is used as a template
139944099b7bSPaul Traina * for the current host entry. Symbol values not explicitly set in the
140044099b7bSPaul Traina * current host entry are inferred from the template entry.
140144099b7bSPaul Traina */
140244099b7bSPaul Traina PRIVATE void
fill_defaults(struct host * hp,char ** src)1403*8b356c88SJohn Baldwin fill_defaults(struct host *hp, char **src)
140444099b7bSPaul Traina {
140544099b7bSPaul Traina unsigned int tlen, hashcode;
140644099b7bSPaul Traina struct host *hp2;
140744099b7bSPaul Traina char tstring[MAXSTRINGLEN];
140844099b7bSPaul Traina
140944099b7bSPaul Traina tlen = sizeof(tstring);
141044099b7bSPaul Traina (void) get_string(src, tstring, &tlen);
141144099b7bSPaul Traina hashcode = hash_HashFunction((u_char *) tstring, tlen);
141244099b7bSPaul Traina hp2 = (struct host *) hash_Lookup(nmhashtable, hashcode, nmcmp, tstring);
141344099b7bSPaul Traina
141444099b7bSPaul Traina if (hp2 == NULL) {
141544099b7bSPaul Traina report(LOG_ERR, "can't find tc=\"%s\"", tstring);
141644099b7bSPaul Traina return;
141744099b7bSPaul Traina }
141844099b7bSPaul Traina DUP_LINK(bootfile);
141944099b7bSPaul Traina DUP_LINK(cookie_server);
142044099b7bSPaul Traina DUP_LINK(domain_server);
142144099b7bSPaul Traina DUP_LINK(gateway);
142244099b7bSPaul Traina /* haddr not copied */
142344099b7bSPaul Traina DUP_LINK(homedir);
142444099b7bSPaul Traina DUP_COPY(htype);
142544099b7bSPaul Traina
142644099b7bSPaul Traina DUP_LINK(impress_server);
142744099b7bSPaul Traina /* iaddr not copied */
142844099b7bSPaul Traina DUP_LINK(log_server);
142944099b7bSPaul Traina DUP_LINK(lpr_server);
143044099b7bSPaul Traina DUP_LINK(name_server);
143144099b7bSPaul Traina DUP_LINK(rlp_server);
143244099b7bSPaul Traina
143344099b7bSPaul Traina DUP_COPY(subnet_mask);
143444099b7bSPaul Traina DUP_COPY(time_offset);
143544099b7bSPaul Traina DUP_LINK(time_server);
143644099b7bSPaul Traina
143744099b7bSPaul Traina if (!hp->flags.vm_cookie) {
143844099b7bSPaul Traina if ((hp->flags.vm_cookie = hp2->flags.vm_cookie)) {
143944099b7bSPaul Traina bcopy(hp2->vm_cookie, hp->vm_cookie, 4);
144044099b7bSPaul Traina }
144144099b7bSPaul Traina }
144244099b7bSPaul Traina if (!hp->flags.name_switch) {
144344099b7bSPaul Traina if ((hp->flags.name_switch = hp2->flags.name_switch)) {
144444099b7bSPaul Traina hp->flags.send_name = hp2->flags.send_name;
144544099b7bSPaul Traina }
144644099b7bSPaul Traina }
144744099b7bSPaul Traina if (!hp->flags.bootsize) {
144844099b7bSPaul Traina if ((hp->flags.bootsize = hp2->flags.bootsize)) {
144944099b7bSPaul Traina hp->flags.bootsize_auto = hp2->flags.bootsize_auto;
145044099b7bSPaul Traina hp->bootsize = hp2->bootsize;
145144099b7bSPaul Traina }
145244099b7bSPaul Traina }
145344099b7bSPaul Traina DUP_COPY(bootserver);
145444099b7bSPaul Traina
145544099b7bSPaul Traina DUP_LINK(tftpdir);
145644099b7bSPaul Traina DUP_LINK(dump_file);
145744099b7bSPaul Traina DUP_LINK(domain_name);
145844099b7bSPaul Traina
145944099b7bSPaul Traina DUP_COPY(swap_server);
146044099b7bSPaul Traina DUP_LINK(root_path);
146144099b7bSPaul Traina DUP_LINK(exten_file);
146244099b7bSPaul Traina
146344099b7bSPaul Traina DUP_COPY(reply_addr);
146444099b7bSPaul Traina
146544099b7bSPaul Traina DUP_LINK(nis_domain);
146644099b7bSPaul Traina DUP_LINK(nis_server);
146744099b7bSPaul Traina DUP_LINK(ntp_server);
146844099b7bSPaul Traina
146944099b7bSPaul Traina #ifdef YORK_EX_OPTION
147044099b7bSPaul Traina DUP_LINK(exec_file);
147144099b7bSPaul Traina #endif
147244099b7bSPaul Traina
147344099b7bSPaul Traina DUP_COPY(msg_size);
147444099b7bSPaul Traina DUP_COPY(min_wait);
147544099b7bSPaul Traina
147644099b7bSPaul Traina /* XXX - Add new tags here */
147744099b7bSPaul Traina
147844099b7bSPaul Traina DUP_LINK(generic);
147944099b7bSPaul Traina
148044099b7bSPaul Traina }
148144099b7bSPaul Traina #undef DUP_COPY
148244099b7bSPaul Traina #undef DUP_LINK
148344099b7bSPaul Traina
148444099b7bSPaul Traina
148544099b7bSPaul Traina
148644099b7bSPaul Traina /*
148744099b7bSPaul Traina * This function adjusts the caller's pointer to point just past the
148844099b7bSPaul Traina * first-encountered colon. If it runs into a null character, it leaves
148944099b7bSPaul Traina * the pointer pointing to it.
149044099b7bSPaul Traina */
149144099b7bSPaul Traina
149244099b7bSPaul Traina PRIVATE void
adjust(char ** s)1493*8b356c88SJohn Baldwin adjust(char **s)
149444099b7bSPaul Traina {
149507ee9f80SPedro F. Giffuni char *t;
149644099b7bSPaul Traina
149744099b7bSPaul Traina t = *s;
149844099b7bSPaul Traina while (*t && (*t != ':')) {
149944099b7bSPaul Traina t++;
150044099b7bSPaul Traina }
150144099b7bSPaul Traina if (*t) {
150244099b7bSPaul Traina t++;
150344099b7bSPaul Traina }
150444099b7bSPaul Traina *s = t;
150544099b7bSPaul Traina }
150644099b7bSPaul Traina
150744099b7bSPaul Traina
150844099b7bSPaul Traina
150944099b7bSPaul Traina
151044099b7bSPaul Traina /*
151144099b7bSPaul Traina * This function adjusts the caller's pointer to point to the first
151244099b7bSPaul Traina * non-whitespace character. If it runs into a null character, it leaves
151344099b7bSPaul Traina * the pointer pointing to it.
151444099b7bSPaul Traina */
151544099b7bSPaul Traina
151644099b7bSPaul Traina PRIVATE void
eat_whitespace(char ** s)1517*8b356c88SJohn Baldwin eat_whitespace(char **s)
151844099b7bSPaul Traina {
151907ee9f80SPedro F. Giffuni char *t;
152044099b7bSPaul Traina
152144099b7bSPaul Traina t = *s;
152244099b7bSPaul Traina while (*t && isspace(*t)) {
152344099b7bSPaul Traina t++;
152444099b7bSPaul Traina }
152544099b7bSPaul Traina *s = t;
152644099b7bSPaul Traina }
152744099b7bSPaul Traina
152844099b7bSPaul Traina
152944099b7bSPaul Traina
153044099b7bSPaul Traina /*
153144099b7bSPaul Traina * This function converts the given string to all lowercase.
153244099b7bSPaul Traina */
153344099b7bSPaul Traina
153444099b7bSPaul Traina PRIVATE void
makelower(char * s)1535*8b356c88SJohn Baldwin makelower(char *s)
153644099b7bSPaul Traina {
153744099b7bSPaul Traina while (*s) {
153844099b7bSPaul Traina if (isupper(*s)) {
153944099b7bSPaul Traina *s = tolower(*s);
154044099b7bSPaul Traina }
154144099b7bSPaul Traina s++;
154244099b7bSPaul Traina }
154344099b7bSPaul Traina }
154444099b7bSPaul Traina
154544099b7bSPaul Traina
154644099b7bSPaul Traina
154744099b7bSPaul Traina /*
154844099b7bSPaul Traina *
154944099b7bSPaul Traina * N O T E :
155044099b7bSPaul Traina *
155144099b7bSPaul Traina * In many of the functions which follow, a parameter such as "src" or
155244099b7bSPaul Traina * "symbol" is passed as a pointer to a pointer to something. This is
155344099b7bSPaul Traina * done for the purpose of letting the called function update the
155444099b7bSPaul Traina * caller's copy of the parameter (i.e. to effect call-by-reference
155544099b7bSPaul Traina * parameter passing). The value of the actual parameter is only used
155644099b7bSPaul Traina * to locate the real parameter of interest and then update this indirect
155744099b7bSPaul Traina * parameter.
155844099b7bSPaul Traina *
155944099b7bSPaul Traina * I'm sure somebody out there won't like this. . . .
156044099b7bSPaul Traina * (Yea, because it usually makes code slower... -gwr)
156144099b7bSPaul Traina *
156244099b7bSPaul Traina */
156344099b7bSPaul Traina
156444099b7bSPaul Traina
156544099b7bSPaul Traina
156644099b7bSPaul Traina /*
156744099b7bSPaul Traina * "src" points to a character pointer which points to an ASCII string of
156844099b7bSPaul Traina * whitespace-separated IP addresses. A pointer to an in_addr_list
156944099b7bSPaul Traina * structure containing the list of addresses is returned. NULL is
157044099b7bSPaul Traina * returned if no addresses were found at all. The pointer pointed to by
157144099b7bSPaul Traina * "src" is updated to point to the first non-address (illegal) character.
157244099b7bSPaul Traina */
157344099b7bSPaul Traina
157444099b7bSPaul Traina PRIVATE struct in_addr_list *
get_addresses(char ** src)1575*8b356c88SJohn Baldwin get_addresses(char **src)
157644099b7bSPaul Traina {
157744099b7bSPaul Traina struct in_addr tmpaddrlist[MAXINADDRS];
157844099b7bSPaul Traina struct in_addr *address1, *address2;
157944099b7bSPaul Traina struct in_addr_list *result;
158044099b7bSPaul Traina unsigned addrcount, totalsize;
158144099b7bSPaul Traina
158244099b7bSPaul Traina address1 = tmpaddrlist;
158344099b7bSPaul Traina for (addrcount = 0; addrcount < MAXINADDRS; addrcount++) {
158444099b7bSPaul Traina while (isspace(**src) || (**src == ',')) {
158544099b7bSPaul Traina (*src)++;
158644099b7bSPaul Traina }
158744099b7bSPaul Traina if (!**src) { /* Quit if nothing more */
158844099b7bSPaul Traina break;
158944099b7bSPaul Traina }
159044099b7bSPaul Traina if (prs_inetaddr(src, &(address1->s_addr)) < 0) {
159144099b7bSPaul Traina break;
159244099b7bSPaul Traina }
159344099b7bSPaul Traina address1++; /* Point to next address slot */
159444099b7bSPaul Traina }
159544099b7bSPaul Traina if (addrcount < 1) {
159644099b7bSPaul Traina result = NULL;
159744099b7bSPaul Traina } else {
159844099b7bSPaul Traina totalsize = sizeof(struct in_addr_list)
159944099b7bSPaul Traina + (addrcount - 1) * sizeof(struct in_addr);
160044099b7bSPaul Traina result = (struct in_addr_list *) smalloc(totalsize);
160144099b7bSPaul Traina result->linkcount = 1;
160244099b7bSPaul Traina result->addrcount = addrcount;
160344099b7bSPaul Traina address1 = tmpaddrlist;
160444099b7bSPaul Traina address2 = result->addr;
160544099b7bSPaul Traina for (; addrcount > 0; addrcount--) {
160644099b7bSPaul Traina address2->s_addr = address1->s_addr;
160744099b7bSPaul Traina address1++;
160844099b7bSPaul Traina address2++;
160944099b7bSPaul Traina }
161044099b7bSPaul Traina }
161144099b7bSPaul Traina return result;
161244099b7bSPaul Traina }
161344099b7bSPaul Traina
161444099b7bSPaul Traina
161544099b7bSPaul Traina
161644099b7bSPaul Traina /*
161744099b7bSPaul Traina * prs_inetaddr(src, result)
161844099b7bSPaul Traina *
161944099b7bSPaul Traina * "src" is a value-result parameter; the pointer it points to is updated
162044099b7bSPaul Traina * to point to the next data position. "result" points to an unsigned long
162144099b7bSPaul Traina * in which an address is returned.
162244099b7bSPaul Traina *
162344099b7bSPaul Traina * This function parses the IP address string in ASCII "dot notation" pointed
162444099b7bSPaul Traina * to by (*src) and places the result (in network byte order) in the unsigned
162544099b7bSPaul Traina * long pointed to by "result". For malformed addresses, -1 is returned,
162644099b7bSPaul Traina * (*src) points to the first illegal character, and the unsigned long pointed
162744099b7bSPaul Traina * to by "result" is unchanged. Successful calls return 0.
162844099b7bSPaul Traina */
162944099b7bSPaul Traina
163044099b7bSPaul Traina PRIVATE int
prs_inetaddr(char ** src,u_int32 * result)1631*8b356c88SJohn Baldwin prs_inetaddr(char **src, u_int32 *result)
163244099b7bSPaul Traina {
163344099b7bSPaul Traina char tmpstr[MAXSTRINGLEN];
163407ee9f80SPedro F. Giffuni u_int32 value;
163544099b7bSPaul Traina u_int32 parts[4], *pp;
163644099b7bSPaul Traina int n;
163744099b7bSPaul Traina char *s, *t;
163844099b7bSPaul Traina
163944099b7bSPaul Traina /* Leading alpha char causes IP addr lookup. */
164044099b7bSPaul Traina if (isalpha(**src)) {
164144099b7bSPaul Traina /* Lookup IP address. */
164244099b7bSPaul Traina s = *src;
164344099b7bSPaul Traina t = tmpstr;
164444099b7bSPaul Traina while ((isalnum(*s) || (*s == '.') ||
164544099b7bSPaul Traina (*s == '-') || (*s == '_') ) &&
164644099b7bSPaul Traina (t < &tmpstr[MAXSTRINGLEN - 1]) )
164744099b7bSPaul Traina *t++ = *s++;
164844099b7bSPaul Traina *t = '\0';
164944099b7bSPaul Traina *src = s;
165044099b7bSPaul Traina
165144099b7bSPaul Traina n = lookup_ipa(tmpstr, result);
165244099b7bSPaul Traina if (n < 0)
165344099b7bSPaul Traina report(LOG_ERR, "can not get IP addr for %s", tmpstr);
165444099b7bSPaul Traina return n;
165544099b7bSPaul Traina }
165644099b7bSPaul Traina
165744099b7bSPaul Traina /*
165844099b7bSPaul Traina * Parse an address in Internet format:
165944099b7bSPaul Traina * a.b.c.d
166044099b7bSPaul Traina * a.b.c (with c treated as 16-bits)
166144099b7bSPaul Traina * a.b (with b treated as 24 bits)
166244099b7bSPaul Traina */
166344099b7bSPaul Traina pp = parts;
166444099b7bSPaul Traina loop:
166544099b7bSPaul Traina /* If it's not a digit, return error. */
166644099b7bSPaul Traina if (!isdigit(**src))
166744099b7bSPaul Traina return -1;
166844099b7bSPaul Traina *pp++ = get_u_long(src);
166944099b7bSPaul Traina if (**src == '.') {
167044099b7bSPaul Traina if (pp < (parts + 4)) {
167144099b7bSPaul Traina (*src)++;
167244099b7bSPaul Traina goto loop;
167344099b7bSPaul Traina }
167444099b7bSPaul Traina return (-1);
167544099b7bSPaul Traina }
167644099b7bSPaul Traina #if 0
167744099b7bSPaul Traina /* This is handled by the caller. */
167844099b7bSPaul Traina if (**src && !(isspace(**src) || (**src == ':'))) {
167944099b7bSPaul Traina return (-1);
168044099b7bSPaul Traina }
168144099b7bSPaul Traina #endif
168244099b7bSPaul Traina
168344099b7bSPaul Traina /*
168444099b7bSPaul Traina * Construct the address according to
168544099b7bSPaul Traina * the number of parts specified.
168644099b7bSPaul Traina */
168744099b7bSPaul Traina n = pp - parts;
168844099b7bSPaul Traina switch (n) {
168944099b7bSPaul Traina case 1: /* a -- 32 bits */
169044099b7bSPaul Traina value = parts[0];
169144099b7bSPaul Traina break;
169244099b7bSPaul Traina case 2: /* a.b -- 8.24 bits */
169344099b7bSPaul Traina value = (parts[0] << 24) | (parts[1] & 0xFFFFFF);
169444099b7bSPaul Traina break;
169544099b7bSPaul Traina case 3: /* a.b.c -- 8.8.16 bits */
169644099b7bSPaul Traina value = (parts[0] << 24) | ((parts[1] & 0xFF) << 16) |
169744099b7bSPaul Traina (parts[2] & 0xFFFF);
169844099b7bSPaul Traina break;
169944099b7bSPaul Traina case 4: /* a.b.c.d -- 8.8.8.8 bits */
170044099b7bSPaul Traina value = (parts[0] << 24) | ((parts[1] & 0xFF) << 16) |
170144099b7bSPaul Traina ((parts[2] & 0xFF) << 8) | (parts[3] & 0xFF);
170244099b7bSPaul Traina break;
170344099b7bSPaul Traina default:
170444099b7bSPaul Traina return (-1);
170544099b7bSPaul Traina }
170644099b7bSPaul Traina *result = htonl(value);
170744099b7bSPaul Traina return (0);
170844099b7bSPaul Traina }
170944099b7bSPaul Traina
171044099b7bSPaul Traina
171144099b7bSPaul Traina
171244099b7bSPaul Traina /*
171344099b7bSPaul Traina * "src" points to a pointer which in turn points to a hexadecimal ASCII
171444099b7bSPaul Traina * string. This string is interpreted as a hardware address and returned
171544099b7bSPaul Traina * as a pointer to the actual hardware address, represented as an array of
171644099b7bSPaul Traina * bytes.
171744099b7bSPaul Traina *
171844099b7bSPaul Traina * The ASCII string must have the proper number of digits for the specified
171944099b7bSPaul Traina * hardware type (e.g. twelve digits for a 48-bit Ethernet address).
172044099b7bSPaul Traina * Two-digit sequences (bytes) may be separated with periods (.) and/or
172144099b7bSPaul Traina * prefixed with '0x' for readability, but this is not required.
172244099b7bSPaul Traina *
172344099b7bSPaul Traina * For bad addresses, the pointer which "src" points to is updated to point
172444099b7bSPaul Traina * to the start of the first two-digit sequence which was bad, and the
172544099b7bSPaul Traina * function returns a NULL pointer.
172644099b7bSPaul Traina */
172744099b7bSPaul Traina
172844099b7bSPaul Traina PRIVATE byte *
prs_haddr(char ** src,u_int htype)1729*8b356c88SJohn Baldwin prs_haddr(char **src, u_int htype)
173044099b7bSPaul Traina {
173144099b7bSPaul Traina static byte haddr[MAXHADDRLEN];
173244099b7bSPaul Traina byte *hap;
173344099b7bSPaul Traina char tmpstr[MAXSTRINGLEN];
173444099b7bSPaul Traina u_int tmplen;
173544099b7bSPaul Traina unsigned hal;
173644099b7bSPaul Traina char *p;
173744099b7bSPaul Traina
173844099b7bSPaul Traina hal = haddrlength(htype); /* Get length of this address type */
173944099b7bSPaul Traina if (hal <= 0) {
174044099b7bSPaul Traina report(LOG_ERR, "Invalid addr type for HW addr parse");
174144099b7bSPaul Traina return NULL;
174244099b7bSPaul Traina }
174344099b7bSPaul Traina tmplen = sizeof(tmpstr);
174444099b7bSPaul Traina get_string(src, tmpstr, &tmplen);
174544099b7bSPaul Traina p = tmpstr;
174644099b7bSPaul Traina
174744099b7bSPaul Traina /* If it's a valid host name, try to lookup the HW address. */
174844099b7bSPaul Traina if (goodname(p)) {
174944099b7bSPaul Traina /* Lookup Hardware Address for hostname. */
175044099b7bSPaul Traina if ((hap = lookup_hwa(p, htype)) != NULL)
175144099b7bSPaul Traina return hap; /* success */
175244099b7bSPaul Traina report(LOG_ERR, "Add 0x prefix if hex value starts with A-F");
175344099b7bSPaul Traina /* OK, assume it must be numeric. */
175444099b7bSPaul Traina }
175544099b7bSPaul Traina
175644099b7bSPaul Traina hap = haddr;
175744099b7bSPaul Traina while (hap < haddr + hal) {
1758e08ac58bSPaul Traina if ((*p == '.') || (*p == ':'))
175944099b7bSPaul Traina p++;
176044099b7bSPaul Traina if (interp_byte(&p, hap++) < 0) {
176144099b7bSPaul Traina return NULL;
176244099b7bSPaul Traina }
176344099b7bSPaul Traina }
176444099b7bSPaul Traina return haddr;
176544099b7bSPaul Traina }
176644099b7bSPaul Traina
176744099b7bSPaul Traina
176844099b7bSPaul Traina
176944099b7bSPaul Traina /*
177044099b7bSPaul Traina * "src" is a pointer to a character pointer which in turn points to a
177144099b7bSPaul Traina * hexadecimal ASCII representation of a byte. This byte is read, the
177244099b7bSPaul Traina * character pointer is updated, and the result is deposited into the
177344099b7bSPaul Traina * byte pointed to by "retbyte".
177444099b7bSPaul Traina *
177544099b7bSPaul Traina * The usual '0x' notation is allowed but not required. The number must be
177644099b7bSPaul Traina * a two digit hexadecimal number. If the number is invalid, "src" and
177744099b7bSPaul Traina * "retbyte" are left untouched and -1 is returned as the function value.
177844099b7bSPaul Traina * Successful calls return 0.
177944099b7bSPaul Traina */
178044099b7bSPaul Traina
178144099b7bSPaul Traina PRIVATE int
interp_byte(char ** src,byte * retbyte)1782*8b356c88SJohn Baldwin interp_byte(char **src, byte *retbyte)
178344099b7bSPaul Traina {
178444099b7bSPaul Traina int v;
178544099b7bSPaul Traina
178644099b7bSPaul Traina if ((*src)[0] == '0' &&
178744099b7bSPaul Traina ((*src)[1] == 'x' ||
178844099b7bSPaul Traina (*src)[1] == 'X')) {
178944099b7bSPaul Traina (*src) += 2; /* allow 0x for hex, but don't require it */
179044099b7bSPaul Traina }
179144099b7bSPaul Traina if (!isxdigit((*src)[0]) || !isxdigit((*src)[1])) {
179244099b7bSPaul Traina return -1;
179344099b7bSPaul Traina }
179444099b7bSPaul Traina if (sscanf(*src, "%2x", &v) != 1) {
179544099b7bSPaul Traina return -1;
179644099b7bSPaul Traina }
179744099b7bSPaul Traina (*src) += 2;
179844099b7bSPaul Traina *retbyte = (byte) (v & 0xFF);
179944099b7bSPaul Traina return 0;
180044099b7bSPaul Traina }
180144099b7bSPaul Traina
180244099b7bSPaul Traina
180344099b7bSPaul Traina
180444099b7bSPaul Traina /*
180544099b7bSPaul Traina * The parameter "src" points to a character pointer which points to an
180644099b7bSPaul Traina * ASCII string representation of an unsigned number. The number is
180744099b7bSPaul Traina * returned as an unsigned long and the character pointer is updated to
180844099b7bSPaul Traina * point to the first illegal character.
180944099b7bSPaul Traina */
181044099b7bSPaul Traina
181144099b7bSPaul Traina PRIVATE u_int32
get_u_long(char ** src)1812*8b356c88SJohn Baldwin get_u_long(char **src)
181344099b7bSPaul Traina {
181407ee9f80SPedro F. Giffuni u_int32 value, base;
181544099b7bSPaul Traina char c;
181644099b7bSPaul Traina
181744099b7bSPaul Traina /*
181844099b7bSPaul Traina * Collect number up to first illegal character. Values are specified
181944099b7bSPaul Traina * as for C: 0x=hex, 0=octal, other=decimal.
182044099b7bSPaul Traina */
182144099b7bSPaul Traina value = 0;
182244099b7bSPaul Traina base = 10;
182344099b7bSPaul Traina if (**src == '0') {
182444099b7bSPaul Traina base = 8;
182544099b7bSPaul Traina (*src)++;
182644099b7bSPaul Traina }
182744099b7bSPaul Traina if (**src == 'x' || **src == 'X') {
182844099b7bSPaul Traina base = 16;
182944099b7bSPaul Traina (*src)++;
183044099b7bSPaul Traina }
183144099b7bSPaul Traina while ((c = **src)) {
183244099b7bSPaul Traina if (isdigit(c)) {
183344099b7bSPaul Traina value = (value * base) + (c - '0');
183444099b7bSPaul Traina (*src)++;
183544099b7bSPaul Traina continue;
183644099b7bSPaul Traina }
183744099b7bSPaul Traina if (base == 16 && isxdigit(c)) {
183844099b7bSPaul Traina value = (value << 4) + ((c & ~32) + 10 - 'A');
183944099b7bSPaul Traina (*src)++;
184044099b7bSPaul Traina continue;
184144099b7bSPaul Traina }
184244099b7bSPaul Traina break;
184344099b7bSPaul Traina }
184444099b7bSPaul Traina return value;
184544099b7bSPaul Traina }
184644099b7bSPaul Traina
184744099b7bSPaul Traina
184844099b7bSPaul Traina
184944099b7bSPaul Traina /*
185044099b7bSPaul Traina * Routines for deletion of data associated with the main data structure.
185144099b7bSPaul Traina */
185244099b7bSPaul Traina
185344099b7bSPaul Traina
185444099b7bSPaul Traina /*
185544099b7bSPaul Traina * Frees the entire host data structure given. Does nothing if the passed
185644099b7bSPaul Traina * pointer is NULL.
185744099b7bSPaul Traina */
185844099b7bSPaul Traina
185944099b7bSPaul Traina PRIVATE void
free_host(hash_datum * hmp)1860*8b356c88SJohn Baldwin free_host(hash_datum *hmp)
186144099b7bSPaul Traina {
186244099b7bSPaul Traina struct host *hostptr = (struct host *) hmp;
186344099b7bSPaul Traina if (hostptr == NULL)
186444099b7bSPaul Traina return;
186544099b7bSPaul Traina assert(hostptr->linkcount > 0);
186644099b7bSPaul Traina if (--(hostptr->linkcount))
186744099b7bSPaul Traina return; /* Still has references */
186844099b7bSPaul Traina del_iplist(hostptr->cookie_server);
186944099b7bSPaul Traina del_iplist(hostptr->domain_server);
187044099b7bSPaul Traina del_iplist(hostptr->gateway);
187144099b7bSPaul Traina del_iplist(hostptr->impress_server);
187244099b7bSPaul Traina del_iplist(hostptr->log_server);
187344099b7bSPaul Traina del_iplist(hostptr->lpr_server);
187444099b7bSPaul Traina del_iplist(hostptr->name_server);
187544099b7bSPaul Traina del_iplist(hostptr->rlp_server);
187644099b7bSPaul Traina del_iplist(hostptr->time_server);
187744099b7bSPaul Traina del_iplist(hostptr->nis_server);
187844099b7bSPaul Traina del_iplist(hostptr->ntp_server);
187944099b7bSPaul Traina
188044099b7bSPaul Traina /*
188144099b7bSPaul Traina * XXX - Add new tags here
188244099b7bSPaul Traina * (if the value is an IP list)
188344099b7bSPaul Traina */
188444099b7bSPaul Traina
188544099b7bSPaul Traina del_string(hostptr->hostname);
188644099b7bSPaul Traina del_string(hostptr->homedir);
188744099b7bSPaul Traina del_string(hostptr->bootfile);
188844099b7bSPaul Traina del_string(hostptr->tftpdir);
188944099b7bSPaul Traina del_string(hostptr->root_path);
189044099b7bSPaul Traina del_string(hostptr->domain_name);
189144099b7bSPaul Traina del_string(hostptr->dump_file);
189244099b7bSPaul Traina del_string(hostptr->exten_file);
189344099b7bSPaul Traina del_string(hostptr->nis_domain);
189444099b7bSPaul Traina
189544099b7bSPaul Traina #ifdef YORK_EX_OPTION
189644099b7bSPaul Traina del_string(hostptr->exec_file);
189744099b7bSPaul Traina #endif
189844099b7bSPaul Traina
189944099b7bSPaul Traina /*
190044099b7bSPaul Traina * XXX - Add new tags here
190144099b7bSPaul Traina * (if it is a shared string)
190244099b7bSPaul Traina */
190344099b7bSPaul Traina
190444099b7bSPaul Traina del_bindata(hostptr->generic);
190544099b7bSPaul Traina free((char *) hostptr);
190644099b7bSPaul Traina }
190744099b7bSPaul Traina
190844099b7bSPaul Traina
190944099b7bSPaul Traina
191044099b7bSPaul Traina /*
191144099b7bSPaul Traina * Decrements the linkcount on the given IP address data structure. If the
191244099b7bSPaul Traina * linkcount goes to zero, the memory associated with the data is freed.
191344099b7bSPaul Traina */
191444099b7bSPaul Traina
191544099b7bSPaul Traina PRIVATE void
del_iplist(struct in_addr_list * iplist)1916*8b356c88SJohn Baldwin del_iplist(struct in_addr_list *iplist)
191744099b7bSPaul Traina {
191844099b7bSPaul Traina if (iplist) {
191944099b7bSPaul Traina if (!(--(iplist->linkcount))) {
192044099b7bSPaul Traina free((char *) iplist);
192144099b7bSPaul Traina }
192244099b7bSPaul Traina }
192344099b7bSPaul Traina }
192444099b7bSPaul Traina
192544099b7bSPaul Traina
192644099b7bSPaul Traina
192744099b7bSPaul Traina /*
192844099b7bSPaul Traina * Decrements the linkcount on a string data structure. If the count
192944099b7bSPaul Traina * goes to zero, the memory associated with the string is freed. Does
193044099b7bSPaul Traina * nothing if the passed pointer is NULL.
193144099b7bSPaul Traina */
193244099b7bSPaul Traina
193344099b7bSPaul Traina PRIVATE void
del_string(struct shared_string * stringptr)1934*8b356c88SJohn Baldwin del_string(struct shared_string *stringptr)
193544099b7bSPaul Traina {
193644099b7bSPaul Traina if (stringptr) {
193744099b7bSPaul Traina if (!(--(stringptr->linkcount))) {
193844099b7bSPaul Traina free((char *) stringptr);
193944099b7bSPaul Traina }
194044099b7bSPaul Traina }
194144099b7bSPaul Traina }
194244099b7bSPaul Traina
194344099b7bSPaul Traina
194444099b7bSPaul Traina
194544099b7bSPaul Traina /*
194644099b7bSPaul Traina * Decrements the linkcount on a shared_bindata data structure. If the
194744099b7bSPaul Traina * count goes to zero, the memory associated with the data is freed. Does
194844099b7bSPaul Traina * nothing if the passed pointer is NULL.
194944099b7bSPaul Traina */
195044099b7bSPaul Traina
195144099b7bSPaul Traina PRIVATE void
del_bindata(struct shared_bindata * dataptr)1952*8b356c88SJohn Baldwin del_bindata(struct shared_bindata *dataptr)
195344099b7bSPaul Traina {
195444099b7bSPaul Traina if (dataptr) {
195544099b7bSPaul Traina if (!(--(dataptr->linkcount))) {
195644099b7bSPaul Traina free((char *) dataptr);
195744099b7bSPaul Traina }
195844099b7bSPaul Traina }
195944099b7bSPaul Traina }
196044099b7bSPaul Traina
196144099b7bSPaul Traina
196244099b7bSPaul Traina
196344099b7bSPaul Traina
196444099b7bSPaul Traina /* smalloc() -- safe malloc()
196544099b7bSPaul Traina *
196644099b7bSPaul Traina * Always returns a valid pointer (if it returns at all). The allocated
196744099b7bSPaul Traina * memory is initialized to all zeros. If malloc() returns an error, a
196844099b7bSPaul Traina * message is printed using the report() function and the program aborts
196944099b7bSPaul Traina * with a status of 1.
197044099b7bSPaul Traina */
197144099b7bSPaul Traina
197244099b7bSPaul Traina PRIVATE char *
smalloc(unsigned nbytes)1973*8b356c88SJohn Baldwin smalloc(unsigned nbytes)
197444099b7bSPaul Traina {
197544099b7bSPaul Traina char *retvalue;
197644099b7bSPaul Traina
197744099b7bSPaul Traina retvalue = malloc(nbytes);
197844099b7bSPaul Traina if (!retvalue) {
197944099b7bSPaul Traina report(LOG_ERR, "malloc() failure -- exiting");
198044099b7bSPaul Traina exit(1);
198144099b7bSPaul Traina }
198244099b7bSPaul Traina bzero(retvalue, nbytes);
198344099b7bSPaul Traina return retvalue;
198444099b7bSPaul Traina }
198544099b7bSPaul Traina
198644099b7bSPaul Traina
198744099b7bSPaul Traina /*
198844099b7bSPaul Traina * Compare function to determine whether two hardware addresses are
198944099b7bSPaul Traina * equivalent. Returns TRUE if "host1" and "host2" are equivalent, FALSE
199044099b7bSPaul Traina * otherwise.
199144099b7bSPaul Traina *
199244099b7bSPaul Traina * This function is used when retrieving elements from the hardware address
199344099b7bSPaul Traina * hash table.
199444099b7bSPaul Traina */
199544099b7bSPaul Traina
199644099b7bSPaul Traina boolean
hwlookcmp(hash_datum * d1,hash_datum * d2)1997*8b356c88SJohn Baldwin hwlookcmp(hash_datum *d1, hash_datum *d2)
199844099b7bSPaul Traina {
199944099b7bSPaul Traina struct host *host1 = (struct host *) d1;
200044099b7bSPaul Traina struct host *host2 = (struct host *) d2;
200144099b7bSPaul Traina
200244099b7bSPaul Traina if (host1->htype != host2->htype) {
200344099b7bSPaul Traina return FALSE;
200444099b7bSPaul Traina }
200544099b7bSPaul Traina if (bcmp(host1->haddr, host2->haddr, haddrlength(host1->htype))) {
200644099b7bSPaul Traina return FALSE;
200744099b7bSPaul Traina }
200844099b7bSPaul Traina return TRUE;
200944099b7bSPaul Traina }
201044099b7bSPaul Traina
201144099b7bSPaul Traina
201244099b7bSPaul Traina /*
201344099b7bSPaul Traina * Compare function for doing IP address hash table lookup.
201444099b7bSPaul Traina */
201544099b7bSPaul Traina
201644099b7bSPaul Traina boolean
iplookcmp(hash_datum * d1,hash_datum * d2)2017*8b356c88SJohn Baldwin iplookcmp(hash_datum *d1, hash_datum *d2)
201844099b7bSPaul Traina {
201944099b7bSPaul Traina struct host *host1 = (struct host *) d1;
202044099b7bSPaul Traina struct host *host2 = (struct host *) d2;
202144099b7bSPaul Traina
202244099b7bSPaul Traina return (host1->iaddr.s_addr == host2->iaddr.s_addr);
202344099b7bSPaul Traina }
202444099b7bSPaul Traina
202544099b7bSPaul Traina /*
202644099b7bSPaul Traina * Local Variables:
202744099b7bSPaul Traina * tab-width: 4
202844099b7bSPaul Traina * c-indent-level: 4
202944099b7bSPaul Traina * c-argdecl-indent: 4
203044099b7bSPaul Traina * c-continued-statement-offset: 4
203144099b7bSPaul Traina * c-continued-brace-offset: -4
203244099b7bSPaul Traina * c-label-offset: -4
203344099b7bSPaul Traina * c-brace-offset: 0
203444099b7bSPaul Traina * End:
203544099b7bSPaul Traina */
2036