parse.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631
  1. /*
  2. * Copyright (c) 2002-2004 MontaVista Software, Inc.
  3. *
  4. * All rights reserved.
  5. *
  6. * Author: Steven Dake (sdake@mvista.com)
  7. *
  8. * This software licensed under BSD license, the text of which follows:
  9. *
  10. * Redistribution and use in source and binary forms, with or without
  11. * modification, are permitted provided that the following conditions are met:
  12. *
  13. * - Redistributions of source code must retain the above copyright notice,
  14. * this list of conditions and the following disclaimer.
  15. * - Redistributions in binary form must reproduce the above copyright notice,
  16. * this list of conditions and the following disclaimer in the documentation
  17. * and/or other materials provided with the distribution.
  18. * - Neither the name of the MontaVista Software, Inc. nor the names of its
  19. * contributors may be used to endorse or promote products derived from this
  20. * software without specific prior written permission.
  21. *
  22. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  23. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  26. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  27. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  28. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  29. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  30. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  31. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  32. * THE POSSIBILITY OF SUCH DAMAGE.
  33. */
  34. #include <stdio.h>
  35. #include <string.h>
  36. #include <stdlib.h>
  37. #include <errno.h>
  38. #include <assert.h>
  39. #include <sys/socket.h>
  40. #include <netinet/in.h>
  41. #include <arpa/inet.h>
  42. #include "../include/ais_types.h"
  43. #include "../include/list.h"
  44. #include "util.h"
  45. #include "parse.h"
  46. #include "mempool.h"
  47. #include "print.h"
  48. DECLARE_LIST_INIT (saAmfGroupHead);
  49. static char error_string_response[512];
  50. typedef enum {
  51. AMF_HEAD,
  52. AMF_GROUP,
  53. AMF_UNIT,
  54. AMF_PROTECTION,
  55. AMF_COMPONENT
  56. } amf_parse_t;
  57. typedef enum {
  58. MAIN_HEAD,
  59. MAIN_NETWORK,
  60. MAIN_LOGGING,
  61. MAIN_KEY,
  62. MAIN_TIMEOUT
  63. } main_parse_t;
  64. void setSaNameT (SaNameT *name, char *str) {
  65. strncpy ((char *)name->value, str, SA_MAX_NAME_LENGTH);
  66. if (strlen ((char *)name->value) > SA_MAX_NAME_LENGTH) {
  67. name->length = SA_MAX_NAME_LENGTH;
  68. } else {
  69. name->length = strlen (str);
  70. }
  71. }
  72. int SaNameTisEqual (SaNameT *str1, char *str2) {
  73. if (str1->length == strlen (str2)) {
  74. return ((strncmp ((char *)str1->value, (char *)str2,
  75. str1->length)) == 0);
  76. } else {
  77. return 0;
  78. }
  79. }
  80. struct saAmfComponent *findComponent (SaNameT *name)
  81. {
  82. struct list_head *AmfGroupList = 0;
  83. struct list_head *AmfUnitList = 0;
  84. struct list_head *AmfComponentList = 0;
  85. struct saAmfGroup *saAmfGroup = 0;
  86. struct saAmfUnit *AmfUnit = 0;
  87. struct saAmfComponent *AmfComponent = 0;
  88. int found = 0;
  89. /*
  90. * Search all groups
  91. */
  92. for (AmfGroupList = saAmfGroupHead.next;
  93. AmfGroupList != &saAmfGroupHead && found == 0;
  94. AmfGroupList = AmfGroupList->next) {
  95. saAmfGroup = list_entry (AmfGroupList,
  96. struct saAmfGroup, saAmfGroupList);
  97. /*
  98. * Search all units
  99. */
  100. for (AmfUnitList = saAmfGroup->saAmfUnitHead.next;
  101. AmfUnitList != &saAmfGroup->saAmfUnitHead && found == 0;
  102. AmfUnitList = AmfUnitList->next) {
  103. AmfUnit = list_entry (AmfUnitList,
  104. struct saAmfUnit, saAmfUnitList);
  105. /*
  106. * Search all components
  107. */
  108. for (AmfComponentList = AmfUnit->saAmfComponentHead.next;
  109. AmfComponentList != &AmfUnit->saAmfComponentHead && found == 0;
  110. AmfComponentList = AmfComponentList->next) {
  111. AmfComponent = list_entry (AmfComponentList,
  112. struct saAmfComponent, saAmfComponentList);
  113. if (name_match (name, &AmfComponent->name)) {
  114. found = 1;
  115. }
  116. }
  117. }
  118. }
  119. if (found) {
  120. return (AmfComponent);
  121. } else {
  122. return (0);
  123. }
  124. }
  125. char *
  126. strstr_rs (const char *haystack, const char *needle)
  127. {
  128. char *end_address;
  129. char *new_needle;
  130. new_needle = (char *)mempool_strdup (needle);
  131. new_needle[strlen(new_needle) - 1] = '\0';
  132. end_address = strstr (haystack, new_needle);
  133. if (end_address) {
  134. end_address += strlen (new_needle);
  135. end_address = strstr (end_address, needle + strlen (new_needle));
  136. }
  137. if (end_address) {
  138. end_address += 1; /* skip past { or = */
  139. do {
  140. if (*end_address == '\t' || *end_address == ' ') {
  141. end_address++;
  142. } else {
  143. break;
  144. }
  145. } while (*end_address != '\0');
  146. }
  147. mempool_free (new_needle);
  148. return (end_address);
  149. }
  150. extern int openais_amf_config_read (char **error_string)
  151. {
  152. char line[255];
  153. FILE *fp;
  154. amf_parse_t current_parse = AMF_HEAD;
  155. int line_number = 0;
  156. char *loc;
  157. int i;
  158. struct saAmfGroup *saAmfGroup = 0;
  159. struct saAmfUnit *saAmfUnit = 0;
  160. struct saAmfProtectionGroup *saAmfProtectionGroup = 0;
  161. struct saAmfComponent *saAmfComponent = 0;
  162. struct list_head *findAmfUnitList = 0;
  163. struct list_head *findAmfComponentList = 0;
  164. struct saAmfUnit *findAmfUnit = 0;
  165. struct saAmfComponent *findAmfComponent = 0;
  166. SaNameT componentName;
  167. fp = fopen ("/etc/ais/groups.conf", "r");
  168. if (fp == 0) {
  169. sprintf (error_string_response,
  170. "Can't read /etc/ais/groups.conf file reason = (%s).\n", strerror (errno));
  171. *error_string = error_string_response;
  172. return (-1);
  173. }
  174. while (fgets (line, 255, fp)) {
  175. line_number += 1;
  176. line[strlen(line) - 1] = '\0';
  177. /*
  178. * Clear out white space and tabs
  179. */
  180. for (i = strlen (line) - 1; i > -1; i--) {
  181. if (line[i] == '\t' || line[i] == ' ') {
  182. line[i] = '\0';
  183. } else {
  184. break;
  185. }
  186. }
  187. /*
  188. * Clear out comments and empty lines
  189. */
  190. if (line[0] == '#' || line[0] == '\0') {
  191. continue;
  192. }
  193. switch (current_parse) {
  194. case AMF_HEAD:
  195. if (strstr_rs (line, "group{")) {
  196. saAmfGroup = (struct saAmfGroup *)mempool_malloc (sizeof (struct saAmfGroup));
  197. memset (saAmfGroup, 0, sizeof (struct saAmfGroup));
  198. list_init (&saAmfGroup->saAmfGroupList);
  199. list_init (&saAmfGroup->saAmfUnitHead);
  200. list_init (&saAmfGroup->saAmfProtectionGroupHead);
  201. list_add (&saAmfGroup->saAmfGroupList, &saAmfGroupHead);
  202. current_parse = AMF_GROUP;
  203. } else
  204. if (strcmp (line, "") == 0) {
  205. } else {
  206. goto parse_error;
  207. }
  208. break;
  209. case AMF_GROUP:
  210. if ((loc = strstr_rs (line, "name=")) != 0) {
  211. setSaNameT (&saAmfGroup->name, loc);
  212. } else
  213. if ((loc = strstr_rs (line, "model=")) != 0) {
  214. if (strcmp (loc, "2n") == 0) {
  215. saAmfGroup->model = GROUPCAPABILITYMODEL_2N;
  216. } else
  217. if (strcmp (loc, "nplusm") == 0) {
  218. saAmfGroup->model = GROUPCAPABILITYMODEL_NPLUSM;
  219. } else
  220. if (strcmp (loc, "nway") == 0) {
  221. printf ("nway redundancy model not supported.\n");
  222. goto parse_error;
  223. } else
  224. if (strcmp (loc, "nwayactive") == 0) {
  225. printf ("nway active redundancy model not supported.\n");
  226. goto parse_error;
  227. } else
  228. if (strcmp (loc, "noredundancy") == 0) {
  229. saAmfGroup->model = GROUPCAPABILITYMODEL_NOREDUNDANCY;
  230. } else {
  231. goto parse_error;
  232. }
  233. } else
  234. if ((loc = strstr_rs (line, "active-units=")) != 0) {
  235. saAmfGroup->saAmfActiveUnitsDesired = atoi (loc);
  236. } else
  237. if ((loc = strstr_rs (line, "backup-units=")) != 0) {
  238. saAmfGroup->saAmfStandbyUnitsDesired = atoi (loc);
  239. } else
  240. if (strstr_rs (line, "unit{")) {
  241. saAmfUnit = (struct saAmfUnit *)mempool_malloc (sizeof (struct saAmfUnit));
  242. memset (saAmfUnit, 0, sizeof (struct saAmfUnit));
  243. saAmfUnit->saAmfGroup = saAmfGroup;
  244. list_init (&saAmfUnit->saAmfComponentHead);
  245. list_add (&saAmfUnit->saAmfUnitList, &saAmfGroup->saAmfUnitHead);
  246. current_parse = AMF_UNIT;
  247. } else
  248. if (strstr_rs (line, "protection{")) {
  249. saAmfProtectionGroup = (struct saAmfProtectionGroup *)mempool_malloc (sizeof (struct saAmfProtectionGroup));
  250. memset (saAmfProtectionGroup, 0, sizeof (struct saAmfProtectionGroup));
  251. list_init (&saAmfProtectionGroup->saAmfMembersHead);
  252. list_init (&saAmfProtectionGroup->saAmfProtectionGroupList);
  253. list_add (&saAmfProtectionGroup->saAmfProtectionGroupList, &saAmfGroup->saAmfProtectionGroupHead);
  254. current_parse = AMF_PROTECTION;
  255. } else
  256. if (strstr_rs (line, "}")) {
  257. current_parse = AMF_HEAD;
  258. } else {
  259. goto parse_error;
  260. }
  261. break;
  262. case AMF_UNIT:
  263. if ((loc = strstr_rs (line, "name=")) != 0) {
  264. setSaNameT (&saAmfUnit->name, loc);
  265. } else
  266. if ((loc = strstr_rs (line, "component{")) != 0) {
  267. saAmfComponent = (struct saAmfComponent *)mempool_malloc (sizeof (struct saAmfComponent));
  268. memset (saAmfComponent, 0, sizeof (struct saAmfComponent));
  269. saAmfComponent->saAmfUnit = saAmfUnit;
  270. saAmfComponent->currentReadinessState = SA_AMF_OUT_OF_SERVICE;
  271. saAmfComponent->newReadinessState = SA_AMF_OUT_OF_SERVICE;
  272. saAmfComponent->currentHAState = SA_AMF_QUIESCED;
  273. saAmfComponent->newHAState = SA_AMF_QUIESCED;
  274. saAmfComponent->healthcheckInterval = 100;
  275. list_init (&saAmfComponent->saAmfComponentList);
  276. list_init (&saAmfComponent->saAmfProtectionGroupList);
  277. list_add (&saAmfComponent->saAmfComponentList, &saAmfUnit->saAmfComponentHead);
  278. current_parse = AMF_COMPONENT;
  279. } else
  280. if (strstr_rs (line, "}")) {
  281. current_parse = AMF_GROUP;
  282. } else {
  283. goto parse_error;
  284. }
  285. break;
  286. case AMF_COMPONENT:
  287. if ((loc = strstr_rs (line, "name=")) != 0) {
  288. setSaNameT (&saAmfComponent->name, loc);
  289. } else
  290. if ((loc = strstr_rs (line, "model=")) != 0) {
  291. if (strcmp (loc, "x_active_and_y_standby") == 0) {
  292. saAmfComponent->componentCapabilityModel = SA_AMF_COMPONENT_CAPABILITY_X_ACTIVE_AND_Y_STANDBY;
  293. } else
  294. if (strcmp (loc, "x_active_or_y_standby") == 0) {
  295. saAmfComponent->componentCapabilityModel = SA_AMF_COMPONENT_CAPABILITY_X_ACTIVE_OR_Y_STANDBY;
  296. } else
  297. if (strcmp (loc, "1_active_or_y_standby") == 0) {
  298. saAmfComponent->componentCapabilityModel = SA_AMF_COMPONENT_CAPABILITY_1_ACTIVE_OR_Y_STANDBY;
  299. } else
  300. if (strcmp (loc, "1_active_or_1_standby") == 0) {
  301. saAmfComponent->componentCapabilityModel = SA_AMF_COMPONENT_CAPABILITY_1_ACTIVE_OR_1_STANDBY;
  302. } else
  303. if (strcmp (loc, "x_active") == 0) {
  304. saAmfComponent->componentCapabilityModel = SA_AMF_COMPONENT_CAPABILITY_X_ACTIVE;
  305. } else
  306. if (strcmp (loc, "1_active") == 0) {
  307. saAmfComponent->componentCapabilityModel = SA_AMF_COMPONENT_CAPABILITY_1_ACTIVE;
  308. } else
  309. if (strcmp (loc, "no_active") == 0) {
  310. saAmfComponent->componentCapabilityModel = SA_AMF_COMPONENT_CAPABILITY_NO_ACTIVE;
  311. } else {
  312. goto parse_error;
  313. }
  314. } else
  315. if (strstr_rs (line, "}")) {
  316. current_parse = AMF_UNIT;
  317. } else {
  318. goto parse_error;
  319. }
  320. break;
  321. case AMF_PROTECTION:
  322. if ((loc = strstr_rs (line, "name=")) != 0) {
  323. setSaNameT (&saAmfProtectionGroup->name, loc);
  324. } else
  325. if ((loc = strstr_rs (line, "member=")) != 0) {
  326. for (findAmfUnitList = saAmfGroup->saAmfUnitHead.next;
  327. findAmfUnitList != &saAmfGroup->saAmfUnitHead;
  328. findAmfUnitList = findAmfUnitList->next) {
  329. findAmfUnit = list_entry (findAmfUnitList,
  330. struct saAmfUnit, saAmfUnitList);
  331. for (findAmfComponentList = findAmfUnit->saAmfComponentHead.next;
  332. findAmfComponentList != &findAmfUnit->saAmfComponentHead;
  333. findAmfComponentList = findAmfComponentList->next) {
  334. findAmfComponent = list_entry (findAmfComponentList,
  335. struct saAmfComponent, saAmfComponentList);
  336. if (SaNameTisEqual (&findAmfComponent->name, loc)) {
  337. list_add (&findAmfComponent->saAmfProtectionGroupList,
  338. &saAmfProtectionGroup->saAmfMembersHead);
  339. }
  340. }
  341. /*
  342. * Connect component to protection group
  343. */
  344. setSaNameT (&componentName, loc);
  345. saAmfComponent = findComponent (&componentName);
  346. saAmfComponent->saAmfProtectionGroup = saAmfProtectionGroup;
  347. }
  348. } else
  349. if (strstr_rs (line, "}")) {
  350. current_parse = AMF_GROUP;
  351. } else {
  352. goto parse_error;
  353. }
  354. break;
  355. default:
  356. printf ("Invalid state\n");
  357. goto parse_error;
  358. break;
  359. }
  360. }
  361. fclose (fp);
  362. return (0);
  363. parse_error:
  364. sprintf (error_string_response,
  365. "parse error at /etc/groups.conf:%d.\n", line_number);
  366. *error_string = error_string_response;
  367. fclose (fp);
  368. return (-1);
  369. }
  370. extern int openais_main_config_read (char **error_string,
  371. struct openais_config *openais_config,
  372. int interface_max)
  373. {
  374. FILE *fp;
  375. int line_number = 0;
  376. main_parse_t parse = MAIN_HEAD;
  377. int network_parsed = 0;
  378. int logging_parsed = 0;
  379. int key_parsed = 0;
  380. int timeout_parsed = 0;
  381. char *loc;
  382. int i;
  383. int parse_done = 0;
  384. char line[512];
  385. char *error_reason = error_string_response;
  386. memset (openais_config, 0, sizeof (struct openais_config));
  387. openais_config->interfaces = malloc (sizeof (struct totem_interface) * interface_max);
  388. if (openais_config->interfaces == 0) {
  389. parse_done = 1;
  390. *error_string = "Out of memory trying to allocate ethernet interface storage area";
  391. return -1;
  392. }
  393. memset (openais_config->interfaces, 0,
  394. sizeof (struct totem_interface) * interface_max);
  395. openais_config->mcast_addr.sin_family = AF_INET;
  396. fp = fopen ("/etc/ais/openais.conf", "r");
  397. if (fp == 0) {
  398. parse_done = 1;
  399. sprintf (error_reason, "Can't read file reason = (%s)\n", strerror (errno));
  400. *error_string = error_reason;
  401. return -1;
  402. }
  403. while (fgets (line, 255, fp)) {
  404. line_number += 1;
  405. line[strlen(line) - 1] = '\0';
  406. /*
  407. * Clear out white space and tabs
  408. */
  409. for (i = strlen (line) - 1; i > -1; i--) {
  410. if (line[i] == '\t' || line[i] == ' ') {
  411. line[i] = '\0';
  412. } else {
  413. break;
  414. }
  415. }
  416. /*
  417. * Clear out comments and empty lines
  418. */
  419. if (line[0] == '#' || line[0] == '\0') {
  420. continue;
  421. }
  422. line_number += 1;
  423. switch (parse) {
  424. case MAIN_HEAD:
  425. if (network_parsed == 0 && strstr_rs (line, "network{")) {
  426. network_parsed = 1;
  427. parse = MAIN_NETWORK;
  428. } else
  429. if (logging_parsed == 0 && strstr_rs (line, "logging{")) {
  430. logging_parsed = 1;
  431. parse = MAIN_LOGGING;
  432. } else
  433. if (key_parsed == 0 && strstr_rs (line, "key{")) {
  434. key_parsed = 1;
  435. parse = MAIN_KEY;
  436. } else
  437. if (timeout_parsed == 0 && strstr_rs (line, "timeout{")) {
  438. timeout_parsed = 1;
  439. parse = MAIN_TIMEOUT;
  440. } else {
  441. goto parse_error;
  442. }
  443. break;
  444. case MAIN_NETWORK:
  445. if ((loc = strstr_rs (line, "mcastaddr:"))) {
  446. inet_aton (loc, &openais_config->mcast_addr.sin_addr);
  447. } else
  448. if ((loc = strstr_rs (line, "mcastport:"))) {
  449. openais_config->mcast_addr.sin_port = htons (atoi (loc));
  450. } else
  451. if ((loc = strstr_rs (line, "bindnetaddr:"))) {
  452. if (interface_max == openais_config->interface_count) {
  453. sprintf (error_reason,
  454. "%d is too many interfaces in /etc/ais/network.conf",
  455. openais_config->interface_count);
  456. goto parse_error;
  457. }
  458. inet_aton (loc,
  459. &openais_config->interfaces[openais_config->interface_count].bindnet.sin_addr);
  460. openais_config->interface_count += 1;
  461. } else
  462. if ((loc = strstr_rs (line, "}"))) {
  463. parse = MAIN_HEAD;
  464. } else {
  465. goto parse_error;
  466. }
  467. break;
  468. case MAIN_LOGGING:
  469. if ((loc = strstr_rs (line, "logoutput:"))) {
  470. if (strcmp (loc, "file") == 0) {
  471. openais_config->logmode |= LOG_MODE_FILE;
  472. } else
  473. if (strcmp (loc, "syslog") == 0) {
  474. openais_config->logmode |= LOG_MODE_SYSLOG;
  475. } else
  476. if (strcmp (loc, "stderr") == 0) {
  477. openais_config->logmode |= LOG_MODE_STDERR;
  478. } else {
  479. goto parse_error;
  480. }
  481. } else
  482. if ((loc = strstr_rs (line, "debug:"))) {
  483. if (strcmp (loc, "on") == 0) {
  484. openais_config->logmode |= LOG_MODE_DEBUG;
  485. } else
  486. if (strcmp (loc, "off") == 0) {
  487. openais_config->logmode &= ~LOG_MODE_DEBUG;
  488. } else {
  489. goto parse_error;
  490. }
  491. } else
  492. if ((loc = strstr_rs (line, "timestamp:"))) {
  493. if (strcmp (loc, "on") == 0) {
  494. openais_config->logmode |= LOG_MODE_TIMESTAMP;
  495. } else
  496. if (strcmp (loc, "off") == 0) {
  497. openais_config->logmode &= ~LOG_MODE_TIMESTAMP;
  498. } else {
  499. goto parse_error;
  500. }
  501. } else
  502. if ((loc = strstr_rs (line, "logfile:"))) {
  503. openais_config->logfile = strdup (loc);
  504. } else
  505. if ((loc = strstr_rs (line, "}"))) {
  506. parse = MAIN_HEAD;
  507. } else {
  508. goto parse_error;
  509. }
  510. break;
  511. case MAIN_TIMEOUT:
  512. if ((loc = strstr_rs (line, "token:"))) {
  513. openais_config->timeouts[TOTEM_TOKEN]= atoi(loc);
  514. } else if ((loc = strstr_rs (line, "retransmit:"))) {
  515. openais_config->timeouts[TOTEM_RETRANSMIT_TOKEN] = atoi(loc);
  516. } else if ((loc = strstr_rs (line, "join:"))) {
  517. openais_config->timeouts[TOTEM_JOIN] = atoi(loc);
  518. } else if ((loc = strstr_rs (line, "consensus:"))) {
  519. openais_config->timeouts[TOTEM_CONSENSUS] = atoi(loc);
  520. } else if ((loc = strstr_rs (line, "merge:"))) {
  521. openais_config->timeouts[TOTEM_MERGE] = atoi(loc);
  522. } else if ((loc = strstr_rs (line, "downcheck:"))) {
  523. openais_config->timeouts[TOTEM_DOWNCHECK] = atoi(loc);
  524. } else if ((loc = strstr_rs (line, "fail_recv_const:"))) {
  525. openais_config->timeouts[TOTEM_FAIL_RECV_CONST] = atoi(loc);
  526. } else if ((loc = strstr_rs (line, "}"))) {
  527. parse = MAIN_HEAD;
  528. } else {
  529. goto parse_error;
  530. }
  531. break;
  532. default:
  533. assert (0 == 1); /* SHOULDN'T HAPPEN */
  534. break;
  535. }
  536. }
  537. /*
  538. * Some error checking of parsed data to make sure its valid
  539. */
  540. parse_done = 1;
  541. if (openais_config->mcast_addr.sin_addr.s_addr == 0) {
  542. error_reason = "No multicast address specified";
  543. goto parse_error;
  544. }
  545. if (openais_config->mcast_addr.sin_port == 0) {
  546. error_reason = "No multicast port specified";
  547. goto parse_error;
  548. }
  549. if (openais_config->interface_count == 0) {
  550. error_reason = "No bindnet specified";
  551. goto parse_error;
  552. }
  553. if ((openais_config->logmode & LOG_MODE_FILE) && openais_config->logfile == 0) {
  554. error_reason = "logmode set to 'file' but no logfile specified";
  555. goto parse_error;
  556. }
  557. if (parse == MAIN_HEAD) {
  558. fclose (fp);
  559. return (0);
  560. } else {
  561. error_reason = "Missing closing brace";
  562. goto parse_error;
  563. }
  564. parse_error:
  565. if (parse_done) {
  566. sprintf (error_string_response,
  567. "parse error in /etc/ais/openais.conf: %s.\n", error_reason);
  568. } else {
  569. sprintf (error_string_response,
  570. "parse error in /etc/ais/openais.conf: %s (line %d).\n",
  571. error_reason, line_number);
  572. }
  573. *error_string = error_string_response;
  574. fclose (fp);
  575. return (-1);
  576. }