1*d2a044efStb /* $OpenBSD: parse.y,v 1.106 2024/08/22 08:34:51 tb Exp $ */ 2204df0f8Sclaudio 3204df0f8Sclaudio /* 43ada9d8fSnorby * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org> 5204df0f8Sclaudio * Copyright (c) 2004 Ryan McBride <mcbride@openbsd.org> 6204df0f8Sclaudio * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org> 7204df0f8Sclaudio * Copyright (c) 2001 Markus Friedl. All rights reserved. 8204df0f8Sclaudio * Copyright (c) 2001 Daniel Hartmeier. All rights reserved. 9204df0f8Sclaudio * Copyright (c) 2001 Theo de Raadt. All rights reserved. 10204df0f8Sclaudio * 11204df0f8Sclaudio * Permission to use, copy, modify, and distribute this software for any 12204df0f8Sclaudio * purpose with or without fee is hereby granted, provided that the above 13204df0f8Sclaudio * copyright notice and this permission notice appear in all copies. 14204df0f8Sclaudio * 15204df0f8Sclaudio * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 16204df0f8Sclaudio * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 17204df0f8Sclaudio * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 18204df0f8Sclaudio * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 19204df0f8Sclaudio * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 20204df0f8Sclaudio * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 21204df0f8Sclaudio * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 22204df0f8Sclaudio */ 23204df0f8Sclaudio 24204df0f8Sclaudio %{ 25204df0f8Sclaudio #include <sys/types.h> 26204df0f8Sclaudio #include <sys/socket.h> 2720741916Sderaadt #include <sys/stat.h> 284c260f66Sremi #include <net/route.h> 29204df0f8Sclaudio #include <netinet/in.h> 30204df0f8Sclaudio #include <arpa/inet.h> 31204df0f8Sclaudio #include <ctype.h> 32204df0f8Sclaudio #include <err.h> 33204df0f8Sclaudio #include <errno.h> 3420741916Sderaadt #include <unistd.h> 35f12637e5Smsf #include <ifaddrs.h> 362e8dee25Smillert #include <limits.h> 37204df0f8Sclaudio #include <stdarg.h> 38204df0f8Sclaudio #include <stdio.h> 39204df0f8Sclaudio #include <string.h> 4036f8cec5Ssthen #include <syslog.h> 41204df0f8Sclaudio 42204df0f8Sclaudio #include "ospf.h" 43204df0f8Sclaudio #include "ospfd.h" 44204df0f8Sclaudio #include "ospfe.h" 45204df0f8Sclaudio #include "log.h" 46204df0f8Sclaudio 4720741916Sderaadt TAILQ_HEAD(files, file) files = TAILQ_HEAD_INITIALIZER(files); 4820741916Sderaadt static struct file { 4920741916Sderaadt TAILQ_ENTRY(file) entry; 5020741916Sderaadt FILE *stream; 5120741916Sderaadt char *name; 52a8823310Sdenis size_t ungetpos; 53a8823310Sdenis size_t ungetsize; 54a8823310Sdenis u_char *ungetbuf; 55a8823310Sdenis int eof_reached; 5620741916Sderaadt int lineno; 5720741916Sderaadt int errors; 58c6004ab9Smpf } *file, *topfile; 5920741916Sderaadt struct file *pushfile(const char *, int); 6020741916Sderaadt int popfile(void); 6120741916Sderaadt int check_file_secrecy(int, const char *); 62204df0f8Sclaudio int yyparse(void); 6320741916Sderaadt int yylex(void); 649c81ce9fSdoug int yyerror(const char *, ...) 659c81ce9fSdoug __attribute__((__format__ (printf, 1, 2))) 669c81ce9fSdoug __attribute__((__nonnull__ (1))); 67204df0f8Sclaudio int kw_cmp(const void *, const void *); 68204df0f8Sclaudio int lookup(char *); 69a8823310Sdenis int igetc(void); 70d5d66eaeSderaadt int lgetc(int); 71a8823310Sdenis void lungetc(int); 72204df0f8Sclaudio int findeol(void); 7320741916Sderaadt 7420741916Sderaadt TAILQ_HEAD(symhead, sym) symhead = TAILQ_HEAD_INITIALIZER(symhead); 7520741916Sderaadt struct sym { 7620741916Sderaadt TAILQ_ENTRY(sym) entry; 7720741916Sderaadt int used; 7820741916Sderaadt int persist; 7920741916Sderaadt char *nam; 8020741916Sderaadt char *val; 8120741916Sderaadt }; 8220741916Sderaadt int symset(const char *, const char *, int); 8320741916Sderaadt char *symget(const char *); 8420741916Sderaadt 85204df0f8Sclaudio void clear_config(struct ospfd_conf *xconf); 86471ee2ebSclaudio int host(const char *, struct in_addr *, struct in_addr *); 87204df0f8Sclaudio 8820741916Sderaadt static struct ospfd_conf *conf; 8920741916Sderaadt static int errors = 0; 9020741916Sderaadt 9120741916Sderaadt struct area *area = NULL; 9220741916Sderaadt struct iface *iface = NULL; 9320741916Sderaadt 94627c6412Sclaudio struct config_defaults { 9576b51f83Sclaudio char auth_key[MAX_SIMPLE_AUTH_LEN]; 9676b51f83Sclaudio struct auth_md_head md_list; 97204df0f8Sclaudio u_int32_t dead_interval; 987afdfd2dSdlg u_int32_t fast_hello_interval; 991d3a1c7dSnorby u_int16_t transmit_delay; 100204df0f8Sclaudio u_int16_t hello_interval; 101204df0f8Sclaudio u_int16_t rxmt_interval; 102204df0f8Sclaudio u_int16_t metric; 10376b51f83Sclaudio enum auth_type auth_type; 10476b51f83Sclaudio u_int8_t auth_keyid; 105204df0f8Sclaudio u_int8_t priority; 10609e8f780Sremi u_int8_t p2p; 107627c6412Sclaudio }; 108627c6412Sclaudio 109627c6412Sclaudio struct config_defaults globaldefs; 110627c6412Sclaudio struct config_defaults areadefs; 111627c6412Sclaudio struct config_defaults ifacedefs; 112627c6412Sclaudio struct config_defaults *defs; 113204df0f8Sclaudio 114204df0f8Sclaudio struct area *conf_get_area(struct in_addr); 11566dd3991Sclaudio struct iface *conf_get_if(struct kif *, struct kif_addr *); 116358269bbSclaudio int conf_check_rdomain(unsigned int); 117204df0f8Sclaudio 118204df0f8Sclaudio typedef struct { 119204df0f8Sclaudio union { 12091d3283aSclaudio int64_t number; 121204df0f8Sclaudio char *string; 1226fa28760Sclaudio struct redistribute *redist; 123cacfc040Sdlg struct in_addr id; 124204df0f8Sclaudio } v; 125204df0f8Sclaudio int lineno; 126204df0f8Sclaudio } YYSTYPE; 127204df0f8Sclaudio 128204df0f8Sclaudio %} 129204df0f8Sclaudio 1304c260f66Sremi %token AREA INTERFACE ROUTERID FIBPRIORITY FIBUPDATE REDISTRIBUTE RTLABEL 1314c260f66Sremi %token RDOMAIN RFC1583COMPAT STUB ROUTER SPFDELAY SPFHOLDTIME EXTTAG 13203431b74Snorby %token AUTHKEY AUTHTYPE AUTHMD AUTHMDKEYID 133ef209401Sremi %token METRIC P2P PASSIVE 1347afdfd2dSdlg %token HELLOINTERVAL FASTHELLOINTERVAL TRANSMITDELAY 135204df0f8Sclaudio %token RETRANSMITINTERVAL ROUTERDEADTIME ROUTERPRIORITY 136f373ed5aSclaudio %token SET TYPE 137619421e7Sclaudio %token YES NO 1387afdfd2dSdlg %token MSEC MINIMAL 139fba2d3d0Sclaudio %token DEMOTE 1404fd4397dSdlg %token INCLUDE 141204df0f8Sclaudio %token ERROR 142ac149fe2Sremi %token DEPEND ON 143204df0f8Sclaudio %token <v.string> STRING 14491d3283aSclaudio %token <v.number> NUMBER 14537877ca4Sdlg %type <v.number> yesno no optlist optlist_l option demotecount msec 1467afdfd2dSdlg %type <v.number> deadtime 147a3f6d01eSclaudio %type <v.string> string dependon dependonopt 1486fa28760Sclaudio %type <v.redist> redistribute 149cacfc040Sdlg %type <v.id> areaid 150204df0f8Sclaudio 151204df0f8Sclaudio %% 152204df0f8Sclaudio 153204df0f8Sclaudio grammar : /* empty */ 1544fd4397dSdlg | grammar include '\n' 155204df0f8Sclaudio | grammar '\n' 156204df0f8Sclaudio | grammar conf_main '\n' 157204df0f8Sclaudio | grammar varset '\n' 158204df0f8Sclaudio | grammar area '\n' 15920741916Sderaadt | grammar error '\n' { file->errors++; } 160204df0f8Sclaudio ; 161204df0f8Sclaudio 1624fd4397dSdlg include : INCLUDE STRING { 1634fd4397dSdlg struct file *nfile; 1644fd4397dSdlg 165a8823310Sdenis if ((nfile = pushfile($2, 166a8823310Sdenis !(conf->opts & OSPFD_OPT_NOACTION))) == NULL) { 1674fd4397dSdlg yyerror("failed to include file %s", $2); 1684fd4397dSdlg free($2); 1694fd4397dSdlg YYERROR; 1704fd4397dSdlg } 1714fd4397dSdlg free($2); 1724fd4397dSdlg 1734fd4397dSdlg file = nfile; 1744fd4397dSdlg lungetc('\n'); 1754fd4397dSdlg } 1764fd4397dSdlg ; 1774fd4397dSdlg 178204df0f8Sclaudio string : string STRING { 179204df0f8Sclaudio if (asprintf(&$$, "%s %s", $1, $2) == -1) { 180204df0f8Sclaudio free($1); 181204df0f8Sclaudio free($2); 182204df0f8Sclaudio yyerror("string: asprintf"); 183204df0f8Sclaudio YYERROR; 184204df0f8Sclaudio } 185204df0f8Sclaudio free($1); 186204df0f8Sclaudio free($2); 187204df0f8Sclaudio } 188204df0f8Sclaudio | STRING 189204df0f8Sclaudio ; 190204df0f8Sclaudio 191619421e7Sclaudio yesno : YES { $$ = 1; } 192619421e7Sclaudio | NO { $$ = 0; } 193204df0f8Sclaudio ; 194204df0f8Sclaudio 195619421e7Sclaudio no : /* empty */ { $$ = 0; } 196619421e7Sclaudio | NO { $$ = 1; } 197bc5f24a9Ssimon ; 198619421e7Sclaudio 19937877ca4Sdlg msec : MSEC NUMBER { 20037877ca4Sdlg $$ = $2; 20137877ca4Sdlg } 20237877ca4Sdlg | NUMBER { 20337877ca4Sdlg $$ = $1 * 1000; 20437877ca4Sdlg } 20537877ca4Sdlg ; 20637877ca4Sdlg 207204df0f8Sclaudio varset : STRING '=' string { 2080c7b4ca6Sbenno char *s = $1; 209204df0f8Sclaudio if (conf->opts & OSPFD_OPT_VERBOSE) 210204df0f8Sclaudio printf("%s = \"%s\"\n", $1, $3); 2110c7b4ca6Sbenno while (*s++) { 2120c7b4ca6Sbenno if (isspace((unsigned char)*s)) { 2130c7b4ca6Sbenno yyerror("macro name cannot contain " 2140c7b4ca6Sbenno "whitespace"); 21516a0a906Skrw free($1); 21616a0a906Skrw free($3); 2170c7b4ca6Sbenno YYERROR; 2180c7b4ca6Sbenno } 2190c7b4ca6Sbenno } 220204df0f8Sclaudio if (symset($1, $3, 0) == -1) 221204df0f8Sclaudio fatal("cannot store variable"); 222204df0f8Sclaudio free($1); 223204df0f8Sclaudio free($3); 224204df0f8Sclaudio } 225204df0f8Sclaudio ; 226204df0f8Sclaudio 227627c6412Sclaudio conf_main : ROUTERID STRING { 22882905b67Sflorian if (inet_pton(AF_INET, $2, &conf->rtr_id) != 1) { 229204df0f8Sclaudio yyerror("error parsing router-id"); 230204df0f8Sclaudio free($2); 231204df0f8Sclaudio YYERROR; 232204df0f8Sclaudio } 2331436b306Sclaudio free($2); 234204df0f8Sclaudio } 2354c260f66Sremi | FIBPRIORITY NUMBER { 2364c260f66Sremi if ($2 <= RTP_NONE || $2 > RTP_MAX) { 2374c260f66Sremi yyerror("invalid fib-priority"); 2384c260f66Sremi YYERROR; 2394c260f66Sremi } 2404c260f66Sremi conf->fib_priority = $2; 2414c260f66Sremi } 242204df0f8Sclaudio | FIBUPDATE yesno { 243204df0f8Sclaudio if ($2 == 0) 244204df0f8Sclaudio conf->flags |= OSPFD_FLAG_NO_FIB_UPDATE; 245204df0f8Sclaudio else 246204df0f8Sclaudio conf->flags &= ~OSPFD_FLAG_NO_FIB_UPDATE; 247204df0f8Sclaudio } 2486fa28760Sclaudio | redistribute { 2496fa28760Sclaudio SIMPLEQ_INSERT_TAIL(&conf->redist_list, $1, entry); 2506fa28760Sclaudio conf->redistribute = 1; 251e2993955Sclaudio } 25291d3283aSclaudio | RTLABEL STRING EXTTAG NUMBER { 25391d3283aSclaudio if ($4 < 0 || $4 > UINT_MAX) { 254fcb4545bSreyk yyerror("invalid external route tag"); 255fcb4545bSreyk free($2); 256fcb4545bSreyk YYERROR; 257fcb4545bSreyk } 258fcb4545bSreyk rtlabel_tag(rtlabel_name2id($2), $4); 259fcb4545bSreyk free($2); 260fcb4545bSreyk } 261e4caa3d9Sclaudio | RDOMAIN NUMBER { 262e4caa3d9Sclaudio if ($2 < 0 || $2 > RT_TABLEID_MAX) { 263e4caa3d9Sclaudio yyerror("invalid rdomain"); 264e4caa3d9Sclaudio YYERROR; 265e4caa3d9Sclaudio } 266e4caa3d9Sclaudio conf->rdomain = $2; 267e4caa3d9Sclaudio } 268bbb7cc9cSnorby | RFC1583COMPAT yesno { 269bbb7cc9cSnorby conf->rfc1583compat = $2; 270bbb7cc9cSnorby } 27137877ca4Sdlg | SPFDELAY msec { 2723ada9d8fSnorby if ($2 < MIN_SPF_DELAY || $2 > MAX_SPF_DELAY) { 2733ada9d8fSnorby yyerror("spf-delay out of range " 2743ada9d8fSnorby "(%d-%d)", MIN_SPF_DELAY, 2753ada9d8fSnorby MAX_SPF_DELAY); 2763ada9d8fSnorby YYERROR; 2773ada9d8fSnorby } 2783ada9d8fSnorby conf->spf_delay = $2; 2793ada9d8fSnorby } 28037877ca4Sdlg | SPFHOLDTIME msec { 2813ada9d8fSnorby if ($2 < MIN_SPF_HOLDTIME || $2 > MAX_SPF_HOLDTIME) { 2823ada9d8fSnorby yyerror("spf-holdtime out of range " 2833ada9d8fSnorby "(%d-%d)", MIN_SPF_HOLDTIME, 2843ada9d8fSnorby MAX_SPF_HOLDTIME); 2853ada9d8fSnorby YYERROR; 2863ada9d8fSnorby } 2873ada9d8fSnorby conf->spf_hold_time = $2; 2883ada9d8fSnorby } 2891891964aSclaudio | STUB ROUTER yesno { 2901891964aSclaudio if ($3) 2911891964aSclaudio conf->flags |= OSPFD_FLAG_STUB_ROUTER; 2921891964aSclaudio else 2931891964aSclaudio /* allow to force non stub mode */ 2941891964aSclaudio conf->flags &= ~OSPFD_FLAG_STUB_ROUTER; 2951891964aSclaudio } 296627c6412Sclaudio | defaults 297204df0f8Sclaudio ; 298204df0f8Sclaudio 2996fa28760Sclaudio 300a3f6d01eSclaudio redistribute : no REDISTRIBUTE NUMBER '/' NUMBER optlist dependonopt { 3016fa28760Sclaudio struct redistribute *r; 3026fa28760Sclaudio 3036fa28760Sclaudio if ((r = calloc(1, sizeof(*r))) == NULL) 3046fa28760Sclaudio fatal(NULL); 3056fa28760Sclaudio r->type = REDIST_ADDR; 3066fa28760Sclaudio if ($3 < 0 || $3 > 255 || $5 < 1 || $5 > 32) { 3076fa28760Sclaudio yyerror("bad network: %llu/%llu", $3, $5); 3086fa28760Sclaudio free(r); 3096fa28760Sclaudio YYERROR; 3106fa28760Sclaudio } 3116fa28760Sclaudio r->addr.s_addr = htonl($3 << IN_CLASSA_NSHIFT); 3126fa28760Sclaudio r->mask.s_addr = prefixlen2mask($5); 3136fa28760Sclaudio 3146fa28760Sclaudio if ($1) 3156fa28760Sclaudio r->type |= REDIST_NO; 316ad4152efSbenno else 317ad4152efSbenno conf->redist_label_or_prefix = 1; 3186fa28760Sclaudio r->metric = $6; 31902ba2abaSjca if ($7) 320ac149fe2Sremi strlcpy(r->dependon, $7, sizeof(r->dependon)); 32102ba2abaSjca else 322ac149fe2Sremi r->dependon[0] = '\0'; 323ac149fe2Sremi free($7); 3246fa28760Sclaudio $$ = r; 3256fa28760Sclaudio } 326a3f6d01eSclaudio | no REDISTRIBUTE STRING optlist dependonopt { 3276fa28760Sclaudio struct redistribute *r; 3286fa28760Sclaudio 3296fa28760Sclaudio if ((r = calloc(1, sizeof(*r))) == NULL) 3306fa28760Sclaudio fatal(NULL); 3316fa28760Sclaudio if (!strcmp($3, "default")) 3326fa28760Sclaudio r->type = REDIST_DEFAULT; 3336fa28760Sclaudio else if (!strcmp($3, "static")) 3346fa28760Sclaudio r->type = REDIST_STATIC; 3356fa28760Sclaudio else if (!strcmp($3, "connected")) 3366fa28760Sclaudio r->type = REDIST_CONNECTED; 337ad4152efSbenno else if (host($3, &r->addr, &r->mask)) { 3386fa28760Sclaudio r->type = REDIST_ADDR; 339ad4152efSbenno conf->redist_label_or_prefix = !$1; 340ad4152efSbenno } else { 3416fa28760Sclaudio yyerror("unknown redistribute type"); 3426fa28760Sclaudio free($3); 3436fa28760Sclaudio free(r); 3446fa28760Sclaudio YYERROR; 3456fa28760Sclaudio } 3466fa28760Sclaudio 3476fa28760Sclaudio if ($1) 3486fa28760Sclaudio r->type |= REDIST_NO; 3496fa28760Sclaudio r->metric = $4; 35002ba2abaSjca if ($5) 351ac149fe2Sremi strlcpy(r->dependon, $5, sizeof(r->dependon)); 35202ba2abaSjca else 353ac149fe2Sremi r->dependon[0] = '\0'; 3546fa28760Sclaudio free($3); 355ac149fe2Sremi free($5); 3566fa28760Sclaudio $$ = r; 3576fa28760Sclaudio } 358c36a82f5Sdlg | no REDISTRIBUTE RTLABEL STRING optlist dependonopt { 3596fa28760Sclaudio struct redistribute *r; 3606fa28760Sclaudio 3616fa28760Sclaudio if ((r = calloc(1, sizeof(*r))) == NULL) 3626fa28760Sclaudio fatal(NULL); 3636fa28760Sclaudio r->type = REDIST_LABEL; 3646fa28760Sclaudio r->label = rtlabel_name2id($4); 3656fa28760Sclaudio if ($1) 3666fa28760Sclaudio r->type |= REDIST_NO; 367ad4152efSbenno else 368ad4152efSbenno conf->redist_label_or_prefix = 1; 3696fa28760Sclaudio r->metric = $5; 370ac149fe2Sremi if ($6) 371ac149fe2Sremi strlcpy(r->dependon, $6, sizeof(r->dependon)); 372ac149fe2Sremi else 373ac149fe2Sremi r->dependon[0] = '\0'; 3746fa28760Sclaudio free($4); 375ac149fe2Sremi free($6); 3766fa28760Sclaudio $$ = r; 3776fa28760Sclaudio } 3786fa28760Sclaudio ; 3796fa28760Sclaudio 380f373ed5aSclaudio optlist : /* empty */ { $$ = DEFAULT_REDIST_METRIC; } 381a5443f34Sclaudio | SET option { 382a5443f34Sclaudio $$ = $2; 383a5443f34Sclaudio if (($$ & LSA_METRIC_MASK) == 0) 384a5443f34Sclaudio $$ |= DEFAULT_REDIST_METRIC; 385a5443f34Sclaudio } 386a5443f34Sclaudio | SET optnl '{' optnl optlist_l optnl '}' { 387a5443f34Sclaudio $$ = $5; 388a5443f34Sclaudio if (($$ & LSA_METRIC_MASK) == 0) 389a5443f34Sclaudio $$ |= DEFAULT_REDIST_METRIC; 390a5443f34Sclaudio } 391f373ed5aSclaudio ; 392f373ed5aSclaudio 393f373ed5aSclaudio optlist_l : optlist_l comma option { 394f373ed5aSclaudio if ($1 & LSA_ASEXT_E_FLAG && $3 & LSA_ASEXT_E_FLAG) { 395f373ed5aSclaudio yyerror("redistribute type already defined"); 396f373ed5aSclaudio YYERROR; 397f373ed5aSclaudio } 398f373ed5aSclaudio if ($1 & LSA_METRIC_MASK && $3 & LSA_METRIC_MASK) { 3991e96e0a1Smichele yyerror("redistribute metric already defined"); 400f373ed5aSclaudio YYERROR; 401f373ed5aSclaudio } 402f373ed5aSclaudio $$ = $1 | $3; 403f373ed5aSclaudio } 404f373ed5aSclaudio | option { $$ = $1; } 405f373ed5aSclaudio ; 406f373ed5aSclaudio 40791d3283aSclaudio option : METRIC NUMBER { 408f373ed5aSclaudio if ($2 == 0 || $2 > MAX_METRIC) { 409f373ed5aSclaudio yyerror("invalid redistribute metric"); 410f373ed5aSclaudio YYERROR; 411f373ed5aSclaudio } 412f373ed5aSclaudio $$ = $2; 413f373ed5aSclaudio } 41491d3283aSclaudio | TYPE NUMBER { 415f373ed5aSclaudio switch ($2) { 416f373ed5aSclaudio case 1: 417f373ed5aSclaudio $$ = 0; 418f373ed5aSclaudio break; 419f373ed5aSclaudio case 2: 420f373ed5aSclaudio $$ = LSA_ASEXT_E_FLAG; 421f373ed5aSclaudio break; 422f373ed5aSclaudio default: 42391d3283aSclaudio yyerror("only external type 1 and 2 allowed"); 424f373ed5aSclaudio YYERROR; 425f373ed5aSclaudio } 426f373ed5aSclaudio } 427f373ed5aSclaudio ; 428f373ed5aSclaudio 429a3f6d01eSclaudio dependonopt : /* empty */ { $$ = NULL; } 430a3f6d01eSclaudio | dependon 431a3f6d01eSclaudio 432a3f6d01eSclaudio dependon : DEPEND ON STRING { 433ac149fe2Sremi struct in_addr addr; 434ac149fe2Sremi struct kif *kif; 435ac149fe2Sremi 436ac149fe2Sremi if (strlen($3) >= IFNAMSIZ) { 437ac149fe2Sremi yyerror("interface name %s too long", $3); 438ac149fe2Sremi free($3); 439ac149fe2Sremi YYERROR; 440ac149fe2Sremi } 441ac149fe2Sremi bzero(&addr, sizeof(addr)); 442ac149fe2Sremi if ((kif = kif_findname($3, addr, NULL)) == NULL) { 443ac149fe2Sremi yyerror("unknown interface %s", $3); 444ac149fe2Sremi free($3); 445ac149fe2Sremi YYERROR; 446ac149fe2Sremi } 447ac149fe2Sremi $$ = $3; 448ac149fe2Sremi } 449ac149fe2Sremi ; 450ac149fe2Sremi 45191d3283aSclaudio authmd : AUTHMD NUMBER STRING { 45203431b74Snorby if ($2 < MIN_MD_ID || $2 > MAX_MD_ID) { 453209c181bSstevesk yyerror("auth-md key-id out of range " 45403431b74Snorby "(%d-%d)", MIN_MD_ID, MAX_MD_ID); 45503431b74Snorby free($3); 45603431b74Snorby YYERROR; 45703431b74Snorby } 458eee4aafbSnorby if (strlen($3) > MD5_DIGEST_LENGTH) { 459209c181bSstevesk yyerror("auth-md key length out of range " 460eee4aafbSnorby "(max length %d)", 461eee4aafbSnorby MD5_DIGEST_LENGTH); 462eee4aafbSnorby free($3); 463eee4aafbSnorby YYERROR; 464eee4aafbSnorby } 46576b51f83Sclaudio md_list_add(&defs->md_list, $2, $3); 46603431b74Snorby free($3); 46703431b74Snorby } 46803431b74Snorby 46991d3283aSclaudio authmdkeyid : AUTHMDKEYID NUMBER { 47003431b74Snorby if ($2 < MIN_MD_ID || $2 > MAX_MD_ID) { 471209c181bSstevesk yyerror("auth-md-keyid out of range " 47203431b74Snorby "(%d-%d)", MIN_MD_ID, MAX_MD_ID); 47303431b74Snorby YYERROR; 47403431b74Snorby } 47576b51f83Sclaudio defs->auth_keyid = $2; 47603431b74Snorby } 47703431b74Snorby 478204df0f8Sclaudio authtype : AUTHTYPE STRING { 479204df0f8Sclaudio enum auth_type type; 480204df0f8Sclaudio 481204df0f8Sclaudio if (!strcmp($2, "none")) 482204df0f8Sclaudio type = AUTH_NONE; 483204df0f8Sclaudio else if (!strcmp($2, "simple")) 484204df0f8Sclaudio type = AUTH_SIMPLE; 485204df0f8Sclaudio else if (!strcmp($2, "crypt")) 48603431b74Snorby type = AUTH_CRYPT; 487204df0f8Sclaudio else { 488204df0f8Sclaudio yyerror("unknown auth-type"); 489204df0f8Sclaudio free($2); 490204df0f8Sclaudio YYERROR; 491204df0f8Sclaudio } 492204df0f8Sclaudio free($2); 49376b51f83Sclaudio defs->auth_type = type; 494204df0f8Sclaudio } 495204df0f8Sclaudio ; 496204df0f8Sclaudio 497204df0f8Sclaudio authkey : AUTHKEY STRING { 498eee4aafbSnorby if (strlen($2) > MAX_SIMPLE_AUTH_LEN) { 499d79d6d90Sclaudio yyerror("auth-key too long (max length %d)", 500d79d6d90Sclaudio MAX_SIMPLE_AUTH_LEN); 501eee4aafbSnorby free($2); 502eee4aafbSnorby YYERROR; 503eee4aafbSnorby } 50476b51f83Sclaudio strncpy(defs->auth_key, $2, 50576b51f83Sclaudio sizeof(defs->auth_key)); 5061436b306Sclaudio free($2); 507204df0f8Sclaudio } 508204df0f8Sclaudio ; 509204df0f8Sclaudio 51091d3283aSclaudio defaults : METRIC NUMBER { 511627c6412Sclaudio if ($2 < MIN_METRIC || $2 > MAX_METRIC) { 512627c6412Sclaudio yyerror("metric out of range (%d-%d)", 513627c6412Sclaudio MIN_METRIC, MAX_METRIC); 514627c6412Sclaudio YYERROR; 515627c6412Sclaudio } 516627c6412Sclaudio defs->metric = $2; 517627c6412Sclaudio } 51891d3283aSclaudio | ROUTERPRIORITY NUMBER { 519627c6412Sclaudio if ($2 < MIN_PRIORITY || $2 > MAX_PRIORITY) { 520627c6412Sclaudio yyerror("router-priority out of range (%d-%d)", 521627c6412Sclaudio MIN_PRIORITY, MAX_PRIORITY); 522627c6412Sclaudio YYERROR; 523627c6412Sclaudio } 524627c6412Sclaudio defs->priority = $2; 525627c6412Sclaudio } 5267afdfd2dSdlg | ROUTERDEADTIME deadtime { 527627c6412Sclaudio defs->dead_interval = $2; 528627c6412Sclaudio } 52991d3283aSclaudio | TRANSMITDELAY NUMBER { 530627c6412Sclaudio if ($2 < MIN_TRANSMIT_DELAY || 531627c6412Sclaudio $2 > MAX_TRANSMIT_DELAY) { 532627c6412Sclaudio yyerror("transmit-delay out of range (%d-%d)", 533627c6412Sclaudio MIN_TRANSMIT_DELAY, MAX_TRANSMIT_DELAY); 534627c6412Sclaudio YYERROR; 535627c6412Sclaudio } 536627c6412Sclaudio defs->transmit_delay = $2; 537627c6412Sclaudio } 53891d3283aSclaudio | HELLOINTERVAL NUMBER { 539627c6412Sclaudio if ($2 < MIN_HELLO_INTERVAL || 540627c6412Sclaudio $2 > MAX_HELLO_INTERVAL) { 541627c6412Sclaudio yyerror("hello-interval out of range (%d-%d)", 542627c6412Sclaudio MIN_HELLO_INTERVAL, MAX_HELLO_INTERVAL); 543627c6412Sclaudio YYERROR; 544627c6412Sclaudio } 545627c6412Sclaudio defs->hello_interval = $2; 546627c6412Sclaudio } 5477afdfd2dSdlg | FASTHELLOINTERVAL MSEC NUMBER { 5487afdfd2dSdlg if ($3 < MIN_FAST_INTERVAL || 5497afdfd2dSdlg $3 > MAX_FAST_INTERVAL) { 5507afdfd2dSdlg yyerror("fast-hello-interval msec out of " 5517afdfd2dSdlg "range (%d-%d)", MIN_FAST_INTERVAL, 5527afdfd2dSdlg MAX_FAST_INTERVAL); 5537afdfd2dSdlg YYERROR; 5547afdfd2dSdlg } 5557afdfd2dSdlg defs->fast_hello_interval = $3; 5567afdfd2dSdlg } 55791d3283aSclaudio | RETRANSMITINTERVAL NUMBER { 558627c6412Sclaudio if ($2 < MIN_RXMT_INTERVAL || $2 > MAX_RXMT_INTERVAL) { 559627c6412Sclaudio yyerror("retransmit-interval out of range " 560627c6412Sclaudio "(%d-%d)", MIN_RXMT_INTERVAL, 561627c6412Sclaudio MAX_RXMT_INTERVAL); 562627c6412Sclaudio YYERROR; 563627c6412Sclaudio } 564627c6412Sclaudio defs->rxmt_interval = $2; 565627c6412Sclaudio } 56609e8f780Sremi | TYPE P2P { 56709e8f780Sremi defs->p2p = 1; 56809e8f780Sremi } 56976b51f83Sclaudio | authtype 57076b51f83Sclaudio | authkey 57176b51f83Sclaudio | authmdkeyid 57276b51f83Sclaudio | authmd 57376b51f83Sclaudio ; 574627c6412Sclaudio 5757afdfd2dSdlg deadtime : NUMBER { 5767afdfd2dSdlg if ($1 < MIN_RTR_DEAD_TIME || $1 > MAX_RTR_DEAD_TIME) { 5777afdfd2dSdlg yyerror("router-dead-time out of range (%d-%d)", 5787afdfd2dSdlg MIN_RTR_DEAD_TIME, MAX_RTR_DEAD_TIME); 5797afdfd2dSdlg YYERROR; 5807afdfd2dSdlg } 5817afdfd2dSdlg $$ = $1; 5827afdfd2dSdlg } 5837afdfd2dSdlg | MINIMAL { 5847afdfd2dSdlg $$ = FAST_RTR_DEAD_TIME; 5857afdfd2dSdlg } 5867afdfd2dSdlg 587204df0f8Sclaudio optnl : '\n' optnl 588204df0f8Sclaudio | 589204df0f8Sclaudio ; 590204df0f8Sclaudio 591204df0f8Sclaudio nl : '\n' optnl /* one newline or more */ 592204df0f8Sclaudio ; 593204df0f8Sclaudio 594f373ed5aSclaudio comma : ',' 595f373ed5aSclaudio | /*empty*/ 596f373ed5aSclaudio ; 597f373ed5aSclaudio 598cacfc040Sdlg area : AREA areaid { 599cacfc040Sdlg area = conf_get_area($2); 600627c6412Sclaudio 601627c6412Sclaudio memcpy(&areadefs, defs, sizeof(areadefs)); 60276b51f83Sclaudio md_list_copy(&areadefs.md_list, &defs->md_list); 603627c6412Sclaudio defs = &areadefs; 604a3f6d01eSclaudio } '{' optnl areaopts_l optnl '}' { 605204df0f8Sclaudio area = NULL; 60676b51f83Sclaudio md_list_clr(&defs->md_list); 607627c6412Sclaudio defs = &globaldefs; 608204df0f8Sclaudio } 609204df0f8Sclaudio ; 610204df0f8Sclaudio 61191d3283aSclaudio demotecount : NUMBER { $$ = $1; } 612a36153efSpyr | /*empty*/ { $$ = 1; } 613a36153efSpyr ; 614a36153efSpyr 615cacfc040Sdlg areaid : NUMBER { 616cacfc040Sdlg if ($1 < 0 || $1 > 0xffffffff) { 617cacfc040Sdlg yyerror("invalid area id"); 618cacfc040Sdlg YYERROR; 619cacfc040Sdlg } 620cacfc040Sdlg $$.s_addr = htonl($1); 621cacfc040Sdlg } 622cacfc040Sdlg | STRING { 62382905b67Sflorian if (inet_pton(AF_INET, $1, &$$) != 1) { 624cacfc040Sdlg yyerror("error parsing area"); 625cacfc040Sdlg free($1); 626cacfc040Sdlg YYERROR; 627cacfc040Sdlg } 628cacfc040Sdlg free($1); 629cacfc040Sdlg } 630cacfc040Sdlg ; 631cacfc040Sdlg 632a3f6d01eSclaudio areaopts_l : areaopts_l nl areaoptsl 633a3f6d01eSclaudio | areaoptsl 634204df0f8Sclaudio ; 635204df0f8Sclaudio 6368785114bSclaudio areaoptsl : interface 637a36153efSpyr | DEMOTE STRING demotecount { 63891d3283aSclaudio if ($3 < 1 || $3 > 255) { 63991d3283aSclaudio yyerror("demote count out of range (1-255)"); 640fba2d3d0Sclaudio free($2); 641fba2d3d0Sclaudio YYERROR; 642fba2d3d0Sclaudio } 643fba2d3d0Sclaudio area->demote_level = $3; 644fba2d3d0Sclaudio if (strlcpy(area->demote_group, $2, 645fba2d3d0Sclaudio sizeof(area->demote_group)) >= 646fba2d3d0Sclaudio sizeof(area->demote_group)) { 6479c81ce9fSdoug yyerror("demote group name \"%s\" too long", 6489c81ce9fSdoug $2); 649fba2d3d0Sclaudio free($2); 650fba2d3d0Sclaudio YYERROR; 651fba2d3d0Sclaudio } 652fba2d3d0Sclaudio free($2); 653fba2d3d0Sclaudio if (carp_demote_init(area->demote_group, 654fba2d3d0Sclaudio conf->opts & OSPFD_OPT_FORCE_DEMOTE) == -1) { 655fba2d3d0Sclaudio yyerror("error initializing group \"%s\"", 656fba2d3d0Sclaudio area->demote_group); 657fba2d3d0Sclaudio YYERROR; 658fba2d3d0Sclaudio } 659fba2d3d0Sclaudio } 6608785114bSclaudio | defaults 66198b447a7Sclaudio | STUB { area->stub = 1; } 6626fa28760Sclaudio | STUB redistribute { 6636fa28760Sclaudio area->stub = 1; 6646fa28760Sclaudio if ($2->type != REDIST_DEFAULT) { 6656fa28760Sclaudio yyerror("bad redistribute option"); 6666fa28760Sclaudio YYERROR; 6676fa28760Sclaudio } 6686fa28760Sclaudio if (!SIMPLEQ_EMPTY(&area->redist_list)) { 6696fa28760Sclaudio yyerror("area redistribute option only " 6706fa28760Sclaudio "allowed once"); 6716fa28760Sclaudio YYERROR; 6726fa28760Sclaudio } 6736fa28760Sclaudio SIMPLEQ_INSERT_TAIL(&area->redist_list, $2, entry); 6746fa28760Sclaudio } 675204df0f8Sclaudio ; 676204df0f8Sclaudio 677204df0f8Sclaudio interface : INTERFACE STRING { 678e9fa2173Sclaudio struct kif *kif; 67966dd3991Sclaudio struct kif_addr *ka = NULL; 68066dd3991Sclaudio char *s; 68166dd3991Sclaudio struct in_addr addr; 682204df0f8Sclaudio 68366dd3991Sclaudio s = strchr($2, ':'); 68466dd3991Sclaudio if (s) { 68566dd3991Sclaudio *s++ = '\0'; 68682905b67Sflorian if (inet_pton(AF_INET, s, &addr) != 1) { 68766dd3991Sclaudio yyerror( 68866dd3991Sclaudio "error parsing interface address"); 68966dd3991Sclaudio free($2); 69066dd3991Sclaudio YYERROR; 69166dd3991Sclaudio } 69266dd3991Sclaudio } else 69366dd3991Sclaudio addr.s_addr = 0; 69466dd3991Sclaudio 69566dd3991Sclaudio if ((kif = kif_findname($2, addr, &ka)) == NULL) { 696204df0f8Sclaudio yyerror("unknown interface %s", $2); 697204df0f8Sclaudio free($2); 698204df0f8Sclaudio YYERROR; 699204df0f8Sclaudio } 70066dd3991Sclaudio if (ka == NULL) { 70166dd3991Sclaudio if (s) 70266dd3991Sclaudio yyerror("address %s not configured on " 70366dd3991Sclaudio "interface %s", s, $2); 70466dd3991Sclaudio else 70566dd3991Sclaudio yyerror("unnumbered interface %s", $2); 706204df0f8Sclaudio free($2); 70766dd3991Sclaudio YYERROR; 70866dd3991Sclaudio } 70966dd3991Sclaudio free($2); 71066dd3991Sclaudio iface = conf_get_if(kif, ka); 711204df0f8Sclaudio if (iface == NULL) 712204df0f8Sclaudio YYERROR; 713204df0f8Sclaudio iface->area = area; 714ecd183dbSclaudio LIST_INSERT_HEAD(&area->iface_list, iface, entry); 715627c6412Sclaudio 716627c6412Sclaudio memcpy(&ifacedefs, defs, sizeof(ifacedefs)); 71776b51f83Sclaudio md_list_copy(&ifacedefs.md_list, &defs->md_list); 718627c6412Sclaudio defs = &ifacedefs; 7193d7c1a39Sclaudio } interface_block { 720627c6412Sclaudio iface->dead_interval = defs->dead_interval; 7217afdfd2dSdlg iface->fast_hello_interval = defs->fast_hello_interval; 722627c6412Sclaudio iface->transmit_delay = defs->transmit_delay; 7237afdfd2dSdlg if (iface->dead_interval == FAST_RTR_DEAD_TIME) 7247afdfd2dSdlg iface->hello_interval = 0; 7257afdfd2dSdlg else 726627c6412Sclaudio iface->hello_interval = defs->hello_interval; 727627c6412Sclaudio iface->rxmt_interval = defs->rxmt_interval; 728627c6412Sclaudio iface->metric = defs->metric; 729627c6412Sclaudio iface->priority = defs->priority; 73076b51f83Sclaudio iface->auth_type = defs->auth_type; 73176b51f83Sclaudio iface->auth_keyid = defs->auth_keyid; 73209e8f780Sremi if (defs->p2p == 1) 73309e8f780Sremi iface->type = IF_TYPE_POINTOPOINT; 73476b51f83Sclaudio memcpy(iface->auth_key, defs->auth_key, 73576b51f83Sclaudio sizeof(iface->auth_key)); 73676b51f83Sclaudio md_list_copy(&iface->auth_md_list, &defs->md_list); 73776b51f83Sclaudio md_list_clr(&defs->md_list); 738204df0f8Sclaudio iface = NULL; 739627c6412Sclaudio /* interface is always part of an area */ 740627c6412Sclaudio defs = &areadefs; 741204df0f8Sclaudio } 742204df0f8Sclaudio ; 743204df0f8Sclaudio 744a3f6d01eSclaudio interface_block : '{' optnl interfaceopts_l optnl '}' 745d4cfe42aSclaudio | '{' optnl '}' 746a3f6d01eSclaudio | /* empty */ 7473d7c1a39Sclaudio ; 7483d7c1a39Sclaudio 749a3f6d01eSclaudio interfaceopts_l : interfaceopts_l nl interfaceoptsl 750a3f6d01eSclaudio | interfaceoptsl 751204df0f8Sclaudio ; 752204df0f8Sclaudio 7538785114bSclaudio interfaceoptsl : PASSIVE { iface->passive = 1; } 754fba2d3d0Sclaudio | DEMOTE STRING { 755fba2d3d0Sclaudio if (strlcpy(iface->demote_group, $2, 756fba2d3d0Sclaudio sizeof(iface->demote_group)) >= 757fba2d3d0Sclaudio sizeof(iface->demote_group)) { 7589c81ce9fSdoug yyerror("demote group name \"%s\" too long", 7599c81ce9fSdoug $2); 760fba2d3d0Sclaudio free($2); 761fba2d3d0Sclaudio YYERROR; 762fba2d3d0Sclaudio } 763fba2d3d0Sclaudio free($2); 764fba2d3d0Sclaudio if (carp_demote_init(iface->demote_group, 765fba2d3d0Sclaudio conf->opts & OSPFD_OPT_FORCE_DEMOTE) == -1) { 766fba2d3d0Sclaudio yyerror("error initializing group \"%s\"", 767fba2d3d0Sclaudio iface->demote_group); 768fba2d3d0Sclaudio YYERROR; 769fba2d3d0Sclaudio } 770fba2d3d0Sclaudio } 771ac149fe2Sremi | dependon { 772ac149fe2Sremi struct in_addr addr; 773ac149fe2Sremi struct kif *kif; 774ac149fe2Sremi 775ac149fe2Sremi if ($1) { 776ac149fe2Sremi strlcpy(iface->dependon, $1, 777ac149fe2Sremi sizeof(iface->dependon)); 778ac149fe2Sremi bzero(&addr, sizeof(addr)); 779ac149fe2Sremi kif = kif_findname($1, addr, NULL); 780ac149fe2Sremi iface->depend_ok = ifstate_is_up(kif); 781ac149fe2Sremi } else { 782ac149fe2Sremi iface->dependon[0] = '\0'; 783ac149fe2Sremi iface->depend_ok = 1; 784ac149fe2Sremi } 785ac149fe2Sremi 786ac149fe2Sremi free($1); 787ac149fe2Sremi } 7888785114bSclaudio | defaults 789204df0f8Sclaudio ; 790204df0f8Sclaudio 791204df0f8Sclaudio %% 792204df0f8Sclaudio 793204df0f8Sclaudio struct keywords { 794204df0f8Sclaudio const char *k_name; 795204df0f8Sclaudio int k_val; 796204df0f8Sclaudio }; 797204df0f8Sclaudio 798204df0f8Sclaudio int 799204df0f8Sclaudio yyerror(const char *fmt, ...) 800204df0f8Sclaudio { 801204df0f8Sclaudio va_list ap; 802d1fe7d6dSbluhm char *msg; 803204df0f8Sclaudio 80420741916Sderaadt file->errors++; 805204df0f8Sclaudio va_start(ap, fmt); 806d1fe7d6dSbluhm if (vasprintf(&msg, fmt, ap) == -1) 807d1fe7d6dSbluhm fatalx("yyerror vasprintf"); 808204df0f8Sclaudio va_end(ap); 809d1fe7d6dSbluhm logit(LOG_CRIT, "%s:%d: %s", file->name, yylval.lineno, msg); 810d1fe7d6dSbluhm free(msg); 811204df0f8Sclaudio return (0); 812204df0f8Sclaudio } 813204df0f8Sclaudio 814204df0f8Sclaudio int 815204df0f8Sclaudio kw_cmp(const void *k, const void *e) 816204df0f8Sclaudio { 817204df0f8Sclaudio return (strcmp(k, ((const struct keywords *)e)->k_name)); 818204df0f8Sclaudio } 819204df0f8Sclaudio 820204df0f8Sclaudio int 821204df0f8Sclaudio lookup(char *s) 822204df0f8Sclaudio { 823204df0f8Sclaudio /* this has to be sorted always */ 824204df0f8Sclaudio static const struct keywords keywords[] = { 825204df0f8Sclaudio {"area", AREA}, 826204df0f8Sclaudio {"auth-key", AUTHKEY}, 82703431b74Snorby {"auth-md", AUTHMD}, 82803431b74Snorby {"auth-md-keyid", AUTHMDKEYID}, 829204df0f8Sclaudio {"auth-type", AUTHTYPE}, 830fba2d3d0Sclaudio {"demote", DEMOTE}, 831ac149fe2Sremi {"depend", DEPEND}, 832fcb4545bSreyk {"external-tag", EXTTAG}, 8337afdfd2dSdlg {"fast-hello-interval", FASTHELLOINTERVAL}, 8344c260f66Sremi {"fib-priority", FIBPRIORITY}, 8358ffc8f84Sgollo {"fib-update", FIBUPDATE}, 836204df0f8Sclaudio {"hello-interval", HELLOINTERVAL}, 8374fd4397dSdlg {"include", INCLUDE}, 838204df0f8Sclaudio {"interface", INTERFACE}, 839204df0f8Sclaudio {"metric", METRIC}, 8407afdfd2dSdlg {"minimal", MINIMAL}, 84137877ca4Sdlg {"msec", MSEC}, 842619421e7Sclaudio {"no", NO}, 843ac149fe2Sremi {"on", ON}, 844ef209401Sremi {"p2p", P2P}, 845204df0f8Sclaudio {"passive", PASSIVE}, 846e4caa3d9Sclaudio {"rdomain", RDOMAIN}, 847e2993955Sclaudio {"redistribute", REDISTRIBUTE}, 848204df0f8Sclaudio {"retransmit-interval", RETRANSMITINTERVAL}, 849bbb7cc9cSnorby {"rfc1583compat", RFC1583COMPAT}, 8501891964aSclaudio {"router", ROUTER}, 851dacb568dSclaudio {"router-dead-time", ROUTERDEADTIME}, 852204df0f8Sclaudio {"router-id", ROUTERID}, 853204df0f8Sclaudio {"router-priority", ROUTERPRIORITY}, 854bbb232d2Sclaudio {"rtlabel", RTLABEL}, 855f373ed5aSclaudio {"set", SET}, 8563ada9d8fSnorby {"spf-delay", SPFDELAY}, 8573ada9d8fSnorby {"spf-holdtime", SPFHOLDTIME}, 8581891964aSclaudio {"stub", STUB}, 859619421e7Sclaudio {"transmit-delay", TRANSMITDELAY}, 860f373ed5aSclaudio {"type", TYPE}, 861619421e7Sclaudio {"yes", YES} 862204df0f8Sclaudio }; 863204df0f8Sclaudio const struct keywords *p; 864204df0f8Sclaudio 865204df0f8Sclaudio p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]), 866204df0f8Sclaudio sizeof(keywords[0]), kw_cmp); 867204df0f8Sclaudio 86874c23245Sclaudio if (p) 869204df0f8Sclaudio return (p->k_val); 87074c23245Sclaudio else 871204df0f8Sclaudio return (STRING); 872204df0f8Sclaudio } 873204df0f8Sclaudio 874a8823310Sdenis #define START_EXPAND 1 875a8823310Sdenis #define DONE_EXPAND 2 876204df0f8Sclaudio 877a8823310Sdenis static int expanding; 878a8823310Sdenis 879a8823310Sdenis int 880a8823310Sdenis igetc(void) 881a8823310Sdenis { 882a8823310Sdenis int c; 883a8823310Sdenis 884a8823310Sdenis while (1) { 885a8823310Sdenis if (file->ungetpos > 0) 886a8823310Sdenis c = file->ungetbuf[--file->ungetpos]; 887a8823310Sdenis else 888a8823310Sdenis c = getc(file->stream); 889a8823310Sdenis 890a8823310Sdenis if (c == START_EXPAND) 891a8823310Sdenis expanding = 1; 892a8823310Sdenis else if (c == DONE_EXPAND) 893a8823310Sdenis expanding = 0; 894a8823310Sdenis else 895a8823310Sdenis break; 896a8823310Sdenis } 897a8823310Sdenis return (c); 898a8823310Sdenis } 899204df0f8Sclaudio 900204df0f8Sclaudio int 90120741916Sderaadt lgetc(int quotec) 902204df0f8Sclaudio { 903204df0f8Sclaudio int c, next; 904204df0f8Sclaudio 90520741916Sderaadt if (quotec) { 906a8823310Sdenis if ((c = igetc()) == EOF) { 907c6004ab9Smpf yyerror("reached end of file while parsing " 908c6004ab9Smpf "quoted string"); 909c6004ab9Smpf if (file == topfile || popfile() == EOF) 91020741916Sderaadt return (EOF); 91120741916Sderaadt return (quotec); 91220741916Sderaadt } 913d5d66eaeSderaadt return (c); 914d5d66eaeSderaadt } 915d5d66eaeSderaadt 916a8823310Sdenis while ((c = igetc()) == '\\') { 917a8823310Sdenis next = igetc(); 918204df0f8Sclaudio if (next != '\n') { 919e3bfd77aSderaadt c = next; 920204df0f8Sclaudio break; 921204df0f8Sclaudio } 92220741916Sderaadt yylval.lineno = file->lineno; 92320741916Sderaadt file->lineno++; 924204df0f8Sclaudio } 925204df0f8Sclaudio 926a8823310Sdenis if (c == EOF) { 927a8823310Sdenis /* 928a8823310Sdenis * Fake EOL when hit EOF for the first time. This gets line 929a8823310Sdenis * count right if last line in included file is syntactically 930a8823310Sdenis * invalid and has no newline. 931a8823310Sdenis */ 932a8823310Sdenis if (file->eof_reached == 0) { 933a8823310Sdenis file->eof_reached = 1; 934a8823310Sdenis return ('\n'); 935a8823310Sdenis } 93620741916Sderaadt while (c == EOF) { 937c6004ab9Smpf if (file == topfile || popfile() == EOF) 93820741916Sderaadt return (EOF); 939a8823310Sdenis c = igetc(); 940a8823310Sdenis } 94120741916Sderaadt } 942204df0f8Sclaudio return (c); 943204df0f8Sclaudio } 944204df0f8Sclaudio 945a8823310Sdenis void 946204df0f8Sclaudio lungetc(int c) 947204df0f8Sclaudio { 948204df0f8Sclaudio if (c == EOF) 949a8823310Sdenis return; 950a8823310Sdenis 951a8823310Sdenis if (file->ungetpos >= file->ungetsize) { 952a8823310Sdenis void *p = reallocarray(file->ungetbuf, file->ungetsize, 2); 953a8823310Sdenis if (p == NULL) 954a062aa9dSkrw err(1, "%s", __func__); 955a8823310Sdenis file->ungetbuf = p; 956a8823310Sdenis file->ungetsize *= 2; 957204df0f8Sclaudio } 958a8823310Sdenis file->ungetbuf[file->ungetpos++] = c; 959204df0f8Sclaudio } 960204df0f8Sclaudio 961204df0f8Sclaudio int 962204df0f8Sclaudio findeol(void) 963204df0f8Sclaudio { 964204df0f8Sclaudio int c; 965204df0f8Sclaudio 966204df0f8Sclaudio /* skip to either EOF or the first real EOL */ 967204df0f8Sclaudio while (1) { 968d5d66eaeSderaadt c = lgetc(0); 969204df0f8Sclaudio if (c == '\n') { 97020741916Sderaadt file->lineno++; 971204df0f8Sclaudio break; 972204df0f8Sclaudio } 973204df0f8Sclaudio if (c == EOF) 974204df0f8Sclaudio break; 975204df0f8Sclaudio } 976204df0f8Sclaudio return (ERROR); 977204df0f8Sclaudio } 978204df0f8Sclaudio 979204df0f8Sclaudio int 980204df0f8Sclaudio yylex(void) 981204df0f8Sclaudio { 98208f6ba19Snaddy char buf[8096]; 98308f6ba19Snaddy char *p, *val; 98420741916Sderaadt int quotec, next, c; 985204df0f8Sclaudio int token; 986204df0f8Sclaudio 987204df0f8Sclaudio top: 988204df0f8Sclaudio p = buf; 9892053f12aSmpf while ((c = lgetc(0)) == ' ' || c == '\t') 990204df0f8Sclaudio ; /* nothing */ 991204df0f8Sclaudio 99220741916Sderaadt yylval.lineno = file->lineno; 993204df0f8Sclaudio if (c == '#') 994d5d66eaeSderaadt while ((c = lgetc(0)) != '\n' && c != EOF) 995204df0f8Sclaudio ; /* nothing */ 996a8823310Sdenis if (c == '$' && !expanding) { 997204df0f8Sclaudio while (1) { 998d5d66eaeSderaadt if ((c = lgetc(0)) == EOF) 999204df0f8Sclaudio return (0); 1000204df0f8Sclaudio 1001204df0f8Sclaudio if (p + 1 >= buf + sizeof(buf) - 1) { 1002204df0f8Sclaudio yyerror("string too long"); 1003204df0f8Sclaudio return (findeol()); 1004204df0f8Sclaudio } 1005204df0f8Sclaudio if (isalnum(c) || c == '_') { 1006015d7b4dSbenno *p++ = c; 1007204df0f8Sclaudio continue; 1008204df0f8Sclaudio } 1009204df0f8Sclaudio *p = '\0'; 1010204df0f8Sclaudio lungetc(c); 1011204df0f8Sclaudio break; 1012204df0f8Sclaudio } 1013204df0f8Sclaudio val = symget(buf); 1014204df0f8Sclaudio if (val == NULL) { 1015204df0f8Sclaudio yyerror("macro '%s' not defined", buf); 1016204df0f8Sclaudio return (findeol()); 1017204df0f8Sclaudio } 1018a8823310Sdenis p = val + strlen(val) - 1; 1019a8823310Sdenis lungetc(DONE_EXPAND); 1020a8823310Sdenis while (p >= val) { 102108f6ba19Snaddy lungetc((unsigned char)*p); 1022a8823310Sdenis p--; 1023a8823310Sdenis } 1024a8823310Sdenis lungetc(START_EXPAND); 1025204df0f8Sclaudio goto top; 1026204df0f8Sclaudio } 1027204df0f8Sclaudio 1028204df0f8Sclaudio switch (c) { 1029204df0f8Sclaudio case '\'': 1030204df0f8Sclaudio case '"': 103120741916Sderaadt quotec = c; 1032204df0f8Sclaudio while (1) { 103320741916Sderaadt if ((c = lgetc(quotec)) == EOF) 1034204df0f8Sclaudio return (0); 1035204df0f8Sclaudio if (c == '\n') { 103620741916Sderaadt file->lineno++; 1037204df0f8Sclaudio continue; 1038d5d66eaeSderaadt } else if (c == '\\') { 103920741916Sderaadt if ((next = lgetc(quotec)) == EOF) 1040d5d66eaeSderaadt return (0); 1041a1533359Ssashan if (next == quotec || next == ' ' || 1042a1533359Ssashan next == '\t') 1043d5d66eaeSderaadt c = next; 1044daf24110Shenning else if (next == '\n') { 1045daf24110Shenning file->lineno++; 1046ea014f46Sderaadt continue; 1047daf24110Shenning } else 1048d5d66eaeSderaadt lungetc(next); 104920741916Sderaadt } else if (c == quotec) { 1050d5d66eaeSderaadt *p = '\0'; 1051d5d66eaeSderaadt break; 105241eef22fSjsg } else if (c == '\0') { 105341eef22fSjsg yyerror("syntax error"); 105441eef22fSjsg return (findeol()); 1055204df0f8Sclaudio } 1056204df0f8Sclaudio if (p + 1 >= buf + sizeof(buf) - 1) { 1057204df0f8Sclaudio yyerror("string too long"); 1058204df0f8Sclaudio return (findeol()); 1059204df0f8Sclaudio } 1060015d7b4dSbenno *p++ = c; 1061204df0f8Sclaudio } 1062204df0f8Sclaudio yylval.v.string = strdup(buf); 1063204df0f8Sclaudio if (yylval.v.string == NULL) 1064a062aa9dSkrw err(1, "%s", __func__); 1065204df0f8Sclaudio return (STRING); 1066204df0f8Sclaudio } 1067204df0f8Sclaudio 106891d3283aSclaudio #define allowed_to_end_number(x) \ 10690cf2c9c3Smpf (isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=') 107091d3283aSclaudio 107191d3283aSclaudio if (c == '-' || isdigit(c)) { 107291d3283aSclaudio do { 107391d3283aSclaudio *p++ = c; 1074915c3f33Sderaadt if ((size_t)(p-buf) >= sizeof(buf)) { 107591d3283aSclaudio yyerror("string too long"); 107691d3283aSclaudio return (findeol()); 107791d3283aSclaudio } 1078d5d66eaeSderaadt } while ((c = lgetc(0)) != EOF && isdigit(c)); 107991d3283aSclaudio lungetc(c); 108091d3283aSclaudio if (p == buf + 1 && buf[0] == '-') 108191d3283aSclaudio goto nodigits; 108291d3283aSclaudio if (c == EOF || allowed_to_end_number(c)) { 108391d3283aSclaudio const char *errstr = NULL; 108491d3283aSclaudio 108591d3283aSclaudio *p = '\0'; 1086d5d66eaeSderaadt yylval.v.number = strtonum(buf, LLONG_MIN, 1087d5d66eaeSderaadt LLONG_MAX, &errstr); 108891d3283aSclaudio if (errstr) { 1089d5d66eaeSderaadt yyerror("\"%s\" invalid number: %s", 1090d5d66eaeSderaadt buf, errstr); 109191d3283aSclaudio return (findeol()); 109291d3283aSclaudio } 109391d3283aSclaudio return (NUMBER); 109491d3283aSclaudio } else { 109591d3283aSclaudio nodigits: 109691d3283aSclaudio while (p > buf + 1) 109708f6ba19Snaddy lungetc((unsigned char)*--p); 109808f6ba19Snaddy c = (unsigned char)*--p; 109991d3283aSclaudio if (c == '-') 110091d3283aSclaudio return (c); 110191d3283aSclaudio } 110291d3283aSclaudio } 110391d3283aSclaudio 1104204df0f8Sclaudio #define allowed_in_string(x) \ 1105204df0f8Sclaudio (isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \ 1106204df0f8Sclaudio x != '{' && x != '}' && \ 1107204df0f8Sclaudio x != '!' && x != '=' && x != '#' && \ 1108204df0f8Sclaudio x != ',')) 1109204df0f8Sclaudio 1110204df0f8Sclaudio if (isalnum(c) || c == ':' || c == '_') { 1111204df0f8Sclaudio do { 1112204df0f8Sclaudio *p++ = c; 1113915c3f33Sderaadt if ((size_t)(p-buf) >= sizeof(buf)) { 1114204df0f8Sclaudio yyerror("string too long"); 1115204df0f8Sclaudio return (findeol()); 1116204df0f8Sclaudio } 1117d5d66eaeSderaadt } while ((c = lgetc(0)) != EOF && (allowed_in_string(c))); 1118204df0f8Sclaudio lungetc(c); 1119204df0f8Sclaudio *p = '\0'; 1120204df0f8Sclaudio if ((token = lookup(buf)) == STRING) 1121204df0f8Sclaudio if ((yylval.v.string = strdup(buf)) == NULL) 1122a062aa9dSkrw err(1, "%s", __func__); 1123204df0f8Sclaudio return (token); 1124204df0f8Sclaudio } 1125204df0f8Sclaudio if (c == '\n') { 112620741916Sderaadt yylval.lineno = file->lineno; 112720741916Sderaadt file->lineno++; 1128204df0f8Sclaudio } 1129204df0f8Sclaudio if (c == EOF) 1130204df0f8Sclaudio return (0); 1131204df0f8Sclaudio return (c); 1132204df0f8Sclaudio } 1133204df0f8Sclaudio 113420741916Sderaadt int 113520741916Sderaadt check_file_secrecy(int fd, const char *fname) 113620741916Sderaadt { 113720741916Sderaadt struct stat st; 113820741916Sderaadt 113920741916Sderaadt if (fstat(fd, &st)) { 114020741916Sderaadt log_warn("cannot stat %s", fname); 114120741916Sderaadt return (-1); 114220741916Sderaadt } 114320741916Sderaadt if (st.st_uid != 0 && st.st_uid != getuid()) { 114420741916Sderaadt log_warnx("%s: owner not root or current user", fname); 114520741916Sderaadt return (-1); 114620741916Sderaadt } 11477140c133Shenning if (st.st_mode & (S_IWGRP | S_IXGRP | S_IRWXO)) { 11487140c133Shenning log_warnx("%s: group writable or world read/writable", fname); 114920741916Sderaadt return (-1); 115020741916Sderaadt } 115120741916Sderaadt return (0); 115220741916Sderaadt } 115320741916Sderaadt 115420741916Sderaadt struct file * 115520741916Sderaadt pushfile(const char *name, int secret) 115620741916Sderaadt { 115720741916Sderaadt struct file *nfile; 115820741916Sderaadt 11597fc93de0Stobias if ((nfile = calloc(1, sizeof(struct file))) == NULL) { 11606a3d55f9Skrw log_warn("%s", __func__); 116120741916Sderaadt return (NULL); 1162e23c639fSpyr } 11637fc93de0Stobias if ((nfile->name = strdup(name)) == NULL) { 11646a3d55f9Skrw log_warn("%s", __func__); 11657fc93de0Stobias free(nfile); 11667fc93de0Stobias return (NULL); 11677fc93de0Stobias } 116820741916Sderaadt if ((nfile->stream = fopen(nfile->name, "r")) == NULL) { 11696a3d55f9Skrw log_warn("%s: %s", __func__, nfile->name); 117020741916Sderaadt free(nfile->name); 117120741916Sderaadt free(nfile); 117220741916Sderaadt return (NULL); 117320741916Sderaadt } else if (secret && 117420741916Sderaadt check_file_secrecy(fileno(nfile->stream), nfile->name)) { 117520741916Sderaadt fclose(nfile->stream); 117620741916Sderaadt free(nfile->name); 117720741916Sderaadt free(nfile); 117820741916Sderaadt return (NULL); 117920741916Sderaadt } 1180a8823310Sdenis nfile->lineno = TAILQ_EMPTY(&files) ? 1 : 0; 1181a8823310Sdenis nfile->ungetsize = 16; 1182a8823310Sdenis nfile->ungetbuf = malloc(nfile->ungetsize); 1183a8823310Sdenis if (nfile->ungetbuf == NULL) { 11846a3d55f9Skrw log_warn("%s", __func__); 1185a8823310Sdenis fclose(nfile->stream); 1186a8823310Sdenis free(nfile->name); 1187a8823310Sdenis free(nfile); 1188a8823310Sdenis return (NULL); 1189a8823310Sdenis } 119020741916Sderaadt TAILQ_INSERT_TAIL(&files, nfile, entry); 119120741916Sderaadt return (nfile); 119220741916Sderaadt } 119320741916Sderaadt 119420741916Sderaadt int 119520741916Sderaadt popfile(void) 119620741916Sderaadt { 119720741916Sderaadt struct file *prev; 119820741916Sderaadt 1199c6004ab9Smpf if ((prev = TAILQ_PREV(file, files, entry)) != NULL) 120020741916Sderaadt prev->errors += file->errors; 1201c6004ab9Smpf 120220741916Sderaadt TAILQ_REMOVE(&files, file, entry); 120320741916Sderaadt fclose(file->stream); 120420741916Sderaadt free(file->name); 1205a8823310Sdenis free(file->ungetbuf); 120620741916Sderaadt free(file); 120720741916Sderaadt file = prev; 1208c6004ab9Smpf return (file ? 0 : EOF); 120920741916Sderaadt } 121020741916Sderaadt 1211204df0f8Sclaudio struct ospfd_conf * 1212204df0f8Sclaudio parse_config(char *filename, int opts) 1213204df0f8Sclaudio { 1214204df0f8Sclaudio struct sym *sym, *next; 1215204df0f8Sclaudio 1216bbb232d2Sclaudio if ((conf = calloc(1, sizeof(struct ospfd_conf))) == NULL) 1217bbb232d2Sclaudio fatal("parse_config"); 121820741916Sderaadt conf->opts = opts; 121920741916Sderaadt if (conf->opts & OSPFD_OPT_STUB_ROUTER) 122020741916Sderaadt conf->flags |= OSPFD_FLAG_STUB_ROUTER; 1221204df0f8Sclaudio 1222627c6412Sclaudio bzero(&globaldefs, sizeof(globaldefs)); 1223627c6412Sclaudio defs = &globaldefs; 122476b51f83Sclaudio TAILQ_INIT(&defs->md_list); 1225627c6412Sclaudio defs->dead_interval = DEFAULT_RTR_DEAD_TIME; 12267afdfd2dSdlg defs->fast_hello_interval = DEFAULT_FAST_INTERVAL; 1227627c6412Sclaudio defs->transmit_delay = DEFAULT_TRANSMIT_DELAY; 1228627c6412Sclaudio defs->hello_interval = DEFAULT_HELLO_INTERVAL; 1229627c6412Sclaudio defs->rxmt_interval = DEFAULT_RXMT_INTERVAL; 1230627c6412Sclaudio defs->metric = DEFAULT_METRIC; 1231627c6412Sclaudio defs->priority = DEFAULT_PRIORITY; 123209e8f780Sremi defs->p2p = 0; 1233204df0f8Sclaudio 12343ada9d8fSnorby conf->spf_delay = DEFAULT_SPF_DELAY; 12353ada9d8fSnorby conf->spf_hold_time = DEFAULT_SPF_HOLDTIME; 12363ada9d8fSnorby conf->spf_state = SPF_IDLE; 12374c260f66Sremi conf->fib_priority = RTP_OSPF; 1238204df0f8Sclaudio 1239a8823310Sdenis if ((file = pushfile(filename, 1240a8823310Sdenis !(conf->opts & OSPFD_OPT_NOACTION))) == NULL) { 1241204df0f8Sclaudio free(conf); 1242204df0f8Sclaudio return (NULL); 1243204df0f8Sclaudio } 1244c6004ab9Smpf topfile = file; 1245204df0f8Sclaudio 1246204df0f8Sclaudio LIST_INIT(&conf->area_list); 1247bbb232d2Sclaudio LIST_INIT(&conf->cand_list); 1248bbb232d2Sclaudio SIMPLEQ_INIT(&conf->redist_list); 1249204df0f8Sclaudio 1250204df0f8Sclaudio yyparse(); 125120741916Sderaadt errors = file->errors; 125220741916Sderaadt popfile(); 1253204df0f8Sclaudio 1254204df0f8Sclaudio /* Free macros and check which have not been used. */ 125546bca67bSkrw TAILQ_FOREACH_SAFE(sym, &symhead, entry, next) { 1256204df0f8Sclaudio if ((conf->opts & OSPFD_OPT_VERBOSE2) && !sym->used) 1257204df0f8Sclaudio fprintf(stderr, "warning: macro '%s' not " 1258204df0f8Sclaudio "used\n", sym->nam); 1259204df0f8Sclaudio if (!sym->persist) { 1260204df0f8Sclaudio free(sym->nam); 1261204df0f8Sclaudio free(sym->val); 126220741916Sderaadt TAILQ_REMOVE(&symhead, sym, entry); 1263204df0f8Sclaudio free(sym); 1264204df0f8Sclaudio } 1265204df0f8Sclaudio } 1266204df0f8Sclaudio 126776b51f83Sclaudio /* free global config defaults */ 126876b51f83Sclaudio md_list_clr(&globaldefs.md_list); 126976b51f83Sclaudio 1270358269bbSclaudio /* check that all interfaces belong to the configured rdomain */ 1271358269bbSclaudio errors += conf_check_rdomain(conf->rdomain); 1272358269bbSclaudio 1273204df0f8Sclaudio if (errors) { 1274204df0f8Sclaudio clear_config(conf); 1275204df0f8Sclaudio return (NULL); 1276204df0f8Sclaudio } 1277204df0f8Sclaudio 1278204df0f8Sclaudio return (conf); 1279204df0f8Sclaudio } 1280204df0f8Sclaudio 1281204df0f8Sclaudio int 1282204df0f8Sclaudio symset(const char *nam, const char *val, int persist) 1283204df0f8Sclaudio { 1284204df0f8Sclaudio struct sym *sym; 1285204df0f8Sclaudio 128654c95b7aSkrw TAILQ_FOREACH(sym, &symhead, entry) { 128754c95b7aSkrw if (strcmp(nam, sym->nam) == 0) 128854c95b7aSkrw break; 128954c95b7aSkrw } 1290204df0f8Sclaudio 1291204df0f8Sclaudio if (sym != NULL) { 1292204df0f8Sclaudio if (sym->persist == 1) 1293204df0f8Sclaudio return (0); 1294204df0f8Sclaudio else { 1295204df0f8Sclaudio free(sym->nam); 1296204df0f8Sclaudio free(sym->val); 129720741916Sderaadt TAILQ_REMOVE(&symhead, sym, entry); 1298204df0f8Sclaudio free(sym); 1299204df0f8Sclaudio } 1300204df0f8Sclaudio } 1301204df0f8Sclaudio if ((sym = calloc(1, sizeof(*sym))) == NULL) 1302204df0f8Sclaudio return (-1); 1303204df0f8Sclaudio 1304204df0f8Sclaudio sym->nam = strdup(nam); 1305204df0f8Sclaudio if (sym->nam == NULL) { 1306204df0f8Sclaudio free(sym); 1307204df0f8Sclaudio return (-1); 1308204df0f8Sclaudio } 1309204df0f8Sclaudio sym->val = strdup(val); 1310204df0f8Sclaudio if (sym->val == NULL) { 1311204df0f8Sclaudio free(sym->nam); 1312204df0f8Sclaudio free(sym); 1313204df0f8Sclaudio return (-1); 1314204df0f8Sclaudio } 1315204df0f8Sclaudio sym->used = 0; 1316204df0f8Sclaudio sym->persist = persist; 131720741916Sderaadt TAILQ_INSERT_TAIL(&symhead, sym, entry); 1318204df0f8Sclaudio return (0); 1319204df0f8Sclaudio } 1320204df0f8Sclaudio 1321204df0f8Sclaudio int 1322204df0f8Sclaudio cmdline_symset(char *s) 1323204df0f8Sclaudio { 1324204df0f8Sclaudio char *sym, *val; 1325204df0f8Sclaudio int ret; 1326204df0f8Sclaudio 1327204df0f8Sclaudio if ((val = strrchr(s, '=')) == NULL) 1328204df0f8Sclaudio return (-1); 1329ed1b9eb8Smiko sym = strndup(s, val - s); 1330ed1b9eb8Smiko if (sym == NULL) 1331ed1b9eb8Smiko errx(1, "%s: strndup", __func__); 1332204df0f8Sclaudio ret = symset(sym, val + 1, 1); 1333204df0f8Sclaudio free(sym); 1334204df0f8Sclaudio 1335204df0f8Sclaudio return (ret); 1336204df0f8Sclaudio } 1337204df0f8Sclaudio 1338204df0f8Sclaudio char * 1339204df0f8Sclaudio symget(const char *nam) 1340204df0f8Sclaudio { 1341204df0f8Sclaudio struct sym *sym; 1342204df0f8Sclaudio 134354c95b7aSkrw TAILQ_FOREACH(sym, &symhead, entry) { 1344204df0f8Sclaudio if (strcmp(nam, sym->nam) == 0) { 1345204df0f8Sclaudio sym->used = 1; 1346204df0f8Sclaudio return (sym->val); 1347204df0f8Sclaudio } 134854c95b7aSkrw } 1349204df0f8Sclaudio return (NULL); 1350204df0f8Sclaudio } 1351204df0f8Sclaudio 1352204df0f8Sclaudio struct area * 1353204df0f8Sclaudio conf_get_area(struct in_addr id) 1354204df0f8Sclaudio { 1355204df0f8Sclaudio struct area *a; 1356204df0f8Sclaudio 1357204df0f8Sclaudio a = area_find(conf, id); 1358204df0f8Sclaudio if (a) 1359204df0f8Sclaudio return (a); 1360204df0f8Sclaudio a = area_new(); 1361204df0f8Sclaudio LIST_INSERT_HEAD(&conf->area_list, a, entry); 1362204df0f8Sclaudio 1363204df0f8Sclaudio a->id.s_addr = id.s_addr; 1364204df0f8Sclaudio 1365204df0f8Sclaudio return (a); 1366204df0f8Sclaudio } 1367204df0f8Sclaudio 1368204df0f8Sclaudio struct iface * 136966dd3991Sclaudio conf_get_if(struct kif *kif, struct kif_addr *ka) 1370204df0f8Sclaudio { 1371204df0f8Sclaudio struct area *a; 1372204df0f8Sclaudio struct iface *i; 1373204df0f8Sclaudio 1374204df0f8Sclaudio LIST_FOREACH(a, &conf->area_list, entry) 1375204df0f8Sclaudio LIST_FOREACH(i, &a->iface_list, entry) 137666dd3991Sclaudio if (i->ifindex == kif->ifindex && 137766dd3991Sclaudio i->addr.s_addr == ka->addr.s_addr) { 1378204df0f8Sclaudio yyerror("interface %s already configured", 1379e9fa2173Sclaudio kif->ifname); 1380204df0f8Sclaudio return (NULL); 1381204df0f8Sclaudio } 1382204df0f8Sclaudio 138366dd3991Sclaudio i = if_new(kif, ka); 1384db162a95Sclaudio i->auth_keyid = 1; 1385204df0f8Sclaudio 1386204df0f8Sclaudio return (i); 1387204df0f8Sclaudio } 1388204df0f8Sclaudio 1389358269bbSclaudio int 1390358269bbSclaudio conf_check_rdomain(unsigned int rdomain) 1391358269bbSclaudio { 1392358269bbSclaudio struct area *a; 1393358269bbSclaudio struct iface *i; 13948a9f8fc9Sremi struct in_addr addr; 13958a9f8fc9Sremi struct kif *kif; 13968a9f8fc9Sremi struct redistribute *r; 1397358269bbSclaudio int errs = 0; 1398358269bbSclaudio 13998a9f8fc9Sremi SIMPLEQ_FOREACH(r, &conf->redist_list, entry) 14008a9f8fc9Sremi if (r->dependon[0] != '\0') { 14018a9f8fc9Sremi bzero(&addr, sizeof(addr)); 14028a9f8fc9Sremi kif = kif_findname(r->dependon, addr, NULL); 14038a9f8fc9Sremi if (kif->rdomain != rdomain) { 14048a9f8fc9Sremi logit(LOG_CRIT, 14058a9f8fc9Sremi "depend on %s: interface not in rdomain %u", 14068a9f8fc9Sremi kif->ifname, rdomain); 14078a9f8fc9Sremi errs++; 14088a9f8fc9Sremi } 14098a9f8fc9Sremi } 14108a9f8fc9Sremi 1411358269bbSclaudio LIST_FOREACH(a, &conf->area_list, entry) 14128a9f8fc9Sremi LIST_FOREACH(i, &a->iface_list, entry) { 1413358269bbSclaudio if (i->rdomain != rdomain) { 1414358269bbSclaudio logit(LOG_CRIT, 1415358269bbSclaudio "interface %s not in rdomain %u", 1416358269bbSclaudio i->name, rdomain); 1417358269bbSclaudio errs++; 1418358269bbSclaudio } 14198a9f8fc9Sremi if (i->dependon[0] != '\0') { 14208a9f8fc9Sremi bzero(&addr, sizeof(addr)); 14218a9f8fc9Sremi kif = kif_findname(i->dependon, addr, NULL); 14228a9f8fc9Sremi if (kif->rdomain != rdomain) { 14238a9f8fc9Sremi logit(LOG_CRIT, 14248a9f8fc9Sremi "depend on %s: interface not in " 14258a9f8fc9Sremi "rdomain %u", 14268a9f8fc9Sremi kif->ifname, rdomain); 14278a9f8fc9Sremi errs++; 14288a9f8fc9Sremi } 14298a9f8fc9Sremi } 14308a9f8fc9Sremi } 1431358269bbSclaudio 1432358269bbSclaudio return (errs); 1433358269bbSclaudio } 1434358269bbSclaudio 1435204df0f8Sclaudio void 1436ac149fe2Sremi conf_clear_redist_list(struct redist_list *rl) 1437ac149fe2Sremi { 1438ac149fe2Sremi struct redistribute *r; 1439ac149fe2Sremi while ((r = SIMPLEQ_FIRST(rl)) != NULL) { 1440ac149fe2Sremi SIMPLEQ_REMOVE_HEAD(rl, entry); 1441ac149fe2Sremi free(r); 1442ac149fe2Sremi } 1443ac149fe2Sremi } 1444ac149fe2Sremi 1445ac149fe2Sremi void 1446204df0f8Sclaudio clear_config(struct ospfd_conf *xconf) 1447204df0f8Sclaudio { 14481436b306Sclaudio struct area *a; 14491436b306Sclaudio 14501436b306Sclaudio while ((a = LIST_FIRST(&xconf->area_list)) != NULL) { 14511436b306Sclaudio LIST_REMOVE(a, entry); 14521436b306Sclaudio area_del(a); 14531436b306Sclaudio } 14541436b306Sclaudio 1455ac149fe2Sremi conf_clear_redist_list(&xconf->redist_list); 1456ac149fe2Sremi 14571436b306Sclaudio free(xconf); 1458204df0f8Sclaudio } 1459f12637e5Smsf 1460f12637e5Smsf u_int32_t 1461f12637e5Smsf get_rtr_id(void) 1462f12637e5Smsf { 1463f12637e5Smsf struct ifaddrs *ifap, *ifa; 1464f12637e5Smsf u_int32_t ip = 0, cur, localnet; 1465f12637e5Smsf 1466f12637e5Smsf localnet = htonl(INADDR_LOOPBACK & IN_CLASSA_NET); 1467f12637e5Smsf 1468f12637e5Smsf if (getifaddrs(&ifap) == -1) 1469f12637e5Smsf fatal("getifaddrs"); 1470f12637e5Smsf 1471f12637e5Smsf for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 147265e33efcSbluhm if (strncmp(ifa->ifa_name, "carp", 4) == 0) 147365e33efcSbluhm continue; 1474c2000e10Sbenno if (ifa->ifa_addr == NULL || 1475c2000e10Sbenno ifa->ifa_addr->sa_family != AF_INET) 1476f12637e5Smsf continue; 1477f12637e5Smsf cur = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr; 1478f12637e5Smsf if ((cur & localnet) == localnet) /* skip 127/8 */ 1479f12637e5Smsf continue; 1480c508cba4Sclaudio if (ntohl(cur) < ntohl(ip) || ip == 0) 1481f12637e5Smsf ip = cur; 1482f12637e5Smsf } 1483f12637e5Smsf freeifaddrs(ifap); 1484f12637e5Smsf 1485f12637e5Smsf if (ip == 0) 1486f12637e5Smsf fatal("router-id is 0.0.0.0"); 1487f12637e5Smsf 1488f12637e5Smsf return (ip); 1489f12637e5Smsf } 1490471ee2ebSclaudio 1491471ee2ebSclaudio int 1492471ee2ebSclaudio host(const char *s, struct in_addr *addr, struct in_addr *mask) 1493471ee2ebSclaudio { 1494471ee2ebSclaudio struct in_addr ina; 1495471ee2ebSclaudio int bits = 32; 1496471ee2ebSclaudio 1497471ee2ebSclaudio bzero(&ina, sizeof(struct in_addr)); 1498471ee2ebSclaudio if (strrchr(s, '/') != NULL) { 1499471ee2ebSclaudio if ((bits = inet_net_pton(AF_INET, s, &ina, sizeof(ina))) == -1) 1500471ee2ebSclaudio return (0); 1501471ee2ebSclaudio } else { 1502471ee2ebSclaudio if (inet_pton(AF_INET, s, &ina) != 1) 1503471ee2ebSclaudio return (0); 1504471ee2ebSclaudio } 1505471ee2ebSclaudio 1506471ee2ebSclaudio addr->s_addr = ina.s_addr; 1507471ee2ebSclaudio mask->s_addr = prefixlen2mask(bits); 1508471ee2ebSclaudio 1509471ee2ebSclaudio return (1); 1510471ee2ebSclaudio } 1511