PageRenderTime 23ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/libexec/rbootd/parseconf.c

https://bitbucket.org/freebsd/freebsd-base
C | 360 lines | 165 code | 36 blank | 159 comment | 68 complexity | 4ee0f211e0b311aee793d74c6a32f3b4 MD5 | raw file
  1. /*-
  2. * SPDX-License-Identifier: BSD-3-Clause
  3. *
  4. * Copyright (c) 1988, 1992 The University of Utah and the Center
  5. * for Software Science (CSS).
  6. * Copyright (c) 1992, 1993
  7. * The Regents of the University of California. All rights reserved.
  8. *
  9. * This code is derived from software contributed to Berkeley by
  10. * the Center for Software Science of the University of Utah Computer
  11. * Science Department. CSS requests users of this software to return
  12. * to css-dist@cs.utah.edu any improvements that they make and grant
  13. * CSS redistribution rights.
  14. *
  15. * Redistribution and use in source and binary forms, with or without
  16. * modification, are permitted provided that the following conditions
  17. * are met:
  18. * 1. Redistributions of source code must retain the above copyright
  19. * notice, this list of conditions and the following disclaimer.
  20. * 2. Redistributions in binary form must reproduce the above copyright
  21. * notice, this list of conditions and the following disclaimer in the
  22. * documentation and/or other materials provided with the distribution.
  23. * 3. Neither the name of the University nor the names of its contributors
  24. * may be used to endorse or promote products derived from this software
  25. * without specific prior written permission.
  26. *
  27. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  28. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  29. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  30. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  31. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  32. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  33. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  34. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  35. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  36. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  37. * SUCH DAMAGE.
  38. *
  39. * from: @(#)parseconf.c 8.1 (Berkeley) 6/4/93
  40. *
  41. * From: Utah Hdr: parseconf.c 3.1 92/07/06
  42. * Author: Jeff Forys, University of Utah CSS
  43. */
  44. #ifndef lint
  45. #if 0
  46. static const char sccsid[] = "@(#)parseconf.c 8.1 (Berkeley) 6/4/93";
  47. #endif
  48. static const char rcsid[] =
  49. "$FreeBSD$";
  50. #endif /* not lint */
  51. #include <sys/param.h>
  52. #include <sys/stat.h>
  53. #include <sys/time.h>
  54. #include <ctype.h>
  55. #include <dirent.h>
  56. #include <fcntl.h>
  57. #include <signal.h>
  58. #include <stdio.h>
  59. #include <stdlib.h>
  60. #include <string.h>
  61. #include <syslog.h>
  62. #include "defs.h"
  63. /*
  64. ** ParseConfig -- parse the config file into linked list of clients.
  65. **
  66. ** Parameters:
  67. ** None.
  68. **
  69. ** Returns:
  70. ** 1 on success, 0 otherwise.
  71. **
  72. ** Side Effects:
  73. ** - Linked list of clients will be (re)allocated.
  74. **
  75. ** Warnings:
  76. ** - GetBootFiles() must be called before this routine
  77. ** to create a linked list of default boot files.
  78. */
  79. int
  80. ParseConfig(void)
  81. {
  82. FILE *fp;
  83. CLIENT *client;
  84. u_int8_t *addr;
  85. char line[C_LINELEN];
  86. char *cp, *bcp;
  87. int i, j;
  88. int omask, linecnt = 0;
  89. if (BootAny) /* ignore config file */
  90. return(1);
  91. FreeClients(); /* delete old list of clients */
  92. if ((fp = fopen(ConfigFile, "r")) == NULL) {
  93. syslog(LOG_ERR, "ParseConfig: can't open config file (%s)",
  94. ConfigFile);
  95. return(0);
  96. }
  97. /*
  98. * We've got to block SIGHUP to prevent reconfiguration while
  99. * dealing with the linked list of Clients. This can be done
  100. * when actually linking the new client into the list, but
  101. * this could have unexpected results if the server was HUP'd
  102. * whilst reconfiguring. Hence, it is done here.
  103. */
  104. omask = sigblock(sigmask(SIGHUP));
  105. /*
  106. * GETSTR positions `bcp' at the start of the current token,
  107. * and null terminates it. `cp' is positioned at the start
  108. * of the next token. spaces & commas are separators.
  109. */
  110. #define GETSTR while (isspace(*cp) || *cp == ',') cp++; \
  111. bcp = cp; \
  112. while (*cp && *cp!=',' && !isspace(*cp)) cp++; \
  113. if (*cp) *cp++ = '\0'
  114. /*
  115. * For each line, parse it into a new CLIENT struct.
  116. */
  117. while (fgets(line, C_LINELEN, fp) != NULL) {
  118. linecnt++; /* line counter */
  119. if (*line == '\0' || *line == '#') /* ignore comment */
  120. continue;
  121. if ((cp = strchr(line,'#')) != NULL) /* trash comments */
  122. *cp = '\0';
  123. cp = line; /* init `cp' */
  124. GETSTR; /* get RMP addr */
  125. if (bcp == cp) /* all delimiters */
  126. continue;
  127. /*
  128. * Get an RMP address from a string. Abort on failure.
  129. */
  130. if ((addr = ParseAddr(bcp)) == NULL) {
  131. syslog(LOG_ERR,
  132. "ParseConfig: line %d: can't parse <%s>",
  133. linecnt, bcp);
  134. continue;
  135. }
  136. if ((client = NewClient(addr)) == NULL) /* alloc new client */
  137. continue;
  138. GETSTR; /* get first file */
  139. /*
  140. * If no boot files are spec'd, use the default list.
  141. * Otherwise, validate each file (`bcp') against the
  142. * list of boot-able files.
  143. */
  144. i = 0;
  145. if (bcp == cp) /* no files spec'd */
  146. for (; i < C_MAXFILE && BootFiles[i] != NULL; i++)
  147. client->files[i] = BootFiles[i];
  148. else {
  149. do {
  150. /*
  151. * For each boot file spec'd, make sure it's
  152. * in our list. If so, include a pointer to
  153. * it in the CLIENT's list of boot files.
  154. */
  155. for (j = 0; ; j++) {
  156. if (j==C_MAXFILE||BootFiles[j]==NULL) {
  157. syslog(LOG_ERR, "ParseConfig: line %d: no boot file (%s)",
  158. linecnt, bcp);
  159. break;
  160. }
  161. if (STREQN(BootFiles[j], bcp)) {
  162. if (i < C_MAXFILE)
  163. client->files[i++] =
  164. BootFiles[j];
  165. else
  166. syslog(LOG_ERR, "ParseConfig: line %d: too many boot files (%s)",
  167. linecnt, bcp);
  168. break;
  169. }
  170. }
  171. GETSTR; /* get next file */
  172. } while (bcp != cp);
  173. /*
  174. * Restricted list of boot files were spec'd,
  175. * however, none of them were found. Since we
  176. * apparently can't let them boot "just anything",
  177. * the entire record is invalidated.
  178. */
  179. if (i == 0) {
  180. FreeClient(client);
  181. continue;
  182. }
  183. }
  184. /*
  185. * Link this client into the linked list of clients.
  186. * SIGHUP has already been blocked.
  187. */
  188. if (Clients)
  189. client->next = Clients;
  190. Clients = client;
  191. }
  192. (void) fclose(fp); /* close config file */
  193. (void) sigsetmask(omask); /* reset signal mask */
  194. return(1); /* return success */
  195. }
  196. /*
  197. ** ParseAddr -- Parse a string containing an RMP address.
  198. **
  199. ** This routine is fairly liberal at parsing an RMP address. The
  200. ** address must contain 6 octets consisting of between 0 and 2 hex
  201. ** chars (upper/lower case) separated by colons. If two colons are
  202. ** together (e.g. "::", the octet between them is recorded as being
  203. ** zero. Hence, the following addrs are all valid and parse to the
  204. ** same thing:
  205. **
  206. ** 08:00:09:00:66:ad 8::9:0:66:AD 8::9::66:aD
  207. **
  208. ** For clarity, an RMP address is really an Ethernet address, but
  209. ** since the HP boot code uses IEEE 802.3, it's really an IEEE
  210. ** 802.3 address. Of course, all of these are identical.
  211. **
  212. ** Parameters:
  213. ** str - string representation of an RMP address.
  214. **
  215. ** Returns:
  216. ** pointer to a static array of RMP_ADDRLEN bytes.
  217. **
  218. ** Side Effects:
  219. ** None.
  220. **
  221. ** Warnings:
  222. ** - The return value points to a static buffer; it must
  223. ** be copied if it's to be saved.
  224. */
  225. u_int8_t *
  226. ParseAddr(char *str)
  227. {
  228. static u_int8_t addr[RMP_ADDRLEN];
  229. char *cp;
  230. unsigned i;
  231. int part, subpart;
  232. memset((char *)&addr[0], 0, RMP_ADDRLEN); /* zero static buffer */
  233. part = subpart = 0;
  234. for (cp = str; *cp; cp++) {
  235. /*
  236. * A colon (`:') must be used to delimit each octet.
  237. */
  238. if (*cp == ':') {
  239. if (++part == RMP_ADDRLEN) /* too many parts */
  240. return(NULL);
  241. subpart = 0;
  242. continue;
  243. }
  244. /*
  245. * Convert hex character to an integer.
  246. */
  247. if (isdigit(*cp))
  248. i = *cp - '0';
  249. else {
  250. i = (isupper(*cp)? tolower(*cp): *cp) - 'a' + 10;
  251. if (i < 10 || i > 15) /* not a hex char */
  252. return(NULL);
  253. }
  254. if (subpart++) {
  255. if (subpart > 2) /* too many hex chars */
  256. return(NULL);
  257. addr[part] <<= 4;
  258. }
  259. addr[part] |= i;
  260. }
  261. if (part != (RMP_ADDRLEN-1)) /* too few parts */
  262. return(NULL);
  263. return(&addr[0]);
  264. }
  265. /*
  266. ** GetBootFiles -- record list of files in current (boot) directory.
  267. **
  268. ** Parameters:
  269. ** None.
  270. **
  271. ** Returns:
  272. ** Number of boot files on success, 0 on failure.
  273. **
  274. ** Side Effects:
  275. ** Strings in `BootFiles' are freed/allocated.
  276. **
  277. ** Warnings:
  278. ** - After this routine is called, ParseConfig() must be
  279. ** called to re-order it's list of boot file pointers.
  280. */
  281. int
  282. GetBootFiles(void)
  283. {
  284. DIR *dfd;
  285. struct stat statb;
  286. struct dirent *dp;
  287. int i;
  288. /*
  289. * Free the current list of boot files.
  290. */
  291. for (i = 0; i < C_MAXFILE && BootFiles[i] != NULL; i++) {
  292. FreeStr(BootFiles[i]);
  293. BootFiles[i] = NULL;
  294. }
  295. /*
  296. * Open current directory to read boot file names.
  297. */
  298. if ((dfd = opendir(".")) == NULL) { /* open BootDir */
  299. syslog(LOG_ERR, "GetBootFiles: can't open directory (%s)\n",
  300. BootDir);
  301. return(0);
  302. }
  303. /*
  304. * Read each boot file name and allocate space for it in the
  305. * list of boot files (BootFiles). All boot files read after
  306. * C_MAXFILE will be ignored.
  307. */
  308. i = 0;
  309. for (dp = readdir(dfd); dp != NULL; dp = readdir(dfd)) {
  310. if (stat(dp->d_name, &statb) < 0 ||
  311. (statb.st_mode & S_IFMT) != S_IFREG)
  312. continue;
  313. if (i == C_MAXFILE)
  314. syslog(LOG_ERR,
  315. "GetBootFiles: too many boot files (%s ignored)",
  316. dp->d_name);
  317. else if ((BootFiles[i] = NewStr(dp->d_name)) != NULL)
  318. i++;
  319. }
  320. (void) closedir(dfd); /* close BootDir */
  321. if (i == 0) /* can't find any boot files */
  322. syslog(LOG_ERR, "GetBootFiles: no boot files (%s)\n", BootDir);
  323. return(i);
  324. }