configuration.c 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348
  1. /*
  2. Copyright (c) 2007-2010 by Juliusz Chroboczek
  3. Permission is hereby granted, free of charge, to any person obtaining a copy
  4. of this software and associated documentation files (the "Software"), to deal
  5. in the Software without restriction, including without limitation the rights
  6. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. copies of the Software, and to permit persons to whom the Software is
  8. furnished to do so, subject to the following conditions:
  9. The above copyright notice and this permission notice shall be included in
  10. all copies or substantial portions of the Software.
  11. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  12. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  13. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  14. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  15. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  16. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  17. THE SOFTWARE.
  18. */
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <stdio.h>
  22. #include <sys/time.h>
  23. #include <assert.h>
  24. #ifdef __linux
  25. /* Defining it rather than including <linux/rtnetlink.h> because this
  26. * implies <asm/types.h> on Linux 2.4 */
  27. #define RTPROT_BOOT 3 /* Route installed during boot */
  28. #endif
  29. #include "babeld.h"
  30. #include "util.h"
  31. #include "interface.h"
  32. #include "route.h"
  33. #include "kernel.h"
  34. #include "configuration.h"
  35. #include "rule.h"
  36. struct filter *input_filters = NULL;
  37. struct filter *output_filters = NULL;
  38. struct filter *redistribute_filters = NULL;
  39. struct filter *install_filters = NULL;
  40. struct interface_conf *default_interface_conf = NULL;
  41. struct interface_conf *interface_confs = NULL;
  42. /* This indicates whether initial configuration is done. See
  43. finalize_config below. */
  44. int config_finalised = 0;
  45. /* This file implements a recursive descent parser with one character
  46. lookahead. The looked-ahead character is returned from most
  47. functions.
  48. Throughout this file, -1 signals that the look-ahead is EOF,
  49. while -2 signals an error. */
  50. /* get_next_char callback */
  51. typedef int (*gnc_t)(void*);
  52. static int
  53. skip_whitespace(int c, gnc_t gnc, void *closure)
  54. {
  55. while(c == ' ' || c == '\t' || c == '\r')
  56. c = gnc(closure);
  57. return c;
  58. }
  59. static int
  60. skip_to_eol(int c, gnc_t gnc, void *closure)
  61. {
  62. while(c != '\n' && c >= 0)
  63. c = gnc(closure);
  64. if(c == '\n')
  65. c = gnc(closure);
  66. return c;
  67. }
  68. static int
  69. skip_eol(int c, gnc_t gnc, void *closure)
  70. {
  71. c = skip_whitespace(c, gnc, closure);
  72. if(c < 0 || c == '\n' || c == '#') {
  73. c = skip_to_eol(c, gnc, closure);
  74. return c;
  75. }
  76. return -2;
  77. }
  78. static int
  79. getword(int c, char **token_r, gnc_t gnc, void *closure)
  80. {
  81. char buf[256];
  82. int i = 0;
  83. c = skip_whitespace(c, gnc, closure);
  84. if(c < 0 || c == '"' || c == '\n' || c == '#' || c < 0)
  85. return -2;
  86. do {
  87. if(i >= 255) return -2;
  88. buf[i++] = c;
  89. c = gnc(closure);
  90. } while(c != ' ' && c != '\t' && c != '\r' && c != '\n' && c != '#' && c >= 0);
  91. buf[i] = '\0';
  92. *token_r = strdup(buf);
  93. if(*token_r == NULL)
  94. return -2;
  95. return c;
  96. }
  97. static int
  98. getstring(int c, char **token_r, gnc_t gnc, void *closure)
  99. {
  100. char buf[256];
  101. int i = 0;
  102. c = skip_whitespace(c, gnc, closure);
  103. if(c < 0 || c == '\n' || c == '#')
  104. return -2;
  105. /* Unquoted strings have the same syntax as words. */
  106. if(c != '"')
  107. return getword(c, token_r, gnc, closure);
  108. c = gnc(closure);
  109. while(1) {
  110. if(i >= 255 || c == '\n') return -2;
  111. if(c == '"') {
  112. c = gnc(closure);
  113. break;
  114. }
  115. if(c == '\\')
  116. c = gnc(closure);
  117. if(c < 0)
  118. return -2;
  119. buf[i++] = c;
  120. c = gnc(closure);
  121. }
  122. buf[i] = '\0';
  123. *token_r = strdup(buf);
  124. if(*token_r == NULL)
  125. return -2;
  126. return c;
  127. }
  128. static int
  129. getint(int c, int *int_r, gnc_t gnc, void *closure)
  130. {
  131. char *t, *end;
  132. int i;
  133. c = getword(c, &t, gnc, closure);
  134. if(c < -1)
  135. return c;
  136. i = strtol(t, &end, 0);
  137. if(*end != '\0') {
  138. free(t);
  139. return -2;
  140. }
  141. free(t);
  142. *int_r = i;
  143. return c;
  144. }
  145. static int
  146. getthousands(int c, int *int_r, gnc_t gnc, void *closure)
  147. {
  148. char *t;
  149. int i;
  150. c = getword(c, &t, gnc, closure);
  151. if(c < -1)
  152. return c;
  153. i = parse_thousands(t);
  154. if(i < 0) {
  155. free(t);
  156. return -2;
  157. }
  158. free(t);
  159. *int_r = i;
  160. return c;
  161. }
  162. static int
  163. getbool(int c, int *bool_r, gnc_t gnc, void *closure)
  164. {
  165. char *t;
  166. int i;
  167. c = getword(c, &t, gnc, closure);
  168. if(c < -1)
  169. return c;
  170. if(strcmp(t, "true") == 0 || strcmp(t, "yes") == 0)
  171. i = CONFIG_YES;
  172. else if(strcmp(t, "false") == 0 || strcmp(t, "no") == 0)
  173. i = CONFIG_NO;
  174. else if(strcmp(t, "default") == 0 || strcmp(t, "auto") == 0)
  175. i = CONFIG_DEFAULT;
  176. else {
  177. free(t);
  178. return -2;
  179. }
  180. free(t);
  181. *bool_r = i;
  182. return c;
  183. }
  184. static int
  185. getip(int c, unsigned char **ip_r, int *af_r, gnc_t gnc, void *closure)
  186. {
  187. char *t;
  188. unsigned char *ip;
  189. unsigned char addr[16];
  190. int af, rc;
  191. c = getword(c, &t, gnc, closure);
  192. if(c < -1)
  193. return c;
  194. rc = parse_address(t, addr, &af);
  195. if(rc < 0) {
  196. free(t);
  197. return -2;
  198. }
  199. free(t);
  200. ip = malloc(16);
  201. if(ip == NULL) {
  202. return -2;
  203. }
  204. memcpy(ip, addr, 16);
  205. *ip_r = ip;
  206. if(af_r)
  207. *af_r = af;
  208. return c;
  209. }
  210. static int
  211. getid(int c, unsigned char **id_r, gnc_t gnc, void *closure)
  212. {
  213. char *t;
  214. unsigned char *idp;
  215. unsigned char id[8];
  216. int rc;
  217. c = getword(c, &t, gnc, closure);
  218. if(c < -1)
  219. return c;
  220. rc = parse_eui64(t, id);
  221. if(rc < 0) {
  222. free(t);
  223. return -2;
  224. }
  225. free(t);
  226. idp = malloc(8);
  227. if(idp == NULL) {
  228. return -2;
  229. }
  230. memcpy(idp, id, 8);
  231. *id_r = idp;
  232. return c;
  233. }
  234. static int
  235. getnet(int c, unsigned char **p_r, unsigned char *plen_r, int *af_r,
  236. gnc_t gnc, void *closure)
  237. {
  238. char *t;
  239. unsigned char *ip;
  240. unsigned char addr[16];
  241. unsigned char plen;
  242. int af, rc;
  243. c = getword(c, &t, gnc, closure);
  244. if(c < -1)
  245. return c;
  246. rc = parse_net(t, addr, &plen, &af);
  247. if(rc < 0) {
  248. free(t);
  249. return -2;
  250. }
  251. free(t);
  252. ip = malloc(16);
  253. if(ip == NULL)
  254. return -2;
  255. memcpy(ip, addr, 16);
  256. *p_r = ip;
  257. *plen_r = plen;
  258. if(af_r) *af_r = af;
  259. return c;
  260. }
  261. static int
  262. get_interface_type(int c, int *type_r, gnc_t gnc, void *closure)
  263. {
  264. char *t;
  265. int i;
  266. c = getword(c, &t, gnc, closure);
  267. if(c < -1)
  268. return c;
  269. if(strcmp(t, "default") == 0 || strcmp(t, "auto") == 0) {
  270. i = IF_TYPE_DEFAULT;
  271. } else if(strcmp(t, "wired") == 0) {
  272. i = IF_TYPE_WIRED;
  273. } else if(strcmp(t, "wireless") == 0) {
  274. i = IF_TYPE_WIRELESS;
  275. } else if(strcmp(t, "tunnel") == 0) {
  276. i = IF_TYPE_TUNNEL;
  277. } else {
  278. free(t);
  279. return -2;
  280. }
  281. free(t);
  282. *type_r = i;
  283. return c;
  284. }
  285. static int
  286. parse_filter(int c, gnc_t gnc, void *closure, struct filter **filter_return)
  287. {
  288. char *token;
  289. struct filter *filter;
  290. filter = calloc(1, sizeof(struct filter));
  291. if(filter == NULL)
  292. return -2;
  293. filter->plen_le = 128;
  294. filter->src_plen_le = 128;
  295. while(1) {
  296. c = skip_whitespace(c, gnc, closure);
  297. if(c < 0 || c == '\n' || c == '#') {
  298. c = skip_to_eol(c, gnc, closure);
  299. break;
  300. }
  301. c = getword(c, &token, gnc, closure);
  302. if(c < -1) {
  303. free(filter);
  304. return -2;
  305. }
  306. if(strcmp(token, "ip") == 0) {
  307. int af;
  308. c = getnet(c, &filter->prefix, &filter->plen, &af,
  309. gnc, closure);
  310. if(c < -1)
  311. goto error;
  312. if(filter->af == AF_UNSPEC)
  313. filter->af = af;
  314. else if(filter->af != af)
  315. goto error;
  316. } else if(strcmp(token, "src-ip") == 0) {
  317. int af;
  318. c = getnet(c, &filter->src_prefix, &filter->src_plen, &af,
  319. gnc, closure);
  320. if(c < -1)
  321. goto error;
  322. if(filter->af == AF_UNSPEC)
  323. filter->af = af;
  324. else if(filter->af != af)
  325. goto error;
  326. } else if(strcmp(token, "eq") == 0) {
  327. int p;
  328. c = getint(c, &p, gnc, closure);
  329. if(c < -1)
  330. goto error;
  331. filter->plen_ge = MAX(filter->plen_ge, p);
  332. filter->plen_le = MIN(filter->plen_le, p);
  333. } else if(strcmp(token, "le") == 0) {
  334. int p;
  335. c = getint(c, &p, gnc, closure);
  336. if(c < -1)
  337. goto error;
  338. filter->plen_le = MIN(filter->plen_le, p);
  339. } else if(strcmp(token, "ge") == 0) {
  340. int p;
  341. c = getint(c, &p, gnc, closure);
  342. if(c < -1)
  343. goto error;
  344. filter->plen_ge = MAX(filter->plen_ge, p);
  345. } else if(strcmp(token, "src-eq") == 0) {
  346. int p;
  347. c = getint(c, &p, gnc, closure);
  348. if(c < -1)
  349. goto error;
  350. filter->src_plen_ge = MAX(filter->src_plen_ge, p);
  351. filter->src_plen_le = MIN(filter->src_plen_le, p);
  352. } else if(strcmp(token, "src-le") == 0) {
  353. int p;
  354. c = getint(c, &p, gnc, closure);
  355. if(c < -1)
  356. goto error;
  357. filter->src_plen_le = MIN(filter->src_plen_le, p);
  358. } else if(strcmp(token, "src-ge") == 0) {
  359. int p;
  360. c = getint(c, &p, gnc, closure);
  361. if(c < -1)
  362. goto error;
  363. filter->src_plen_ge = MAX(filter->src_plen_ge, p);
  364. } else if(strcmp(token, "neigh") == 0) {
  365. unsigned char *neigh = NULL;
  366. c = getip(c, &neigh, NULL, gnc, closure);
  367. if(c < -1)
  368. goto error;
  369. filter->neigh = neigh;
  370. } else if(strcmp(token, "id") == 0) {
  371. unsigned char *id = NULL;
  372. c = getid(c, &id, gnc, closure);
  373. if(c < -1)
  374. goto error;
  375. filter->id = id;
  376. } else if(strcmp(token, "proto") == 0) {
  377. int proto;
  378. c = getint(c, &proto, gnc, closure);
  379. if(c < -1)
  380. goto error;
  381. filter->proto = proto;
  382. } else if(strcmp(token, "local") == 0) {
  383. filter->proto = RTPROT_BABEL_LOCAL;
  384. } else if(strcmp(token, "if") == 0) {
  385. char *interface;
  386. c = getstring(c, &interface, gnc, closure);
  387. if(c < -1)
  388. goto error;
  389. filter->ifname = interface;
  390. filter->ifindex = if_nametoindex(interface);
  391. } else if(strcmp(token, "allow") == 0) {
  392. filter->action.add_metric = 0;
  393. } else if(strcmp(token, "deny") == 0) {
  394. filter->action.add_metric = INFINITY;
  395. } else if(strcmp(token, "metric") == 0) {
  396. int metric;
  397. c = getint(c, &metric, gnc, closure);
  398. if(c < -1) goto error;
  399. if(metric <= 0 || metric > INFINITY)
  400. goto error;
  401. filter->action.add_metric = metric;
  402. } else if(strcmp(token, "src-prefix") == 0) {
  403. int af;
  404. c = getnet(c, &filter->action.src_prefix, &filter->action.src_plen,
  405. &af, gnc, closure);
  406. if(c < -1)
  407. goto error;
  408. if(filter->af == AF_UNSPEC)
  409. filter->af = af;
  410. else if(filter->af != af)
  411. goto error;
  412. if(af == AF_INET && filter->action.src_plen == 96)
  413. memset(&filter->action.src_prefix, 0, 16);
  414. } else if(strcmp(token, "table") == 0) {
  415. int table;
  416. c = getint(c, &table, gnc, closure);
  417. if(c < -1) goto error;
  418. if(table <= 0 || table > INFINITY)
  419. goto error;
  420. filter->action.table = table;
  421. } else {
  422. goto error;
  423. }
  424. free(token);
  425. }
  426. if(filter->af == 0) {
  427. if(filter->plen_le < 128 || filter->plen_ge > 0 ||
  428. filter->src_plen_le < 128 || filter->src_plen_ge > 0)
  429. filter->af = AF_INET6;
  430. } else if(filter->af == AF_INET) {
  431. filter->plen_le += 96;
  432. filter->plen_ge += 96;
  433. }
  434. *filter_return = filter;
  435. return c;
  436. error:
  437. free(token);
  438. free(filter);
  439. return -2;
  440. }
  441. static int
  442. parse_anonymous_ifconf(int c, gnc_t gnc, void *closure,
  443. struct interface_conf *if_conf,
  444. struct interface_conf **if_conf_return)
  445. {
  446. char *token;
  447. if(if_conf == NULL) {
  448. if_conf = calloc(1, sizeof(struct interface_conf));
  449. if(if_conf == NULL)
  450. goto error;
  451. }
  452. while(1) {
  453. c = skip_whitespace(c, gnc, closure);
  454. if(c < 0 || c == '\n' || c == '#') {
  455. c = skip_to_eol(c, gnc, closure);
  456. break;
  457. }
  458. c = getword(c, &token, gnc, closure);
  459. if(c < -1)
  460. goto error;
  461. if(strcmp(token, "rxcost") == 0) {
  462. int cost;
  463. c = getint(c, &cost, gnc, closure);
  464. if(c < -1 || cost <= 0 || cost > 0xFFFF)
  465. goto error;
  466. if_conf->cost = cost;
  467. } else if(strcmp(token, "hello-interval") == 0) {
  468. int interval;
  469. c = getthousands(c, &interval, gnc, closure);
  470. if(c < -1 || interval <= 0 || interval > 10 * 0xFFFF)
  471. goto error;
  472. if_conf->hello_interval = interval;
  473. } else if(strcmp(token, "update-interval") == 0) {
  474. int interval;
  475. c = getthousands(c, &interval, gnc, closure);
  476. if(c < -1 || interval <= 0 || interval > 10 * 0xFFFF)
  477. goto error;
  478. if_conf->update_interval = interval;
  479. } else if(strcmp(token, "type") == 0) {
  480. int type = IF_TYPE_DEFAULT;
  481. c = get_interface_type(c, &type, gnc, closure);
  482. if(c < -1)
  483. goto error;
  484. if_conf->type = type;
  485. } else if(strcmp(token, "wired") == 0) {
  486. int v;
  487. fprintf(stderr, "Warning: keyword \"wired\" is deprecated -- "
  488. "please use \"type\" instead.\n");
  489. c = getbool(c, &v, gnc, closure);
  490. if(c < -1)
  491. goto error;
  492. if_conf->type = (v == CONFIG_YES) ?
  493. IF_TYPE_WIRED : IF_TYPE_WIRELESS;
  494. } else if(strcmp(token, "faraway") == 0) {
  495. int v;
  496. c = getbool(c, &v, gnc, closure);
  497. if(c < -1)
  498. goto error;
  499. if_conf->faraway = v;
  500. } else if(strcmp(token, "link-quality") == 0) {
  501. int v;
  502. c = getbool(c, &v, gnc, closure);
  503. if(c < -1)
  504. goto error;
  505. if_conf->lq = v;
  506. } else if(strcmp(token, "split-horizon") == 0) {
  507. int v;
  508. c = getbool(c, &v, gnc, closure);
  509. if(c < -1)
  510. goto error;
  511. if_conf->split_horizon = v;
  512. } else if(strcmp(token, "channel") == 0) {
  513. char *t, *end;
  514. c = getword(c, &t, gnc, closure);
  515. if(c < -1)
  516. goto error;
  517. if(strcmp(t, "noninterfering") == 0)
  518. if_conf->channel = IF_CHANNEL_NONINTERFERING;
  519. else if(strcmp(t, "interfering") == 0)
  520. if_conf->channel = IF_CHANNEL_INTERFERING;
  521. else {
  522. if_conf->channel = strtol(t, &end, 0);
  523. if(*end != '\0')
  524. goto error;
  525. }
  526. free(t);
  527. if((if_conf->channel < 1 || if_conf->channel > 255) &&
  528. if_conf->channel != IF_CHANNEL_NONINTERFERING)
  529. goto error;
  530. } else if(strcmp(token, "enable-timestamps") == 0) {
  531. int v;
  532. c = getbool(c, &v, gnc, closure);
  533. if(c < -1)
  534. goto error;
  535. if_conf->enable_timestamps = v;
  536. } else if(strcmp(token, "rtt-decay") == 0) {
  537. int decay;
  538. c = getint(c, &decay, gnc, closure);
  539. if(c < -1 || decay <= 0 || decay > 256)
  540. goto error;
  541. if_conf->rtt_decay = decay;
  542. } else if(strcmp(token, "rtt-min") == 0) {
  543. int rtt;
  544. c = getthousands(c, &rtt, gnc, closure);
  545. if(c < -1 || rtt <= 0)
  546. goto error;
  547. if_conf->rtt_min = rtt;
  548. } else if(strcmp(token, "rtt-max") == 0) {
  549. int rtt;
  550. c = getthousands(c, &rtt, gnc, closure);
  551. if(c < -1 || rtt <= 0)
  552. goto error;
  553. if_conf->rtt_max = rtt;
  554. } else if(strcmp(token, "max-rtt-penalty") == 0) {
  555. int penalty;
  556. c = getint(c, &penalty, gnc, closure);
  557. if(c < -1 || penalty <= 0 || penalty > 0xFFFF)
  558. goto error;
  559. if_conf->max_rtt_penalty = penalty;
  560. } else {
  561. goto error;
  562. }
  563. free(token);
  564. }
  565. *if_conf_return = if_conf;
  566. return c;
  567. error:
  568. free(if_conf);
  569. return -2;
  570. }
  571. static int
  572. parse_ifconf(int c, gnc_t gnc, void *closure,
  573. struct interface_conf **if_conf_return)
  574. {
  575. char *token;
  576. struct interface_conf *if_conf;
  577. if_conf = calloc(1, sizeof(struct interface_conf));
  578. if(if_conf == NULL)
  579. goto error;
  580. c = skip_whitespace(c, gnc, closure);
  581. if(c < -1 || c == '\n' || c == '#')
  582. goto error;
  583. c = getstring(c, &token, gnc, closure);
  584. if(c < -1 || token == NULL)
  585. goto error;
  586. if_conf->ifname = token;
  587. return parse_anonymous_ifconf(c, gnc, closure, if_conf, if_conf_return);
  588. error:
  589. free(if_conf);
  590. return -2;
  591. }
  592. static void
  593. add_filter(struct filter *filter, struct filter **filters)
  594. {
  595. if(*filters == NULL) {
  596. filter->next = NULL;
  597. *filters = filter;
  598. } else {
  599. struct filter *f;
  600. f = *filters;
  601. while(f->next)
  602. f = f->next;
  603. filter->next = NULL;
  604. f->next = filter;
  605. }
  606. }
  607. static void
  608. merge_ifconf(struct interface_conf *dest,
  609. const struct interface_conf *src1,
  610. const struct interface_conf *src2)
  611. {
  612. #define MERGE(field) \
  613. do { \
  614. if(src1->field) \
  615. dest->field = src1->field; \
  616. else \
  617. dest->field = src2->field; \
  618. } while(0)
  619. MERGE(hello_interval);
  620. MERGE(update_interval);
  621. MERGE(cost);
  622. MERGE(type);
  623. MERGE(split_horizon);
  624. MERGE(lq);
  625. MERGE(faraway);
  626. MERGE(channel);
  627. MERGE(enable_timestamps);
  628. MERGE(rtt_decay);
  629. MERGE(rtt_min);
  630. MERGE(rtt_max);
  631. MERGE(max_rtt_penalty);
  632. #undef MERGE
  633. }
  634. static void
  635. add_ifconf(struct interface_conf *if_conf, struct interface_conf **if_confs)
  636. {
  637. if(*if_confs == NULL) {
  638. if_conf->next = NULL;
  639. *if_confs = if_conf;
  640. } else {
  641. struct interface_conf *prev, *next;
  642. next = *if_confs;
  643. prev = NULL;
  644. while(next) {
  645. if(strcmp(next->ifname, if_conf->ifname) == 0) {
  646. merge_ifconf(next, if_conf, next);
  647. free(if_conf);
  648. if_conf = next;
  649. goto done;
  650. }
  651. prev = next;
  652. next = next->next;
  653. }
  654. if_conf->next = NULL;
  655. prev->next = if_conf;
  656. }
  657. done:
  658. if(config_finalised)
  659. add_interface(if_conf->ifname, if_conf);
  660. }
  661. void
  662. flush_ifconf(struct interface_conf *if_conf)
  663. {
  664. if(if_conf == interface_confs) {
  665. interface_confs = if_conf->next;
  666. free(if_conf);
  667. return;
  668. } else {
  669. struct interface_conf *prev = interface_confs;
  670. while(prev) {
  671. if(prev->next == if_conf) {
  672. prev->next = if_conf->next;
  673. free(if_conf);
  674. return;
  675. }
  676. prev = prev->next;
  677. }
  678. }
  679. fprintf(stderr, "Warning: attempting to free nonexistent ifconf.\n");
  680. }
  681. static int
  682. parse_option(int c, gnc_t gnc, void *closure, char *token)
  683. {
  684. /* These are the only options that are allowed at runtime, either
  685. because they require no special setup or because there is special
  686. case code for them. */
  687. if(config_finalised) {
  688. if(strcmp(token, "keep-unfeasible") != 0 &&
  689. strcmp(token, "link-detect") != 0 &&
  690. strcmp(token, "log-file") != 0 &&
  691. strcmp(token, "diversity") != 0 &&
  692. strcmp(token, "diversity-factor") != 0 &&
  693. strcmp(token, "smoothing-half-life") != 0)
  694. goto error;
  695. }
  696. if(strcmp(token, "protocol-port") == 0 ||
  697. strcmp(token, "kernel-priority") == 0 ||
  698. strcmp(token, "allow-duplicates") == 0 ||
  699. strcmp(token, "local-port") == 0 ||
  700. strcmp(token, "local-port-readwrite") == 0 ||
  701. strcmp(token, "export-table") == 0 ||
  702. strcmp(token, "import-table") == 0) {
  703. int v;
  704. c = getint(c, &v, gnc, closure);
  705. if(c < -1 || v <= 0 || v >= 0xFFFF)
  706. goto error;
  707. if(strcmp(token, "protocol-port") == 0)
  708. protocol_port = v;
  709. else if(strcmp(token, "kernel-priority") == 0)
  710. kernel_metric = v;
  711. else if(strcmp(token, "allow_duplicates") == 0)
  712. allow_duplicates = v;
  713. else if(strcmp(token, "local-port") == 0) {
  714. local_server_port = v;
  715. free(local_server_path);
  716. local_server_path = NULL;
  717. local_server_write = 0;
  718. } else if(strcmp(token, "local-port-readwrite") == 0) {
  719. local_server_port = v;
  720. free(local_server_path);
  721. local_server_path = NULL;
  722. local_server_write = 1;
  723. } else if(strcmp(token, "export-table") == 0)
  724. export_table = v;
  725. else if(strcmp(token, "import-table") == 0)
  726. add_import_table(v);
  727. else
  728. abort();
  729. } else if(strcmp(token, "keep-unfeasible") == 0 ||
  730. strcmp(token, "link-detect") == 0 ||
  731. strcmp(token, "random-id") == 0 ||
  732. strcmp(token, "daemonise") == 0 ||
  733. strcmp(token, "skip-kernel-setup") == 0 ||
  734. strcmp(token, "ipv6-subtrees") == 0 ||
  735. strcmp(token, "reflect-kernel-metric") == 0) {
  736. int b;
  737. c = getbool(c, &b, gnc, closure);
  738. if(c < -1)
  739. goto error;
  740. b = (b == CONFIG_YES);
  741. if(strcmp(token, "keep-unfeasible") == 0)
  742. keep_unfeasible = b;
  743. else if(strcmp(token, "link-detect") == 0)
  744. link_detect = b;
  745. else if(strcmp(token, "random-id") == 0)
  746. random_id = b;
  747. else if(strcmp(token, "daemonise") == 0)
  748. do_daemonise = b;
  749. else if(strcmp(token, "skip-kernel-setup") == 0)
  750. skip_kernel_setup = b;
  751. else if(strcmp(token, "ipv6-subtrees") == 0)
  752. has_ipv6_subtrees = b;
  753. else if(strcmp(token, "reflect-kernel-metric") == 0)
  754. reflect_kernel_metric = b;
  755. else
  756. abort();
  757. } else if(strcmp(token, "protocol-group") == 0) {
  758. unsigned char *group = NULL;
  759. c = getip(c, &group, NULL, gnc, closure);
  760. if(c < -1)
  761. goto error;
  762. memcpy(protocol_group, group, 16);
  763. free(group);
  764. } else if(strcmp(token, "state-file") == 0 ||
  765. strcmp(token, "log-file") == 0 ||
  766. strcmp(token, "pid-file") == 0 ||
  767. strcmp(token, "local-path") == 0 ||
  768. strcmp(token, "local-path-readwrite") == 0) {
  769. char *file;
  770. c = getstring(c, &file, gnc, closure);
  771. if(c < -1)
  772. goto error;
  773. if(strcmp(token, "state-file") == 0)
  774. state_file = file;
  775. else if(strcmp(token, "log-file") == 0) {
  776. logfile = file;
  777. if(config_finalised)
  778. reopen_logfile();
  779. } else if(strcmp(token, "pid-file") == 0)
  780. pidfile = file;
  781. else if(strcmp(token, "local-path") == 0) {
  782. local_server_port = -1;
  783. free(local_server_path);
  784. local_server_path = file;
  785. local_server_write = 0;
  786. } else if(strcmp(token, "local-path-readwrite") == 0) {
  787. local_server_port = -1;
  788. free(local_server_path);
  789. local_server_path = file;
  790. local_server_write = 1;
  791. } else
  792. abort();
  793. } else if(strcmp(token, "debug") == 0) {
  794. int d;
  795. c = getint(c, &d, gnc, closure);
  796. if(c < -1 || d < 0)
  797. goto error;
  798. debug = d;
  799. } else if(strcmp(token, "diversity") == 0) {
  800. int d;
  801. c = skip_whitespace(c, gnc, closure);
  802. if(c >= '0' && c <= '9') {
  803. c = getint(c, &d, gnc, closure);
  804. if(c < -1)
  805. goto error;
  806. } else {
  807. int b;
  808. c = getbool(c, &b, gnc, closure);
  809. if(c < -1)
  810. goto error;
  811. d = (b == CONFIG_YES) ? 3 : 0;
  812. }
  813. diversity_kind = d;
  814. } else if(strcmp(token, "diversity-factor") == 0) {
  815. int f;
  816. c = getint(c, &f, gnc, closure);
  817. if(c < -1 || f < 0 || f > 256)
  818. goto error;
  819. diversity_factor = f;
  820. } else if(strcmp(token, "smoothing-half-life") == 0) {
  821. int h;
  822. c = getint(c, &h, gnc, closure);
  823. if(c < -1 || h < 0)
  824. goto error;
  825. change_smoothing_half_life(h);
  826. } else if(strcmp(token, "first-table-number") == 0) {
  827. int n;
  828. c = getint(c, &n, gnc, closure);
  829. if(c < -1 || n <= 0 || n + SRC_TABLE_NUM >= 254)
  830. goto error;
  831. src_table_idx = n;
  832. } else if(strcmp(token, "first-rule-priority") == 0) {
  833. int n;
  834. c = getint(c, &n, gnc, closure);
  835. if(c < -1 || n <= 0 || n + SRC_TABLE_NUM >= 32765)
  836. goto error;
  837. src_table_prio = n;
  838. } else if(strcmp(token, "router-id") == 0) {
  839. unsigned char *id = NULL;
  840. c = getid(c, &id, gnc, closure);
  841. if(c < -1 || id == NULL)
  842. goto error;
  843. memcpy(myid, id, 8);
  844. free(id);
  845. have_id = 1;
  846. } else {
  847. goto error;
  848. }
  849. return skip_eol(c, gnc, closure);
  850. error:
  851. return -2;
  852. }
  853. static int
  854. parse_config_line(int c, gnc_t gnc, void *closure,
  855. int *action_return, const char **message_return)
  856. {
  857. char *token;
  858. if(action_return)
  859. *action_return = CONFIG_ACTION_DONE;
  860. if(message_return)
  861. *message_return = NULL;
  862. c = skip_whitespace(c, gnc, closure);
  863. if(c < 0 || c == '\n' || c == '#')
  864. return skip_to_eol(c, gnc, closure);
  865. c = getword(c, &token, gnc, closure);
  866. if(c < -1)
  867. return c;
  868. /* Directives allowed in read-only mode */
  869. if(strcmp(token, "quit") == 0) {
  870. c = skip_eol(c, gnc, closure);
  871. if(c < -1 || !action_return)
  872. goto fail;
  873. *action_return = CONFIG_ACTION_QUIT;
  874. } else if(strcmp(token, "dump") == 0) {
  875. c = skip_eol(c, gnc, closure);
  876. if(c < -1 || !action_return)
  877. goto fail;
  878. *action_return = CONFIG_ACTION_DUMP;
  879. } else if(strcmp(token, "monitor") == 0) {
  880. c = skip_eol(c, gnc, closure);
  881. if(c < -1 || !action_return)
  882. goto fail;
  883. *action_return = CONFIG_ACTION_MONITOR;
  884. } else if(strcmp(token, "unmonitor") == 0) {
  885. c = skip_eol(c, gnc, closure);
  886. if(c < -1 || !action_return)
  887. goto fail;
  888. *action_return = CONFIG_ACTION_UNMONITOR;
  889. } else if(config_finalised && !local_server_write) {
  890. /* The remaining directives are only allowed in read-write mode. */
  891. c = skip_to_eol(c, gnc, closure);
  892. if(c < -1 || !action_return)
  893. goto fail;
  894. /* Unfortunately, we cannot report NO here, since we don't know if
  895. the line is parsable. Oh, well. */
  896. goto fail;
  897. } else if(strcmp(token, "in") == 0) {
  898. struct filter *filter;
  899. if(config_finalised)
  900. goto fail;
  901. c = parse_filter(c, gnc, closure, &filter);
  902. if(c < -1)
  903. goto fail;
  904. add_filter(filter, &input_filters);
  905. } else if(strcmp(token, "out") == 0) {
  906. struct filter *filter;
  907. if(config_finalised)
  908. goto fail;
  909. c = parse_filter(c, gnc, closure, &filter);
  910. if(c < -1)
  911. goto fail;
  912. add_filter(filter, &output_filters);
  913. } else if(strcmp(token, "redistribute") == 0) {
  914. struct filter *filter;
  915. if(config_finalised)
  916. goto fail;
  917. c = parse_filter(c, gnc, closure, &filter);
  918. if(c < -1)
  919. goto fail;
  920. add_filter(filter, &redistribute_filters);
  921. } else if(strcmp(token, "install") == 0) {
  922. struct filter *filter;
  923. if(config_finalised)
  924. goto fail;
  925. c = parse_filter(c, gnc, closure, &filter);
  926. if(c < -1)
  927. goto fail;
  928. } else if(strcmp(token, "interface") == 0) {
  929. struct interface_conf *if_conf;
  930. c = parse_ifconf(c, gnc, closure, &if_conf);
  931. if(c < -1)
  932. goto fail;
  933. add_ifconf(if_conf, &interface_confs);
  934. } else if(strcmp(token, "default") == 0) {
  935. struct interface_conf *if_conf;
  936. c = parse_anonymous_ifconf(c, gnc, closure, NULL, &if_conf);
  937. if(c < -1)
  938. goto fail;
  939. if(default_interface_conf == NULL)
  940. default_interface_conf = if_conf;
  941. else {
  942. merge_ifconf(default_interface_conf,
  943. if_conf, default_interface_conf);
  944. free(if_conf);
  945. }
  946. } else if(strcmp(token, "flush") == 0) {
  947. char *token2;
  948. c = skip_whitespace(c, gnc, closure);
  949. c = getword(c, &token2, gnc, closure);
  950. if(c < -1)
  951. goto fail;
  952. if(strcmp(token2, "interface") == 0) {
  953. char *ifname;
  954. int rc;
  955. c = getword(c, &ifname, gnc, closure);
  956. c = skip_eol(c, gnc, closure);
  957. if(c < -1) {
  958. free(token2);
  959. goto fail;
  960. }
  961. rc = flush_interface(ifname);
  962. if(rc <= 0) {
  963. if(action_return)
  964. *action_return = CONFIG_ACTION_NO;
  965. if(message_return) {
  966. if(rc < 0)
  967. *message_return = "Couldn't flush interface";
  968. else
  969. *message_return = "No such interface";
  970. }
  971. }
  972. free(token2);
  973. free(ifname);
  974. } else {
  975. free(token2);
  976. goto fail;
  977. }
  978. } else if(strcmp(token, "reopen-logfile") == 0) {
  979. c = skip_eol(c, gnc, closure);
  980. if(c < -1 || !action_return)
  981. goto fail;
  982. reopen_logfile();
  983. } else {
  984. c = parse_option(c, gnc, closure, token);
  985. if(c < -1)
  986. goto fail;
  987. }
  988. free(token);
  989. return c;
  990. fail:
  991. free(token);
  992. return -2;
  993. }
  994. struct file_state {
  995. FILE *f;
  996. int line;
  997. };
  998. static int
  999. gnc_file(struct file_state *s)
  1000. {
  1001. int c;
  1002. c = fgetc(s->f);
  1003. if(c == '\n')
  1004. s->line++;
  1005. return c;
  1006. }
  1007. int
  1008. parse_config_from_file(const char *filename, int *line_return)
  1009. {
  1010. struct file_state s = { NULL, 1 };
  1011. int c;
  1012. s.f = fopen(filename, "r");
  1013. if(s.f == NULL) {
  1014. *line_return = 0;
  1015. return -1;
  1016. }
  1017. c = gnc_file(&s);
  1018. if(c < 0)
  1019. return 0;
  1020. while(1) {
  1021. c = parse_config_line(c, (gnc_t)gnc_file, &s, NULL, NULL);
  1022. if(c < -1) {
  1023. *line_return = s.line;
  1024. return -1;
  1025. }
  1026. if(c == -1)
  1027. break;
  1028. }
  1029. fclose(s.f);
  1030. return 1;
  1031. }
  1032. struct buf_state {
  1033. char *buf;
  1034. int i, n;
  1035. };
  1036. static int
  1037. gnc_buf(struct buf_state *s)
  1038. {
  1039. if(s->i < s->n)
  1040. return (s->buf[s->i++]) & 0xFF;
  1041. else
  1042. return -1;
  1043. }
  1044. int
  1045. parse_config_from_string(char *string, int n, const char **message_return)
  1046. {
  1047. int c, action;
  1048. const char *message;
  1049. struct buf_state s = { string, 0, n };
  1050. c = gnc_buf(&s);
  1051. if(c < 0)
  1052. return -1;
  1053. c = parse_config_line(c, (gnc_t)gnc_buf, &s, &action, &message);
  1054. if(c == -1) {
  1055. if(message_return)
  1056. *message_return = message;
  1057. return action;
  1058. } else
  1059. return -1;
  1060. }
  1061. static void
  1062. renumber_filter(struct filter *filter)
  1063. {
  1064. while(filter) {
  1065. if(filter->ifname)
  1066. filter->ifindex = if_nametoindex(filter->ifname);
  1067. filter = filter->next;
  1068. }
  1069. }
  1070. void
  1071. renumber_filters()
  1072. {
  1073. renumber_filter(input_filters);
  1074. renumber_filter(output_filters);
  1075. renumber_filter(redistribute_filters);
  1076. renumber_filter(install_filters);
  1077. }
  1078. static int
  1079. filter_match(struct filter *f, const unsigned char *id,
  1080. const unsigned char *prefix, unsigned short plen,
  1081. const unsigned char *src_prefix, unsigned short src_plen,
  1082. const unsigned char *neigh, unsigned int ifindex, int proto)
  1083. {
  1084. if(f->af) {
  1085. if(plen >= 96 && v4mapped(prefix)) {
  1086. if(f->af == AF_INET6) return 0;
  1087. } else {
  1088. if(f->af == AF_INET) return 0;
  1089. }
  1090. }
  1091. if(f->id) {
  1092. if(!id || memcmp(f->id, id, 8) != 0)
  1093. return 0;
  1094. }
  1095. if(f->prefix) {
  1096. if(!prefix || plen < f->plen || !in_prefix(prefix, f->prefix, f->plen))
  1097. return 0;
  1098. }
  1099. if(f->src_prefix) {
  1100. if(!src_prefix || src_plen < f->src_plen ||
  1101. !in_prefix(src_prefix, f->src_prefix, f->src_plen))
  1102. return 0;
  1103. }
  1104. if(f->plen_ge > 0 || f->plen_le < 128) {
  1105. if(!prefix)
  1106. return 0;
  1107. if(plen > f->plen_le)
  1108. return 0;
  1109. if(plen < f->plen_ge)
  1110. return 0;
  1111. }
  1112. if(f->src_plen_ge > 0 || f->src_plen_le < 128) {
  1113. if(!src_prefix)
  1114. return 0;
  1115. if(src_plen > f->src_plen_le)
  1116. return 0;
  1117. if(src_plen < f->src_plen_ge)
  1118. return 0;
  1119. }
  1120. if(f->neigh) {
  1121. if(!neigh || memcmp(f->neigh, neigh, 16) != 0)
  1122. return 0;
  1123. }
  1124. if(f->ifname) {
  1125. if(!f->ifindex) /* no such interface */
  1126. return 0;
  1127. if(!ifindex || f->ifindex != ifindex)
  1128. return 0;
  1129. }
  1130. if(f->proto) {
  1131. if(!proto || f->proto != proto)
  1132. return 0;
  1133. } else if(proto == RTPROT_BABEL_LOCAL) {
  1134. return 0;
  1135. #ifdef __linux
  1136. } else if(proto == RTPROT_BOOT) {
  1137. return 0;
  1138. #endif
  1139. }
  1140. return 1;
  1141. }
  1142. static int
  1143. do_filter(struct filter *f, const unsigned char *id,
  1144. const unsigned char *prefix, unsigned short plen,
  1145. const unsigned char *src_prefix, unsigned short src_plen,
  1146. const unsigned char *neigh, unsigned int ifindex, int proto,
  1147. struct filter_result *result)
  1148. {
  1149. if(result)
  1150. memset(result, 0, sizeof(struct filter_result));
  1151. while(f) {
  1152. if(filter_match(f, id, prefix, plen, src_prefix, src_plen,
  1153. neigh, ifindex, proto)) {
  1154. if(result)
  1155. memcpy(result, &f->action, sizeof(struct filter_result));
  1156. return f->action.add_metric;
  1157. }
  1158. f = f->next;
  1159. }
  1160. return -1;
  1161. }
  1162. int
  1163. input_filter(const unsigned char *id,
  1164. const unsigned char *prefix, unsigned short plen,
  1165. const unsigned char *src_prefix, unsigned short src_plen,
  1166. const unsigned char *neigh, unsigned int ifindex)
  1167. {
  1168. int res;
  1169. res = do_filter(input_filters, id, prefix, plen,
  1170. src_prefix, src_plen, neigh, ifindex, 0, NULL);
  1171. if(res < 0)
  1172. res = 0;
  1173. return res;
  1174. }
  1175. int
  1176. output_filter(const unsigned char *id,
  1177. const unsigned char *prefix, unsigned short plen,
  1178. const unsigned char *src_prefix, unsigned short src_plen,
  1179. unsigned int ifindex)
  1180. {
  1181. int res;
  1182. res = do_filter(output_filters, id, prefix, plen,
  1183. src_prefix, src_plen, NULL, ifindex, 0, NULL);
  1184. if(res < 0)
  1185. res = 0;
  1186. return res;
  1187. }
  1188. int
  1189. redistribute_filter(const unsigned char *prefix, unsigned short plen,
  1190. const unsigned char *src_prefix, unsigned short src_plen,
  1191. unsigned int ifindex, int proto,
  1192. struct filter_result *result)
  1193. {
  1194. int res;
  1195. res = do_filter(redistribute_filters, NULL, prefix, plen,
  1196. src_prefix, src_plen, NULL, ifindex, proto, result);
  1197. if(res < 0)
  1198. res = INFINITY;
  1199. return res;
  1200. }
  1201. int
  1202. install_filter(const unsigned char *prefix, unsigned short plen,
  1203. const unsigned char *src_prefix, unsigned short src_plen,
  1204. struct filter_result *result)
  1205. {
  1206. int res;
  1207. res = do_filter(install_filters, NULL, prefix, plen,
  1208. src_prefix, src_plen, NULL, 0, 0, result);
  1209. if(res < 0)
  1210. res = INFINITY;
  1211. return res;
  1212. }
  1213. int
  1214. finalise_config()
  1215. {
  1216. struct filter *filter = calloc(1, sizeof(struct filter));
  1217. if(filter == NULL)
  1218. return -1;
  1219. filter->proto = RTPROT_BABEL_LOCAL;
  1220. filter->plen_le = 128;
  1221. filter->src_plen_le = 128;
  1222. add_filter(filter, &redistribute_filters);
  1223. while(interface_confs) {
  1224. struct interface_conf *if_conf;
  1225. void *vrc;
  1226. if_conf = interface_confs;
  1227. interface_confs = interface_confs->next;
  1228. if_conf->next = NULL;
  1229. if(default_interface_conf)
  1230. merge_ifconf(if_conf, if_conf, default_interface_conf);
  1231. vrc = add_interface(if_conf->ifname, if_conf);
  1232. if(vrc == NULL) {
  1233. fprintf(stderr, "Couldn't add interface %s.\n", if_conf->ifname);
  1234. return -1;
  1235. }
  1236. }
  1237. config_finalised = 1;
  1238. return 1;
  1239. }