11592Srgrimes/* 21592Srgrimes * Copyright (c) 1988, 1992 The University of Utah and the Center 31592Srgrimes * for Software Science (CSS). 41592Srgrimes * Copyright (c) 1992, 1993 51592Srgrimes * The Regents of the University of California. All rights reserved. 61592Srgrimes * 71592Srgrimes * This code is derived from software contributed to Berkeley by 81592Srgrimes * the Center for Software Science of the University of Utah Computer 91592Srgrimes * Science Department. CSS requests users of this software to return 101592Srgrimes * to css-dist@cs.utah.edu any improvements that they make and grant 111592Srgrimes * CSS redistribution rights. 121592Srgrimes * 131592Srgrimes * Redistribution and use in source and binary forms, with or without 141592Srgrimes * modification, are permitted provided that the following conditions 151592Srgrimes * are met: 161592Srgrimes * 1. Redistributions of source code must retain the above copyright 171592Srgrimes * notice, this list of conditions and the following disclaimer. 181592Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 191592Srgrimes * notice, this list of conditions and the following disclaimer in the 201592Srgrimes * documentation and/or other materials provided with the distribution. 21262435Sbrueffer * 3. Neither the name of the University nor the names of its contributors 221592Srgrimes * may be used to endorse or promote products derived from this software 231592Srgrimes * without specific prior written permission. 241592Srgrimes * 251592Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 261592Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 271592Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 281592Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 291592Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 301592Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 311592Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 321592Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 331592Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 341592Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 351592Srgrimes * SUCH DAMAGE. 361592Srgrimes * 3727077Ssteve * from: @(#)parseconf.c 8.1 (Berkeley) 6/4/93 381592Srgrimes * 3927077Ssteve * From: Utah Hdr: parseconf.c 3.1 92/07/06 401592Srgrimes * Author: Jeff Forys, University of Utah CSS 411592Srgrimes */ 421592Srgrimes 431592Srgrimes#ifndef lint 4431386Scharnier#if 0 4527077Sstevestatic const char sccsid[] = "@(#)parseconf.c 8.1 (Berkeley) 6/4/93"; 4631386Scharnier#endif 4731386Scharnierstatic const char rcsid[] = 4850476Speter "$FreeBSD$"; 491592Srgrimes#endif /* not lint */ 501592Srgrimes 511592Srgrimes#include <sys/param.h> 521592Srgrimes#include <sys/stat.h> 5366907Swollman#include <sys/time.h> 541592Srgrimes 551592Srgrimes#include <ctype.h> 561592Srgrimes#include <dirent.h> 571592Srgrimes#include <fcntl.h> 581592Srgrimes#include <signal.h> 591592Srgrimes#include <stdio.h> 601592Srgrimes#include <stdlib.h> 611592Srgrimes#include <string.h> 621592Srgrimes#include <syslog.h> 631592Srgrimes#include "defs.h" 641592Srgrimes 651592Srgrimes/* 661592Srgrimes** ParseConfig -- parse the config file into linked list of clients. 671592Srgrimes** 681592Srgrimes** Parameters: 691592Srgrimes** None. 701592Srgrimes** 711592Srgrimes** Returns: 721592Srgrimes** 1 on success, 0 otherwise. 731592Srgrimes** 741592Srgrimes** Side Effects: 751592Srgrimes** - Linked list of clients will be (re)allocated. 761592Srgrimes** 771592Srgrimes** Warnings: 781592Srgrimes** - GetBootFiles() must be called before this routine 791592Srgrimes** to create a linked list of default boot files. 801592Srgrimes*/ 811592Srgrimesint 8290377SimpParseConfig(void) 831592Srgrimes{ 841592Srgrimes FILE *fp; 851592Srgrimes CLIENT *client; 8627077Ssteve u_int8_t *addr; 871592Srgrimes char line[C_LINELEN]; 8827079Ssteve char *cp, *bcp; 8927079Ssteve int i, j; 901592Srgrimes int omask, linecnt = 0; 911592Srgrimes 921592Srgrimes if (BootAny) /* ignore config file */ 931592Srgrimes return(1); 941592Srgrimes 951592Srgrimes FreeClients(); /* delete old list of clients */ 961592Srgrimes 971592Srgrimes if ((fp = fopen(ConfigFile, "r")) == NULL) { 981592Srgrimes syslog(LOG_ERR, "ParseConfig: can't open config file (%s)", 991592Srgrimes ConfigFile); 1001592Srgrimes return(0); 1011592Srgrimes } 1021592Srgrimes 1031592Srgrimes /* 1041592Srgrimes * We've got to block SIGHUP to prevent reconfiguration while 1051592Srgrimes * dealing with the linked list of Clients. This can be done 1061592Srgrimes * when actually linking the new client into the list, but 1071592Srgrimes * this could have unexpected results if the server was HUP'd 1081592Srgrimes * whilst reconfiguring. Hence, it is done here. 1091592Srgrimes */ 1101592Srgrimes omask = sigblock(sigmask(SIGHUP)); 1111592Srgrimes 1121592Srgrimes /* 1131592Srgrimes * GETSTR positions `bcp' at the start of the current token, 1141592Srgrimes * and null terminates it. `cp' is positioned at the start 1151592Srgrimes * of the next token. spaces & commas are separators. 1161592Srgrimes */ 1171592Srgrimes#define GETSTR while (isspace(*cp) || *cp == ',') cp++; \ 1181592Srgrimes bcp = cp; \ 1191592Srgrimes while (*cp && *cp!=',' && !isspace(*cp)) cp++; \ 1201592Srgrimes if (*cp) *cp++ = '\0' 1211592Srgrimes 1221592Srgrimes /* 1231592Srgrimes * For each line, parse it into a new CLIENT struct. 1241592Srgrimes */ 1251592Srgrimes while (fgets(line, C_LINELEN, fp) != NULL) { 1261592Srgrimes linecnt++; /* line counter */ 1271592Srgrimes 1281592Srgrimes if (*line == '\0' || *line == '#') /* ignore comment */ 1291592Srgrimes continue; 1301592Srgrimes 13127079Ssteve if ((cp = strchr(line,'#')) != NULL) /* trash comments */ 1321592Srgrimes *cp = '\0'; 1331592Srgrimes 1341592Srgrimes cp = line; /* init `cp' */ 1351592Srgrimes GETSTR; /* get RMP addr */ 1361592Srgrimes if (bcp == cp) /* all delimiters */ 1371592Srgrimes continue; 1381592Srgrimes 1391592Srgrimes /* 1401592Srgrimes * Get an RMP address from a string. Abort on failure. 1411592Srgrimes */ 1421592Srgrimes if ((addr = ParseAddr(bcp)) == NULL) { 1431592Srgrimes syslog(LOG_ERR, 144229780Suqs "ParseConfig: line %d: can't parse <%s>", 1451592Srgrimes linecnt, bcp); 1461592Srgrimes continue; 1471592Srgrimes } 1481592Srgrimes 1491592Srgrimes if ((client = NewClient(addr)) == NULL) /* alloc new client */ 1501592Srgrimes continue; 1511592Srgrimes 1521592Srgrimes GETSTR; /* get first file */ 1531592Srgrimes 1541592Srgrimes /* 1551592Srgrimes * If no boot files are spec'd, use the default list. 1561592Srgrimes * Otherwise, validate each file (`bcp') against the 1571592Srgrimes * list of boot-able files. 1581592Srgrimes */ 1591592Srgrimes i = 0; 1601592Srgrimes if (bcp == cp) /* no files spec'd */ 1611592Srgrimes for (; i < C_MAXFILE && BootFiles[i] != NULL; i++) 1621592Srgrimes client->files[i] = BootFiles[i]; 1631592Srgrimes else { 1641592Srgrimes do { 1651592Srgrimes /* 1661592Srgrimes * For each boot file spec'd, make sure it's 1671592Srgrimes * in our list. If so, include a pointer to 1681592Srgrimes * it in the CLIENT's list of boot files. 1691592Srgrimes */ 1701592Srgrimes for (j = 0; ; j++) { 1711592Srgrimes if (j==C_MAXFILE||BootFiles[j]==NULL) { 1721592Srgrimes syslog(LOG_ERR, "ParseConfig: line %d: no boot file (%s)", 1731592Srgrimes linecnt, bcp); 1741592Srgrimes break; 1751592Srgrimes } 1761592Srgrimes if (STREQN(BootFiles[j], bcp)) { 1771592Srgrimes if (i < C_MAXFILE) 1781592Srgrimes client->files[i++] = 1791592Srgrimes BootFiles[j]; 1801592Srgrimes else 1811592Srgrimes syslog(LOG_ERR, "ParseConfig: line %d: too many boot files (%s)", 1821592Srgrimes linecnt, bcp); 1831592Srgrimes break; 1841592Srgrimes } 1851592Srgrimes } 1861592Srgrimes GETSTR; /* get next file */ 1871592Srgrimes } while (bcp != cp); 1881592Srgrimes 1891592Srgrimes /* 1901592Srgrimes * Restricted list of boot files were spec'd, 1911592Srgrimes * however, none of them were found. Since we 192229780Suqs * apparently can't let them boot "just anything", 1931592Srgrimes * the entire record is invalidated. 1941592Srgrimes */ 1951592Srgrimes if (i == 0) { 1968870Srgrimes FreeClient(client); 1971592Srgrimes continue; 1981592Srgrimes } 1991592Srgrimes } 2001592Srgrimes 2011592Srgrimes /* 2021592Srgrimes * Link this client into the linked list of clients. 2031592Srgrimes * SIGHUP has already been blocked. 2041592Srgrimes */ 2051592Srgrimes if (Clients) 2061592Srgrimes client->next = Clients; 2071592Srgrimes Clients = client; 2081592Srgrimes } 2091592Srgrimes 2101592Srgrimes (void) fclose(fp); /* close config file */ 2111592Srgrimes 2121592Srgrimes (void) sigsetmask(omask); /* reset signal mask */ 2131592Srgrimes 2141592Srgrimes return(1); /* return success */ 2151592Srgrimes} 2161592Srgrimes 2171592Srgrimes/* 2181592Srgrimes** ParseAddr -- Parse a string containing an RMP address. 2191592Srgrimes** 2201592Srgrimes** This routine is fairly liberal at parsing an RMP address. The 2211592Srgrimes** address must contain 6 octets consisting of between 0 and 2 hex 2221592Srgrimes** chars (upper/lower case) separated by colons. If two colons are 2231592Srgrimes** together (e.g. "::", the octet between them is recorded as being 2241592Srgrimes** zero. Hence, the following addrs are all valid and parse to the 2251592Srgrimes** same thing: 2261592Srgrimes** 2271592Srgrimes** 08:00:09:00:66:ad 8::9:0:66:AD 8::9::66:aD 2281592Srgrimes** 2291592Srgrimes** For clarity, an RMP address is really an Ethernet address, but 2301592Srgrimes** since the HP boot code uses IEEE 802.3, it's really an IEEE 2311592Srgrimes** 802.3 address. Of course, all of these are identical. 2321592Srgrimes** 2331592Srgrimes** Parameters: 2341592Srgrimes** str - string representation of an RMP address. 2351592Srgrimes** 2361592Srgrimes** Returns: 2371592Srgrimes** pointer to a static array of RMP_ADDRLEN bytes. 2381592Srgrimes** 2391592Srgrimes** Side Effects: 2401592Srgrimes** None. 2411592Srgrimes** 2421592Srgrimes** Warnings: 2431592Srgrimes** - The return value points to a static buffer; it must 2441592Srgrimes** be copied if it's to be saved. 2451592Srgrimes*/ 24627077Ssteveu_int8_t * 24790377SimpParseAddr(char *str) 2481592Srgrimes{ 24927077Ssteve static u_int8_t addr[RMP_ADDRLEN]; 25027079Ssteve char *cp; 25127079Ssteve unsigned i; 25227079Ssteve int part, subpart; 2531592Srgrimes 25427079Ssteve memset((char *)&addr[0], 0, RMP_ADDRLEN); /* zero static buffer */ 2551592Srgrimes 2561592Srgrimes part = subpart = 0; 2571592Srgrimes for (cp = str; *cp; cp++) { 2581592Srgrimes /* 2591592Srgrimes * A colon (`:') must be used to delimit each octet. 2601592Srgrimes */ 2611592Srgrimes if (*cp == ':') { 2621592Srgrimes if (++part == RMP_ADDRLEN) /* too many parts */ 2631592Srgrimes return(NULL); 2641592Srgrimes subpart = 0; 2651592Srgrimes continue; 2661592Srgrimes } 2671592Srgrimes 2681592Srgrimes /* 2691592Srgrimes * Convert hex character to an integer. 2701592Srgrimes */ 2711592Srgrimes if (isdigit(*cp)) 2721592Srgrimes i = *cp - '0'; 2731592Srgrimes else { 2741592Srgrimes i = (isupper(*cp)? tolower(*cp): *cp) - 'a' + 10; 2751592Srgrimes if (i < 10 || i > 15) /* not a hex char */ 2761592Srgrimes return(NULL); 2771592Srgrimes } 2781592Srgrimes 2791592Srgrimes if (subpart++) { 2801592Srgrimes if (subpart > 2) /* too many hex chars */ 2811592Srgrimes return(NULL); 2821592Srgrimes addr[part] <<= 4; 2831592Srgrimes } 2841592Srgrimes addr[part] |= i; 2851592Srgrimes } 2861592Srgrimes 2871592Srgrimes if (part != (RMP_ADDRLEN-1)) /* too few parts */ 2881592Srgrimes return(NULL); 2891592Srgrimes 2901592Srgrimes return(&addr[0]); 2911592Srgrimes} 2921592Srgrimes 2931592Srgrimes/* 2941592Srgrimes** GetBootFiles -- record list of files in current (boot) directory. 2951592Srgrimes** 2961592Srgrimes** Parameters: 2971592Srgrimes** None. 2981592Srgrimes** 2991592Srgrimes** Returns: 3001592Srgrimes** Number of boot files on success, 0 on failure. 3011592Srgrimes** 3021592Srgrimes** Side Effects: 3031592Srgrimes** Strings in `BootFiles' are freed/allocated. 3041592Srgrimes** 3051592Srgrimes** Warnings: 3061592Srgrimes** - After this routine is called, ParseConfig() must be 3071592Srgrimes** called to re-order it's list of boot file pointers. 3081592Srgrimes*/ 3091592Srgrimesint 31090377SimpGetBootFiles(void) 3111592Srgrimes{ 3121592Srgrimes DIR *dfd; 3131592Srgrimes struct stat statb; 31427079Ssteve struct dirent *dp; 31527079Ssteve int i; 3161592Srgrimes 3171592Srgrimes /* 3181592Srgrimes * Free the current list of boot files. 3191592Srgrimes */ 3201592Srgrimes for (i = 0; i < C_MAXFILE && BootFiles[i] != NULL; i++) { 3211592Srgrimes FreeStr(BootFiles[i]); 3221592Srgrimes BootFiles[i] = NULL; 3231592Srgrimes } 3241592Srgrimes 3251592Srgrimes /* 3261592Srgrimes * Open current directory to read boot file names. 3271592Srgrimes */ 3281592Srgrimes if ((dfd = opendir(".")) == NULL) { /* open BootDir */ 3291592Srgrimes syslog(LOG_ERR, "GetBootFiles: can't open directory (%s)\n", 3301592Srgrimes BootDir); 3311592Srgrimes return(0); 3321592Srgrimes } 3331592Srgrimes 3341592Srgrimes /* 3351592Srgrimes * Read each boot file name and allocate space for it in the 3361592Srgrimes * list of boot files (BootFiles). All boot files read after 3371592Srgrimes * C_MAXFILE will be ignored. 3381592Srgrimes */ 3391592Srgrimes i = 0; 3401592Srgrimes for (dp = readdir(dfd); dp != NULL; dp = readdir(dfd)) { 3411592Srgrimes if (stat(dp->d_name, &statb) < 0 || 3421592Srgrimes (statb.st_mode & S_IFMT) != S_IFREG) 3431592Srgrimes continue; 3441592Srgrimes if (i == C_MAXFILE) 3451592Srgrimes syslog(LOG_ERR, 3461592Srgrimes "GetBootFiles: too many boot files (%s ignored)", 3471592Srgrimes dp->d_name); 3481592Srgrimes else if ((BootFiles[i] = NewStr(dp->d_name)) != NULL) 3491592Srgrimes i++; 3501592Srgrimes } 3511592Srgrimes 3521592Srgrimes (void) closedir(dfd); /* close BootDir */ 3531592Srgrimes 354229780Suqs if (i == 0) /* can't find any boot files */ 3551592Srgrimes syslog(LOG_ERR, "GetBootFiles: no boot files (%s)\n", BootDir); 3561592Srgrimes 3571592Srgrimes return(i); 3581592Srgrimes} 359