#include <stdlib.h>
#include <string.h>
#define YYBYACC 1
#define YYMAJOR 1
#define YYMINOR 9
#define YYLEX yylex()
#define YYEMPTY -1
#define yyclearin (yychar=(YYEMPTY))
#define yyerrok (yyerrflag=0)
#define YYRECOVERING() (yyerrflag!=0)
#define YYPREFIX "yy"
#line 26 "../../../openbgpd-portable/src/bgpd/parse.y"
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <netinet/ip_ipsp.h>
#include <netinet/icmp6.h>
#include <arpa/inet.h>

#include <ctype.h>
#include <endian.h>
#include <err.h>
#include <unistd.h>
#include <errno.h>
#include <limits.h>
#include <netdb.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>

#include "bgpd.h"
#include "session.h"
#include "rde.h"
#include "log.h"

#define MACRO_NAME_LEN		128

TAILQ_HEAD(files, file)		 files = TAILQ_HEAD_INITIALIZER(files);
static struct file {
	TAILQ_ENTRY(file)	 entry;
	FILE			*stream;
	char			*name;
	size_t			 ungetpos;
	size_t			 ungetsize;
	u_char			*ungetbuf;
	int			 eof_reached;
	int			 lineno;
	int			 errors;
} *file, *topfile;
struct file	*pushfile(const char *, int);
int		 popfile(void);
int		 check_file_secrecy(int, const char *);
int		 yyparse(void);
int		 yylex(void);
int		 yyerror(const char *, ...)
    __attribute__((__format__ (printf, 1, 2)))
    __attribute__((__nonnull__ (1)));
int		 kw_cmp(const void *, const void *);
int		 lookup(char *);
int		 igetc(void);
int		 lgetc(int);
void		 lungetc(int);
int		 findeol(void);
int		 expand_macro(void);

TAILQ_HEAD(symhead, sym)	 symhead = TAILQ_HEAD_INITIALIZER(symhead);
struct sym {
	TAILQ_ENTRY(sym)	 entry;
	int			 used;
	int			 persist;
	char			*nam;
	char			*val;
};
int		 symset(const char *, const char *, int);
char		*symget(const char *);

struct filter_rib_l {
	struct filter_rib_l	*next;
	char			 name[PEER_DESCR_LEN];
};

struct filter_peers_l {
	struct filter_peers_l	*next;
	struct filter_peers	 p;
};

struct filter_prefix_l {
	struct filter_prefix_l	*next;
	struct filter_prefix	 p;
};

struct filter_prefixlen {
	enum comp_ops		op;
	int			len_min;
	int			len_max;
};

struct filter_as_l {
	struct filter_as_l	*next;
	struct filter_as	 a;
};

struct filter_match_l {
	struct filter_match	 m;
	struct filter_prefix_l	*prefix_l;
	struct filter_as_l	*as_l;
	struct filter_prefixset	*prefixset;
} fmopts;

struct aspa_tas_l {
	struct aspa_tas_l	*next;
	uint32_t		 as;
	uint32_t		 num;
};

struct flowspec_context {
	uint8_t			*components[FLOWSPEC_TYPE_MAX];
	uint16_t		 complen[FLOWSPEC_TYPE_MAX];
	uint8_t			 aid;
	uint8_t			 type;
	uint8_t			 addr_type;
};

struct peer	*alloc_peer(void);
struct peer	*new_peer(void);
struct peer	*new_group(void);
int		 add_mrtconfig(enum mrt_type, char *, int, struct peer *,
		    char *);
struct rde_rib	*add_rib(char *);
struct rde_rib	*find_rib(char *);
int		 rib_add_fib(struct rde_rib *, u_int);
int		 get_id(struct peer *);
int		 merge_prefixspec(struct filter_prefix *,
		    struct filter_prefixlen *);
int		 expand_rule(struct filter_rule *, struct filter_rib_l *,
		    struct filter_peers_l *, struct filter_match_l *,
		    struct filter_set_head *);
int		 str2key(char *, char *, size_t);
int		 neighbor_consistent(struct peer *);
int		 merge_filterset(struct filter_set_head *, struct filter_set *);
void		 optimize_filters(struct filter_head *);
struct filter_rule	*get_rule(enum action_types);

int		 parsecommunity(struct community *, int, char *);
int		 parseextcommunity(struct community *, char *,
		    char *);
static int	 new_as_set(char *);
static void	 add_as_set(uint32_t);
static void	 done_as_set(void);
static struct prefixset	*new_prefix_set(char *, int);
static void	 add_roa_set(struct prefixset_item *, uint32_t, uint8_t,
		    time_t);
static struct rtr_config	*get_rtr(struct bgpd_addr *);
static int	 insert_rtr(struct rtr_config *);
static int	 merge_aspa_set(uint32_t, struct aspa_tas_l *, time_t);
static int	 map_tos(char *, int *);
static int	 getservice(char *);
static int	 parse_flags(char *);
static struct flowspec_config	*flow_to_flowspec(struct flowspec_context *);
static void	 flow_free(struct flowspec_context *);
static int	 push_prefix(struct bgpd_addr *, uint8_t);
static int	 push_binop(uint8_t, long long);
static int	 push_unary_numop(enum comp_ops, long long);
static int	 push_binary_numop(enum comp_ops, long long, long long);
static int	 geticmptypebyname(char *, uint8_t);
static int	 geticmpcodebyname(u_long, char *, uint8_t);
static int	 merge_auth_conf(struct auth_config *, struct auth_config *);

static struct bgpd_config	*conf;
static struct network_head	*netconf;
static struct peer_head		*new_peers, *cur_peers;
static struct rtr_config_head	*cur_rtrs;
static struct peer		*curpeer;
static struct peer		*curgroup;
static struct rde_rib		*currib;
static struct l3vpn		*curvpn;
static struct prefixset		*curpset, *curoset;
static struct roa_tree		*curroatree;
static struct rtr_config	*currtr;
static struct filter_head	*filter_l;
static struct filter_head	*peerfilter_l;
static struct filter_head	*groupfilter_l;
static struct filter_rule	*curpeer_filter[2];
static struct filter_rule	*curgroup_filter[2];
static struct flowspec_context	*curflow;
static int			 noexpires;

typedef struct {
	union {
		long long		 number;
		char			*string;
		struct bgpd_addr	 addr;
		uint8_t			 u8;
		struct filter_rib_l	*filter_rib;
		struct filter_peers_l	*filter_peers;
		struct filter_match_l	 filter_match;
		struct filter_prefixset	*filter_prefixset;
		struct filter_prefix_l	*filter_prefix;
		struct filter_as_l	*filter_as;
		struct filter_set	*filter_set;
		struct filter_set_head	*filter_set_head;
		struct aspa_tas_l	*aspa_elm;
		struct {
			struct bgpd_addr	prefix;
			uint8_t			len;
		}			prefix;
		struct filter_prefixlen	prefixlen;
		struct prefixset_item	*prefixset_item;
		struct auth_config	authconf;
		struct {
			enum auth_enc_alg	enc_alg;
			uint8_t			enc_key_len;
			char			enc_key[IPSEC_ENC_KEY_LEN];
		}			encspec;
	} v;
	int lineno;
} YYSTYPE;

#line 226 "parse.c"
#define AS 257
#define ROUTERID 258
#define HOLDTIME 259
#define YMIN 260
#define LISTEN 261
#define ON 262
#define FIBUPDATE 263
#define FIBPRIORITY 264
#define RTABLE 265
#define NONE 266
#define UNICAST 267
#define VPN 268
#define RD 269
#define EXPORT 270
#define EXPORTTRGT 271
#define IMPORTTRGT 272
#define DEFAULTROUTE 273
#define RDE 274
#define RIB 275
#define EVALUATE 276
#define IGNORE 277
#define COMPARE 278
#define RTR 279
#define PORT 280
#define MINVERSION 281
#define STALETIME 282
#define GROUP 283
#define NEIGHBOR 284
#define NETWORK 285
#define EBGP 286
#define IBGP 287
#define FLOWSPEC 288
#define PROTO 289
#define FLAGS 290
#define FRAGMENT 291
#define TOS 292
#define LENGTH 293
#define ICMPTYPE 294
#define CODE 295
#define LOCALAS 296
#define REMOTEAS 297
#define DESCR 298
#define LOCALADDR 299
#define MULTIHOP 300
#define PASSIVE 301
#define MAXPREFIX 302
#define RESTART 303
#define ANNOUNCE 304
#define REFRESH 305
#define AS4BYTE 306
#define CONNECTRETRY 307
#define ENHANCED 308
#define ADDPATH 309
#define EXTENDED 310
#define SEND 311
#define RECV 312
#define PLUS 313
#define POLICY 314
#define ROLE 315
#define GRACEFUL 316
#define NOTIFICATION 317
#define MESSAGE 318
#define DEMOTE 319
#define ENFORCE 320
#define NEIGHBORAS 321
#define ASOVERRIDE 322
#define REFLECTOR 323
#define DEPEND 324
#define DOWN 325
#define DUMP 326
#define IN 327
#define OUT 328
#define SOCKET 329
#define RESTRICTED 330
#define LOG 331
#define TRANSPARENT 332
#define FILTERED 333
#define TCP 334
#define MD5SIG 335
#define PASSWORD 336
#define KEY 337
#define TTLSECURITY 338
#define ALLOW 339
#define DENY 340
#define MATCH 341
#define QUICK 342
#define FROM 343
#define TO 344
#define ANY 345
#define CONNECTED 346
#define STATIC 347
#define COMMUNITY 348
#define EXTCOMMUNITY 349
#define LARGECOMMUNITY 350
#define DELETE 351
#define MAXCOMMUNITIES 352
#define MAXEXTCOMMUNITIES 353
#define MAXLARGECOMMUNITIES 354
#define PREFIX 355
#define PREFIXLEN 356
#define PREFIXSET 357
#define ASPASET 358
#define ROASET 359
#define ORIGINSET 360
#define OVS 361
#define AVS 362
#define EXPIRES 363
#define ASSET 364
#define SOURCEAS 365
#define TRANSITAS 366
#define PEERAS 367
#define PROVIDERAS 368
#define CUSTOMERAS 369
#define MAXASLEN 370
#define MAXASSEQ 371
#define SET 372
#define LOCALPREF 373
#define MED 374
#define METRIC 375
#define NEXTHOP 376
#define REJECT 377
#define BLACKHOLE 378
#define NOMODIFY 379
#define SELF 380
#define PREPEND_SELF 381
#define PREPEND_PEER 382
#define PFTABLE 383
#define WEIGHT 384
#define RTLABEL 385
#define ORIGIN 386
#define PRIORITY 387
#define ERROR 388
#define INCLUDE 389
#define IPSEC 390
#define ESP 391
#define AH 392
#define SPI 393
#define IKE 394
#define IPV4 395
#define IPV6 396
#define EVPN 397
#define QUALIFY 398
#define VIA 399
#define NE 400
#define LE 401
#define GE 402
#define XRANGE 403
#define LONGER 404
#define MAXLEN 405
#define MAX 406
#define STRING 407
#define NUMBER 408
#define YYERRCODE 256
const short yylhs[] =
	{                                        -1,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    1,    2,    2,    3,    3,   27,   27,   11,   68,   69,
   87,   70,   70,   86,   86,   90,   71,   71,   89,   89,
   31,   92,   72,   72,   93,   74,   74,   14,   14,   91,
   91,   73,   73,   94,   94,   95,   67,   67,   66,   66,
   75,   96,   75,   97,   97,   98,   98,   98,   98,   98,
   80,   80,   80,   80,   80,   80,   80,   80,   80,   80,
   80,   80,   80,   80,   80,   80,   80,   80,   80,   80,
   80,   80,   80,   80,  100,   76,   99,   99,   99,  101,
  101,   79,   77,   77,   77,   77,   77,  103,   78,  104,
  104,  105,  105,   22,   22,  108,  106,  110,  109,  107,
  107,  107,  111,  111,  112,  112,  114,  114,  113,  113,
  113,   21,   21,  102,  102,  115,  115,  116,  116,  118,
  116,  119,  116,  116,  122,  116,  116,  116,  117,  117,
  117,  117,   25,  120,  120,  124,  124,  123,  123,  123,
   26,   26,   23,   23,  121,  121,  126,  126,  125,  125,
  125,   24,   12,   12,   13,   13,   28,   29,   29,   30,
   30,    4,    4,  127,   81,  128,  128,  128,  128,  129,
  129,  129,  129,  129,  130,  132,   82,  133,   83,  134,
  134,  134,  134,  134,   19,   19,   20,   20,  131,  131,
  131,  136,  136,  136,  136,  135,  135,  135,  135,  135,
  135,  135,  135,  135,  135,  135,  135,  135,  135,  135,
  135,  135,  135,  135,  135,  135,  135,  135,  135,  135,
  135,  135,  135,  135,  135,  135,  135,  135,  135,  135,
  135,  135,  135,  135,  135,  135,  135,  135,  135,  135,
  135,  135,  135,  135,    8,    8,    6,    6,    7,    7,
    7,    7,   10,   10,   64,   64,   64,   64,    5,    5,
   65,   65,   84,   32,   32,   32,   33,   33,   34,   34,
   37,   37,   37,   38,   38,   39,   42,   42,   41,   41,
   40,   40,   40,   40,   40,   40,   58,   58,   58,   58,
   59,   59,   59,   57,   57,   56,   48,   48,   50,   50,
   49,   49,   49,   51,   51,   51,   47,   47,   46,   46,
   46,   46,   45,  137,   45,   43,   43,   44,   44,   44,
   44,   44,   44,   44,   44,   44,   44,   44,   44,   44,
   44,   44,   44,   52,   52,   52,   52,   52,   63,   63,
   63,   63,   54,   54,   54,   55,   55,   36,   36,   35,
   35,   16,   16,   15,   15,   53,   53,   53,   53,   53,
   53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
   53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
   53,    9,   17,   18,   85,   85,   88,   88,   88,   88,
   60,   60,   60,   60,   60,   60,   61,   61,   62,   62,
};
const short yylen[] =
	{                                         2,
    0,    2,    3,    3,    3,    3,    3,    3,    3,    3,
    3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
    1,    1,    1,    1,    1,    2,    1,    1,    3,    2,
    0,    8,    5,    1,    3,    0,    8,    5,    1,    3,
    2,    0,    7,    4,    0,    8,    5,    0,    2,    4,
    6,    6,    4,    1,    3,    9,    1,    3,    1,    2,
    2,    0,    8,    1,    3,    2,    2,    2,    2,    1,
    2,    3,    2,    2,    3,    2,    3,    5,    2,    2,
    2,    3,    2,    4,    6,    3,    3,    4,    3,    5,
    4,    2,    2,    3,    0,    5,    1,    3,    2,    0,
    2,    5,    3,    4,    5,    5,    4,    0,    5,    2,
    6,    1,    3,    1,    1,    0,    3,    0,    3,    1,
    3,    2,    1,    1,    1,    5,    1,    3,    1,    2,
    3,    1,    1,    0,    1,    1,    2,    1,    1,    0,
    3,    0,    3,    1,    0,    3,    1,    2,    3,    2,
    1,    1,    1,    2,    6,    1,    3,    1,    3,    3,
    1,    1,    1,    1,    1,    5,    1,    3,    1,    2,
    3,    1,    1,    1,    0,    1,    1,    3,    3,    1,
    1,    0,    1,    0,    8,    0,    2,    3,    3,    2,
    3,    3,    2,    1,    0,    0,    5,    0,    6,    0,
    2,    3,    3,    3,    0,    2,    0,    2,    4,    3,
    0,    0,    2,    3,    3,    2,    2,    3,    2,    2,
    2,    2,    1,    1,    2,    2,    2,    3,    2,    4,
    3,    3,    4,    3,    4,    3,    4,    7,    3,    4,
    4,    2,    2,    2,    2,    3,    3,    2,    3,    4,
    1,    2,    2,    6,    1,    1,    2,    3,    2,    2,
    2,    3,    2,    3,    0,    2,    1,    1,    1,    1,
    1,    1,    1,    1,    4,    4,    3,    8,    1,    1,
    0,    2,    7,    1,    1,    1,    0,    1,    1,    1,
    0,    2,    6,    1,    3,    1,    1,    5,    1,    3,
    1,    1,    2,    2,    1,    1,    2,    2,    2,    4,
    1,    3,    4,    1,    3,    2,    1,    3,    1,    3,
    2,    4,    3,    1,    3,    4,    1,    3,    1,    1,
    2,    3,    0,    0,    2,    1,    2,    1,    1,    2,
    2,    2,    3,    3,    2,    2,    2,    2,    2,    3,
    2,    2,    2,    0,    1,    2,    3,    4,    1,    1,
    1,    1,    0,    2,    6,    3,    1,    1,    1,    0,
    1,    0,    1,    1,    1,    2,    3,    3,    2,    3,
    3,    2,    3,    3,    2,    3,    3,    2,    2,    2,
    2,    2,    2,    2,    1,    2,    2,    3,    4,    4,
    2,    1,    1,    1,    0,    2,    0,    1,    2,    3,
    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
};
const short yydefred[] =
	{                                      1,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,  284,  285,  286,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    2,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,   20,   22,   21,   23,    0,  177,   73,
    0,   74,    0,   28,   80,   79,   92,    0,    0,    0,
    0,    0,    0,   76,   27,    0,    0,  267,  268,    0,
    0,    0,    0,  108,   93,    0,    0,    0,   83,   81,
    0,    0,    0,    0,    0,    0,    0,   30,    0,  288,
    0,    3,    4,    5,    6,    7,    8,    9,   10,   11,
   12,   13,   14,   15,   16,   17,   18,   19,    0,   72,
   75,    0,    0,    0,   89,    0,   86,   87,    0,   26,
    0,    0,    0,    0,  274,  273,    0,    0,    0,    0,
  103,    0,    0,  173,  174,    0,    0,  176,   94,    0,
    0,    0,    0,    0,    0,    0,   82,    0,    0,    0,
    0,  180,  181,  196,    0,  184,    0,    0,   88,    0,
  200,  104,  178,  179,    0,    0,  107,  395,  368,    0,
  369,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,  364,    0,  140,  142,    0,  145,    0,
  116,  118,    0,  147,  138,  139,    0,  136,  144,    0,
  183,   84,    0,    0,  406,    0,   53,    0,   54,   44,
    0,    0,    0,   91,  296,    0,  292,  289,  290,    0,
    0,  133,  132,   78,    0,   90,    0,    0,    0,   96,
   97,    0,    0,  105,  106,  371,    0,  376,    0,    0,
  379,    0,    0,  382,    0,    0,  390,  389,  391,  392,
  388,  393,  394,  396,  385,    0,    0,  397,  402,  401,
    0,    0,  114,  115,    0,  110,    0,    0,  163,  164,
  148,    0,  161,  162,    0,    0,  154,    0,    0,  109,
  137,    0,  102,   38,    0,    0,    0,    0,    0,    0,
    0,    0,    0,   47,    0,   33,    0,    0,    0,    0,
  305,  306,  301,    0,  302,  297,    0,    0,  197,  186,
  101,    0,   99,    0,    0,    0,    0,    0,    0,   70,
    0,   64,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,  223,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  201,  199,    0,  251,  255,    0,    0,    0,    0,  377,
  378,  380,  381,  383,  384,  386,  387,  367,    0,  398,
    0,  152,  153,    0,    0,  141,  143,  412,  413,  415,
  172,  411,    0,  414,  416,    0,    0,  146,  165,    0,
    0,    0,  123,  124,  117,    0,  119,   85,   39,    0,
    0,    0,    0,    0,   52,   55,    0,  355,    0,   41,
    0,    0,    0,    0,   24,   25,   34,    0,    0,  294,
  303,  304,    0,    0,    0,  212,    0,    0,   98,   68,
   69,   66,   67,    0,  279,  280,    0,    0,  204,    0,
  227,  244,  245,    0,  226,  263,  229,    0,  216,    0,
  220,  222,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,  243,  242,  259,    0,    0,  248,  257,
    0,  225,    0,  261,  260,  252,    0,  253,    0,  221,
  203,  202,  400,  399,    0,    0,  112,    0,  150,    0,
    0,  420,  419,    0,  170,  156,    0,  159,  160,    0,
    0,    0,  122,  125,    0,    0,    0,   49,    0,  410,
    0,    0,  356,    0,   43,    0,    0,    0,    0,    0,
    0,  299,    0,  283,  359,    0,    0,    0,    0,    0,
    0,    0,    0,    0,  360,  361,  362,    0,    0,    0,
    0,    0,    0,    0,    0,  336,  339,  317,  338,    0,
    0,  210,    0,    0,    0,    0,    0,  187,  185,  194,
    0,    0,    0,  277,    0,   63,   65,  228,  264,  218,
    0,    0,  249,  375,  374,  234,  232,  236,    0,    0,
    0,    0,    0,  239,    0,  373,  231,  269,  270,  271,
  272,    0,  247,  246,  258,    0,  262,  365,  366,    0,
    0,  149,  167,    0,  171,    0,    0,    0,    0,  130,
  121,   37,   40,    0,    0,  357,   50,    0,   46,   32,
   35,  293,  295,    0,    0,    0,    0,  345,  346,  347,
    0,    0,  309,    0,  351,  403,  352,  404,  353,  340,
  341,  349,  348,  307,  308,  319,    0,  342,  337,  330,
    0,  418,  417,    0,    0,  321,    0,    0,  213,  209,
    0,  189,  193,  190,    0,    0,  188,    0,    0,    0,
  266,  250,  233,    0,  237,  240,  241,  235,  230,    0,
  111,  113,    0,    0,  155,  157,  127,    0,  131,    0,
  358,    0,  298,  300,  344,  343,    0,  314,    0,    0,
  316,  350,    0,  318,    0,  323,    0,  327,    0,    0,
    0,  331,  215,  214,  191,  192,    0,    0,    0,    0,
  166,  168,    0,    0,    0,   57,    0,   51,    0,    0,
  310,  409,  320,    0,    0,  322,  332,    0,  206,    0,
    0,  254,  126,  128,   60,    0,    0,    0,  315,    0,
  328,    0,  208,  238,   56,   58,  313,  326,    0,  278,
  282,
};
const short yydgoto[] =
	{                                       1,
  426,   58,  665,  212,  447,   82,  602,  583,  270,  139,
  585,  147,  149,  412,  586,  597,  647,  649,  729,  751,
  511,  276,  281,  396,  385,  286,   76,  315,  301,  164,
  302,   35,  101,  230,  247,  193,  160,  429,  227,  316,
  533,  317,  555,  556,  434,  718,  719,  557,  558,  657,
  720,  420,  378,  141,  379,  708,  709,  559,  710,  512,
  667,  504,  560,  364,  770,  736,  737,   36,   37,   38,
   39,   40,   41,   42,   43,   44,   45,   46,  365,   48,
   49,   50,   51,   52,  152,  428,  307,  423,  410,  295,
  303,  221,  305,  218,  219,  129,  331,  332,  240,  168,
  241,  203,  142,  204,  498,  205,  405,  288,  206,  289,
  406,  513,  514,  698,  207,  208,  386,  277,  278,  209,
  398,  282,  287,  507,  399,  614,  235,  438,  571,   53,
  319,  231,  131,  243,  367,  561,  435,
};
const short yysindex[] =
	{                                      0,
  432,   78, -263, -306, -193, -155, -298, -291, -283, -286,
  -81, -306, -271, -274,  518, -115, -207, -190, -158, -144,
 -298,    0,    0,    0, -129,  163,  169, -109, -105,  -86,
  -37,  -88,  260,    0,  -13,  347,  351,  353,  372,  398,
  401,  410,  413,  415,  417,  420,  433,  436,  447,  454,
  471,  477,  214,    0,    0,    0,    0,   97,    0,    0,
  100,    0, -306,    0,    0,    0,    0,  252,  121,  126,
  267,  202,    0,    0,    0,  145,  155,    0,    0,  519,
  541,  232,  227,    0,    0,  197,  117,  286,    0,    0,
  497,  628,  628,  526,  530,  266, -298,    0, -274,    0,
  400,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,   63,    0,
    0,  383,  278,  305,    0,  298,    0,    0,  584,    0,
  585,  227,  302,  311,    0,    0,  306,  328,  227,  830,
    0,  614,  331,    0,    0,  338,  335,    0,    0,  628,
  628,  -87,  624,  628,  628,  344,    0,  145, -102,  140,
  519,    0,    0,    0,   84,    0,  429, -174,    0,  628,
    0,    0,    0,    0,  227,  227,    0,    0,    0,  419,
    0,  -19,   -8,   -1,  475,  360,  366,  369,    9,  370,
  377,  628,  419,    0,  -83,    0,    0,   89,    0,  -73,
    0,    0,  227,    0,    0,    0,  614,    0,    0,  381,
    0,    0,  338,  650,    0, -263,    0,   74,    0,    0,
  113,  668,  669,    0,    0,  628,    0,    0,    0,  543,
  672,    0,    0,    0,  680,    0, -298,  403,  538,    0,
    0,  388,  545,    0,    0,    0, -305,    0,  408,  409,
    0,  414,  416,    0,  423,  424,    0,    0,    0,    0,
    0,    0,    0,    0,    0,  426,  428,    0,    0,    0,
 1288,  411,    0,    0,  628,    0,   -6,   -6,    0,    0,
    0,   93,    0,    0,  628,  528,    0, -209, -209,    0,
    0,  338,    0,    0,  113,  465,  628,  827,  715,  479,
 -246,  486,   74,    0,  113,    0,  149,  450, -263,  451,
    0,    0,    0,  628,    0,    0,    0,  740,    0,    0,
    0,  596,    0,   84,  453,  455, -306,  531,  168,    0,
  628,    0,  853, -187, -135,  602,  478,   84,  464, -263,
 -263, -274, -306,  476,    0,  482,  918, -170,  480, -136,
 -298, -306,  631,  487,  488,  489, -298, -298, 1249,  522,
    0,    0,  610,    0,    0,  891,  900,  511,  512,    0,
    0,    0,    0,    0,    0,    0,    0,    0,   74,    0,
  176,    0,    0,  513,  877,    0,    0,    0,    0,    0,
    0,    0,  628,    0,    0,  -34,  520,    0,    0,  189,
  195,   51,    0,    0,    0,  652,    0,    0,    0,   74,
  525,  568,    0,  628,    0,    0,  102,    0,  536,    0,
  149,  824,  113,   74,    0,    0,    0,   74,   74,    0,
    0,    0, -164,  227,  988,    0,  829,  731,    0,    0,
    0,    0,    0,  291,    0,    0,  179,  499,    0,  547,
    0,    0,    0,  552,    0,    0,    0,   97,    0,  145,
    0,    0, -200,  -43,  -43,  -43,  657,  324, -226,  -43,
  651,  654,  663,    0,    0,    0, -298, -298,    0,    0,
  569,    0,  334,    0,    0,    0,  628,    0, -298,    0,
    0,    0,    0,    0,  852, 1288,    0,   74,    0,  513,
  115,    0,    0,  520,    0,    0,   74,    0,    0,  628,
  -34,   84,    0,    0,   51,  855,  113,    0,  859,    0,
  -34,  570,    0,  465,    0,  620,  861,  866,  149,  867,
  450,    0,   74,    0,    0, -266,  587,  588,  589,  -66,
  586,  591,  594,  597,    0,    0,    0,  598,  599, -216,
 -246, -246,  274,  601,  988,    0,    0,    0,    0,  250,
  641,    0,  995, -298,  604,  605,  612,    0,    0,    0,
  999, -274, -274,    0,  630,    0,    0,    0,    0,    0,
  609,  718,    0,    0,    0,    0,    0,    0,  -43,  617,
  -43,  -43,  -43,    0, -298,    0,    0,    0,    0,    0,
    0,  654,    0,    0,    0, 1288,    0,    0,    0,  901,
  176,    0,    0,   74,    0,  902,  189,  142,   84,    0,
    0,    0,    0,  628,  621,    0,    0,  149,    0,    0,
    0,    0,    0,  903, -164,  618,  623,    0,    0,    0,
  -62, -246,    0, -246,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,   64,    0,    0,    0,
  625,    0,    0,  -42,  -34,    0,  149, 1023,    0,    0,
 1025,    0,    0,    0,  636,  638,    0,  145,  145,  639,
    0,    0,    0,  736,    0,    0,    0,    0,    0,   74,
    0,    0,  925,  115,    0,    0,    0,   74,    0,  149,
    0,  465,    0,    0,    0,    0,  113,    0,  240,  926,
    0,    0,  628,    0,  274,    0,  205,    0,  240,  927,
  149,    0,    0,    0,    0,    0,  646,  648,  655,  929,
    0,    0,  932,  142, -115,    0,   74,    0,   95,  113,
    0,    0,    0,  122,  205,    0,    0,  660,    0,  661,
  654,    0,    0,    0,    0,  933,  149,  -62,    0,  -42,
    0,  666,    0,    0,    0,    0,    0,    0,  676,    0,
    0,};
const short yyrindex[] =
	{                                      0,
  784,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,  124,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0, 1060,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,   69,    0,    0,  962,    0,    0,    0,    0,
    0,    0, 1076,    0,    0,    0,    0, 1080,    0,    0,
    0,  -80,  -98,    0,    0,    0,    0,    0,    0,    0,
  300,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0, 1081,    0,    7,    0,    0,    0,    0,    0,    0,
    0, 1076,    0,    0,    0,    0,    0,    0, 1076,    0,
    0,   -4,    0,    0,    0, 1085,    0,    0,    0,  -98,
  909,    0,  264,  -98,  -98,    0,    0, 1086,    0,    0,
   73,    0,    0,    0,    0,    0,    0, 1094,    0,  600,
    0,    0,    0,    0, 1076, 1076,    0,    0,    0, -255,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0, 1306,  698,    0,    0,    0,    0,    0,    0,    0,
    0,    0, 1076,    0,    0,    0,   18,    0,    0,    0,
    0,    0,   72,  272,    0,    0,    0,  -78,    0,    0,
    0,  294,  296,    0,    0,  699,    0,    0,    0,    0,
 1097,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,  784,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,  337,    0,    0,    0,    0,    0,
    0,    0,    0,    0,  337,  340,    0,    0,    0,    0,
    0, 1085,    0,    0,    0,  741, 1176, 1040,    0,    0,
    2,    0,  -91,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,  395,    0,    0,  727,    0,    0,    0,
    0, 1094,    0,    0,    0,    0,    0,    0,    0,    0,
  593,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,  119,    0,  133,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0, 1267,    0,
    0,    0,    0,    0,  438,    0,    0,    0,    0,    0,
    0,    0,  207,    0,    0,  246,    0,    0,    0,    0,
    0,    0,    0,    0,    0,  463,    0,    0,    0,  -91,
    0,    0, 1219, 1108,    0,    0,    0,    0,    0,    0,
    0,    0,    0,  -91,    0,    0,    0,  -91, -103,    0,
    0,    0,    0, 1076,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,  137,    0,  160,
    0,    0,  174,    0,    0,    0,    0,    0,    0,    0,
    0,  178,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0, 1306,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,  -91,    0,    0,
    0,    0,    0,    0,    0,    0,  -91,    0,    0,  193,
  146,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    5,    0,    0,    0,    0,    0,    0,
    0,    0,  -45,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  789,  789,    0,    0,   22,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,  174,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,  178,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,  111,    0,    0,    0,    0,    0,    0,
    0,    0,    0,  337,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,  215,    0,  789,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,  368,    0,    0,    0,
    0,    0,    0,    0,   26,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,   15,  151,    0,
    0,    0,    0,   10,    0,    0,    0,    0,    0, 1267,
    0,    0,    0,    0,    0,    0,    0,   54,    0,    0,
    0,    5,    0,    0,    0,    0,    0,    0,  -48,    0,
    0,    0,  581,    0,    0,    0,    0,    0,  405,    0,
    0,    0,    0,    0,    0,    0,    0,    0,   23,    0,
    0,    0,    0,    0,   21,    0,  -91,    0,  352,    0,
    0,    0,    0,  316,    0,    0,    0,    0,    0,    0,
  178,    0,    0,    0,    0,    0,    0,  983,    0,  985,
    0,  375,    0,    0,    0,    0,    0,    0,    0,    0,
    0,};
const short yygindex[] =
	{                                      0,
   11,  358, -297, -114,    0,  -14,    0,  532,    0,    0,
   -3,  671,    0, -471,  194, -542,    0,    0,    0,    0,
 -156, -351,    0, -240, -287,    0,  -96,    1,  -15,    0,
 -256,    0,    0,    0,  920, -345,    0,    0, -279, -390,
    0,    0,    0,  560,    0, -488,  399,    0, -487,    0,
  359,  125, -124,   48,  514, -465,  418,    0,  363, -275,
    0, -435,    0, -219,    0,  367,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,  688,    0, 1126,    0,
    0,  885,    0,    0,  -92,    0,    0, -210,    0,    0,
  826,    0,    0,    0,  832,    0,    0,  681,    0,    0,
  811,    0,    0,    0,    0,    0,  845,    0,    0,    0,
    0,  633, -520,    0,    0,  928,  858,    0,    0,    0,
    0,    0, -352,    0, -446,    0,    0,    0,    0,    0,
    0,    0,    0,    0, -267,    0,    0,
};
#define YYTABLESIZE 1692
const short yytable[] =
	{                                      83,
  153,   84,  158,   65,   60,  134,  397,  300,  234,  427,
  503,  354,   73,   57,   48,  194,   95,   90,  663,  205,
  226,  405,  330,  249,  275,  250,  405,  135,  430,  497,
   59,  335,  207,  405,  252,  329,  253,  217,  409,  275,
  384,  255,  532,  256,  405,  354,  405,  506,   48,  285,
  437,  266,  627,  267,  613,  368,  641,  214,  215,  689,
  707,  222,  223,  122,   59,  656,   61,  652,  120,  329,
  402,  666,  450,  713,  643,  619,  311,  242,   61,  405,
  717,  182,  177,  297,   86,  625,  329,   54,  237,  554,
  238,  592,  309,  157,  636,  474,  499,  697,  293,  271,
   59,  369,  581,  163,  713,  370,   63,  298,   64,  417,
  394,  392,  395,  407,  407,  407,   66,  298,  310,  162,
   68,  311,  312,  524,   67,  299,  354,  582,  256,   48,
  452,  713,   75,  308,  205,  403,   74,  453,  298,  275,
  637,  522,  224,   55,   56,   59,  217,  207,  329,  593,
  329,  370,  394,  392,  395,  129,  505,  418,  419,  477,
  276,  394,  392,  395,  239,  298,  526,  440,  496,  219,
  407,  407,  407,  510,  394,  392,  395,  408,  405,  172,
  313,  456,  381,  265,  478,  261,  177,  372,  714,  129,
   59,   62,  400,   69,   70,  177,  182,   80,   81,  517,
   85,  394,  392,  395,  413,  129,  129,  129,  764,  554,
  422,  407,  612,  754,   62,  393,   87,  529,  531,  758,
  451,  433,  244,  245,  354,  397,   57,  743,  330,  721,
  738,  631,   64,  321,  488,  405,  475,  407,  448,  363,
  407,  407,   59,  256,  704,  460,  760,  732,   88,  713,
  290,  633,  405,  405,  405,  169,  761,  224,  354,  692,
  623,  217,   89,  615,  696,  663,  405,  405,  405,   95,
  129,   95,  404,  404,  759,  276,  584,   91,  660,   78,
   79,  216,  329,  298,  219,   92,  495,  611,  405,  169,
  407,   93,   71,  671,  275,  275,  617,   94,  265,  407,
  501,   95,  372,  407,  225,  169,  169,  169,  405,  405,
  663,   96,  275,  275,  363,  407,  407,  516,   98,   57,
   99,  520,  635,  273,  274,   72,   97,  443,  100,  205,
  702,  527,  473,  283,  284,  528,  530,  354,  382,  354,
   80,   81,  207,  461,   80,   81,  329,  479,  275,  158,
   57,   57,  480,  485,  486,  620,  102,  662,  407,  407,
  103,  407,  104,   64,  425,   56,  354,  134,  502,  722,
  169,  609,  664,  329,  329,  329,  407,  329,  329,  329,
  329,  105,  329,  158,  281,  329,  329,  329,  248,  135,
  329,  329,  329,  335,  606,  329,  329,  329,  287,  251,
  383,  329,  735,  694,  275,  610,  254,  106,  354,  354,
  107,   48,   48,   95,  616,  205,  265,  618,  397,  108,
  329,  329,  109,  747,  110,  329,  111,   59,   59,  112,
  276,  276,  329,  329,  129,  129,  129,  129,  129,  129,
  634,   34,  113,  144,  145,  114,  715,  151,  276,  276,
  388,  389,  390,  407,  407,  407,  115,  232,  233,  735,
  407,  407,  699,  116,  158,  407,  287,  287,  580,  161,
   81,  354,  120,  603,  604,  678,  679,  127,  128,  496,
  117,  534,  228,  229,  276,  607,  118,  734,  129,  129,
  232,  233,  388,  389,  390,  279,  280,  119,  740,  281,
  391,  388,  389,  390,   56,  144,  145,  121,  745,  521,
  407,  407,  407,  123,  388,  389,  390,  129,  407,   80,
   81,  693,  391,  146,  642,  660,  757,  124,  740,  324,
  535,  700,  125,  745,  169,  169,  169,  169,  169,  169,
  276,  388,  389,  390,  126,  129,  129,  129,  232,  233,
  653,  130,  129,  129,  361,  425,   56,  363,  445,  446,
  673,  132,  354,  354,  354,  133,  354,  354,  354,  354,
  660,  354,  574,  296,  354,  354,  354,  135,  136,  354,
  354,  354,  273,  274,  354,  354,  354,  134,  169,  169,
  354,  688,  405,  405,  405,  283,  284,  730,  140,  405,
  405,  508,  509,  143,  662,  733,  405,  405,  405,  354,
  354,  425,   56,  661,  405,  148,  137,  169,  138,  150,
  742,  354,  354,  576,  407,  642,  572,  573,  158,  158,
  158,  158,  158,  158,  590,  591,  407,  151,  545,  546,
  547,  405,  291,  291,  756,  169,  169,  169,  154,  662,
  669,  405,  155,  169,  281,  281,  425,   56,  587,  588,
  144,  145,  165,  594,  156,  314,  431,  324,  325,  362,
   42,   42,  281,  281,  159,  654,  655,  405,   36,   36,
  405,  405,  158,  158,  166,  326,  327,    2,    3,    4,
    5,  642,    6,  167,    7,    8,    9,  458,  459,   10,
   45,   45,   31,   31,  169,   11,  170,  171,  281,  173,
   12,  158,  175,   13,   14,  407,   15,  405,  174,   16,
  755,  328,  407,  407,  642,  407,  151,  151,  151,  151,
  151,  151,  407,  407,  407,  176,  333,  210,   17,  405,
  568,  213,  642,  405,  405,  211,  158,  158,  220,  436,
  224,  120,  120,  120,  120,  120,  120,   18,  407,  407,
   19,  236,   20,   21,  281,  670,  711,  262,  712,  246,
   22,   23,   24,  263,  294,  264,  268,  329,  324,  325,
  151,  151,  683,  269,  685,  686,  687,  292,   25,   26,
   27,   28,  304,  306,  318,   29,  326,  327,  354,  309,
  333,  405,  320,  334,  407,  120,  120,   30,   31,  151,
  322,  407,  407,  323,  335,  370,  371,  380,  336,  337,
   32,  372,  401,  373,  338,  310,  339,  411,  311,  312,
  374,  375,  328,  376,  120,  377,  414,  405,   33,  415,
  340,  341,  342,  343,  344,  345,  346,  216,  347,  334,
  421,  257,  258,  259,  260,  569,  225,  432,  237,  348,
  441,  442,  449,  349,  350,  444,  351,  352,  353,  354,
  355,  457,  405,  405,   77,  356,  357,  454,  328,  405,
  405,   59,  358,  462,  455,  489,  476,  313,  329,  463,
  405,  405,  481,  482,  483,  484,  668,  405,  405,  334,
  491,  405,  195,  196,  197,  198,  199,  200,  490,  492,
  335,  354,   78,   79,  336,  337,  359,  493,  494,  383,
  338,  360,  339,  500,   80,   81,  405,  391,  598,  599,
  600,  515,  518,  405,  329,  519,  340,  341,  342,  343,
  344,  345,  346,  523,  347,  405,  405,  405,  525,   59,
  601,   64,  192,  562,  578,  348,  201,  202,  579,  349,
  350,  589,  351,  352,  353,  354,  355,  595,  405,  405,
  405,  356,  357,  596,  328,  605,  608,  626,  358,  622,
  405,  624,  405,  334,  628,  629,  563,  405,  405,  405,
  630,  632,  644,  564,  638,  639,  640,  645,  334,  565,
  646,  566,  567,  648,  672,  650,  651,  658,  677,  335,
  674,  675,  359,  336,  337,   15,  681,  360,  676,  338,
  581,  339,  680,  684,  705,  691,  695,  703,  701,  706,
  329,  716,  723,  405,  724,  340,  341,  342,  343,  344,
  345,  346,  725,  347,  726,  354,  727,   64,  728,  731,
  741,  746,  748,  752,  348,  749,  753,  765,  349,  350,
  750,  351,  352,  353,  354,  355,  762,  195,  763,   71,
  356,  357,  769,  328,  334,  334,  334,  358,  334,  334,
  334,  334,  771,  334,  198,  363,  334,  334,  334,  175,
   77,  334,  334,  334,  182,   29,  334,  334,  333,  408,
  408,  408,  334,  100,  370,  405,  211,  312,   48,  325,
  553,  359,  272,  682,  659,  744,  360,  575,  768,  690,
  767,  334,  334,  766,  739,  570,   47,  366,  577,  329,
  424,  416,  439,  407,  291,  387,  354,  354,  354,    0,
  354,  354,  354,  354,    0,  354,   64,  621,  354,  354,
  354,  178,    0,  354,  354,  354,    0,    0,  354,  354,
  354,    0,    0,    0,  354,  405,    0,  405,  405,  405,
    0,    0,    0,    0,    0,    0,    0,  179,  180,  181,
    0,    0,    0,  354,  354,    0,    0,    0,  405,  405,
    0,  405,    0,    0,  405,  405,    0,    0,    0,    0,
    0,    0,  182,  183,  184,  185,  405,  405,    0,    0,
  186,  187,  188,  189,  190,  191,    0,    0,    0,    0,
  464,    0,  465,  466,    0,  467,  468,  469,    0,  405,
  405,  470,    0,  471,    0,  405,  405,  405,    0,    0,
    0,    0,  405,    0,  535,    0,    0,    0,    0,    0,
    0,    0,    0,  405,    0,    0,  405,  405,  405,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,  405,  405,  405,    0,  405,  409,  409,
  409,  405,  405,  405,  405,    0,    0,    0,    0,  405,
  405,  405,  405,  405,  405,    0,  408,    0,  405,    0,
  405,    0,    0,    0,    0,    0,    0,    0,  405,  405,
  405,    0,   78,   79,  472,  405,  405,    0,    0,    0,
    0,    0,  408,    0,    0,  408,  408,    0,    0,    0,
    0,    0,    0,    0,    0,  179,  536,  181,    0,  537,
  538,  539,  540,  406,  541,    0,    0,  542,  543,  544,
    0,    0,  545,  546,  547,    0,    0,  548,  549,    0,
  408,  408,    0,  550,  405,    0,    0,    0,    0,    0,
    0,  487,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,  551,  552,  408,    0,    0,  408,  408,  408,
  405,  405,    0,  405,  405,    0,    0,    0,    0,    0,
    0,    0,    0,    0,  408,  408,  408,    0,  408,    0,
    0,    0,  408,  408,  408,  408,    0,    0,    0,    0,
  408,  408,  408,  408,  408,  408,    0,    0,  405,  405,
    0,    0,  405,    0,    0,    0,    0,    0,    0,  408,
  408,  408,    0,    0,    0,    0,  408,  408,    0,    0,
    0,    0,  405,    0,    0,  405,  405,  405,  405,    0,
    0,  405,  405,    0,    0,    0,    0,    0,    0,    0,
    0,    0,  405,  405,  405,  409,  405,    0,    0,    0,
  405,  405,  405,  405,    0,    0,    0,    0,  405,  405,
  405,  405,  405,  405,    0,    0,    0,  405,    0,    0,
    0,  409,    0,    0,  409,  409,    0,  405,  405,  405,
    0,    0,    0,    0,  405,  405,    0,    0,    0,    0,
  405,    0,    0,  405,  405,  405,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  409,    0,    0,    0,  405,    0,    0,    0,  405,  405,
  405,  405,    0,    0,    0,    0,  405,  405,  405,  405,
  405,  405,    0,  409,    0,    0,  409,  409,  409,    0,
  178,    0,    0,    0,    0,  405,  405,  405,    0,    0,
    0,    0,  405,  405,    0,    0,    0,  409,  407,    0,
    0,  409,  409,  409,  409,    0,  179,  180,  181,  409,
  409,  409,  409,  409,  409,    0,    0,    0,    0,  178,
    0,    0,    0,    0,  407,  407,  407,    0,  409,  409,
  409,  182,  183,  184,  185,  409,  409,  405,    0,  186,
  187,  188,  189,  190,  191,  179,  180,  181,    0,  407,
  407,  407,  407,    0,    0,    0,    0,  407,  407,  407,
  407,  407,  407,  405,  405,  405,    0,    0,    0,    0,
  182,  183,  184,  185,    0,    0,    0,    0,  186,  187,
  188,  189,  190,  191,    0,    0,    0,    0,  405,  405,
  405,  405,    0,    0,    0,    0,  405,  405,  405,  405,
  405,  405,
};
const short yycheck[] =
	{                                      15,
   93,   16,   99,    7,    4,   10,  282,  218,  165,  307,
   45,   10,   12,    3,   10,  140,   10,   21,   61,   10,
  123,  125,  242,   43,   10,   45,  125,   10,  308,  381,
   10,   10,   10,  125,   43,   10,   45,  125,  295,  123,
   47,   43,  433,   45,  125,   44,  125,  400,   44,  123,
  318,   43,  524,   45,  501,  361,  123,  150,  151,  602,
  123,  154,  155,   63,   44,  553,  260,  284,   58,   44,
  280,  560,  260,   10,  540,  511,  125,  170,   10,  125,
  123,   10,   10,   10,  275,  521,   61,   10,  263,  435,
  265,  318,  257,   97,  361,  266,  384,  618,  213,  192,
  407,  407,  303,  119,   10,  361,  262,   44,  407,  356,
   60,   61,   62,   60,   61,   62,  408,   44,  283,  119,
  407,  286,  287,  421,  408,  218,  125,  328,   10,  125,
  266,   10,  407,  226,  125,  345,  408,  273,   44,  125,
  407,  417,   10,  407,  408,  125,   10,  125,  123,  376,
  125,  407,   60,   61,   62,   10,  397,  404,  405,  296,
   10,   60,   61,   62,  168,   44,  423,  324,  379,   10,
   60,   61,   62,  123,   60,   61,   62,  292,  125,  132,
  345,  338,  275,   10,  321,  185,  139,   10,  125,   44,
  407,  123,  285,  275,  276,  123,  125,  407,  408,  410,
  408,   60,   61,   62,  297,   60,   61,   62,  751,  555,
  303,  257,  500,  734,  408,  123,  407,  428,  429,  125,
  408,  314,  175,  176,   10,  501,  216,  715,  448,  665,
  702,  529,  407,  237,  359,  125,  407,  283,  331,  243,
  286,  287,  407,  125,  635,  342,  125,  694,  407,   10,
  203,  531,   60,   61,   62,   10,  745,  125,   44,  611,
  517,  125,  407,  504,  617,   61,   60,   61,   62,  263,
  125,  265,  288,  289,  740,  125,  320,  407,  321,  395,
  396,  369,  257,   44,  125,  123,  379,  498,  369,   44,
  369,  123,  374,  561,  280,  281,  507,  407,  125,  345,
  393,  407,  125,  407,  407,   60,   61,   62,  407,  408,
   61,  398,  298,  299,  318,  407,  408,  410,  407,  309,
   61,  414,  533,  407,  408,  407,  364,  327,  342,  320,
  628,  424,  347,  407,  408,  428,  429,  123,  345,  125,
  407,  408,  320,  343,  407,  408,  321,  351,  334,   10,
  340,  341,  352,  357,  358,  512,   10,  400,  407,  408,
   10,  407,   10,  407,  407,  408,  365,  372,  403,  667,
  125,  496,  123,  348,  349,  350,   61,  352,  353,  354,
  355,   10,  357,   44,   10,  360,  361,  362,  408,  372,
  365,  366,  367,  372,  487,  370,  371,  372,  275,  408,
  407,  376,  700,  614,  390,  498,  408,   10,  407,  408,
   10,  407,  408,  407,  507,  406,  408,  510,  694,   10,
  395,  396,   10,  721,   10,  400,   10,  407,  408,   10,
  280,  281,  407,  408,  289,  290,  291,  292,  293,  294,
  533,   10,   10,  327,  328,   10,  657,   10,  298,  299,
  400,  401,  402,  400,  401,  402,   10,  407,  408,  757,
  407,  408,  619,   10,  125,   61,  343,  344,  458,  407,
  408,  257,   10,  477,  478,  572,  573,  276,  277,  690,
   10,  434,  343,  344,  334,  489,   10,  698,  343,  344,
  407,  408,  400,  401,  402,  407,  408,  284,  709,  125,
  408,  400,  401,  402,  408,  327,  328,  408,  719,  408,
  400,  401,  402,  262,  400,  401,  402,  372,  408,  407,
  408,  614,  408,  407,  540,  321,  737,  407,  739,  125,
  257,  624,  407,  744,  289,  290,  291,  292,  293,  294,
  390,  400,  401,  402,  278,  400,  401,  402,  407,  408,
  550,  407,  407,  408,   10,  407,  408,  561,  391,  392,
  564,  407,  348,  349,  350,   47,  352,  353,  354,  355,
  321,  357,  394,  216,  360,  361,  362,  346,  347,  365,
  366,  367,  407,  408,  370,  371,  372,   47,  343,  344,
  376,  595,  400,  401,  402,  407,  408,  690,  372,  407,
  408,  407,  408,  407,  400,  698,  400,  401,  402,  395,
  396,  407,  408,  364,  408,  330,  385,  372,  387,  123,
  713,  407,  408,  125,  257,  641,  336,  337,  289,  290,
  291,  292,  293,  294,  311,  312,  321,   10,  365,  366,
  367,   61,  343,  344,  737,  400,  401,  402,  123,  400,
   10,  257,  123,  408,  280,  281,  407,  408,  465,  466,
  327,  328,  280,  470,  399,  123,  309,  280,  281,  125,
  407,  408,  298,  299,  275,  551,  552,  283,  407,  408,
  286,  287,  343,  344,  407,  298,  299,  256,  257,  258,
  259,  707,  261,  389,  263,  264,  265,  340,  341,  268,
  407,  408,  407,  408,  407,  274,  123,  123,  334,  408,
  279,  372,  407,  282,  283,  400,  285,  125,  408,  288,
  735,  334,  407,  408,  740,  321,  289,  290,  291,  292,
  293,  294,  365,  366,  367,  408,   10,  407,  307,  345,
   10,  407,  758,  407,  408,  408,  407,  408,  125,   10,
  407,  289,  290,  291,  292,  293,  294,  326,  407,  408,
  329,  333,  331,  332,  390,  125,  642,  408,  644,  351,
  339,  340,  341,  408,  125,  407,  407,  390,  280,  281,
  343,  344,  589,  407,  591,  592,  593,  407,  357,  358,
  359,  360,  125,  125,  123,  364,  298,  299,   10,  257,
  256,  407,  123,  259,  400,  343,  344,  376,  377,  372,
  408,  407,  408,  276,  270,  408,  408,  407,  274,  275,
  389,  408,  295,  408,  280,  283,  282,  363,  286,  287,
  408,  408,  334,  408,  372,  408,   10,  257,  407,  125,
  296,  297,  298,  299,  300,  301,  302,  369,  304,  123,
  365,  377,  378,  379,  380,  125,  407,  407,  263,  315,
  408,  407,   10,  319,  320,  335,  322,  323,  324,  325,
  326,  408,  280,  281,  357,  331,  332,  276,  334,  280,
  281,  407,  338,  408,  407,  364,  407,  345,  390,  408,
  298,  299,  262,  407,  407,  407,  256,  298,  299,  259,
   10,  321,  289,  290,  291,  292,  293,  294,  299,   10,
  270,  123,  395,  396,  274,  275,  372,  407,  407,  407,
  280,  377,  282,   47,  407,  408,  334,  408,  266,  267,
  268,  280,  408,  334,  390,  368,  296,  297,  298,  299,
  300,  301,  302,  408,  304,  365,  366,  367,  125,  407,
  288,  407,  123,  125,  408,  315,  343,  344,  407,  319,
  320,  305,  322,  323,  324,  325,  326,  317,   60,   61,
   62,  331,  332,  320,  334,  407,  125,  408,  338,  125,
  400,  123,  390,  257,  365,  125,  256,  407,  408,  390,
  125,  125,  407,  263,  408,  408,  408,  407,  259,  269,
  407,  271,  272,  407,   10,  408,  408,  407,   10,  270,
  407,  407,  372,  274,  275,  285,  408,  377,  407,  280,
  303,  282,  393,  407,  407,  125,  125,  125,  408,  407,
  390,  407,   10,  125,   10,  296,  297,  298,  299,  300,
  301,  302,  407,  304,  407,  257,  408,  407,  313,  125,
  125,  125,  407,  125,  315,  408,  125,  125,  319,  320,
  406,  322,  323,  324,  325,  326,  407,  284,  408,   10,
  331,  332,  407,  334,  348,  349,  350,  338,  352,  353,
  354,  355,  407,  357,  123,   10,  360,  361,  362,   10,
   10,  365,  366,  367,   10,   10,  370,  371,  372,   60,
   61,   62,  376,   10,  407,  407,   10,  125,  368,  125,
  123,  372,  193,  582,  555,  717,  377,  447,  760,  606,
  758,  395,  396,  757,  707,  438,    1,  243,  448,  390,
  305,  300,  322,  289,  207,  278,  348,  349,  350,   -1,
  352,  353,  354,  355,   -1,  357,  407,  515,  360,  361,
  362,  322,   -1,  365,  366,  367,   -1,   -1,  370,  371,
  372,   -1,   -1,   -1,  376,  257,   -1,   60,   61,   62,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,  348,  349,  350,
   -1,   -1,   -1,  395,  396,   -1,   -1,   -1,  280,  281,
   -1,  283,   -1,   -1,  286,  287,   -1,   -1,   -1,   -1,
   -1,   -1,  373,  374,  375,  376,  298,  299,   -1,   -1,
  381,  382,  383,  384,  385,  386,   -1,   -1,   -1,   -1,
  303,   -1,  305,  306,   -1,  308,  309,  310,   -1,  321,
  322,  314,   -1,  316,   -1,   60,   61,   62,   -1,   -1,
   -1,   -1,  334,   -1,  257,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,  345,   -1,   -1,  348,  349,  350,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,  365,  366,  367,   -1,  369,   60,   61,
   62,  373,  374,  375,  376,   -1,   -1,   -1,   -1,  381,
  382,  383,  384,  385,  386,   -1,  257,   -1,  390,   -1,
  125,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  400,  401,
  402,   -1,  395,  396,  397,  407,  408,   -1,   -1,   -1,
   -1,   -1,  283,   -1,   -1,  286,  287,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,  348,  349,  350,   -1,  352,
  353,  354,  355,  125,  357,   -1,   -1,  360,  361,  362,
   -1,   -1,  365,  366,  367,   -1,   -1,  370,  371,   -1,
  321,  322,   -1,  376,  257,   -1,   -1,   -1,   -1,   -1,
   -1,  123,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,  395,  396,  345,   -1,   -1,  348,  349,  350,
  283,  125,   -1,  286,  287,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,  365,  366,  367,   -1,  369,   -1,
   -1,   -1,  373,  374,  375,  376,   -1,   -1,   -1,   -1,
  381,  382,  383,  384,  385,  386,   -1,   -1,  321,  322,
   -1,   -1,  257,   -1,   -1,   -1,   -1,   -1,   -1,  400,
  401,  402,   -1,   -1,   -1,   -1,  407,  408,   -1,   -1,
   -1,   -1,  345,   -1,   -1,  348,  349,  350,  283,   -1,
   -1,  286,  287,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,  365,  366,  367,  257,  369,   -1,   -1,   -1,
  373,  374,  375,  376,   -1,   -1,   -1,   -1,  381,  382,
  383,  384,  385,  386,   -1,   -1,   -1,  322,   -1,   -1,
   -1,  283,   -1,   -1,  286,  287,   -1,  400,  401,  402,
   -1,   -1,   -1,   -1,  407,  408,   -1,   -1,   -1,   -1,
  345,   -1,   -1,  348,  349,  350,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
  322,   -1,   -1,   -1,  369,   -1,   -1,   -1,  373,  374,
  375,  376,   -1,   -1,   -1,   -1,  381,  382,  383,  384,
  385,  386,   -1,  345,   -1,   -1,  348,  349,  350,   -1,
  322,   -1,   -1,   -1,   -1,  400,  401,  402,   -1,   -1,
   -1,   -1,  407,  408,   -1,   -1,   -1,  369,  322,   -1,
   -1,  373,  374,  375,  376,   -1,  348,  349,  350,  381,
  382,  383,  384,  385,  386,   -1,   -1,   -1,   -1,  322,
   -1,   -1,   -1,   -1,  348,  349,  350,   -1,  400,  401,
  402,  373,  374,  375,  376,  407,  408,  322,   -1,  381,
  382,  383,  384,  385,  386,  348,  349,  350,   -1,  373,
  374,  375,  376,   -1,   -1,   -1,   -1,  381,  382,  383,
  384,  385,  386,  348,  349,  350,   -1,   -1,   -1,   -1,
  373,  374,  375,  376,   -1,   -1,   -1,   -1,  381,  382,
  383,  384,  385,  386,   -1,   -1,   -1,   -1,  373,  374,
  375,  376,   -1,   -1,   -1,   -1,  381,  382,  383,  384,
  385,  386,
};
#define YYFINAL 1
#ifndef YYDEBUG
#define YYDEBUG 0
#endif
#define YYMAXTOKEN 408
#if YYDEBUG
const char * const yyname[] =
	{
"end-of-file",0,0,0,0,0,0,0,0,0,"'\\n'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,"'+'","','","'-'",0,"'/'",0,0,0,0,0,0,0,0,0,0,0,0,"'<'",
"'='","'>'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"'{'",0,"'}'",0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,"AS","ROUTERID","HOLDTIME","YMIN","LISTEN","ON","FIBUPDATE",
"FIBPRIORITY","RTABLE","NONE","UNICAST","VPN","RD","EXPORT","EXPORTTRGT",
"IMPORTTRGT","DEFAULTROUTE","RDE","RIB","EVALUATE","IGNORE","COMPARE","RTR",
"PORT","MINVERSION","STALETIME","GROUP","NEIGHBOR","NETWORK","EBGP","IBGP",
"FLOWSPEC","PROTO","FLAGS","FRAGMENT","TOS","LENGTH","ICMPTYPE","CODE",
"LOCALAS","REMOTEAS","DESCR","LOCALADDR","MULTIHOP","PASSIVE","MAXPREFIX",
"RESTART","ANNOUNCE","REFRESH","AS4BYTE","CONNECTRETRY","ENHANCED","ADDPATH",
"EXTENDED","SEND","RECV","PLUS","POLICY","ROLE","GRACEFUL","NOTIFICATION",
"MESSAGE","DEMOTE","ENFORCE","NEIGHBORAS","ASOVERRIDE","REFLECTOR","DEPEND",
"DOWN","DUMP","IN","OUT","SOCKET","RESTRICTED","LOG","TRANSPARENT","FILTERED",
"TCP","MD5SIG","PASSWORD","KEY","TTLSECURITY","ALLOW","DENY","MATCH","QUICK",
"FROM","TO","ANY","CONNECTED","STATIC","COMMUNITY","EXTCOMMUNITY",
"LARGECOMMUNITY","DELETE","MAXCOMMUNITIES","MAXEXTCOMMUNITIES",
"MAXLARGECOMMUNITIES","PREFIX","PREFIXLEN","PREFIXSET","ASPASET","ROASET",
"ORIGINSET","OVS","AVS","EXPIRES","ASSET","SOURCEAS","TRANSITAS","PEERAS",
"PROVIDERAS","CUSTOMERAS","MAXASLEN","MAXASSEQ","SET","LOCALPREF","MED",
"METRIC","NEXTHOP","REJECT","BLACKHOLE","NOMODIFY","SELF","PREPEND_SELF",
"PREPEND_PEER","PFTABLE","WEIGHT","RTLABEL","ORIGIN","PRIORITY","ERROR",
"INCLUDE","IPSEC","ESP","AH","SPI","IKE","IPV4","IPV6","EVPN","QUALIFY","VIA",
"NE","LE","GE","XRANGE","LONGER","MAXLEN","MAX","STRING","NUMBER",
};
const char * const yyrule[] =
	{"$accept : grammar",
"grammar :",
"grammar : grammar '\\n'",
"grammar : grammar varset '\\n'",
"grammar : grammar include '\\n'",
"grammar : grammar as_set '\\n'",
"grammar : grammar prefixset '\\n'",
"grammar : grammar roa_set '\\n'",
"grammar : grammar aspa_set '\\n'",
"grammar : grammar origin_set '\\n'",
"grammar : grammar rtr '\\n'",
"grammar : grammar rib '\\n'",
"grammar : grammar network '\\n'",
"grammar : grammar flowspec '\\n'",
"grammar : grammar mrtdump '\\n'",
"grammar : grammar conf_main '\\n'",
"grammar : grammar l3vpn '\\n'",
"grammar : grammar neighbor '\\n'",
"grammar : grammar group '\\n'",
"grammar : grammar filterrule '\\n'",
"grammar : grammar error '\\n'",
"asnumber : NUMBER",
"as4number : STRING",
"as4number : asnumber",
"as4number_any : STRING",
"as4number_any : asnumber",
"string : string STRING",
"string : STRING",
"yesno : STRING",
"varset : STRING '=' string",
"include : INCLUDE STRING",
"$$1 :",
"as_set : ASSET STRING '{' optnl $$1 as_set_l optnl '}'",
"as_set : ASSET STRING '{' optnl '}'",
"as_set_l : as4number_any",
"as_set_l : as_set_l comma as4number_any",
"$$2 :",
"prefixset : PREFIXSET STRING '{' optnl $$2 prefixset_l optnl '}'",
"prefixset : PREFIXSET STRING '{' optnl '}'",
"prefixset_l : prefixset_item",
"prefixset_l : prefixset_l comma prefixset_item",
"prefixset_item : prefix prefixlenop",
"$$3 :",
"roa_set : ROASET '{' optnl $$3 roa_set_l optnl '}'",
"roa_set : ROASET '{' optnl '}'",
"$$4 :",
"origin_set : ORIGINSET STRING '{' optnl $$4 roa_set_l optnl '}'",
"origin_set : ORIGINSET STRING '{' optnl '}'",
"expires :",
"expires : EXPIRES NUMBER",
"roa_set_l : prefixset_item SOURCEAS as4number_any expires",
"roa_set_l : roa_set_l comma prefixset_item SOURCEAS as4number_any expires",
"aspa_set : ASPASET '{' optnl aspa_set_l optnl '}'",
"aspa_set : ASPASET '{' optnl '}'",
"aspa_set_l : aspa_elm",
"aspa_set_l : aspa_set_l comma aspa_elm",
"aspa_elm : CUSTOMERAS as4number expires PROVIDERAS '{' optnl aspa_tas_l optnl '}'",
"aspa_tas_l : aspa_tas",
"aspa_tas_l : aspa_tas_l comma aspa_tas",
"aspa_tas : as4number_any",
"aspa_tas : as4number_any af",
"rtr : RTR address",
"$$5 :",
"rtr : RTR address $$5 '{' optnl rtropt_l optnl '}'",
"rtropt_l : rtropt",
"rtropt_l : rtropt_l optnl rtropt",
"rtropt : DESCR STRING",
"rtropt : LOCALADDR address",
"rtropt : PORT port",
"rtropt : MINVERSION NUMBER",
"rtropt : authconf",
"conf_main : AS as4number",
"conf_main : AS as4number asnumber",
"conf_main : ROUTERID address",
"conf_main : HOLDTIME NUMBER",
"conf_main : HOLDTIME YMIN NUMBER",
"conf_main : STALETIME NUMBER",
"conf_main : LISTEN ON address",
"conf_main : LISTEN ON address PORT port",
"conf_main : FIBPRIORITY NUMBER",
"conf_main : FIBUPDATE yesno",
"conf_main : TRANSPARENT yesno",
"conf_main : REJECT ASSET yesno",
"conf_main : LOG STRING",
"conf_main : DUMP STRING STRING optnumber",
"conf_main : DUMP RIB STRING STRING STRING optnumber",
"conf_main : RDE STRING EVALUATE",
"conf_main : RDE STRING IGNORE",
"conf_main : RDE MED COMPARE STRING",
"conf_main : RDE EVALUATE STRING",
"conf_main : RDE RIB STRING INCLUDE FILTERED",
"conf_main : NEXTHOP QUALIFY VIA STRING",
"conf_main : RTABLE NUMBER",
"conf_main : CONNECTRETRY NUMBER",
"conf_main : SOCKET STRING restricted",
"$$6 :",
"rib : RDE RIB STRING $$6 ribopts",
"ribopts : fibupdate",
"ribopts : RTABLE NUMBER fibupdate",
"ribopts : yesno EVALUATE",
"fibupdate :",
"fibupdate : FIBUPDATE yesno",
"mrtdump : DUMP STRING inout STRING optnumber",
"network : NETWORK prefix filter_set",
"network : NETWORK PREFIXSET STRING filter_set",
"network : NETWORK af RTLABEL STRING filter_set",
"network : NETWORK af PRIORITY NUMBER filter_set",
"network : NETWORK af nettype filter_set",
"$$7 :",
"flowspec : FLOWSPEC af $$7 flow_rules filter_set",
"proto : PROTO proto_item",
"proto : PROTO '{' optnl proto_list optnl '}'",
"proto_list : proto_item",
"proto_list : proto_list comma proto_item",
"proto_item : STRING",
"proto_item : NUMBER",
"$$8 :",
"from : FROM $$8 ipportspec",
"$$9 :",
"to : TO $$9 ipportspec",
"ipportspec : ipspec",
"ipportspec : ipspec PORT portspec",
"ipportspec : PORT portspec",
"ipspec : ANY",
"ipspec : prefix",
"portspec : port_item",
"portspec : '{' optnl port_list optnl '}'",
"port_list : port_item",
"port_list : port_list comma port_item",
"port_item : port",
"port_item : unaryop port",
"port_item : port binaryop port",
"port : NUMBER",
"port : STRING",
"flow_rules :",
"flow_rules : flow_rules_l",
"flow_rules_l : flowrule",
"flow_rules_l : flow_rules_l flowrule",
"flowrule : from",
"flowrule : to",
"$$10 :",
"flowrule : FLAGS $$10 flags",
"$$11 :",
"flowrule : FRAGMENT $$11 flags",
"flowrule : icmpspec",
"$$12 :",
"flowrule : LENGTH $$12 lengthspec",
"flowrule : proto",
"flowrule : TOS tos",
"flags : flag '/' flag",
"flags : '/' flag",
"flags : flag",
"flags : ANY",
"flag : STRING",
"icmpspec : ICMPTYPE icmp_item",
"icmpspec : ICMPTYPE '{' optnl icmp_list optnl '}'",
"icmp_list : icmp_item",
"icmp_list : icmp_list comma icmp_item",
"icmp_item : icmptype",
"icmp_item : icmptype CODE STRING",
"icmp_item : icmptype CODE NUMBER",
"icmptype : STRING",
"icmptype : NUMBER",
"tos : STRING",
"tos : NUMBER",
"lengthspec : length_item",
"lengthspec : '{' optnl length_list optnl '}'",
"length_list : length_item",
"length_list : length_list comma length_item",
"length_item : length",
"length_item : unaryop length",
"length_item : length binaryop length",
"length : NUMBER",
"inout : IN",
"inout : OUT",
"restricted :",
"restricted : RESTRICTED",
"address : STRING",
"prefix : STRING '/' NUMBER",
"prefix : NUMBER '/' NUMBER",
"addrspec : address",
"addrspec : prefix",
"optnumber :",
"optnumber : NUMBER",
"$$13 :",
"l3vpn : VPN STRING ON STRING $$13 '{' l3vpnopts_l '}'",
"l3vpnopts_l :",
"l3vpnopts_l : l3vpnopts_l '\\n'",
"l3vpnopts_l : l3vpnopts_l l3vpnopts '\\n'",
"l3vpnopts_l : l3vpnopts_l error '\\n'",
"l3vpnopts : RD STRING",
"l3vpnopts : EXPORTTRGT STRING STRING",
"l3vpnopts : IMPORTTRGT STRING STRING",
"l3vpnopts : FIBUPDATE yesno",
"l3vpnopts : network",
"$$14 :",
"$$15 :",
"neighbor : $$14 NEIGHBOR addrspec $$15 peeropts_h",
"$$16 :",
"group : GROUP string $$16 '{' groupopts_l '}'",
"groupopts_l :",
"groupopts_l : groupopts_l '\\n'",
"groupopts_l : groupopts_l peeropts '\\n'",
"groupopts_l : groupopts_l neighbor '\\n'",
"groupopts_l : groupopts_l error '\\n'",
"addpathextra :",
"addpathextra : PLUS NUMBER",
"addpathmax :",
"addpathmax : MAX NUMBER",
"peeropts_h : '{' '\\n' peeropts_l '}'",
"peeropts_h : '{' peeropts '}'",
"peeropts_h :",
"peeropts_l :",
"peeropts_l : peeropts_l '\\n'",
"peeropts_l : peeropts_l peeropts '\\n'",
"peeropts_l : peeropts_l error '\\n'",
"peeropts : REMOTEAS as4number",
"peeropts : LOCALAS as4number",
"peeropts : LOCALAS as4number asnumber",
"peeropts : DESCR string",
"peeropts : LOCALADDR address",
"peeropts : yesno LOCALADDR",
"peeropts : MULTIHOP NUMBER",
"peeropts : PASSIVE",
"peeropts : DOWN",
"peeropts : DOWN STRING",
"peeropts : RIB STRING",
"peeropts : HOLDTIME NUMBER",
"peeropts : HOLDTIME YMIN NUMBER",
"peeropts : STALETIME NUMBER",
"peeropts : ANNOUNCE af safi enforce",
"peeropts : ANNOUNCE EVPN enforce",
"peeropts : ANNOUNCE REFRESH yesnoenforce",
"peeropts : ANNOUNCE ENHANCED REFRESH yesnoenforce",
"peeropts : ANNOUNCE RESTART yesnoenforce",
"peeropts : ANNOUNCE GRACEFUL NOTIFICATION yesno",
"peeropts : ANNOUNCE AS4BYTE yesnoenforce",
"peeropts : ANNOUNCE ADDPATH RECV yesnoenforce",
"peeropts : ANNOUNCE ADDPATH SEND STRING addpathextra addpathmax enforce",
"peeropts : ANNOUNCE POLICY yesnoenforce",
"peeropts : ANNOUNCE EXTENDED MESSAGE yesnoenforce",
"peeropts : ANNOUNCE EXTENDED NEXTHOP yesnoenforce",
"peeropts : ROLE STRING",
"peeropts : ROLE NONE",
"peeropts : EXPORT NONE",
"peeropts : EXPORT DEFAULTROUTE",
"peeropts : ENFORCE NEIGHBORAS yesno",
"peeropts : ENFORCE LOCALAS yesno",
"peeropts : ASOVERRIDE yesno",
"peeropts : MAXPREFIX NUMBER restart",
"peeropts : MAXPREFIX NUMBER OUT restart",
"peeropts : authconf",
"peeropts : TTLSECURITY yesno",
"peeropts : SET filter_set_opt",
"peeropts : SET '{' optnl filter_set_l optnl '}'",
"peeropts : mrtdump",
"peeropts : REFLECTOR",
"peeropts : REFLECTOR address",
"peeropts : DEPEND ON STRING",
"peeropts : DEMOTE STRING",
"peeropts : TRANSPARENT yesno",
"peeropts : LOG STRING",
"peeropts : REJECT ASSET yesno",
"peeropts : PORT port",
"peeropts : RDE EVALUATE STRING",
"restart :",
"restart : RESTART NUMBER",
"af : IPV4",
"af : IPV6",
"safi : NONE",
"safi : UNICAST",
"safi : VPN",
"safi : FLOWSPEC",
"nettype : STATIC",
"nettype : CONNECTED",
"authconf : TCP MD5SIG PASSWORD string",
"authconf : TCP MD5SIG KEY string",
"authconf : IPSEC espah IKE",
"authconf : IPSEC espah inout SPI NUMBER STRING STRING encspec",
"espah : ESP",
"espah : AH",
"encspec :",
"encspec : STRING STRING",
"filterrule : action quick filter_rib_h direction filter_peer_h filter_match_h filter_set",
"action : ALLOW",
"action : DENY",
"action : MATCH",
"quick :",
"quick : QUICK",
"direction : FROM",
"direction : TO",
"filter_rib_h :",
"filter_rib_h : RIB filter_rib",
"filter_rib_h : RIB '{' optnl filter_rib_l optnl '}'",
"filter_rib_l : filter_rib",
"filter_rib_l : filter_rib_l comma filter_rib",
"filter_rib : STRING",
"filter_peer_h : filter_peer",
"filter_peer_h : '{' optnl filter_peer_l optnl '}'",
"filter_peer_l : filter_peer",
"filter_peer_l : filter_peer_l comma filter_peer",
"filter_peer : ANY",
"filter_peer : address",
"filter_peer : AS as4number",
"filter_peer : GROUP STRING",
"filter_peer : EBGP",
"filter_peer : IBGP",
"filter_prefix_h : IPV4 prefixlenop",
"filter_prefix_h : IPV6 prefixlenop",
"filter_prefix_h : PREFIX filter_prefix",
"filter_prefix_h : PREFIX '{' filter_prefix_m '}'",
"filter_prefix_m : filter_prefix_l",
"filter_prefix_m : '{' filter_prefix_l '}'",
"filter_prefix_m : '{' filter_prefix_l '}' filter_prefix_m",
"filter_prefix_l : filter_prefix",
"filter_prefix_l : filter_prefix_l comma filter_prefix",
"filter_prefix : prefix prefixlenop",
"filter_as_h : filter_as_t",
"filter_as_h : '{' filter_as_t_l '}'",
"filter_as_t_l : filter_as_t",
"filter_as_t_l : filter_as_t_l comma filter_as_t",
"filter_as_t : filter_as_type filter_as",
"filter_as_t : filter_as_type '{' filter_as_l_h '}'",
"filter_as_t : filter_as_type ASSET STRING",
"filter_as_l_h : filter_as_l",
"filter_as_l_h : '{' filter_as_l '}'",
"filter_as_l_h : '{' filter_as_l '}' filter_as_l_h",
"filter_as_l : filter_as",
"filter_as_l : filter_as_l comma filter_as",
"filter_as : as4number_any",
"filter_as : NEIGHBORAS",
"filter_as : equalityop as4number_any",
"filter_as : as4number_any binaryop as4number_any",
"filter_match_h :",
"$$17 :",
"filter_match_h : $$17 filter_match",
"filter_match : filter_elm",
"filter_match : filter_match filter_elm",
"filter_elm : filter_prefix_h",
"filter_elm : filter_as_h",
"filter_elm : MAXASLEN NUMBER",
"filter_elm : MAXASSEQ NUMBER",
"filter_elm : community STRING",
"filter_elm : EXTCOMMUNITY STRING STRING",
"filter_elm : EXTCOMMUNITY OVS STRING",
"filter_elm : MAXCOMMUNITIES NUMBER",
"filter_elm : MAXEXTCOMMUNITIES NUMBER",
"filter_elm : MAXLARGECOMMUNITIES NUMBER",
"filter_elm : NEXTHOP address",
"filter_elm : NEXTHOP NEIGHBOR",
"filter_elm : PREFIXSET STRING prefixlenop",
"filter_elm : ORIGINSET STRING",
"filter_elm : OVS validity",
"filter_elm : AVS aspa_validity",
"prefixlenop :",
"prefixlenop : LONGER",
"prefixlenop : MAXLEN NUMBER",
"prefixlenop : PREFIXLEN unaryop NUMBER",
"prefixlenop : PREFIXLEN NUMBER binaryop NUMBER",
"filter_as_type : AS",
"filter_as_type : SOURCEAS",
"filter_as_type : TRANSITAS",
"filter_as_type : PEERAS",
"filter_set :",
"filter_set : SET filter_set_opt",
"filter_set : SET '{' optnl filter_set_l optnl '}'",
"filter_set_l : filter_set_l comma filter_set_opt",
"filter_set_l : filter_set_opt",
"community : COMMUNITY",
"community : LARGECOMMUNITY",
"delete :",
"delete : DELETE",
"enforce :",
"enforce : ENFORCE",
"yesnoenforce : yesno",
"yesnoenforce : ENFORCE",
"filter_set_opt : LOCALPREF NUMBER",
"filter_set_opt : LOCALPREF '+' NUMBER",
"filter_set_opt : LOCALPREF '-' NUMBER",
"filter_set_opt : MED NUMBER",
"filter_set_opt : MED '+' NUMBER",
"filter_set_opt : MED '-' NUMBER",
"filter_set_opt : METRIC NUMBER",
"filter_set_opt : METRIC '+' NUMBER",
"filter_set_opt : METRIC '-' NUMBER",
"filter_set_opt : WEIGHT NUMBER",
"filter_set_opt : WEIGHT '+' NUMBER",
"filter_set_opt : WEIGHT '-' NUMBER",
"filter_set_opt : NEXTHOP address",
"filter_set_opt : NEXTHOP BLACKHOLE",
"filter_set_opt : NEXTHOP REJECT",
"filter_set_opt : NEXTHOP NOMODIFY",
"filter_set_opt : NEXTHOP SELF",
"filter_set_opt : PREPEND_SELF NUMBER",
"filter_set_opt : PREPEND_PEER NUMBER",
"filter_set_opt : ASOVERRIDE",
"filter_set_opt : PFTABLE STRING",
"filter_set_opt : RTLABEL STRING",
"filter_set_opt : community delete STRING",
"filter_set_opt : EXTCOMMUNITY delete STRING STRING",
"filter_set_opt : EXTCOMMUNITY delete OVS STRING",
"filter_set_opt : ORIGIN origincode",
"origincode : STRING",
"validity : STRING",
"aspa_validity : STRING",
"optnl :",
"optnl : '\\n' optnl",
"comma :",
"comma : ','",
"comma : '\\n' optnl",
"comma : ',' '\\n' optnl",
"unaryop : '='",
"unaryop : NE",
"unaryop : LE",
"unaryop : '<'",
"unaryop : GE",
"unaryop : '>'",
"equalityop : '='",
"equalityop : NE",
"binaryop : '-'",
"binaryop : XRANGE",
};
#endif
#ifdef YYSTACKSIZE
#undef YYMAXDEPTH
#define YYMAXDEPTH YYSTACKSIZE
#else
#ifdef YYMAXDEPTH
#define YYSTACKSIZE YYMAXDEPTH
#else
#define YYSTACKSIZE 10000
#define YYMAXDEPTH 10000
#endif
#endif
#define YYINITSTACKSIZE 200
/* LINTUSED */
int yydebug;
int yynerrs;
int yyerrflag;
int yychar;
short *yyssp;
YYSTYPE *yyvsp;
YYSTYPE yyval;
YYSTYPE yylval;
short *yyss;
short *yysslim;
YYSTYPE *yyvs;
unsigned int yystacksize;
int yyparse(void);
#line 3554 "../../../openbgpd-portable/src/bgpd/parse.y"

struct keywords {
	const char	*k_name;
	int		 k_val;
};

int
yyerror(const char *fmt, ...)
{
	va_list		 ap;
	char		*msg;

	file->errors++;
	va_start(ap, fmt);
	if (vasprintf(&msg, fmt, ap) == -1)
		fatalx("yyerror vasprintf");
	va_end(ap);
	logit(LOG_CRIT, "%s:%d: %s", file->name, yylval.lineno, msg);
	free(msg);
	return (0);
}

int
kw_cmp(const void *k, const void *e)
{
	return (strcmp(k, ((const struct keywords *)e)->k_name));
}

int
lookup(char *s)
{
	/* this has to be sorted always */
	static const struct keywords keywords[] = {
		{ "AS",			AS },
		{ "EVPN",		EVPN },
		{ "IPv4",		IPV4 },
		{ "IPv6",		IPV6 },
		{ "add-path",		ADDPATH },
		{ "ah",			AH },
		{ "allow",		ALLOW },
		{ "announce",		ANNOUNCE },
		{ "any",		ANY },
		{ "as-4byte",		AS4BYTE },
		{ "as-override",	ASOVERRIDE },
		{ "as-set",		ASSET },
		{ "aspa-set",		ASPASET },
		{ "avs",		AVS },
		{ "blackhole",		BLACKHOLE },
		{ "community",		COMMUNITY },
		{ "compare",		COMPARE },
		{ "connect-retry",	CONNECTRETRY },
		{ "connected",		CONNECTED },
		{ "customer-as",	CUSTOMERAS },
		{ "default-route",	DEFAULTROUTE },
		{ "delete",		DELETE },
		{ "demote",		DEMOTE },
		{ "deny",		DENY },
		{ "depend",		DEPEND },
		{ "descr",		DESCR },
		{ "down",		DOWN },
		{ "dump",		DUMP },
		{ "ebgp",		EBGP },
		{ "enforce",		ENFORCE },
		{ "enhanced",		ENHANCED },
		{ "esp",		ESP },
		{ "evaluate",		EVALUATE },
		{ "expires",		EXPIRES },
		{ "export",		EXPORT },
		{ "export-target",	EXPORTTRGT },
		{ "ext-community",	EXTCOMMUNITY },
		{ "extended",		EXTENDED },
		{ "fib-priority",	FIBPRIORITY },
		{ "fib-update",		FIBUPDATE },
		{ "filtered",		FILTERED },
		{ "flags",		FLAGS },
		{ "flowspec",		FLOWSPEC },
		{ "fragment",		FRAGMENT },
		{ "from",		FROM },
		{ "graceful",		GRACEFUL },
		{ "group",		GROUP },
		{ "holdtime",		HOLDTIME },
		{ "ibgp",		IBGP },
		{ "ignore",		IGNORE },
		{ "ike",		IKE },
		{ "import-target",	IMPORTTRGT },
		{ "in",			IN },
		{ "include",		INCLUDE },
		{ "inet",		IPV4 },
		{ "inet6",		IPV6 },
		{ "ipsec",		IPSEC },
		{ "key",		KEY },
		{ "large-community",	LARGECOMMUNITY },
		{ "listen",		LISTEN },
		{ "local-address",	LOCALADDR },
		{ "local-as",		LOCALAS },
		{ "localpref",		LOCALPREF },
		{ "log",		LOG },
		{ "match",		MATCH },
		{ "max",		MAX },
		{ "max-as-len",		MAXASLEN },
		{ "max-as-seq",		MAXASSEQ },
		{ "max-communities",	MAXCOMMUNITIES },
		{ "max-ext-communities",	MAXEXTCOMMUNITIES },
		{ "max-large-communities",	MAXLARGECOMMUNITIES },
		{ "max-prefix",		MAXPREFIX },
		{ "maxlen",		MAXLEN },
		{ "md5sig",		MD5SIG },
		{ "med",		MED },
		{ "message",		MESSAGE },
		{ "metric",		METRIC },
		{ "min",		YMIN },
		{ "min-version",	MINVERSION },
		{ "multihop",		MULTIHOP },
		{ "neighbor",		NEIGHBOR },
		{ "neighbor-as",	NEIGHBORAS },
		{ "network",		NETWORK },
		{ "nexthop",		NEXTHOP },
		{ "no-modify",		NOMODIFY },
		{ "none",		NONE },
		{ "notification",	NOTIFICATION },
		{ "on",			ON },
		{ "or-longer",		LONGER },
		{ "origin",		ORIGIN },
		{ "origin-set",		ORIGINSET },
		{ "out",		OUT },
		{ "ovs",		OVS },
		{ "passive",		PASSIVE },
		{ "password",		PASSWORD },
		{ "peer-as",		PEERAS },
		{ "pftable",		PFTABLE },
		{ "plus",		PLUS },
		{ "policy",		POLICY },
		{ "port",		PORT },
		{ "prefix",		PREFIX },
		{ "prefix-set",		PREFIXSET },
		{ "prefixlen",		PREFIXLEN },
		{ "prepend-neighbor",	PREPEND_PEER },
		{ "prepend-self",	PREPEND_SELF },
		{ "priority",		PRIORITY },
		{ "proto",		PROTO },
		{ "provider-as",	PROVIDERAS },
		{ "qualify",		QUALIFY },
		{ "quick",		QUICK },
		{ "rd",			RD },
		{ "rde",		RDE },
		{ "recv",		RECV },
		{ "refresh",		REFRESH },
		{ "reject",		REJECT },
		{ "remote-as",		REMOTEAS },
		{ "restart",		RESTART },
		{ "restricted",		RESTRICTED },
		{ "rib",		RIB },
		{ "roa-set",		ROASET },
		{ "role",		ROLE },
		{ "route-reflector",	REFLECTOR },
		{ "router-id",		ROUTERID },
		{ "rtable",		RTABLE },
		{ "rtlabel",		RTLABEL },
		{ "rtr",		RTR },
		{ "self",		SELF },
		{ "send",		SEND },
		{ "set",		SET },
		{ "socket",		SOCKET },
		{ "source-as",		SOURCEAS },
		{ "spi",		SPI },
		{ "staletime",		STALETIME },
		{ "static",		STATIC },
		{ "tcp",		TCP },
		{ "to",			TO },
		{ "tos",		TOS },
		{ "transit-as",		TRANSITAS },
		{ "transparent-as",	TRANSPARENT },
		{ "ttl-security",	TTLSECURITY },
		{ "unicast",		UNICAST },
		{ "via",		VIA },
		{ "vpn",		VPN },
		{ "weight",		WEIGHT },
	};
	const struct keywords	*p;

	p = bsearch(s, keywords, nitems(keywords), sizeof(keywords[0]), kw_cmp);

	if (p)
		return (p->k_val);
	else
		return (STRING);
}

#define START_EXPAND	1
#define DONE_EXPAND	2

static int	expanding;

int
igetc(void)
{
	int	c;

	while (1) {
		if (file->ungetpos > 0)
			c = file->ungetbuf[--file->ungetpos];
		else
			c = getc(file->stream);

		if (c == START_EXPAND)
			expanding = 1;
		else if (c == DONE_EXPAND)
			expanding = 0;
		else
			break;
	}
	return (c);
}

int
lgetc(int quotec)
{
	int		c, next;

	if (quotec) {
		if ((c = igetc()) == EOF) {
			yyerror("reached end of file while parsing "
			    "quoted string");
			if (file == topfile || popfile() == EOF)
				return (EOF);
			return (quotec);
		}
		return (c);
	}

	while ((c = igetc()) == '\\') {
		next = igetc();
		if (next != '\n') {
			c = next;
			break;
		}
		yylval.lineno = file->lineno;
		file->lineno++;
	}

	if (c == EOF) {
		/*
		 * Fake EOL when hit EOF for the first time. This gets line
		 * count right if last line in included file is syntactically
		 * invalid and has no newline.
		 */
		if (file->eof_reached == 0) {
			file->eof_reached = 1;
			return ('\n');
		}
		while (c == EOF) {
			if (file == topfile || popfile() == EOF)
				return (EOF);
			c = igetc();
		}
	}
	return (c);
}

void
lungetc(int c)
{
	if (c == EOF)
		return;

	if (file->ungetpos >= file->ungetsize) {
		void *p = reallocarray(file->ungetbuf, file->ungetsize, 2);
		if (p == NULL)
			err(1, "lungetc");
		file->ungetbuf = p;
		file->ungetsize *= 2;
	}
	file->ungetbuf[file->ungetpos++] = c;
}

int
findeol(void)
{
	int	c;

	/* skip to either EOF or the first real EOL */
	while (1) {
		c = lgetc(0);
		if (c == '\n') {
			file->lineno++;
			break;
		}
		if (c == EOF)
			break;
	}
	return (ERROR);
}

int
expand_macro(void)
{
	char	 buf[MACRO_NAME_LEN];
	char	*p, *val;
	int	 c;

	p = buf;
	while (1) {
		if ((c = lgetc('$')) == EOF)
			return (ERROR);
		if (p + 1 >= buf + sizeof(buf) - 1) {
			yyerror("macro name too long");
			return (ERROR);
		}
		if (isalnum(c) || c == '_') {
			*p++ = c;
			continue;
		}
		*p = '\0';
		lungetc(c);
		break;
	}
	val = symget(buf);
	if (val == NULL) {
		yyerror("macro '%s' not defined", buf);
		return (ERROR);
	}
	p = val + strlen(val) - 1;
	lungetc(DONE_EXPAND);
	while (p >= val) {
		lungetc((unsigned char)*p);
		p--;
	}
	lungetc(START_EXPAND);
	return (0);
}

int
yylex(void)
{
	char	 buf[8096];
	char	*p;
	int	 quotec, next, c;
	int	 token;

top:
	p = buf;
	while ((c = lgetc(0)) == ' ' || c == '\t')
		; /* nothing */

	yylval.lineno = file->lineno;
	if (c == '#')
		while ((c = lgetc(0)) != '\n' && c != EOF)
			; /* nothing */
	if (c == '$' && !expanding) {
		c = expand_macro();
		if (c != 0)
			return (c);
		goto top;
	}

	switch (c) {
	case '\'':
	case '"':
		quotec = c;
		while (1) {
			if ((c = lgetc(quotec)) == EOF)
				return (0);
			if (c == '\n') {
				file->lineno++;
				continue;
			} else if (c == '\\') {
				if ((next = lgetc(quotec)) == EOF)
					return (0);
				if (next == quotec || next == ' ' ||
				    next == '\t')
					c = next;
				else if (next == '\n') {
					file->lineno++;
					continue;
				} else
					lungetc(next);
			} else if (c == quotec) {
				*p = '\0';
				break;
			} else if (c == '\0') {
				yyerror("syntax error: unterminated quote");
				return (findeol());
			}
			if (p + 1 >= buf + sizeof(buf) - 1) {
				yyerror("string too long");
				return (findeol());
			}
			*p++ = c;
		}
		yylval.v.string = strdup(buf);
		if (yylval.v.string == NULL)
			fatal("yylex: strdup");
		return (STRING);
	case '!':
		next = lgetc(0);
		if (next == '=')
			return (NE);
		lungetc(next);
		break;
	case '<':
		next = lgetc(0);
		if (next == '=')
			return (LE);
		lungetc(next);
		break;
	case '>':
		next = lgetc(0);
		if (next == '<')
			return (XRANGE);
		else if (next == '=')
			return (GE);
		lungetc(next);
		break;
	}

#define allowed_to_end_number(x) \
	(isspace(x) || x == ')' || x == ',' || x == '/' || x == '}' || x == '=')

	if (c == '-' || isdigit(c)) {
		do {
			*p++ = c;
			if ((size_t)(p-buf) >= sizeof(buf)) {
				yyerror("string too long");
				return (findeol());
			}
		} while ((c = lgetc(0)) != EOF && isdigit(c));
		lungetc(c);
		if (p == buf + 1 && buf[0] == '-')
			goto nodigits;
		if (c == EOF || allowed_to_end_number(c)) {
			const char *errstr = NULL;

			*p = '\0';
			yylval.v.number = strtonum(buf, LLONG_MIN,
			    LLONG_MAX, &errstr);
			if (errstr) {
				yyerror("\"%s\" invalid number: %s",
				    buf, errstr);
				return (findeol());
			}
			return (NUMBER);
		} else {
nodigits:
			while (p > buf + 1)
				lungetc((unsigned char)*--p);
			c = (unsigned char)*--p;
			if (c == '-')
				return (c);
		}
	}

#define allowed_in_string(x) \
	(isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
	x != '{' && x != '}' && x != '<' && x != '>' && \
	x != '!' && x != '=' && x != '/' && x != '#' && \
	x != ','))

	if (isalnum(c) || c == ':' || c == '_' || c == '*') {
		do {
			if (c == '$' && !expanding) {
				c = expand_macro();
				if (c != 0)
					return (c);
			} else
				*p++ = c;

			if ((size_t)(p-buf) >= sizeof(buf)) {
				yyerror("string too long");
				return (findeol());
			}
		} while ((c = lgetc(0)) != EOF && (allowed_in_string(c)));
		lungetc(c);
		*p = '\0';
		if ((token = lookup(buf)) == STRING)
			if ((yylval.v.string = strdup(buf)) == NULL)
				fatal("yylex: strdup");
		return (token);
	}
	if (c == '\n') {
		yylval.lineno = file->lineno;
		file->lineno++;
	}
	if (c == EOF)
		return (0);
	return (c);
}

int
check_file_secrecy(int fd, const char *fname)
{
	struct stat	st;

	if (fstat(fd, &st)) {
		log_warn("cannot stat %s", fname);
		return (-1);
	}
	return (0);
}

struct file *
pushfile(const char *name, int secret)
{
	struct file	*nfile;

	if ((nfile = calloc(1, sizeof(struct file))) == NULL) {
		log_warn("%s", __func__);
		return (NULL);
	}
	if ((nfile->name = strdup(name)) == NULL) {
		log_warn("%s", __func__);
		free(nfile);
		return (NULL);
	}
	if ((nfile->stream = fopen(nfile->name, "r")) == NULL) {
		log_warn("%s: %s", __func__, nfile->name);
		free(nfile->name);
		free(nfile);
		return (NULL);
	}
	if (secret &&
	    check_file_secrecy(fileno(nfile->stream), nfile->name)) {
		fclose(nfile->stream);
		free(nfile->name);
		free(nfile);
		return (NULL);
	}
	nfile->lineno = TAILQ_EMPTY(&files) ? 1 : 0;
	nfile->ungetsize = 16;
	nfile->ungetbuf = malloc(nfile->ungetsize);
	if (nfile->ungetbuf == NULL) {
		log_warn("%s", __func__);
		fclose(nfile->stream);
		free(nfile->name);
		free(nfile);
		return (NULL);
	}
	TAILQ_INSERT_TAIL(&files, nfile, entry);
	return (nfile);
}

int
popfile(void)
{
	struct file	*prev;

	if ((prev = TAILQ_PREV(file, files, entry)) != NULL)
		prev->errors += file->errors;

	TAILQ_REMOVE(&files, file, entry);
	fclose(file->stream);
	free(file->name);
	free(file->ungetbuf);
	free(file);
	file = prev;
	return (file ? 0 : EOF);
}

static void
init_config(struct bgpd_config *c)
{
	u_int rdomid;

	c->min_holdtime = MIN_HOLDTIME;
	c->holdtime = INTERVAL_HOLD;
	c->staletime = INTERVAL_STALE;
	c->connectretry = INTERVAL_CONNECTRETRY;
	c->bgpid = get_bgpid();
	c->fib_priority = kr_default_prio();
	c->default_tableid = getrtable();
	if (!ktable_exists(c->default_tableid, &rdomid))
		fatalx("current routing table %u does not exist",
		    c->default_tableid);
	if (rdomid != c->default_tableid)
		fatalx("current routing table %u is not a routing domain",
		    c->default_tableid);

	if (asprintf(&c->csock, "%s.%d", SOCKET_NAME, c->default_tableid) == -1)
		fatal(NULL);
}

struct bgpd_config *
parse_config(const char *filename, struct peer_head *ph,
    struct rtr_config_head *rh)
{
	struct sym		*sym, *next;
	struct rde_rib		*rr;
	struct network		*n;
	int			 errors = 0;

	conf = new_config();
	init_config(conf);

	if ((filter_l = calloc(1, sizeof(struct filter_head))) == NULL)
		fatal(NULL);
	if ((peerfilter_l = calloc(1, sizeof(struct filter_head))) == NULL)
		fatal(NULL);
	if ((groupfilter_l = calloc(1, sizeof(struct filter_head))) == NULL)
		fatal(NULL);
	TAILQ_INIT(filter_l);
	TAILQ_INIT(peerfilter_l);
	TAILQ_INIT(groupfilter_l);

	curpeer = NULL;
	curgroup = NULL;

	cur_peers = ph;
	cur_rtrs = rh;
	new_peers = &conf->peers;
	netconf = &conf->networks;

	if ((rr = add_rib("Adj-RIB-In")) == NULL)
		fatal("add_rib failed");
	rr->flags = F_RIB_NOFIB | F_RIB_NOEVALUATE;
	if ((rr = add_rib("Loc-RIB")) == NULL)
		fatal("add_rib failed");
	rib_add_fib(rr, conf->default_tableid);
	rr->flags = F_RIB_LOCAL;

	if ((file = pushfile(filename, 1)) == NULL)
		goto errors;
	topfile = file;

	yyparse();
	errors = file->errors;
	popfile();

	/* check that we dont try to announce our own routes */
	TAILQ_FOREACH(n, netconf, entry)
		if (n->net.priority == conf->fib_priority) {
			errors++;
			logit(LOG_CRIT, "network priority %d == fib-priority "
			    "%d is not allowed.",
			    n->net.priority, conf->fib_priority);
		}

	/* Free macros and check which have not been used. */
	TAILQ_FOREACH_SAFE(sym, &symhead, entry, next) {
		if ((cmd_opts & BGPD_OPT_VERBOSE2) && !sym->used)
			fprintf(stderr, "warning: macro \"%s\" not "
			    "used\n", sym->nam);
		if (!sym->persist) {
			free(sym->nam);
			free(sym->val);
			TAILQ_REMOVE(&symhead, sym, entry);
			free(sym);
		}
	}

	if (!conf->as) {
		log_warnx("configuration error: AS not given");
		errors++;
	}

	/* clear the globals */
	curpeer = NULL;
	curgroup = NULL;
	cur_peers = NULL;
	new_peers = NULL;
	netconf = NULL;
	curflow = NULL;

	if (errors) {
errors:
		while ((rr = SIMPLEQ_FIRST(&ribnames)) != NULL) {
			SIMPLEQ_REMOVE_HEAD(&ribnames, entry);
			free(rr);
		}

		filterlist_free(filter_l);
		filterlist_free(peerfilter_l);
		filterlist_free(groupfilter_l);

		free_config(conf);
		return (NULL);
	}

	/* Create default listeners if none where specified. */
	if (TAILQ_EMPTY(conf->listen_addrs)) {
		struct listen_addr *la;

		if ((la = calloc(1, sizeof(struct listen_addr))) == NULL)
			fatal("setup_listeners calloc");
		la->fd = -1;
		la->flags = DEFAULT_LISTENER;
		la->reconf = RECONF_REINIT;
		la->sa_len = sizeof(struct sockaddr_in);
		((struct sockaddr_in *)&la->sa)->sin_family = AF_INET;
		((struct sockaddr_in *)&la->sa)->sin_addr.s_addr =
		    htonl(INADDR_ANY);
		((struct sockaddr_in *)&la->sa)->sin_port = htons(BGP_PORT);
		TAILQ_INSERT_TAIL(conf->listen_addrs, la, entry);

		if ((la = calloc(1, sizeof(struct listen_addr))) == NULL)
			fatal("setup_listeners calloc");
		la->fd = -1;
		la->flags = DEFAULT_LISTENER;
		la->reconf = RECONF_REINIT;
		la->sa_len = sizeof(struct sockaddr_in6);
		((struct sockaddr_in6 *)&la->sa)->sin6_family = AF_INET6;
		((struct sockaddr_in6 *)&la->sa)->sin6_port = htons(BGP_PORT);
		TAILQ_INSERT_TAIL(conf->listen_addrs, la, entry);
	}

	/* update clusterid in case it was not set explicitly */
	if ((conf->flags & BGPD_FLAG_REFLECTOR) && conf->clusterid == 0)
		conf->clusterid = conf->bgpid;

	/*
	 * Concatenate filter list and static group and peer filtersets
	 * together. Static group sets come first then peer sets
	 * last normal filter rules.
	 */
	TAILQ_CONCAT(conf->filters, groupfilter_l, entry);
	TAILQ_CONCAT(conf->filters, peerfilter_l, entry);
	TAILQ_CONCAT(conf->filters, filter_l, entry);

	optimize_filters(conf->filters);

	free(filter_l);
	free(peerfilter_l);
	free(groupfilter_l);

	return (conf);
}

int
symset(const char *nam, const char *val, int persist)
{
	struct sym	*sym;

	TAILQ_FOREACH(sym, &symhead, entry) {
		if (strcmp(nam, sym->nam) == 0)
			break;
	}

	if (sym != NULL) {
		if (sym->persist == 1)
			return (0);
		else {
			free(sym->nam);
			free(sym->val);
			TAILQ_REMOVE(&symhead, sym, entry);
			free(sym);
		}
	}
	if ((sym = calloc(1, sizeof(*sym))) == NULL)
		return (-1);

	sym->nam = strdup(nam);
	if (sym->nam == NULL) {
		free(sym);
		return (-1);
	}
	sym->val = strdup(val);
	if (sym->val == NULL) {
		free(sym->nam);
		free(sym);
		return (-1);
	}
	sym->used = 0;
	sym->persist = persist;
	TAILQ_INSERT_TAIL(&symhead, sym, entry);
	return (0);
}

int
cmdline_symset(char *s)
{
	char	*sym, *val;
	int	ret;

	if ((val = strrchr(s, '=')) == NULL)
		return (-1);
	sym = strndup(s, val - s);
	if (sym == NULL)
		fatal("%s: strndup", __func__);
	ret = symset(sym, val + 1, 1);
	free(sym);

	return (ret);
}

char *
symget(const char *nam)
{
	struct sym	*sym;

	TAILQ_FOREACH(sym, &symhead, entry) {
		if (strcmp(nam, sym->nam) == 0) {
			sym->used = 1;
			return (sym->val);
		}
	}
	return (NULL);
}

static int
cmpcommunity(struct community *a, struct community *b)
{
	if (a->flags > b->flags)
		return 1;
	if (a->flags < b->flags)
		return -1;
	if (a->data1 > b->data1)
		return 1;
	if (a->data1 < b->data1)
		return -1;
	if (a->data2 > b->data2)
		return 1;
	if (a->data2 < b->data2)
		return -1;
	if (a->data3 > b->data3)
		return 1;
	if (a->data3 < b->data3)
		return -1;
	return 0;
}

static int
getcommunity(char *s, int large, uint32_t *val, uint32_t *flag)
{
	long long	 max = USHRT_MAX;
	const char	*errstr;

	*flag = 0;
	*val = 0;
	if (strcmp(s, "*") == 0) {
		*flag = COMMUNITY_ANY;
		return 0;
	} else if (strcmp(s, "neighbor-as") == 0) {
		*flag = COMMUNITY_NEIGHBOR_AS;
		return 0;
	} else if (strcmp(s, "local-as") == 0) {
		*flag = COMMUNITY_LOCAL_AS;
		return 0;
	}
	if (large)
		max = UINT_MAX;
	*val = strtonum(s, 0, max, &errstr);
	if (errstr) {
		yyerror("Community %s is %s (max: %lld)", s, errstr, max);
		return -1;
	}
	return 0;
}

static void
setcommunity(struct community *c, uint32_t as, uint32_t data,
    uint32_t asflag, uint32_t dataflag)
{
	c->flags = COMMUNITY_TYPE_BASIC;
	c->flags |= asflag << 8;
	c->flags |= dataflag << 16;
	c->data1 = as;
	c->data2 = data;
	c->data3 = 0;
}

static int
parselargecommunity(struct community *c, char *s)
{
	char *p, *q;
	uint32_t dflag1, dflag2, dflag3;

	if ((p = strchr(s, ':')) == NULL) {
		yyerror("Bad community syntax");
		return (-1);
	}
	*p++ = 0;

	if ((q = strchr(p, ':')) == NULL) {
		yyerror("Bad community syntax");
		return (-1);
	}
	*q++ = 0;

	if (getcommunity(s, 1, &c->data1, &dflag1) == -1 ||
	    getcommunity(p, 1, &c->data2, &dflag2) == -1 ||
	    getcommunity(q, 1, &c->data3, &dflag3) == -1)
		return (-1);
	c->flags = COMMUNITY_TYPE_LARGE;
	c->flags |= dflag1 << 8;
	c->flags |= dflag2 << 16;
	c->flags |= dflag3 << 24;
	return (0);
}

int
parsecommunity(struct community *c, int type, char *s)
{
	char *p;
	uint32_t as, data, asflag, dataflag;

	if (type == COMMUNITY_TYPE_LARGE)
		return parselargecommunity(c, s);

	/* Well-known communities */
	if (strcasecmp(s, "GRACEFUL_SHUTDOWN") == 0) {
		setcommunity(c, COMMUNITY_WELLKNOWN,
		    COMMUNITY_GRACEFUL_SHUTDOWN, 0, 0);
		return (0);
	} else if (strcasecmp(s, "NO_EXPORT") == 0) {
		setcommunity(c, COMMUNITY_WELLKNOWN,
		    COMMUNITY_NO_EXPORT, 0, 0);
		return (0);
	} else if (strcasecmp(s, "NO_ADVERTISE") == 0) {
		setcommunity(c, COMMUNITY_WELLKNOWN,
		    COMMUNITY_NO_ADVERTISE, 0, 0);
		return (0);
	} else if (strcasecmp(s, "NO_EXPORT_SUBCONFED") == 0) {
		setcommunity(c, COMMUNITY_WELLKNOWN,
		    COMMUNITY_NO_EXPSUBCONFED, 0, 0);
		return (0);
	} else if (strcasecmp(s, "NO_PEER") == 0) {
		setcommunity(c, COMMUNITY_WELLKNOWN,
		    COMMUNITY_NO_PEER, 0, 0);
		return (0);
	} else if (strcasecmp(s, "BLACKHOLE") == 0) {
		setcommunity(c, COMMUNITY_WELLKNOWN,
		    COMMUNITY_BLACKHOLE, 0, 0);
		return (0);
	}

	if ((p = strchr(s, ':')) == NULL) {
		yyerror("Bad community syntax");
		return (-1);
	}
	*p++ = 0;

	if (getcommunity(s, 0, &as, &asflag) == -1 ||
	    getcommunity(p, 0, &data, &dataflag) == -1)
		return (-1);
	setcommunity(c, as, data, asflag, dataflag);
	return (0);
}

static int
parsesubtype(char *name, int *type, int *subtype)
{
	const struct ext_comm_pairs *cp;
	int found = 0;

	for (cp = iana_ext_comms; cp->subname != NULL; cp++) {
		if (strcmp(name, cp->subname) == 0) {
			if (found == 0) {
				*type = cp->type;
				*subtype = cp->subtype;
			}
			found++;
		}
	}
	if (found > 1)
		*type = -1;
	return (found);
}

static int
parseextvalue(int type, char *s, uint32_t *v, uint32_t *flag)
{
	const char	*errstr;
	char		*p;
	struct in_addr	 ip;
	uint32_t	 uvalh, uval;

	if (type != -1) {
		/* nothing */
	} else if (strcmp(s, "neighbor-as") == 0) {
		*flag = COMMUNITY_NEIGHBOR_AS;
		*v = 0;
		return EXT_COMMUNITY_TRANS_TWO_AS;
	} else if (strcmp(s, "local-as") == 0) {
		*flag = COMMUNITY_LOCAL_AS;
		*v = 0;
		return EXT_COMMUNITY_TRANS_TWO_AS;
	} else if ((p = strchr(s, '.')) == NULL) {
		/* AS_PLAIN number (4 or 2 byte) */
		strtonum(s, 0, USHRT_MAX, &errstr);
		if (errstr == NULL)
			type = EXT_COMMUNITY_TRANS_TWO_AS;
		else
			type = EXT_COMMUNITY_TRANS_FOUR_AS;
	} else if (strchr(p + 1, '.') == NULL) {
		/* AS_DOT number (4-byte) */
		type = EXT_COMMUNITY_TRANS_FOUR_AS;
	} else {
		/* more than one dot -> IP address */
		type = EXT_COMMUNITY_TRANS_IPV4;
	}

	switch (type & EXT_COMMUNITY_VALUE) {
	case EXT_COMMUNITY_TRANS_TWO_AS:
		uval = strtonum(s, 0, USHRT_MAX, &errstr);
		if (errstr) {
			yyerror("Bad ext-community %s is %s", s, errstr);
			return (-1);
		}
		*v = uval;
		break;
	case EXT_COMMUNITY_TRANS_FOUR_AS:
		if ((p = strchr(s, '.')) == NULL) {
			uval = strtonum(s, 0, UINT_MAX, &errstr);
			if (errstr) {
				yyerror("Bad ext-community %s is %s", s,
				    errstr);
				return (-1);
			}
			*v = uval;
			break;
		}
		*p++ = '\0';
		uvalh = strtonum(s, 0, USHRT_MAX, &errstr);
		if (errstr) {
			yyerror("Bad ext-community %s is %s", s, errstr);
			return (-1);
		}
		uval = strtonum(p, 0, USHRT_MAX, &errstr);
		if (errstr) {
			yyerror("Bad ext-community %s is %s", p, errstr);
			return (-1);
		}
		*v = uval | (uvalh << 16);
		break;
	case EXT_COMMUNITY_TRANS_IPV4:
		if (inet_pton(AF_INET, s, &ip) != 1) {
			yyerror("Bad ext-community %s not parseable", s);
			return (-1);
		}
		*v = ntohl(ip.s_addr);
		break;
	default:
		fatalx("%s: unexpected type %d", __func__, type);
	}
	return (type);
}

int
parseextcommunity(struct community *c, char *t, char *s)
{
	const struct ext_comm_pairs *cp;
	char		*p, *ep;
	uint64_t	 ullval;
	uint32_t	 uval, uval2, dflag1 = 0, dflag2 = 0;
	int		 type = 0, subtype = 0;

	if (strcmp(t, "*") == 0 && strcmp(s, "*") == 0) {
		c->flags = COMMUNITY_TYPE_EXT;
		c->flags |= COMMUNITY_ANY << 24;
		return (0);
	}
	if (parsesubtype(t, &type, &subtype) == 0) {
		yyerror("Bad ext-community unknown type");
		return (-1);
	}

	switch (type) {
	case EXT_COMMUNITY_TRANS_TWO_AS:
	case EXT_COMMUNITY_TRANS_FOUR_AS:
	case EXT_COMMUNITY_TRANS_IPV4:
	case EXT_COMMUNITY_GEN_TWO_AS:
	case EXT_COMMUNITY_GEN_FOUR_AS:
	case EXT_COMMUNITY_GEN_IPV4:
	case -1:
		if (strcmp(s, "*") == 0) {
			dflag1 = COMMUNITY_ANY;
			break;
		}
		if ((p = strchr(s, ':')) == NULL) {
			yyerror("Bad ext-community %s", s);
			return (-1);
		}
		*p++ = '\0';
		if ((type = parseextvalue(type, s, &uval, &dflag1)) == -1)
			return (-1);

		switch (type) {
		case EXT_COMMUNITY_TRANS_TWO_AS:
		case EXT_COMMUNITY_GEN_TWO_AS:
			if (getcommunity(p, 1, &uval2, &dflag2) == -1)
				return (-1);
			break;
		case EXT_COMMUNITY_TRANS_IPV4:
		case EXT_COMMUNITY_TRANS_FOUR_AS:
		case EXT_COMMUNITY_GEN_IPV4:
		case EXT_COMMUNITY_GEN_FOUR_AS:
			if (getcommunity(p, 0, &uval2, &dflag2) == -1)
				return (-1);
			break;
		default:
			fatalx("parseextcommunity: unexpected result");
		}

		c->data1 = uval;
		c->data2 = uval2;
		break;
	case EXT_COMMUNITY_TRANS_OPAQUE:
	case EXT_COMMUNITY_TRANS_EVPN:
		if (strcmp(s, "*") == 0) {
			dflag1 = COMMUNITY_ANY;
			break;
		}
		errno = 0;
		ullval = strtoull(s, &ep, 0);
		if (s[0] == '\0' || *ep != '\0') {
			yyerror("Bad ext-community bad value");
			return (-1);
		}
		if (errno == ERANGE && ullval > EXT_COMMUNITY_OPAQUE_MAX) {
			yyerror("Bad ext-community value too big");
			return (-1);
		}
		c->data1 = ullval >> 32;
		c->data2 = ullval;
		break;
	case EXT_COMMUNITY_NON_TRANS_OPAQUE:
		if (subtype == EXT_COMMUNITY_SUBTYPE_OVS) {
			if (strcmp(s, "valid") == 0) {
				c->data2 = EXT_COMMUNITY_OVS_VALID;
				break;
			} else if (strcmp(s, "invalid") == 0) {
				c->data2 = EXT_COMMUNITY_OVS_INVALID;
				break;
			} else if (strcmp(s, "not-found") == 0) {
				c->data2 = EXT_COMMUNITY_OVS_NOTFOUND;
				break;
			} else if (strcmp(s, "*") == 0) {
				dflag1 = COMMUNITY_ANY;
				break;
			}
		}
		yyerror("Bad ext-community %s", s);
		return (-1);
	}

	c->data3 = type << 8 | subtype;

	/* special handling of ext-community rt * since type is not known */
	if (dflag1 == COMMUNITY_ANY && type == -1) {
		c->flags = COMMUNITY_TYPE_EXT;
		c->flags |= dflag1 << 8;
		return (0);
	}

	/* verify type/subtype combo */
	for (cp = iana_ext_comms; cp->subname != NULL; cp++) {
		if (cp->type == type && cp->subtype == subtype) {
			c->flags = COMMUNITY_TYPE_EXT;
			c->flags |= dflag1 << 8;
			c->flags |= dflag2 << 16;
			return (0);
		}
	}

	yyerror("Bad ext-community bad format for type");
	return (-1);
}

struct peer *
alloc_peer(void)
{
	struct peer	*p;

	if ((p = calloc(1, sizeof(struct peer))) == NULL)
		fatal("new_peer");

	/* some sane defaults */
	p->state = STATE_NONE;
	p->reconf_action = RECONF_REINIT;
	p->conf.distance = 1;
	p->conf.export_type = EXPORT_UNSET;
	p->conf.capabilities.refresh = 1;
	p->conf.capabilities.grestart.restart = 1;
	p->conf.capabilities.as4byte = 2;
	p->conf.capabilities.policy = 1;
	p->conf.local_as = conf->as;
	p->conf.local_short_as = conf->short_as;
	p->conf.remote_port = BGP_PORT;

	if (conf->flags & BGPD_FLAG_DECISION_TRANS_AS)
		p->conf.flags |= PEERFLAG_TRANS_AS;
	if (conf->flags & BGPD_FLAG_DECISION_ALL_PATHS)
		p->conf.flags |= PEERFLAG_EVALUATE_ALL;
	if (conf->flags & BGPD_FLAG_PERMIT_AS_SET)
		p->conf.flags |= PEERFLAG_PERMIT_AS_SET;

	return (p);
}

struct peer *
new_peer(void)
{
	struct peer		*p;

	p = alloc_peer();

	if (curgroup != NULL) {
		p->conf = curgroup->conf;
		p->auth_conf = curgroup->auth_conf;
		p->conf.groupid = curgroup->conf.id;
	}
	return (p);
}

struct peer *
new_group(void)
{
	return (alloc_peer());
}

int
add_mrtconfig(enum mrt_type type, char *name, int timeout, struct peer *p,
    char *rib)
{
	struct mrt	*m, *n;

	LIST_FOREACH(m, conf->mrt, entry) {
		if ((rib && strcmp(rib, m->rib)) ||
		    (!rib && *m->rib))
			continue;
		if (p == NULL) {
			if (m->peer_id != 0 || m->group_id != 0)
				continue;
		} else {
			if (m->peer_id != p->conf.id ||
			    m->group_id != p->conf.groupid)
				continue;
		}
		if (m->type == type) {
			yyerror("only one mrtdump per type allowed.");
			return (-1);
		}
	}

	if ((n = calloc(1, sizeof(struct mrt_config))) == NULL)
		fatal("add_mrtconfig");

	n->type = type;
	n->state = MRT_STATE_OPEN;
	if (strlcpy(MRT2MC(n)->name, name, sizeof(MRT2MC(n)->name)) >=
	    sizeof(MRT2MC(n)->name)) {
		yyerror("filename \"%s\" too long: max %zu",
		    name, sizeof(MRT2MC(n)->name) - 1);
		free(n);
		return (-1);
	}
	TAILQ_INIT(&MRT2MC(n)->timer);
	MRT2MC(n)->ReopenTimerInterval = timeout;
	if (p != NULL) {
		if (curgroup == p) {
			n->peer_id = 0;
			n->group_id = p->conf.id;
		} else {
			n->peer_id = p->conf.id;
			n->group_id = 0;
		}
	}
	if (rib) {
		if (!find_rib(rib)) {
			yyerror("rib \"%s\" does not exist.", rib);
			free(n);
			return (-1);
		}
		if (strlcpy(n->rib, rib, sizeof(n->rib)) >=
		    sizeof(n->rib)) {
			yyerror("rib name \"%s\" too long: max %zu",
			    name, sizeof(n->rib) - 1);
			free(n);
			return (-1);
		}
	}

	LIST_INSERT_HEAD(conf->mrt, n, entry);

	return (0);
}

struct rde_rib *
add_rib(char *name)
{
	struct rde_rib	*rr;

	if ((rr = find_rib(name)) == NULL) {
		if ((rr = calloc(1, sizeof(*rr))) == NULL) {
			log_warn("add_rib");
			return (NULL);
		}
		if (strlcpy(rr->name, name, sizeof(rr->name)) >=
		    sizeof(rr->name)) {
			yyerror("rib name \"%s\" too long: max %zu",
			    name, sizeof(rr->name) - 1);
			free(rr);
			return (NULL);
		}
		rr->flags = F_RIB_NOFIB;
		SIMPLEQ_INSERT_TAIL(&ribnames, rr, entry);
	}
	return (rr);
}

struct rde_rib *
find_rib(char *name)
{
	struct rde_rib	*rr;

	SIMPLEQ_FOREACH(rr, &ribnames, entry) {
		if (!strcmp(rr->name, name))
			return (rr);
	}
	return (NULL);
}

int
rib_add_fib(struct rde_rib *rr, u_int rtableid)
{
	u_int	rdom;

	if (!ktable_exists(rtableid, &rdom)) {
		yyerror("rtable id %u does not exist", rtableid);
		return (-1);
	}
	/*
	 * conf->default_tableid is also a rdomain because that is checked
	 * in init_config()
	 */
	if (rdom != conf->default_tableid) {
		log_warnx("rtable %u does not belong to rdomain %u",
		    rtableid, conf->default_tableid);
		return (-1);
	}
	rr->rtableid = rtableid;
	rr->flags &= ~F_RIB_NOFIB;
	return (0);
}

struct prefixset *
find_prefixset(char *name, struct prefixset_head *p)
{
	struct prefixset *ps;

	SIMPLEQ_FOREACH(ps, p, entry) {
		if (!strcmp(ps->name, name))
			return (ps);
	}
	return (NULL);
}

int
get_id(struct peer *newpeer)
{
	static uint32_t id = PEER_ID_STATIC_MIN;
	struct peer	*p = NULL;

	/* check if the peer already existed before */
	if (newpeer->conf.remote_addr.aid) {
		/* neighbor */
		if (cur_peers)
			RB_FOREACH(p, peer_head, cur_peers)
				if (p->conf.remote_masklen ==
				    newpeer->conf.remote_masklen &&
				    memcmp(&p->conf.remote_addr,
				    &newpeer->conf.remote_addr,
				    sizeof(p->conf.remote_addr)) == 0)
					break;
		if (p) {
			newpeer->conf.id = p->conf.id;
			return (0);
		}
	} else {
		/* group */
		if (cur_peers)
			RB_FOREACH(p, peer_head, cur_peers)
				if (strcmp(p->conf.group,
				    newpeer->conf.group) == 0)
					break;
		if (p) {
			newpeer->conf.id = p->conf.groupid;
			return (0);
		}
	}

	/* else new one */
	if (id < PEER_ID_STATIC_MAX) {
		newpeer->conf.id = id++;
		return (0);
	}

	return (-1);
}

int
merge_prefixspec(struct filter_prefix *p, struct filter_prefixlen *pl)
{
	uint8_t max_len = 0;

	switch (p->addr.aid) {
	case AID_INET:
	case AID_VPN_IPv4:
		max_len = 32;
		break;
	case AID_INET6:
	case AID_VPN_IPv6:
		max_len = 128;
		break;
	}

	if (pl->op == OP_NONE) {
		p->len_min = p->len_max = p->len;
		return (0);
	}

	if (pl->len_min == -1)
		pl->len_min = p->len;
	if (pl->len_max == -1)
		pl->len_max = max_len;

	if (pl->len_max > max_len) {
		yyerror("prefixlen %d too big, limit %d",
		    pl->len_max, max_len);
		return (-1);
	}
	if (pl->len_min > pl->len_max) {
		yyerror("prefixlen %d too big, limit %d",
		    pl->len_min, pl->len_max);
		return (-1);
	}
	if (pl->len_min < p->len) {
		yyerror("prefixlen %d smaller than prefix, limit %d",
		    pl->len_min, p->len);
		return (-1);
	}

	p->op = pl->op;
	p->len_min = pl->len_min;
	p->len_max = pl->len_max;
	return (0);
}

int
expand_rule(struct filter_rule *rule, struct filter_rib_l *rib,
    struct filter_peers_l *peer, struct filter_match_l *match,
    struct filter_set_head *set)
{
	struct filter_rule	*r;
	struct filter_rib_l	*rb, *rbnext;
	struct filter_peers_l	*p, *pnext;
	struct filter_prefix_l	*prefix, *prefix_next;
	struct filter_as_l	*a, *anext;
	struct filter_set	*s;

	rb = rib;
	do {
		p = peer;
		do {
			a = match->as_l;
			do {
				prefix = match->prefix_l;
				do {
					if ((r = calloc(1,
					    sizeof(struct filter_rule))) ==
						 NULL) {
						log_warn("expand_rule");
						return (-1);
					}

					memcpy(r, rule, sizeof(*r));
					memcpy(&r->match, match,
					    sizeof(struct filter_match));
					filterset_copy(set, &r->set);

					if (rb != NULL)
						strlcpy(r->rib, rb->name,
						    sizeof(r->rib));

					if (p != NULL)
						memcpy(&r->peer, &p->p,
						    sizeof(r->peer));

					if (prefix != NULL)
						memcpy(&r->match.prefix,
						    &prefix->p,
						    sizeof(r->match.prefix));

					if (a != NULL)
						memcpy(&r->match.as, &a->a,
						    sizeof(struct filter_as));

					TAILQ_INSERT_TAIL(filter_l, r, entry);

					if (prefix != NULL)
						prefix = prefix->next;
				} while (prefix != NULL);

				if (a != NULL)
					a = a->next;
			} while (a != NULL);

			if (p != NULL)
				p = p->next;
		} while (p != NULL);

		if (rb != NULL)
			rb = rb->next;
	} while (rb != NULL);

	for (rb = rib; rb != NULL; rb = rbnext) {
		rbnext = rb->next;
		free(rb);
	}

	for (p = peer; p != NULL; p = pnext) {
		pnext = p->next;
		free(p);
	}

	for (a = match->as_l; a != NULL; a = anext) {
		anext = a->next;
		free(a);
	}

	for (prefix = match->prefix_l; prefix != NULL; prefix = prefix_next) {
		prefix_next = prefix->next;
		free(prefix);
	}

	if (set != NULL) {
		while ((s = TAILQ_FIRST(set)) != NULL) {
			TAILQ_REMOVE(set, s, entry);
			free(s);
		}
		free(set);
	}

	return (0);
}

static int
h2i(char c)
{
	if (c >= '0' && c <= '9')
		return c - '0';
	else if (c >= 'a' && c <= 'f')
		return c - 'a' + 10;
	else if (c >= 'A' && c <= 'F')
		return c - 'A' + 10;
	else
		return -1;
}

int
str2key(char *s, char *dest, size_t max_len)
{
	size_t	i;

	if (strlen(s) / 2 > max_len) {
		yyerror("key too long");
		return (-1);
	}

	if (strlen(s) % 2) {
		yyerror("key must be of even length");
		return (-1);
	}

	for (i = 0; i < strlen(s) / 2; i++) {
		int hi, lo;

		hi = h2i(s[2 * i]);
		lo = h2i(s[2 * i + 1]);
		if (hi == -1 || lo == -1) {
			yyerror("key must be specified in hex");
			return (-1);
		}
		dest[i] = (hi << 4) | lo;
	}

	return (0);
}

int
neighbor_consistent(struct peer *p)
{
	struct bgpd_addr *local_addr;
	struct peer *xp;

	switch (p->conf.remote_addr.aid) {
	case AID_INET:
		local_addr = &p->conf.local_addr_v4;
		break;
	case AID_INET6:
		local_addr = &p->conf.local_addr_v6;
		break;
	default:
		yyerror("Bad address family for remote-addr");
		return (-1);
	}

	/* with any form of ipsec local-address is required */
	if ((p->auth_conf.method == AUTH_IPSEC_IKE_ESP ||
	    p->auth_conf.method == AUTH_IPSEC_IKE_AH ||
	    p->auth_conf.method == AUTH_IPSEC_MANUAL_ESP ||
	    p->auth_conf.method == AUTH_IPSEC_MANUAL_AH) &&
	    local_addr->aid == AID_UNSPEC) {
		yyerror("neighbors with any form of IPsec configured "
		    "need local-address to be specified");
		return (-1);
	}

	/* with static keying we need both directions */
	if ((p->auth_conf.method == AUTH_IPSEC_MANUAL_ESP ||
	    p->auth_conf.method == AUTH_IPSEC_MANUAL_AH) &&
	    (!p->auth_conf.spi_in || !p->auth_conf.spi_out)) {
		yyerror("with manual keyed IPsec, SPIs and keys "
		    "for both directions are required");
		return (-1);
	}

	if (!conf->as) {
		yyerror("AS needs to be given before neighbor definitions");
		return (-1);
	}

	/* set default values if they where undefined */
	p->conf.ebgp = (p->conf.remote_as != conf->as);
	if (p->conf.enforce_as == ENFORCE_AS_UNDEF)
		p->conf.enforce_as = p->conf.ebgp ?
		    ENFORCE_AS_ON : ENFORCE_AS_OFF;
	if (p->conf.enforce_local_as == ENFORCE_AS_UNDEF)
		p->conf.enforce_local_as = ENFORCE_AS_ON;

	if (p->conf.remote_as == 0 && !p->conf.template) {
		yyerror("peer AS may not be zero");
		return (-1);
	}

	/* EBGP neighbors are not allowed in route reflector clusters */
	if (p->conf.reflector_client && p->conf.ebgp) {
		yyerror("EBGP neighbors are not allowed in route "
		    "reflector clusters");
		return (-1);
	}

	/* BGP role and RFC 9234 role are only valid for EBGP neighbors */
	if (!p->conf.ebgp) {
		p->conf.role = ROLE_NONE;
		p->conf.capabilities.policy = 0;
	} else if (p->conf.role == ROLE_NONE) {
		/* no role, no policy capability */
		p->conf.capabilities.policy = 0;
	}

	/* check for duplicate peer definitions */
	RB_FOREACH(xp, peer_head, new_peers)
		if (xp->conf.remote_masklen ==
		    p->conf.remote_masklen &&
		    memcmp(&xp->conf.remote_addr,
		    &p->conf.remote_addr,
		    sizeof(p->conf.remote_addr)) == 0)
			break;
	if (xp != NULL) {
		char *descr = log_fmt_peer(&p->conf);
		yyerror("duplicate %s", descr);
		free(descr);
		return (-1);
	}

	return (0);
}

static void
filterset_add(struct filter_set_head *sh, struct filter_set *s)
{
	struct filter_set	*t;

	TAILQ_FOREACH(t, sh, entry) {
		if (s->type < t->type) {
			TAILQ_INSERT_BEFORE(t, s, entry);
			return;
		}
		if (s->type == t->type) {
			switch (s->type) {
			case ACTION_SET_COMMUNITY:
			case ACTION_DEL_COMMUNITY:
				switch (cmpcommunity(&s->action.community,
				    &t->action.community)) {
				case -1:
					TAILQ_INSERT_BEFORE(t, s, entry);
					return;
				case 0:
					break;
				case 1:
					continue;
				}
				break;
			case ACTION_SET_NEXTHOP:
				/* only last nexthop per AF matters */
				if (s->action.nexthop.aid <
				    t->action.nexthop.aid) {
					TAILQ_INSERT_BEFORE(t, s, entry);
					return;
				} else if (s->action.nexthop.aid ==
				    t->action.nexthop.aid) {
					t->action.nexthop = s->action.nexthop;
					break;
				}
				continue;
			case ACTION_SET_NEXTHOP_BLACKHOLE:
			case ACTION_SET_NEXTHOP_REJECT:
			case ACTION_SET_NEXTHOP_NOMODIFY:
			case ACTION_SET_NEXTHOP_SELF:
				/* set it only once */
				break;
			case ACTION_SET_LOCALPREF:
			case ACTION_SET_MED:
			case ACTION_SET_WEIGHT:
				/* only last set matters */
				t->action.metric = s->action.metric;
				break;
			case ACTION_SET_RELATIVE_LOCALPREF:
			case ACTION_SET_RELATIVE_MED:
			case ACTION_SET_RELATIVE_WEIGHT:
				/* sum all relative numbers */
				t->action.relative += s->action.relative;
				break;
			case ACTION_SET_ORIGIN:
				/* only last set matters */
				t->action.origin = s->action.origin;
				break;
			case ACTION_PFTABLE:
				/* only last set matters */
				strlcpy(t->action.pftable, s->action.pftable,
				    sizeof(t->action.pftable));
				break;
			case ACTION_RTLABEL:
				/* only last set matters */
				strlcpy(t->action.rtlabel, s->action.rtlabel,
				    sizeof(t->action.rtlabel));
				break;
			default:
				break;
			}
			free(s);
			return;
		}
	}

	TAILQ_INSERT_TAIL(sh, s, entry);
}

int
merge_filterset(struct filter_set_head *sh, struct filter_set *s)
{
	struct filter_set	*t;

	TAILQ_FOREACH(t, sh, entry) {
		/*
		 * need to cycle across the full list because even
		 * if types are not equal filterset_cmp() may return 0.
		 */
		if (filterset_cmp(s, t) == 0) {
			if (s->type == ACTION_SET_COMMUNITY)
				yyerror("community is already set");
			else if (s->type == ACTION_DEL_COMMUNITY)
				yyerror("community will already be deleted");
			else
				yyerror("redefining set parameter %s",
				    filterset_name(s->type));
			return (-1);
		}
	}

	filterset_add(sh, s);
	return (0);
}

static int
filter_equal(struct filter_rule *fa, struct filter_rule *fb)
{
	if (fa == NULL || fb == NULL)
		return 0;
	if (fa->action != fb->action || fa->quick != fb->quick ||
	    fa->dir != fb->dir)
		return 0;
	if (memcmp(&fa->peer, &fb->peer, sizeof(fa->peer)))
		return 0;
	if (memcmp(&fa->match, &fb->match, sizeof(fa->match)))
		return 0;

	return 1;
}

/* do a basic optimization by folding equal rules together */
void
optimize_filters(struct filter_head *fh)
{
	struct filter_rule *r, *nr;

	TAILQ_FOREACH_SAFE(r, fh, entry, nr) {
		while (filter_equal(r, nr)) {
			struct filter_set	*t;

			while ((t = TAILQ_FIRST(&nr->set)) != NULL) {
				TAILQ_REMOVE(&nr->set, t, entry);
				filterset_add(&r->set, t);
			}

			TAILQ_REMOVE(fh, nr, entry);
			free(nr);
			nr = TAILQ_NEXT(r, entry);
		}
	}
}

struct filter_rule *
get_rule(enum action_types type)
{
	struct filter_rule	*r;
	int			 out;

	switch (type) {
	case ACTION_SET_PREPEND_SELF:
	case ACTION_SET_NEXTHOP_NOMODIFY:
	case ACTION_SET_NEXTHOP_SELF:
		out = 1;
		break;
	default:
		out = 0;
		break;
	}
	r = (curpeer == curgroup) ? curgroup_filter[out] : curpeer_filter[out];
	if (r == NULL) {
		if ((r = calloc(1, sizeof(struct filter_rule))) == NULL)
			fatal(NULL);
		r->quick = 0;
		r->dir = out ? DIR_OUT : DIR_IN;
		r->action = ACTION_NONE;
		TAILQ_INIT(&r->set);
		if (curpeer == curgroup) {
			/* group */
			r->peer.groupid = curgroup->conf.id;
			curgroup_filter[out] = r;
		} else {
			/* peer */
			r->peer.peerid = curpeer->conf.id;
			curpeer_filter[out] = r;
		}
	}
	return (r);
}

struct set_table *curset;
static int
new_as_set(char *name)
{
	struct as_set *aset;

	if (as_sets_lookup(&conf->as_sets, name) != NULL) {
		yyerror("as-set \"%s\" already exists", name);
		return -1;
	}

	aset = as_sets_new(&conf->as_sets, name, 0, sizeof(uint32_t));
	if (aset == NULL)
		fatal(NULL);

	curset = aset->set;
	return 0;
}

static void
add_as_set(uint32_t as)
{
	if (curset == NULL)
		fatalx("%s: bad mojo jojo", __func__);

	if (set_add(curset, &as, 1) != 0)
		fatal(NULL);
}

static void
done_as_set(void)
{
	curset = NULL;
}

static struct prefixset *
new_prefix_set(char *name, int is_roa)
{
	const char *type = "prefix-set";
	struct prefixset_head *sets = &conf->prefixsets;
	struct prefixset *pset;

	if (is_roa) {
		type = "origin-set";
		sets = &conf->originsets;
	}

	if (find_prefixset(name, sets) != NULL) {
		yyerror("%s \"%s\" already exists", type, name);
		return NULL;
	}
	if ((pset = calloc(1, sizeof(*pset))) == NULL)
		fatal("prefixset");
	if (strlcpy(pset->name, name, sizeof(pset->name)) >=
	    sizeof(pset->name)) {
		yyerror("%s \"%s\" too long: max %zu", type,
		    name, sizeof(pset->name) - 1);
		free(pset);
		return NULL;
	}
	RB_INIT(&pset->psitems);
	RB_INIT(&pset->roaitems);
	return pset;
}

static void
add_roa_set(struct prefixset_item *npsi, uint32_t as, uint8_t max,
    time_t expires)
{
	struct roa *roa, *r;

	if ((roa = calloc(1, sizeof(*roa))) == NULL)
		fatal("add_roa_set");

	roa->aid = npsi->p.addr.aid;
	roa->prefixlen = npsi->p.len;
	roa->maxlen = max;
	roa->asnum = as;
	roa->expires = expires;
	switch (roa->aid) {
	case AID_INET:
		roa->prefix.inet = npsi->p.addr.v4;
		break;
	case AID_INET6:
		roa->prefix.inet6 = npsi->p.addr.v6;
		break;
	default:
		fatalx("Bad address family for roa_set address");
	}

	r = RB_INSERT(roa_tree, curroatree, roa);
	if (r != NULL) {
		/* just ignore duplicates */
		if (r->expires != 0 && expires != 0 && expires > r->expires)
			r->expires = expires;
		free(roa);
	}
}

static struct rtr_config *
get_rtr(struct bgpd_addr *addr)
{
	struct rtr_config *n;

	n = calloc(1, sizeof(*n));
	if (n == NULL) {
		yyerror("out of memory");
		return NULL;
	}

	n->remote_addr = *addr;
	strlcpy(n->descr, log_addr(addr), sizeof(currtr->descr));

	return n;
}

static int
insert_rtr(struct rtr_config *new)
{
	static uint32_t id;
	struct rtr_config *r;

	if (id == UINT32_MAX) {
		yyerror("out of rtr session IDs");
		return -1;
	}

	SIMPLEQ_FOREACH(r, &conf->rtrs, entry)
		if (memcmp(&r->remote_addr, &new->remote_addr,
		    sizeof(r->remote_addr)) == 0 &&
		    r->remote_port == new->remote_port) {
			yyerror("duplicate rtr session to %s:%u",
			    log_addr(&new->remote_addr), new->remote_port);
			return -1;
		}

	if (cur_rtrs)
		SIMPLEQ_FOREACH(r, cur_rtrs, entry)
			if (memcmp(&r->remote_addr, &new->remote_addr,
			    sizeof(r->remote_addr)) == 0 &&
			    r->remote_port == new->remote_port) {
				new->id = r->id;
				break;
			}

	if (new->id == 0)
		new->id = ++id;

	SIMPLEQ_INSERT_TAIL(&conf->rtrs, new, entry);

	return 0;
}

static int
merge_aspa_set(uint32_t as, struct aspa_tas_l *tas, time_t expires)
{
	struct aspa_set	*aspa, needle = { .as = as };
	uint32_t i, num, *newtas;

	aspa = RB_FIND(aspa_tree, &conf->aspa, &needle);
	if (aspa == NULL) {
		if ((aspa = calloc(1, sizeof(*aspa))) == NULL) {
			yyerror("out of memory");
			return -1;
		}
		aspa->as = as;
		aspa->expires = expires;
		RB_INSERT(aspa_tree, &conf->aspa, aspa);
	}

	if (tas->num > MAX_ASPA_SPAS_COUNT - aspa->num) {
		yyerror("too many providers for customer-as %u", as);
		return -1;
	}
	num = aspa->num + tas->num;
	newtas = recallocarray(aspa->tas, aspa->num, num, sizeof(uint32_t));
	if (newtas == NULL) {
		yyerror("out of memory");
		return -1;
	}
	/* fill starting at the end since the tas list is reversed */
	if (num > 0) {
		for (i = num - 1; tas; tas = tas->next, i--)
			newtas[i] = tas->as;
	}

	aspa->num = num;
	aspa->tas = newtas;

	/* take the longest expiry time, same logic as for ROA entries */
	if (aspa->expires != 0 && expires != 0 && expires > aspa->expires)
		aspa->expires = expires;

	return 0;
}

static int
kw_casecmp(const void *k, const void *e)
{
	return (strcasecmp(k, ((const struct keywords *)e)->k_name));
}

static int
map_tos(char *s, int *val)
{
	/* DiffServ Codepoints and other TOS mappings */
	const struct keywords	 toswords[] = {
		{ "af11",		IPTOS_DSCP_AF11 },
		{ "af12",		IPTOS_DSCP_AF12 },
		{ "af13",		IPTOS_DSCP_AF13 },
		{ "af21",		IPTOS_DSCP_AF21 },
		{ "af22",		IPTOS_DSCP_AF22 },
		{ "af23",		IPTOS_DSCP_AF23 },
		{ "af31",		IPTOS_DSCP_AF31 },
		{ "af32",		IPTOS_DSCP_AF32 },
		{ "af33",		IPTOS_DSCP_AF33 },
		{ "af41",		IPTOS_DSCP_AF41 },
		{ "af42",		IPTOS_DSCP_AF42 },
		{ "af43",		IPTOS_DSCP_AF43 },
		{ "critical",		IPTOS_PREC_CRITIC_ECP },
		{ "cs0",		IPTOS_DSCP_CS0 },
		{ "cs1",		IPTOS_DSCP_CS1 },
		{ "cs2",		IPTOS_DSCP_CS2 },
		{ "cs3",		IPTOS_DSCP_CS3 },
		{ "cs4",		IPTOS_DSCP_CS4 },
		{ "cs5",		IPTOS_DSCP_CS5 },
		{ "cs6",		IPTOS_DSCP_CS6 },
		{ "cs7",		IPTOS_DSCP_CS7 },
		{ "ef",			IPTOS_DSCP_EF },
		{ "inetcontrol",	IPTOS_PREC_INTERNETCONTROL },
		{ "lowdelay",		IPTOS_LOWDELAY },
		{ "netcontrol",		IPTOS_PREC_NETCONTROL },
		{ "reliability",	IPTOS_RELIABILITY },
		{ "throughput",		IPTOS_THROUGHPUT },
		{ "va",			IPTOS_DSCP_VA },
	};
	const struct keywords	*p;

	p = bsearch(s, toswords, nitems(toswords), sizeof(toswords[0]),
	    kw_casecmp);

	if (p) {
		*val = p->k_val;
		return (1);
	}
	return (0);
}

static int
getservice(char *n)
{
	struct servent	*s;

	s = getservbyname(n, "tcp");
	if (s == NULL)
		s = getservbyname(n, "udp");
	if (s == NULL)
		return -1;
	return ntohs(s->s_port);
}

static int
parse_flags(char *s)
{
	const char *flags = FLOWSPEC_TCP_FLAG_STRING;
	char *p, *q;
	uint8_t f = 0;

	if (curflow->type == FLOWSPEC_TYPE_FRAG) {
		if (curflow->aid == AID_INET)
			flags = FLOWSPEC_FRAG_STRING4;
		else
			flags = FLOWSPEC_FRAG_STRING6;
	}

	for (p = s; *p; p++) {
		if ((q = strchr(flags, *p)) == NULL)
			return -1;
		f |= 1 << (q - flags);
	}
	return (f ? f : 0xff);
}

static void
component_finish(int type, uint8_t *data, int len)
{
	uint8_t *last;
	int i;

	switch (type) {
	case FLOWSPEC_TYPE_DEST:
	case FLOWSPEC_TYPE_SOURCE:
		/* nothing to do */
		return;
	default:
		break;
	}

	i = 0;
	do {
		last = data + i;
		i += FLOWSPEC_OP_LEN(*last) + 1;
	} while (i < len);
	*last |= FLOWSPEC_OP_EOL;
}

static struct flowspec_config *
flow_to_flowspec(struct flowspec_context *ctx)
{
	struct flowspec_config *f;
	int i, len = 0;
	uint8_t aid;

	switch (ctx->aid) {
	case AID_INET:
		aid = AID_FLOWSPECv4;
		break;
	case AID_INET6:
		aid = AID_FLOWSPECv6;
		break;
	default:
		yyerror("unknown AID %d", ctx->aid);
		return NULL;
	}

	for (i = FLOWSPEC_TYPE_MIN; i < FLOWSPEC_TYPE_MAX; i++)
		if (ctx->components[i] != NULL)
			len += ctx->complen[i] + 1;

	if (len > FLOWSPEC_SIZE_MAX) {
		yyerror("flowspec too long %d > %d", len, FLOWSPEC_SIZE_MAX);
		return NULL;
	}

	f = flowspec_alloc(aid, len);
	if (f == NULL) {
		yyerror("out of memory");
		return NULL;
	}

	len = 0;
	for (i = FLOWSPEC_TYPE_MIN; i < FLOWSPEC_TYPE_MAX; i++)
		if (ctx->components[i] != NULL) {
			f->flow->data[len++] = i;
			component_finish(i, ctx->components[i],
			    ctx->complen[i]);
			memcpy(f->flow->data + len, ctx->components[i],
			    ctx->complen[i]);
			len += ctx->complen[i];
		}

	return f;
}

static void
flow_free(struct flowspec_context *ctx)
{
	int i;

	for (i = 0; i < FLOWSPEC_TYPE_MAX; i++)
		free(ctx->components[i]);
	free(ctx);
}

static int
push_prefix(struct bgpd_addr *addr, uint8_t len)
{
	void *data;
	uint8_t *comp;
	int complen, l;

	if (curflow->components[curflow->addr_type] != NULL) {
		yyerror("flowspec address already set");
		return -1;
	}

	if (curflow->aid != addr->aid) {
		yyerror("wrong address family for flowspec address");
		return -1;
	}

	switch (curflow->aid) {
	case AID_INET:
		complen = PREFIX_SIZE(len);
		data = &addr->v4;
		break;
	case AID_INET6:
		/* IPv6 includes an offset byte */
		complen = PREFIX_SIZE(len) + 1;
		data = &addr->v6;
		break;
	default:
		yyerror("unsupported address family for flowspec address");
		return -1;
	}
	comp = malloc(complen);
	if (comp == NULL) {
		yyerror("out of memory");
		return -1;
	}

	l = 0;
	comp[l++] = len;
	if (curflow->aid == AID_INET6)
		comp[l++] = 0;
	memcpy(comp + l, data, complen - l);

	curflow->complen[curflow->addr_type] = complen;
	curflow->components[curflow->addr_type] = comp;

	return 0;
}

static int
push_binop(uint8_t binop, long long val)
{
	uint8_t *comp;
	int complen;
	uint8_t u8;

	if (val < 0 || val > 0xff) {
		yyerror("unsupported value for flowspec bin_op");
		return -1;
	}
	u8 = val;

	complen = curflow->complen[curflow->type];
	comp = realloc(curflow->components[curflow->type],
	    complen + 2);
	if (comp == NULL) {
		yyerror("out of memory");
		return -1;
	}

	comp[complen++] = binop;
	comp[complen++] = u8;
	curflow->complen[curflow->type] = complen;
	curflow->components[curflow->type] = comp;

	return 0;
}

static uint8_t
component_numop(enum comp_ops op, int and, int len)
{
	uint8_t flag = 0;

	switch (op) {
	case OP_EQ:
		flag |= FLOWSPEC_OP_NUM_EQ;
		break;
	case OP_NE:
		flag |= FLOWSPEC_OP_NUM_NOT;
		break;
	case OP_LE:
		flag |= FLOWSPEC_OP_NUM_LE;
		break;
	case OP_LT:
		flag |= FLOWSPEC_OP_NUM_LT;
		break;
	case OP_GE:
		flag |= FLOWSPEC_OP_NUM_GE;
		break;
	case OP_GT:
		flag |= FLOWSPEC_OP_NUM_GT;
		break;
	default:
		fatalx("unsupported op");
	}

	switch (len) {
	case 2:
		flag |= 1 << FLOWSPEC_OP_LEN_SHIFT;
		break;
	case 4:
		flag |= 2 << FLOWSPEC_OP_LEN_SHIFT;
		break;
	case 8:
		flag |= 3 << FLOWSPEC_OP_LEN_SHIFT;
		break;
	}

	if (and)
		flag |= FLOWSPEC_OP_AND;

	return flag;
}

static int
push_numop(enum comp_ops op, int and, long long val)
{
	uint8_t *comp;
	void *data;
	uint32_t u32;
	uint16_t u16;
	uint8_t u8;
	int len, complen;

	if (val < 0 || val > 0xffffffff) {
		yyerror("unsupported value for flowspec num_op");
		return -1;
	} else if (val <= 255) {
		len = 1;
		u8 = val;
		data = &u8;
	} else if (val <= 0xffff) {
		len = 2;
		u16 = htons(val);
		data = &u16;
	} else {
		len = 4;
		u32 = htonl(val);
		data = &u32;
	}

	complen = curflow->complen[curflow->type];
	comp = realloc(curflow->components[curflow->type],
	    complen + len + 1);
	if (comp == NULL) {
		yyerror("out of memory");
		return -1;
	}

	comp[complen++] = component_numop(op, and, len);
	memcpy(comp + complen, data, len);
	complen += len;
	curflow->complen[curflow->type] = complen;
	curflow->components[curflow->type] = comp;

	return 0;
}

static int
push_unary_numop(enum comp_ops op, long long val)
{
	return push_numop(op, 0, val);
}

static int
push_binary_numop(enum comp_ops op, long long min, long long max)
{
	switch (op) {
	case OP_RANGE:
		if (push_numop(OP_GE, 0, min) == -1)
			return -1;
		return push_numop(OP_LE, 1, max);
	case OP_XRANGE:
		if (push_numop(OP_LT, 0, min) == -1)
			return -1;
		return push_numop(OP_GT, 0, max);
	default:
		yyerror("unsupported binary flowspec num_op");
		return -1;
	}
}

struct icmptypeent {
	const char *name;
	uint8_t type;
};

struct icmpcodeent {
	const char *name;
	uint8_t type;
	uint8_t code;
};

static const struct icmptypeent icmp_type[] = {
	{ "echoreq",	ICMP_ECHO },
	{ "echorep",	ICMP_ECHOREPLY },
	{ "unreach",	ICMP_UNREACH },
	{ "squench",	ICMP_SOURCEQUENCH },
	{ "redir",	ICMP_REDIRECT },
	{ "althost",	ICMP_ALTHOSTADDR },
	{ "routeradv",	ICMP_ROUTERADVERT },
	{ "routersol",	ICMP_ROUTERSOLICIT },
	{ "timex",	ICMP_TIMXCEED },
	{ "paramprob",	ICMP_PARAMPROB },
	{ "timereq",	ICMP_TSTAMP },
	{ "timerep",	ICMP_TSTAMPREPLY },
	{ "inforeq",	ICMP_IREQ },
	{ "inforep",	ICMP_IREQREPLY },
	{ "maskreq",	ICMP_MASKREQ },
	{ "maskrep",	ICMP_MASKREPLY },
	{ "trace",	ICMP_TRACEROUTE },
	{ "dataconv",	ICMP_DATACONVERR },
	{ "mobredir",	ICMP_MOBILE_REDIRECT },
	{ "ipv6-where",	ICMP_IPV6_WHEREAREYOU },
	{ "ipv6-here",	ICMP_IPV6_IAMHERE },
	{ "mobregreq",	ICMP_MOBILE_REGREQUEST },
	{ "mobregrep",	ICMP_MOBILE_REGREPLY },
	{ "skip",	ICMP_SKIP },
	{ "photuris",	ICMP_PHOTURIS },
};

static const struct icmptypeent icmp6_type[] = {
	{ "unreach",	ICMP6_DST_UNREACH },
	{ "toobig",	ICMP6_PACKET_TOO_BIG },
	{ "timex",	ICMP6_TIME_EXCEEDED },
	{ "paramprob",	ICMP6_PARAM_PROB },
	{ "echoreq",	ICMP6_ECHO_REQUEST },
	{ "echorep",	ICMP6_ECHO_REPLY },
	{ "groupqry",	ICMP6_MEMBERSHIP_QUERY },
	{ "listqry",	MLD_LISTENER_QUERY },
	{ "grouprep",	ICMP6_MEMBERSHIP_REPORT },
	{ "listenrep",	MLD_LISTENER_REPORT },
	{ "groupterm",	ICMP6_MEMBERSHIP_REDUCTION },
	{ "listendone", MLD_LISTENER_DONE },
	{ "routersol",	ND_ROUTER_SOLICIT },
	{ "routeradv",	ND_ROUTER_ADVERT },
	{ "neighbrsol", ND_NEIGHBOR_SOLICIT },
	{ "neighbradv", ND_NEIGHBOR_ADVERT },
	{ "redir",	ND_REDIRECT },
	{ "routrrenum", ICMP6_ROUTER_RENUMBERING },
	{ "wrureq",	ICMP6_WRUREQUEST },
	{ "wrurep",	ICMP6_WRUREPLY },
	{ "fqdnreq",	ICMP6_FQDN_QUERY },
	{ "fqdnrep",	ICMP6_FQDN_REPLY },
	{ "niqry",	ICMP6_NI_QUERY },
	{ "nirep",	ICMP6_NI_REPLY },
	{ "mtraceresp",	MLD_MTRACE_RESP },
	{ "mtrace",	MLD_MTRACE },
	{ "listenrepv2", MLDV2_LISTENER_REPORT },
};

static const struct icmpcodeent icmp_code[] = {
	{ "net-unr",		ICMP_UNREACH,	ICMP_UNREACH_NET },
	{ "host-unr",		ICMP_UNREACH,	ICMP_UNREACH_HOST },
	{ "proto-unr",		ICMP_UNREACH,	ICMP_UNREACH_PROTOCOL },
	{ "port-unr",		ICMP_UNREACH,	ICMP_UNREACH_PORT },
	{ "needfrag",		ICMP_UNREACH,	ICMP_UNREACH_NEEDFRAG },
	{ "srcfail",		ICMP_UNREACH,	ICMP_UNREACH_SRCFAIL },
	{ "net-unk",		ICMP_UNREACH,	ICMP_UNREACH_NET_UNKNOWN },
	{ "host-unk",		ICMP_UNREACH,	ICMP_UNREACH_HOST_UNKNOWN },
	{ "isolate",		ICMP_UNREACH,	ICMP_UNREACH_ISOLATED },
	{ "net-prohib",		ICMP_UNREACH,	ICMP_UNREACH_NET_PROHIB },
	{ "host-prohib",	ICMP_UNREACH,	ICMP_UNREACH_HOST_PROHIB },
	{ "net-tos",		ICMP_UNREACH,	ICMP_UNREACH_TOSNET },
	{ "host-tos",		ICMP_UNREACH,	ICMP_UNREACH_TOSHOST },
	{ "filter-prohib",	ICMP_UNREACH,	ICMP_UNREACH_FILTER_PROHIB },
	{ "host-preced",	ICMP_UNREACH,	ICMP_UNREACH_HOST_PRECEDENCE },
	{ "cutoff-preced",	ICMP_UNREACH,	ICMP_UNREACH_PRECEDENCE_CUTOFF },
	{ "redir-net",		ICMP_REDIRECT,	ICMP_REDIRECT_NET },
	{ "redir-host",		ICMP_REDIRECT,	ICMP_REDIRECT_HOST },
	{ "redir-tos-net",	ICMP_REDIRECT,	ICMP_REDIRECT_TOSNET },
	{ "redir-tos-host",	ICMP_REDIRECT,	ICMP_REDIRECT_TOSHOST },
	{ "normal-adv",		ICMP_ROUTERADVERT, ICMP_ROUTERADVERT_NORMAL },
	{ "common-adv",		ICMP_ROUTERADVERT, ICMP_ROUTERADVERT_NOROUTE_COMMON },
	{ "transit",		ICMP_TIMXCEED,	ICMP_TIMXCEED_INTRANS },
	{ "reassemb",		ICMP_TIMXCEED,	ICMP_TIMXCEED_REASS },
	{ "badhead",		ICMP_PARAMPROB,	ICMP_PARAMPROB_ERRATPTR },
	{ "optmiss",		ICMP_PARAMPROB,	ICMP_PARAMPROB_OPTABSENT },
	{ "badlen",		ICMP_PARAMPROB,	ICMP_PARAMPROB_LENGTH },
	{ "unknown-ind",	ICMP_PHOTURIS,	ICMP_PHOTURIS_UNKNOWN_INDEX },
	{ "auth-fail",		ICMP_PHOTURIS,	ICMP_PHOTURIS_AUTH_FAILED },
	{ "decrypt-fail",	ICMP_PHOTURIS,	ICMP_PHOTURIS_DECRYPT_FAILED },
};

static const struct icmpcodeent icmp6_code[] = {
	{ "admin-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN },
	{ "noroute-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOROUTE },
	{ "beyond-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_BEYONDSCOPE },
	{ "addr-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADDR },
	{ "port-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT },
	{ "transit", ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_TRANSIT },
	{ "reassemb", ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_REASSEMBLY },
	{ "badhead", ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER },
	{ "nxthdr", ICMP6_PARAM_PROB, ICMP6_PARAMPROB_NEXTHEADER },
	{ "redironlink", ND_REDIRECT, ND_REDIRECT_ONLINK },
	{ "redirrouter", ND_REDIRECT, ND_REDIRECT_ROUTER },
};

static int
geticmptypebyname(char *w, uint8_t aid)
{
	size_t	i;

	switch (aid) {
	case AID_INET:
		for (i = 0; i < nitems(icmp_type); i++) {
			if (!strcmp(w, icmp_type[i].name))
				return (icmp_type[i].type);
		}
		break;
	case AID_INET6:
		for (i = 0; i < nitems(icmp6_type); i++) {
			if (!strcmp(w, icmp6_type[i].name))
				return (icmp6_type[i].type);
		}
		break;
	}
	return -1;
}

static int
geticmpcodebyname(u_long type, char *w, uint8_t aid)
{
	size_t	i;

	switch (aid) {
	case AID_INET:
		for (i = 0; i < nitems(icmp_code); i++) {
			if (type == icmp_code[i].type &&
			    !strcmp(w, icmp_code[i].name))
				return (icmp_code[i].code);
		}
		break;
	case AID_INET6:
		for (i = 0; i < nitems(icmp6_code); i++) {
			if (type == icmp6_code[i].type &&
			    !strcmp(w, icmp6_code[i].name))
				return (icmp6_code[i].code);
		}
		break;
	}
	return -1;
}

static int
merge_auth_conf(struct auth_config *to, struct auth_config *from)
{
	if (to->method != 0) {
		/* extra magic for manual ipsec rules */
		if (to->method == from->method &&
		    (to->method == AUTH_IPSEC_MANUAL_ESP ||
		    to->method == AUTH_IPSEC_MANUAL_AH)) {
			if (to->spi_in == 0 && from->spi_in != 0) {
				to->spi_in = from->spi_in;
				to->auth_alg_in = from->auth_alg_in;
				to->enc_alg_in = from->enc_alg_in;
				memcpy(to->auth_key_in, from->auth_key_in,
				    sizeof(to->auth_key_in));
				memcpy(to->enc_key_in, from->enc_key_in,
				    sizeof(to->enc_key_in));
				to->enc_keylen_in = from->enc_keylen_in;
				to->auth_keylen_in = from->auth_keylen_in;
				return 1;
			} else if (to->spi_out == 0 && from->spi_out != 0) {
				to->spi_out = from->spi_out;
				to->auth_alg_out = from->auth_alg_out;
				to->enc_alg_out = from->enc_alg_out;
				memcpy(to->auth_key_out, from->auth_key_out,
				    sizeof(to->auth_key_out));
				memcpy(to->enc_key_out, from->enc_key_out,
				    sizeof(to->enc_key_out));
				to->enc_keylen_out = from->enc_keylen_out;
				to->auth_keylen_out = from->auth_keylen_out;
				return 1;
			}
		}
		yyerror("auth method cannot be redefined");
		return 0;
	}
	*to = *from;
	return 1;
}

#line 4176 "parse.c"
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
static int yygrowstack(void)
{
    unsigned int newsize;
    long sslen;
    short *newss;
    YYSTYPE *newvs;

    if ((newsize = yystacksize) == 0)
        newsize = YYINITSTACKSIZE;
    else if (newsize >= YYMAXDEPTH)
        return -1;
    else if ((newsize *= 2) > YYMAXDEPTH)
        newsize = YYMAXDEPTH;
    sslen = yyssp - yyss;
#ifdef SIZE_MAX
#define YY_SIZE_MAX SIZE_MAX
#else
#define YY_SIZE_MAX 0xffffffffU
#endif
    if (newsize && YY_SIZE_MAX / newsize < sizeof *newss)
        goto bail;
    newss = (short *)realloc(yyss, newsize * sizeof *newss);
    if (newss == NULL)
        goto bail;
    yyss = newss;
    yyssp = newss + sslen;
    if (newsize && YY_SIZE_MAX / newsize < sizeof *newvs)
        goto bail;
    newvs = (YYSTYPE *)realloc(yyvs, newsize * sizeof *newvs);
    if (newvs == NULL)
        goto bail;
    yyvs = newvs;
    yyvsp = newvs + sslen;
    yystacksize = newsize;
    yysslim = yyss + newsize - 1;
    return 0;
bail:
    if (yyss)
            free(yyss);
    if (yyvs)
            free(yyvs);
    yyss = yyssp = NULL;
    yyvs = yyvsp = NULL;
    yystacksize = 0;
    return -1;
}

#define YYABORT goto yyabort
#define YYREJECT goto yyabort
#define YYACCEPT goto yyaccept
#define YYERROR goto yyerrlab
int
yyparse(void)
{
    int yym, yyn, yystate;
#if YYDEBUG
    const char *yys;

    if ((yys = getenv("YYDEBUG")))
    {
        yyn = *yys;
        if (yyn >= '0' && yyn <= '9')
            yydebug = yyn - '0';
    }
#endif /* YYDEBUG */

    yynerrs = 0;
    yyerrflag = 0;
    yychar = (-1);

    if (yyss == NULL && yygrowstack()) goto yyoverflow;
    yyssp = yyss;
    yyvsp = yyvs;
    *yyssp = yystate = 0;

yyloop:
    if ((yyn = yydefred[yystate]) != 0) goto yyreduce;
    if (yychar < 0)
    {
        if ((yychar = yylex()) < 0) yychar = 0;
#if YYDEBUG
        if (yydebug)
        {
            yys = 0;
            if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
            if (!yys) yys = "illegal-symbol";
            printf("%sdebug: state %d, reading %d (%s)\n",
                    YYPREFIX, yystate, yychar, yys);
        }
#endif
    }
    if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 &&
            yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
    {
#if YYDEBUG
        if (yydebug)
            printf("%sdebug: state %d, shifting to state %d\n",
                    YYPREFIX, yystate, yytable[yyn]);
#endif
        if (yyssp >= yysslim && yygrowstack())
        {
            goto yyoverflow;
        }
        *++yyssp = yystate = yytable[yyn];
        *++yyvsp = yylval;
        yychar = (-1);
        if (yyerrflag > 0)  --yyerrflag;
        goto yyloop;
    }
    if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 &&
            yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
    {
        yyn = yytable[yyn];
        goto yyreduce;
    }
    if (yyerrflag) goto yyinrecovery;
#if defined(__GNUC__)
    goto yynewerror;
#endif
yynewerror:
    yyerror("syntax error");
#if defined(__GNUC__)
    goto yyerrlab;
#endif
yyerrlab:
    ++yynerrs;
yyinrecovery:
    if (yyerrflag < 3)
    {
        yyerrflag = 3;
        for (;;)
        {
            if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 &&
                    yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE)
            {
#if YYDEBUG
                if (yydebug)
                    printf("%sdebug: state %d, error recovery shifting\
 to state %d\n", YYPREFIX, *yyssp, yytable[yyn]);
#endif
                if (yyssp >= yysslim && yygrowstack())
                {
                    goto yyoverflow;
                }
                *++yyssp = yystate = yytable[yyn];
                *++yyvsp = yylval;
                goto yyloop;
            }
            else
            {
#if YYDEBUG
                if (yydebug)
                    printf("%sdebug: error recovery discarding state %d\n",
                            YYPREFIX, *yyssp);
#endif
                if (yyssp <= yyss) goto yyabort;
                --yyssp;
                --yyvsp;
            }
        }
    }
    else
    {
        if (yychar == 0) goto yyabort;
#if YYDEBUG
        if (yydebug)
        {
            yys = 0;
            if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
            if (!yys) yys = "illegal-symbol";
            printf("%sdebug: state %d, error recovery discards token %d (%s)\n",
                    YYPREFIX, yystate, yychar, yys);
        }
#endif
        yychar = (-1);
        goto yyloop;
    }
yyreduce:
#if YYDEBUG
    if (yydebug)
        printf("%sdebug: state %d, reducing by rule %d (%s)\n",
                YYPREFIX, yystate, yyn, yyrule[yyn]);
#endif
    yym = yylen[yyn];
    if (yym)
        yyval = yyvsp[1-yym];
    else
        memset(&yyval, 0, sizeof yyval);
    switch (yyn)
    {
case 20:
#line 318 "../../../openbgpd-portable/src/bgpd/parse.y"
{ file->errors++; }
break;
case 21:
#line 321 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			/*
			 * According to iana 65535 and 4294967295 are reserved
			 * but enforcing this is not duty of the parser.
			 */
			if (yyvsp[0].v.number < 0 || yyvsp[0].v.number > UINT_MAX) {
				yyerror("AS too big: max %u", UINT_MAX);
				YYERROR;
			}
		}
break;
case 22:
#line 332 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			const char	*errstr;
			char		*dot;
			uint32_t	 uvalh = 0, uval;

			if ((dot = strchr(yyvsp[0].v.string, '.')) != NULL) {
				*dot++ = '\0';
				uvalh = strtonum(yyvsp[0].v.string, 0, USHRT_MAX, &errstr);
				if (errstr) {
					yyerror("number %s is %s", yyvsp[0].v.string, errstr);
					free(yyvsp[0].v.string);
					YYERROR;
				}
				uval = strtonum(dot, 0, USHRT_MAX, &errstr);
				if (errstr) {
					yyerror("number %s is %s", dot, errstr);
					free(yyvsp[0].v.string);
					YYERROR;
				}
				free(yyvsp[0].v.string);
			} else {
				yyerror("AS %s is bad", yyvsp[0].v.string);
				free(yyvsp[0].v.string);
				YYERROR;
			}
			if (uvalh == 0 && (uval == AS_TRANS || uval == 0)) {
				yyerror("AS %u is reserved and may not be used",
				    uval);
				YYERROR;
			}
			yyval.v.number = uval | (uvalh << 16);
		}
break;
case 23:
#line 364 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.number == AS_TRANS || yyvsp[0].v.number == 0) {
				yyerror("AS %u is reserved and may not be used",
				    (uint32_t)yyvsp[0].v.number);
				YYERROR;
			}
			yyval.v.number = yyvsp[0].v.number;
		}
break;
case 24:
#line 374 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			const char	*errstr;
			char		*dot;
			uint32_t	 uvalh = 0, uval;

			if ((dot = strchr(yyvsp[0].v.string, '.')) != NULL) {
				*dot++ = '\0';
				uvalh = strtonum(yyvsp[0].v.string, 0, USHRT_MAX, &errstr);
				if (errstr) {
					yyerror("number %s is %s", yyvsp[0].v.string, errstr);
					free(yyvsp[0].v.string);
					YYERROR;
				}
				uval = strtonum(dot, 0, USHRT_MAX, &errstr);
				if (errstr) {
					yyerror("number %s is %s", dot, errstr);
					free(yyvsp[0].v.string);
					YYERROR;
				}
				free(yyvsp[0].v.string);
			} else {
				yyerror("AS %s is bad", yyvsp[0].v.string);
				free(yyvsp[0].v.string);
				YYERROR;
			}
			yyval.v.number = uval | (uvalh << 16);
		}
break;
case 25:
#line 401 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			yyval.v.number = yyvsp[0].v.number;
		}
break;
case 26:
#line 406 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (asprintf(&yyval.v.string, "%s %s", yyvsp[-1].v.string, yyvsp[0].v.string) == -1)
				fatal("string: asprintf");
			free(yyvsp[-1].v.string);
			free(yyvsp[0].v.string);
		}
break;
case 28:
#line 415 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (!strcmp(yyvsp[0].v.string, "yes"))
				yyval.v.number = 1;
			else if (!strcmp(yyvsp[0].v.string, "no"))
				yyval.v.number = 0;
			else {
				yyerror("syntax error, "
				    "either yes or no expected");
				free(yyvsp[0].v.string);
				YYERROR;
			}
			free(yyvsp[0].v.string);
		}
break;
case 29:
#line 430 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			char *s = yyvsp[-2].v.string;
			if (strlen(yyvsp[-2].v.string) >= MACRO_NAME_LEN) {
				yyerror("macro name too long, "
				    "max %d characters", MACRO_NAME_LEN - 1);
				free(yyvsp[-2].v.string);
				free(yyvsp[0].v.string);
				YYERROR;
			}
			do {
				if (isalnum((unsigned char)*s) || *s == '_')
					continue;
				yyerror("macro name can only contain "
					    "alphanumerics and '_'");
				free(yyvsp[-2].v.string);
				free(yyvsp[0].v.string);
				YYERROR;
			} while (*++s);

			if (cmd_opts & BGPD_OPT_VERBOSE)
				printf("%s = \"%s\"\n", yyvsp[-2].v.string, yyvsp[0].v.string);
			if (symset(yyvsp[-2].v.string, yyvsp[0].v.string, 0) == -1)
				fatal("cannot store variable");
			free(yyvsp[-2].v.string);
			free(yyvsp[0].v.string);
		}
break;
case 30:
#line 458 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			struct file	*nfile;

			if ((nfile = pushfile(yyvsp[0].v.string, 1)) == NULL) {
				yyerror("failed to include file %s", yyvsp[0].v.string);
				free(yyvsp[0].v.string);
				YYERROR;
			}
			free(yyvsp[0].v.string);

			file = nfile;
			lungetc('\n');
		}
break;
case 31:
#line 473 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (strlen(yyvsp[-2].v.string) >= SET_NAME_LEN) {
				yyerror("as-set name %s too long", yyvsp[-2].v.string);
				free(yyvsp[-2].v.string);
				YYERROR;
			}
			if (new_as_set(yyvsp[-2].v.string) != 0) {
				free(yyvsp[-2].v.string);
				YYERROR;
			}
			free(yyvsp[-2].v.string);
		}
break;
case 32:
#line 484 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			done_as_set();
		}
break;
case 33:
#line 487 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (new_as_set(yyvsp[-3].v.string) != 0) {
				free(yyvsp[-3].v.string);
				YYERROR;
			}
			free(yyvsp[-3].v.string);
		}
break;
case 34:
#line 495 "../../../openbgpd-portable/src/bgpd/parse.y"
{ add_as_set(yyvsp[0].v.number); }
break;
case 35:
#line 496 "../../../openbgpd-portable/src/bgpd/parse.y"
{ add_as_set(yyvsp[0].v.number); }
break;
case 36:
#line 498 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if ((curpset = new_prefix_set(yyvsp[-2].v.string, 0)) == NULL) {
				free(yyvsp[-2].v.string);
				YYERROR;
			}
			free(yyvsp[-2].v.string);
		}
break;
case 37:
#line 504 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			SIMPLEQ_INSERT_TAIL(&conf->prefixsets, curpset, entry);
			curpset = NULL;
		}
break;
case 38:
#line 508 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if ((curpset = new_prefix_set(yyvsp[-3].v.string, 0)) == NULL) {
				free(yyvsp[-3].v.string);
				YYERROR;
			}
			free(yyvsp[-3].v.string);
			SIMPLEQ_INSERT_TAIL(&conf->prefixsets, curpset, entry);
			curpset = NULL;
		}
break;
case 39:
#line 518 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			struct prefixset_item	*psi;
			if (yyvsp[0].v.prefixset_item->p.op != OP_NONE)
				curpset->sflags |= PREFIXSET_FLAG_OPS;
			psi = RB_INSERT(prefixset_tree, &curpset->psitems, yyvsp[0].v.prefixset_item);
			if (psi != NULL) {
				if (cmd_opts & BGPD_OPT_VERBOSE2)
					log_warnx("warning: duplicate entry in "
					    "prefixset \"%s\" for %s/%u",
					    curpset->name,
					    log_addr(&yyvsp[0].v.prefixset_item->p.addr), yyvsp[0].v.prefixset_item->p.len);
				free(yyvsp[0].v.prefixset_item);
			}
		}
break;
case 40:
#line 532 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			struct prefixset_item	*psi;
			if (yyvsp[0].v.prefixset_item->p.op != OP_NONE)
				curpset->sflags |= PREFIXSET_FLAG_OPS;
			psi = RB_INSERT(prefixset_tree, &curpset->psitems, yyvsp[0].v.prefixset_item);
			if (psi != NULL) {
				if (cmd_opts & BGPD_OPT_VERBOSE2)
					log_warnx("warning: duplicate entry in "
					    "prefixset \"%s\" for %s/%u",
					    curpset->name,
					    log_addr(&yyvsp[0].v.prefixset_item->p.addr), yyvsp[0].v.prefixset_item->p.len);
				free(yyvsp[0].v.prefixset_item);
			}
		}
break;
case 41:
#line 548 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.prefixlen.op != OP_NONE && yyvsp[0].v.prefixlen.op != OP_RANGE) {
				yyerror("unsupported prefixlen operation in "
				    "prefix-set");
				YYERROR;
			}
			if ((yyval.v.prefixset_item = calloc(1, sizeof(*yyval.v.prefixset_item))) == NULL)
				fatal(NULL);
			memcpy(&yyval.v.prefixset_item->p.addr, &yyvsp[-1].v.prefix.prefix, sizeof(yyval.v.prefixset_item->p.addr));
			yyval.v.prefixset_item->p.len = yyvsp[-1].v.prefix.len;
			if (merge_prefixspec(&yyval.v.prefixset_item->p, &yyvsp[0].v.prefixlen) == -1) {
				free(yyval.v.prefixset_item);
				YYERROR;
			}
		}
break;
case 42:
#line 565 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			curroatree = &conf->roa;
		}
break;
case 43:
#line 567 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			curroatree = NULL;
		}
break;
case 45:
#line 573 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if ((curoset = new_prefix_set(yyvsp[-2].v.string, 1)) == NULL) {
				free(yyvsp[-2].v.string);
				YYERROR;
			}
			curroatree = &curoset->roaitems;
			noexpires = 1;
			free(yyvsp[-2].v.string);
		}
break;
case 46:
#line 581 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			SIMPLEQ_INSERT_TAIL(&conf->originsets, curoset, entry);
			curoset = NULL;
			curroatree = NULL;
			noexpires = 0;
		}
break;
case 47:
#line 587 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if ((curoset = new_prefix_set(yyvsp[-3].v.string, 1)) == NULL) {
				free(yyvsp[-3].v.string);
				YYERROR;
			}
			free(yyvsp[-3].v.string);
			SIMPLEQ_INSERT_TAIL(&conf->originsets, curoset, entry);
			curoset = NULL;
			curroatree = NULL;
		}
break;
case 48:
#line 599 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			yyval.v.number = 0;
		}
break;
case 49:
#line 602 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (noexpires) {
				yyerror("syntax error, expires not allowed");
				YYERROR;
			}
			yyval.v.number = yyvsp[0].v.number;
		}
break;
case 50:
#line 610 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[-3].v.prefixset_item->p.len_min != yyvsp[-3].v.prefixset_item->p.len) {
				yyerror("unsupported prefixlen operation in "
				    "roa-set");
				free(yyvsp[-3].v.prefixset_item);
				YYERROR;
			}
			add_roa_set(yyvsp[-3].v.prefixset_item, yyvsp[-1].v.number, yyvsp[-3].v.prefixset_item->p.len_max, yyvsp[0].v.number);
			free(yyvsp[-3].v.prefixset_item);
		}
break;
case 51:
#line 620 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[-3].v.prefixset_item->p.len_min != yyvsp[-3].v.prefixset_item->p.len) {
				yyerror("unsupported prefixlen operation in "
				    "roa-set");
				free(yyvsp[-3].v.prefixset_item);
				YYERROR;
			}
			add_roa_set(yyvsp[-3].v.prefixset_item, yyvsp[-1].v.number, yyvsp[-3].v.prefixset_item->p.len_max, yyvsp[0].v.number);
			free(yyvsp[-3].v.prefixset_item);
		}
break;
case 56:
#line 641 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			int rv;
			struct aspa_tas_l *a, *n;

			rv = merge_aspa_set(yyvsp[-7].v.number, yyvsp[-2].v.aspa_elm, yyvsp[-6].v.number);

			for (a = yyvsp[-2].v.aspa_elm; a != NULL; a = n) {
				n = a->next;
				free(a);
			}

			if (rv == -1)
				YYERROR;
		}
break;
case 57:
#line 657 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.aspa_elm = yyvsp[0].v.aspa_elm; }
break;
case 58:
#line 658 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			yyvsp[0].v.aspa_elm->next = yyvsp[-2].v.aspa_elm;
			yyvsp[0].v.aspa_elm->num = yyvsp[-2].v.aspa_elm->num + 1;
			yyval.v.aspa_elm = yyvsp[0].v.aspa_elm;
		}
break;
case 59:
#line 665 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if ((yyval.v.aspa_elm = calloc(1, sizeof(*yyval.v.aspa_elm))) == NULL)
				fatal(NULL);
			yyval.v.aspa_elm->as = yyvsp[0].v.number;
			yyval.v.aspa_elm->num = 1;
		}
break;
case 60:
#line 671 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if ((yyval.v.aspa_elm = calloc(1, sizeof(*yyval.v.aspa_elm))) == NULL)
				fatal(NULL);
			yyval.v.aspa_elm->as = yyvsp[-1].v.number;
			yyval.v.aspa_elm->num = 1;
		}
break;
case 61:
#line 679 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			currtr = get_rtr(&yyvsp[0].v.addr);
			currtr->remote_port = RTR_PORT;
			if (insert_rtr(currtr) == -1) {
				free(currtr);
				currtr = NULL;
				YYERROR;
			}
			currtr = NULL;
		}
break;
case 62:
#line 689 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			currtr = get_rtr(&yyvsp[0].v.addr);
			currtr->remote_port = RTR_PORT;
		}
break;
case 63:
#line 692 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (insert_rtr(currtr) == -1) {
				free(currtr);
				currtr = NULL;
				YYERROR;
			}
			currtr = NULL;
		}
break;
case 66:
#line 706 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (strlcpy(currtr->descr, yyvsp[0].v.string,
			    sizeof(currtr->descr)) >=
			    sizeof(currtr->descr)) {
				yyerror("descr \"%s\" too long: max %zu",
				    yyvsp[0].v.string, sizeof(currtr->descr) - 1);
				free(yyvsp[0].v.string);
				YYERROR;
			}
			free(yyvsp[0].v.string);
		}
break;
case 67:
#line 717 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.addr.aid != currtr->remote_addr.aid) {
				yyerror("Bad address family %s for "
				    "local-addr", aid2str(yyvsp[0].v.addr.aid));
				YYERROR;
			}
			currtr->local_addr = yyvsp[0].v.addr;
		}
break;
case 68:
#line 725 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			currtr->remote_port = yyvsp[0].v.number;
		}
break;
case 69:
#line 728 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.number < 0 || yyvsp[0].v.number > RTR_MAX_VERSION) {
				yyerror("min-version must be between %u and %u",
				    0, RTR_MAX_VERSION);
				YYERROR;
			}
			currtr->min_version = yyvsp[0].v.number;
		}
break;
case 70:
#line 736 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (merge_auth_conf(&currtr->auth, &yyvsp[0].v.authconf) == 0)
				YYERROR;
		}
break;
case 71:
#line 742 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			conf->as = yyvsp[0].v.number;
			if (yyvsp[0].v.number > USHRT_MAX)
				conf->short_as = AS_TRANS;
			else
				conf->short_as = yyvsp[0].v.number;
		}
break;
case 72:
#line 749 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			conf->as = yyvsp[-1].v.number;
			conf->short_as = yyvsp[0].v.number;
		}
break;
case 73:
#line 753 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.addr.aid != AID_INET) {
				yyerror("router-id must be an IPv4 address");
				YYERROR;
			}
			conf->bgpid = ntohl(yyvsp[0].v.addr.v4.s_addr);
		}
break;
case 74:
#line 760 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.number < MIN_HOLDTIME || yyvsp[0].v.number > USHRT_MAX) {
				yyerror("holdtime must be between %u and %u",
				    MIN_HOLDTIME, USHRT_MAX);
				YYERROR;
			}
			conf->holdtime = yyvsp[0].v.number;
		}
break;
case 75:
#line 768 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.number < MIN_HOLDTIME || yyvsp[0].v.number > USHRT_MAX) {
				yyerror("holdtime must be between %u and %u",
				    MIN_HOLDTIME, USHRT_MAX);
				YYERROR;
			}
			conf->min_holdtime = yyvsp[0].v.number;
		}
break;
case 76:
#line 776 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.number < MIN_HOLDTIME || yyvsp[0].v.number > CAPA_GR_TIMEMASK) {
				yyerror("staletime must be between %u and %u",
				    MIN_HOLDTIME, CAPA_GR_TIMEMASK);
				YYERROR;
			}
			conf->staletime = yyvsp[0].v.number;
		}
break;
case 77:
#line 784 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			struct listen_addr	*la;
			struct sockaddr		*sa;

			if ((la = calloc(1, sizeof(struct listen_addr))) ==
			    NULL)
				fatal("parse conf_main listen on calloc");

			la->fd = -1;
			la->reconf = RECONF_REINIT;
			sa = addr2sa(&yyvsp[0].v.addr, BGP_PORT, &la->sa_len);
			memcpy(&la->sa, sa, la->sa_len);
			TAILQ_INSERT_TAIL(conf->listen_addrs, la, entry);
		}
break;
case 78:
#line 798 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			struct listen_addr	*la;
			struct sockaddr		*sa;

			if ((la = calloc(1, sizeof(struct listen_addr))) ==
			    NULL)
				fatal("parse conf_main listen on calloc");

			la->fd = -1;
			la->reconf = RECONF_REINIT;
			sa = addr2sa(&yyvsp[-2].v.addr, yyvsp[0].v.number, &la->sa_len);
			memcpy(&la->sa, sa, la->sa_len);
			TAILQ_INSERT_TAIL(conf->listen_addrs, la, entry);
		}
break;
case 79:
#line 812 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (!kr_check_prio(yyvsp[0].v.number)) {
				yyerror("fib-priority %lld out of range", yyvsp[0].v.number);
				YYERROR;
			}
			conf->fib_priority = yyvsp[0].v.number;
		}
break;
case 80:
#line 819 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			struct rde_rib *rr;
			rr = find_rib("Loc-RIB");
			if (rr == NULL)
				fatalx("RTABLE cannot find the main RIB!");

			if (yyvsp[0].v.number == 0)
				rr->flags |= F_RIB_NOFIBSYNC;
			else
				rr->flags &= ~F_RIB_NOFIBSYNC;
		}
break;
case 81:
#line 830 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.number == 1)
				conf->flags |= BGPD_FLAG_DECISION_TRANS_AS;
			else
				conf->flags &= ~BGPD_FLAG_DECISION_TRANS_AS;
		}
break;
case 82:
#line 836 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.number == 1)
				conf->flags &= ~BGPD_FLAG_PERMIT_AS_SET;
			else
				conf->flags |= BGPD_FLAG_PERMIT_AS_SET;
		}
break;
case 83:
#line 842 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (!strcmp(yyvsp[0].v.string, "updates"))
				conf->log |= BGPD_LOG_UPDATES;
			else {
				free(yyvsp[0].v.string);
				YYERROR;
			}
			free(yyvsp[0].v.string);
		}
break;
case 84:
#line 851 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			int action;

			if (yyvsp[0].v.number < 0 || yyvsp[0].v.number > INT_MAX) {
				yyerror("bad timeout");
				free(yyvsp[-2].v.string);
				free(yyvsp[-1].v.string);
				YYERROR;
			}
			if (!strcmp(yyvsp[-2].v.string, "table"))
				action = MRT_TABLE_DUMP;
			else if (!strcmp(yyvsp[-2].v.string, "table-mp"))
				action = MRT_TABLE_DUMP_MP;
			else if (!strcmp(yyvsp[-2].v.string, "table-v2"))
				action = MRT_TABLE_DUMP_V2;
			else {
				yyerror("unknown mrt dump type");
				free(yyvsp[-2].v.string);
				free(yyvsp[-1].v.string);
				YYERROR;
			}
			free(yyvsp[-2].v.string);
			if (add_mrtconfig(action, yyvsp[-1].v.string, yyvsp[0].v.number, NULL, NULL) == -1) {
				free(yyvsp[-1].v.string);
				YYERROR;
			}
			free(yyvsp[-1].v.string);
		}
break;
case 85:
#line 879 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			int action;

			if (yyvsp[0].v.number < 0 || yyvsp[0].v.number > INT_MAX) {
				yyerror("bad timeout");
				free(yyvsp[-3].v.string);
				free(yyvsp[-2].v.string);
				free(yyvsp[-1].v.string);
				YYERROR;
			}
			if (!strcmp(yyvsp[-2].v.string, "table"))
				action = MRT_TABLE_DUMP;
			else if (!strcmp(yyvsp[-2].v.string, "table-mp"))
				action = MRT_TABLE_DUMP_MP;
			else if (!strcmp(yyvsp[-2].v.string, "table-v2"))
				action = MRT_TABLE_DUMP_V2;
			else {
				yyerror("unknown mrt dump type");
				free(yyvsp[-3].v.string);
				free(yyvsp[-2].v.string);
				free(yyvsp[-1].v.string);
				YYERROR;
			}
			free(yyvsp[-2].v.string);
			if (add_mrtconfig(action, yyvsp[-1].v.string, yyvsp[0].v.number, NULL, yyvsp[-3].v.string) == -1) {
				free(yyvsp[-3].v.string);
				free(yyvsp[-1].v.string);
				YYERROR;
			}
			free(yyvsp[-3].v.string);
			free(yyvsp[-1].v.string);
		}
break;
case 86:
#line 911 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (!strcmp(yyvsp[-1].v.string, "route-age"))
				conf->flags |= BGPD_FLAG_DECISION_ROUTEAGE;
			else {
				yyerror("unknown route decision type");
				free(yyvsp[-1].v.string);
				YYERROR;
			}
			free(yyvsp[-1].v.string);
		}
break;
case 87:
#line 921 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (!strcmp(yyvsp[-1].v.string, "route-age"))
				conf->flags &= ~BGPD_FLAG_DECISION_ROUTEAGE;
			else {
				yyerror("unknown route decision type");
				free(yyvsp[-1].v.string);
				YYERROR;
			}
			free(yyvsp[-1].v.string);
		}
break;
case 88:
#line 931 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (!strcmp(yyvsp[0].v.string, "always"))
				conf->flags |= BGPD_FLAG_DECISION_MED_ALWAYS;
			else if (!strcmp(yyvsp[0].v.string, "strict"))
				conf->flags &= ~BGPD_FLAG_DECISION_MED_ALWAYS;
			else {
				yyerror("rde med compare: "
				    "unknown setting \"%s\"", yyvsp[0].v.string);
				free(yyvsp[0].v.string);
				YYERROR;
			}
			free(yyvsp[0].v.string);
		}
break;
case 89:
#line 944 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (!strcmp(yyvsp[0].v.string, "all"))
				conf->flags |= BGPD_FLAG_DECISION_ALL_PATHS;
			else if (!strcmp(yyvsp[0].v.string, "default"))
				conf->flags &= ~BGPD_FLAG_DECISION_ALL_PATHS;
			else {
				yyerror("rde evaluate: "
				    "unknown setting \"%s\"", yyvsp[0].v.string);
				free(yyvsp[0].v.string);
				YYERROR;
			}
			free(yyvsp[0].v.string);
		}
break;
case 90:
#line 957 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (strcmp(yyvsp[-2].v.string, "Loc-RIB") != 0) {
				yyerror("include filtered only supported in "
				    "Loc-RIB");
				YYERROR;
			}
			conf->filtered_in_locrib = 1;
		}
break;
case 91:
#line 965 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (!strcmp(yyvsp[0].v.string, "bgp"))
				conf->flags |= BGPD_FLAG_NEXTHOP_BGP;
			else if (!strcmp(yyvsp[0].v.string, "default"))
				conf->flags |= BGPD_FLAG_NEXTHOP_DEFAULT;
			else {
				yyerror("nexthop depend on: "
				    "unknown setting \"%s\"", yyvsp[0].v.string);
				free(yyvsp[0].v.string);
				YYERROR;
			}
			free(yyvsp[0].v.string);
		}
break;
case 92:
#line 978 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			struct rde_rib *rr;
			if (yyvsp[0].v.number > RT_TABLEID_MAX) {
				yyerror("rtable %llu too big: max %u", yyvsp[0].v.number,
				    RT_TABLEID_MAX);
				YYERROR;
			}
			if (!ktable_exists(yyvsp[0].v.number, NULL)) {
				yyerror("rtable id %lld does not exist", yyvsp[0].v.number);
				YYERROR;
			}
			rr = find_rib("Loc-RIB");
			if (rr == NULL)
				fatalx("RTABLE cannot find the main RIB!");
			rr->rtableid = yyvsp[0].v.number;
		}
break;
case 93:
#line 994 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.number > USHRT_MAX || yyvsp[0].v.number < 1) {
				yyerror("invalid connect-retry");
				YYERROR;
			}
			conf->connectretry = yyvsp[0].v.number;
		}
break;
case 94:
#line 1001 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (strlen(yyvsp[-1].v.string) >=
			    sizeof(((struct sockaddr_un *)0)->sun_path)) {
				yyerror("socket path too long");
				YYERROR;
			}
			if (yyvsp[0].v.number) {
				free(conf->rcsock);
				conf->rcsock = yyvsp[-1].v.string;
			} else {
				free(conf->csock);
				conf->csock = yyvsp[-1].v.string;
			}
		}
break;
case 95:
#line 1017 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if ((currib = add_rib(yyvsp[0].v.string)) == NULL) {
				free(yyvsp[0].v.string);
				YYERROR;
			}
			free(yyvsp[0].v.string);
		}
break;
case 96:
#line 1023 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			currib = NULL;
		}
break;
case 98:
#line 1028 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[-1].v.number > RT_TABLEID_MAX) {
				yyerror("rtable %llu too big: max %u", yyvsp[-1].v.number,
				    RT_TABLEID_MAX);
				YYERROR;
			}
			if (rib_add_fib(currib, yyvsp[-1].v.number) == -1)
				YYERROR;
		}
break;
case 99:
#line 1037 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[-1].v.number) {
				yyerror("bad rde rib definition");
				YYERROR;
			}
			currib->flags |= F_RIB_NOEVALUATE;
		}
break;
case 101:
#line 1047 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.number == 0)
				currib->flags |= F_RIB_NOFIBSYNC;
			else
				currib->flags &= ~F_RIB_NOFIBSYNC;
		}
break;
case 102:
#line 1055 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			int action;

			if (yyvsp[0].v.number < 0 || yyvsp[0].v.number > INT_MAX) {
				yyerror("bad timeout");
				free(yyvsp[-3].v.string);
				free(yyvsp[-1].v.string);
				YYERROR;
			}
			if (!strcmp(yyvsp[-3].v.string, "all"))
				action = yyvsp[-2].v.number ? MRT_ALL_IN : MRT_ALL_OUT;
			else if (!strcmp(yyvsp[-3].v.string, "updates"))
				action = yyvsp[-2].v.number ? MRT_UPDATE_IN : MRT_UPDATE_OUT;
			else {
				yyerror("unknown mrt msg dump type");
				free(yyvsp[-3].v.string);
				free(yyvsp[-1].v.string);
				YYERROR;
			}
			if (add_mrtconfig(action, yyvsp[-1].v.string, yyvsp[0].v.number, curpeer, NULL) ==
			    -1) {
				free(yyvsp[-3].v.string);
				free(yyvsp[-1].v.string);
				YYERROR;
			}
			free(yyvsp[-3].v.string);
			free(yyvsp[-1].v.string);
		}
break;
case 103:
#line 1085 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			struct network	*n, *m;

			if ((n = calloc(1, sizeof(struct network))) == NULL)
				fatal("new_network");
			memcpy(&n->net.prefix, &yyvsp[-1].v.prefix.prefix,
			    sizeof(n->net.prefix));
			n->net.prefixlen = yyvsp[-1].v.prefix.len;
			filterset_move(yyvsp[0].v.filter_set_head, &n->net.attrset);
			free(yyvsp[0].v.filter_set_head);
			TAILQ_FOREACH(m, netconf, entry) {
				if (n->net.type == m->net.type &&
				    n->net.prefixlen == m->net.prefixlen &&
				    prefix_compare(&n->net.prefix,
				    &m->net.prefix, n->net.prefixlen) == 0)
					yyerror("duplicate prefix "
					    "in network statement");
			}

			TAILQ_INSERT_TAIL(netconf, n, entry);
		}
break;
case 104:
#line 1106 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			struct prefixset *ps;
			struct network	*n;
			if ((ps = find_prefixset(yyvsp[-1].v.string, &conf->prefixsets))
			    == NULL) {
				yyerror("prefix-set '%s' not defined", yyvsp[-1].v.string);
				free(yyvsp[-1].v.string);
				filterset_free(yyvsp[0].v.filter_set_head);
				free(yyvsp[0].v.filter_set_head);
				YYERROR;
			}
			if (ps->sflags & PREFIXSET_FLAG_OPS) {
				yyerror("prefix-set %s has prefixlen operators "
				    "and cannot be used in network statements.",
				    ps->name);
				free(yyvsp[-1].v.string);
				filterset_free(yyvsp[0].v.filter_set_head);
				free(yyvsp[0].v.filter_set_head);
				YYERROR;
			}
			if ((n = calloc(1, sizeof(struct network))) == NULL)
				fatal("new_network");
			strlcpy(n->net.psname, ps->name, sizeof(n->net.psname));
			filterset_move(yyvsp[0].v.filter_set_head, &n->net.attrset);
			n->net.type = NETWORK_PREFIXSET;
			TAILQ_INSERT_TAIL(netconf, n, entry);
			free(yyvsp[-1].v.string);
			free(yyvsp[0].v.filter_set_head);
		}
break;
case 105:
#line 1135 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			struct network	*n;

			if ((n = calloc(1, sizeof(struct network))) == NULL)
				fatal("new_network");
			if (afi2aid(yyvsp[-3].v.number, SAFI_UNICAST, &n->net.prefix.aid) ==
			    -1) {
				yyerror("unknown address family");
				filterset_free(yyvsp[0].v.filter_set_head);
				free(yyvsp[0].v.filter_set_head);
				YYERROR;
			}
			n->net.type = NETWORK_RTLABEL;
			n->net.rtlabel = rtlabel_name2id(yyvsp[-1].v.string);
			filterset_move(yyvsp[0].v.filter_set_head, &n->net.attrset);
			free(yyvsp[0].v.filter_set_head);

			TAILQ_INSERT_TAIL(netconf, n, entry);
		}
break;
case 106:
#line 1154 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			struct network	*n;
			if (!kr_check_prio(yyvsp[-1].v.number)) {
				yyerror("priority %lld out of range", yyvsp[-1].v.number);
				YYERROR;
			}

			if ((n = calloc(1, sizeof(struct network))) == NULL)
				fatal("new_network");
			if (afi2aid(yyvsp[-3].v.number, SAFI_UNICAST, &n->net.prefix.aid) ==
			    -1) {
				yyerror("unknown address family");
				filterset_free(yyvsp[0].v.filter_set_head);
				free(yyvsp[0].v.filter_set_head);
				YYERROR;
			}
			n->net.type = NETWORK_PRIORITY;
			n->net.priority = yyvsp[-1].v.number;
			filterset_move(yyvsp[0].v.filter_set_head, &n->net.attrset);
			free(yyvsp[0].v.filter_set_head);

			TAILQ_INSERT_TAIL(netconf, n, entry);
		}
break;
case 107:
#line 1177 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			struct network	*n;

			if ((n = calloc(1, sizeof(struct network))) == NULL)
				fatal("new_network");
			if (afi2aid(yyvsp[-2].v.number, SAFI_UNICAST, &n->net.prefix.aid) ==
			    -1) {
				yyerror("unknown address family");
				filterset_free(yyvsp[0].v.filter_set_head);
				free(yyvsp[0].v.filter_set_head);
				YYERROR;
			}
			n->net.type = yyvsp[-1].v.number ? NETWORK_STATIC : NETWORK_CONNECTED;
			filterset_move(yyvsp[0].v.filter_set_head, &n->net.attrset);
			free(yyvsp[0].v.filter_set_head);

			TAILQ_INSERT_TAIL(netconf, n, entry);
		}
break;
case 108:
#line 1197 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if ((curflow = calloc(1, sizeof(*curflow))) == NULL)
				fatal("new_flowspec");
			curflow->aid = yyvsp[0].v.number;
		}
break;
case 109:
#line 1201 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			struct flowspec_config *f;

			f = flow_to_flowspec(curflow);
			if (f == NULL) {
				free(yyvsp[0].v.filter_set_head);
				flow_free(curflow);
				curflow = NULL;
				YYERROR;
			}
			filterset_move(yyvsp[0].v.filter_set_head, &f->attrset);
			free(yyvsp[0].v.filter_set_head);
			flow_free(curflow);
			curflow = NULL;

			if (RB_INSERT(flowspec_tree, &conf->flowspecs, f) !=
			    NULL) {
				yyerror("duplicate flowspec definition");
				flowspec_free(f);
				YYERROR;
			}
		}
break;
case 110:
#line 1225 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			curflow->type = FLOWSPEC_TYPE_PROTO;
			if (push_unary_numop(OP_EQ, yyvsp[0].v.number) == -1)
				YYERROR;
		}
break;
case 112:
#line 1233 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			curflow->type = FLOWSPEC_TYPE_PROTO;
			if (push_unary_numop(OP_EQ, yyvsp[0].v.number) == -1)
				YYERROR;
		}
break;
case 113:
#line 1238 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			curflow->type = FLOWSPEC_TYPE_PROTO;
			if (push_unary_numop(OP_EQ, yyvsp[0].v.number) == -1)
				YYERROR;
		}
break;
case 114:
#line 1245 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			struct protoent *p;

			p = getprotobyname(yyvsp[0].v.string);
			if (p == NULL) {
				yyerror("unknown protocol %s", yyvsp[0].v.string);
				free(yyvsp[0].v.string);
				YYERROR;
			}
			yyval.v.number = p->p_proto;
			free(yyvsp[0].v.string);
		}
break;
case 115:
#line 1257 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.number < 0 || yyvsp[0].v.number > 255) {
				yyerror("protocol outside range");
				YYERROR;
			}
			yyval.v.number = yyvsp[0].v.number;
		}
break;
case 116:
#line 1266 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			curflow->type = FLOWSPEC_TYPE_SRC_PORT;
			curflow->addr_type = FLOWSPEC_TYPE_SOURCE;
		}
break;
case 118:
#line 1272 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			curflow->type = FLOWSPEC_TYPE_DST_PORT;
			curflow->addr_type = FLOWSPEC_TYPE_DEST;
		}
break;
case 124:
#line 1284 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (push_prefix(&yyvsp[0].v.prefix.prefix, yyvsp[0].v.prefix.len) == -1)
				YYERROR;
		}
break;
case 129:
#line 1298 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (push_unary_numop(OP_EQ, yyvsp[0].v.number) == -1)
				YYERROR;
		}
break;
case 130:
#line 1302 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (push_unary_numop(yyvsp[-1].v.u8, yyvsp[0].v.number) == -1)
				YYERROR;
		}
break;
case 131:
#line 1306 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (push_binary_numop(yyvsp[-1].v.u8, yyvsp[-2].v.number, yyvsp[0].v.number))
				YYERROR;
		}
break;
case 132:
#line 1312 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.number < 1 || yyvsp[0].v.number > USHRT_MAX) {
				yyerror("port must be between %u and %u",
				    1, USHRT_MAX);
				YYERROR;
			}
			yyval.v.number = yyvsp[0].v.number;
		}
break;
case 133:
#line 1320 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if ((yyval.v.number = getservice(yyvsp[0].v.string)) == -1) {
				yyerror("unknown port '%s'", yyvsp[0].v.string);
				free(yyvsp[0].v.string);
				YYERROR;
			}
			free(yyvsp[0].v.string);
		}
break;
case 140:
#line 1340 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			curflow->type = FLOWSPEC_TYPE_TCP_FLAGS;
		}
break;
case 142:
#line 1343 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			curflow->type = FLOWSPEC_TYPE_FRAG;
		}
break;
case 145:
#line 1347 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			curflow->type = FLOWSPEC_TYPE_PKT_LEN;
		}
break;
case 148:
#line 1351 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			curflow->type = FLOWSPEC_TYPE_DSCP;
			if (push_unary_numop(OP_EQ, yyvsp[0].v.number >> 2) == -1)
				YYERROR;
		}
break;
case 149:
#line 1358 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if ((yyvsp[-2].v.number & yyvsp[0].v.number) != yyvsp[-2].v.number) {
				yyerror("bad flag combination, "
				    "check bit not in mask");
				YYERROR;
			}
			if (push_binop(FLOWSPEC_OP_BIT_MATCH, yyvsp[-2].v.number) == -1)
				YYERROR;
			/* check if extra mask op is needed */
			if (yyvsp[0].v.number & ~yyvsp[-2].v.number) {
				if (push_binop(FLOWSPEC_OP_BIT_NOT |
				    FLOWSPEC_OP_AND, yyvsp[0].v.number & ~yyvsp[-2].v.number) == -1)
					YYERROR;
			}
		}
break;
case 150:
#line 1373 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (push_binop(FLOWSPEC_OP_BIT_NOT, yyvsp[0].v.number) == -1)
				YYERROR;
		}
break;
case 151:
#line 1377 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (push_binop(0, yyvsp[0].v.number) == -1)
				YYERROR;
		}
break;
case 153:
#line 1384 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if ((yyval.v.number = parse_flags(yyvsp[0].v.string)) < 0) {
				yyerror("bad flags %s", yyvsp[0].v.string);
				free(yyvsp[0].v.string);
				YYERROR;
			}
			free(yyvsp[0].v.string);
		}
break;
case 158:
#line 1402 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			curflow->type = FLOWSPEC_TYPE_ICMP_TYPE;
			if (push_unary_numop(OP_EQ, yyvsp[0].v.number) == -1)
				YYERROR;
		}
break;
case 159:
#line 1407 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			int code;

			if ((code = geticmpcodebyname(yyvsp[-2].v.number, yyvsp[0].v.string, curflow->aid)) ==
			    -1) {
				yyerror("unknown icmp-code %s", yyvsp[0].v.string);
				free(yyvsp[0].v.string);
				YYERROR;
			}
			free(yyvsp[0].v.string);

			curflow->type = FLOWSPEC_TYPE_ICMP_TYPE;
			if (push_unary_numop(OP_EQ, yyvsp[-2].v.number) == -1)
				YYERROR;
			curflow->type = FLOWSPEC_TYPE_ICMP_CODE;
			if (push_unary_numop(OP_EQ, code) == -1)
				YYERROR;
		}
break;
case 160:
#line 1425 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.number < 0 || yyvsp[0].v.number > 255) {
				yyerror("illegal icmp-code %lld", yyvsp[0].v.number);
				YYERROR;
			}
			curflow->type = FLOWSPEC_TYPE_ICMP_TYPE;
			if (push_unary_numop(OP_EQ, yyvsp[-2].v.number) == -1)
				YYERROR;
			curflow->type = FLOWSPEC_TYPE_ICMP_CODE;
			if (push_unary_numop(OP_EQ, yyvsp[0].v.number) == -1)
				YYERROR;
		}
break;
case 161:
#line 1439 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			int type;

			if ((type = geticmptypebyname(yyvsp[0].v.string, curflow->aid)) ==
			    -1) {
				yyerror("unknown icmp-type %s", yyvsp[0].v.string);
				free(yyvsp[0].v.string);
				YYERROR;
			}
			yyval.v.number = type;
			free(yyvsp[0].v.string);
		}
break;
case 162:
#line 1451 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.number < 0 || yyvsp[0].v.number > 255) {
				yyerror("illegal icmp-type %lld", yyvsp[0].v.number);
				YYERROR;
			}
			yyval.v.number = yyvsp[0].v.number;
		}
break;
case 163:
#line 1460 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			int val;
			char *end;

			if (map_tos(yyvsp[0].v.string, &val))
				yyval.v.number = val;
			else if (yyvsp[0].v.string[0] == '0' && yyvsp[0].v.string[1] == 'x') {
				errno = 0;
				yyval.v.number = strtoul(yyvsp[0].v.string, &end, 16);
				if (errno || *end != '\0')
					yyval.v.number = 256;
			} else
				yyval.v.number = 256;
			if (yyval.v.number < 0 || yyval.v.number > 255) {
				yyerror("illegal tos value %s", yyvsp[0].v.string);
				free(yyvsp[0].v.string);
				YYERROR;
			}
			free(yyvsp[0].v.string);
		}
break;
case 164:
#line 1480 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.number < 0 || yyvsp[0].v.number > 255) {
				yyerror("illegal tos value %lld", yyvsp[0].v.number);
				YYERROR;
			}
			yyval.v.number = yyvsp[0].v.number;
		}
break;
case 169:
#line 1497 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (push_unary_numop(OP_EQ, yyvsp[0].v.number) == -1)
				YYERROR;
		}
break;
case 170:
#line 1501 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (push_unary_numop(yyvsp[-1].v.u8, yyvsp[0].v.number) == -1)
				YYERROR;
		}
break;
case 171:
#line 1505 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (push_binary_numop(yyvsp[-1].v.u8, yyvsp[-2].v.number, yyvsp[0].v.number) == -1)
				YYERROR;
		}
break;
case 172:
#line 1511 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.number < 0 || yyvsp[0].v.number > USHRT_MAX) {
				yyerror("illegal ptk length value %lld", yyvsp[0].v.number);
				YYERROR;
			}
			yyval.v.number = yyvsp[0].v.number;
		}
break;
case 173:
#line 1519 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.number = 1; }
break;
case 174:
#line 1520 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.number = 0; }
break;
case 175:
#line 1523 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.number = 0; }
break;
case 176:
#line 1524 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.number = 1; }
break;
case 177:
#line 1527 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			uint8_t	len;

			if (!host(yyvsp[0].v.string, &yyval.v.addr, &len)) {
				yyerror("could not parse address spec \"%s\"",
				    yyvsp[0].v.string);
				free(yyvsp[0].v.string);
				YYERROR;
			}
			free(yyvsp[0].v.string);

			if ((yyval.v.addr.aid == AID_INET && len != 32) ||
			    (yyval.v.addr.aid == AID_INET6 && len != 128)) {
				/* unreachable */
				yyerror("got prefixlen %u, expected %u",
				    len, yyval.v.addr.aid == AID_INET ? 32 : 128);
				YYERROR;
			}
		}
break;
case 178:
#line 1548 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			char	*s;
			if (yyvsp[0].v.number < 0 || yyvsp[0].v.number > 128) {
				yyerror("bad prefixlen %lld", yyvsp[0].v.number);
				free(yyvsp[-2].v.string);
				YYERROR;
			}
			if (asprintf(&s, "%s/%lld", yyvsp[-2].v.string, yyvsp[0].v.number) == -1)
				fatal(NULL);
			free(yyvsp[-2].v.string);

			if (!host(s, &yyval.v.prefix.prefix, &yyval.v.prefix.len)) {
				yyerror("could not parse address \"%s\"", s);
				free(s);
				YYERROR;
			}
			free(s);
		}
break;
case 179:
#line 1566 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			char	*s;

			/* does not match IPv6 */
			if (yyvsp[-2].v.number < 0 || yyvsp[-2].v.number > 255 || yyvsp[0].v.number < 0 || yyvsp[0].v.number > 32) {
				yyerror("bad prefix %lld/%lld", yyvsp[-2].v.number, yyvsp[0].v.number);
				YYERROR;
			}
			if (asprintf(&s, "%lld/%lld", yyvsp[-2].v.number, yyvsp[0].v.number) == -1)
				fatal(NULL);

			if (!host(s, &yyval.v.prefix.prefix, &yyval.v.prefix.len)) {
				yyerror("could not parse address \"%s\"", s);
				free(s);
				YYERROR;
			}
			free(s);
		}
break;
case 180:
#line 1586 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			memcpy(&yyval.v.prefix.prefix, &yyvsp[0].v.addr, sizeof(struct bgpd_addr));
			if (yyval.v.prefix.prefix.aid == AID_INET)
				yyval.v.prefix.len = 32;
			else
				yyval.v.prefix.len = 128;
		}
break;
case 182:
#line 1596 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.number = 0; }
break;
case 184:
#line 1600 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			u_int rdomain, label;

			if (get_mpe_config(yyvsp[0].v.string, &rdomain, &label) == -1) {
				if ((cmd_opts & BGPD_OPT_NOACTION) == 0) {
					yyerror("troubles getting config of %s",
					    yyvsp[0].v.string);
					free(yyvsp[0].v.string);
					free(yyvsp[-2].v.string);
					YYERROR;
				}
			}

			if (!(curvpn = calloc(1, sizeof(struct l3vpn))))
				fatal(NULL);
			strlcpy(curvpn->ifmpe, yyvsp[0].v.string, IFNAMSIZ);

			if (strlcpy(curvpn->descr, yyvsp[-2].v.string,
			    sizeof(curvpn->descr)) >=
			    sizeof(curvpn->descr)) {
				yyerror("descr \"%s\" too long: max %zu",
				    yyvsp[-2].v.string, sizeof(curvpn->descr) - 1);
				free(yyvsp[-2].v.string);
				free(yyvsp[0].v.string);
				free(curvpn);
				curvpn = NULL;
				YYERROR;
			}
			free(yyvsp[-2].v.string);
			free(yyvsp[0].v.string);

			TAILQ_INIT(&curvpn->import);
			TAILQ_INIT(&curvpn->export);
			TAILQ_INIT(&curvpn->net_l);
			curvpn->label = label;
			curvpn->rtableid = rdomain;
			netconf = &curvpn->net_l;
		}
break;
case 185:
#line 1637 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			/* insert into list */
			SIMPLEQ_INSERT_TAIL(&conf->l3vpns, curvpn, entry);
			curvpn = NULL;
			netconf = &conf->networks;
		}
break;
case 190:
#line 1651 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			struct community	ext;

			memset(&ext, 0, sizeof(ext));
			if (parseextcommunity(&ext, "rt", yyvsp[0].v.string) == -1) {
				free(yyvsp[0].v.string);
				YYERROR;
			}
			free(yyvsp[0].v.string);
			/*
			 * RD is almost encoded like an ext-community,
			 * but only almost so convert here.
			 */
			if (community_to_rd(&ext, &curvpn->rd) == -1) {
				yyerror("bad encoding of rd");
				YYERROR;
			}
		}
break;
case 191:
#line 1669 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			struct filter_set	*set;

			if ((set = calloc(1, sizeof(struct filter_set))) ==
			    NULL)
				fatal(NULL);
			set->type = ACTION_SET_COMMUNITY;
			if (parseextcommunity(&set->action.community,
			    yyvsp[-1].v.string, yyvsp[0].v.string) == -1) {
				free(yyvsp[0].v.string);
				free(yyvsp[-1].v.string);
				free(set);
				YYERROR;
			}
			free(yyvsp[0].v.string);
			free(yyvsp[-1].v.string);
			TAILQ_INSERT_TAIL(&curvpn->export, set, entry);
		}
break;
case 192:
#line 1687 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			struct filter_set	*set;

			if ((set = calloc(1, sizeof(struct filter_set))) ==
			    NULL)
				fatal(NULL);
			set->type = ACTION_SET_COMMUNITY;
			if (parseextcommunity(&set->action.community,
			    yyvsp[-1].v.string, yyvsp[0].v.string) == -1) {
				free(yyvsp[0].v.string);
				free(yyvsp[-1].v.string);
				free(set);
				YYERROR;
			}
			free(yyvsp[0].v.string);
			free(yyvsp[-1].v.string);
			TAILQ_INSERT_TAIL(&curvpn->import, set, entry);
		}
break;
case 193:
#line 1705 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.number == 0)
				curvpn->flags |= F_RIB_NOFIBSYNC;
			else
				curvpn->flags &= ~F_RIB_NOFIBSYNC;
		}
break;
case 195:
#line 1714 "../../../openbgpd-portable/src/bgpd/parse.y"
{ curpeer = new_peer(); }
break;
case 196:
#line 1715 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			memcpy(&curpeer->conf.remote_addr, &yyvsp[0].v.prefix.prefix,
			    sizeof(curpeer->conf.remote_addr));
			curpeer->conf.remote_masklen = yyvsp[0].v.prefix.len;
			if ((yyvsp[0].v.prefix.prefix.aid == AID_INET && yyvsp[0].v.prefix.len != 32) ||
			    (yyvsp[0].v.prefix.prefix.aid == AID_INET6 && yyvsp[0].v.prefix.len != 128))
				curpeer->conf.template = 1;
			if (get_id(curpeer)) {
				yyerror("get_id failed");
				YYERROR;
			}
		}
break;
case 197:
#line 1727 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			u_int		aid;

			if (curpeer_filter[0] != NULL)
				TAILQ_INSERT_TAIL(peerfilter_l,
				    curpeer_filter[0], entry);
			if (curpeer_filter[1] != NULL)
				TAILQ_INSERT_TAIL(peerfilter_l,
				    curpeer_filter[1], entry);
			curpeer_filter[0] = NULL;
			curpeer_filter[1] = NULL;

			/*
			 * Check if any MP capa is set, if none is set and
			 * and the default AID was not disabled via none then
			 * enable it. Finally fixup the disabled AID.
			 */
			for (aid = AID_MIN; aid < AID_MAX; aid++) {
				if (curpeer->conf.capabilities.mp[aid] > 0)
					break;
			}
			if (aid == AID_MAX &&
			    curpeer->conf.capabilities.mp[
			    curpeer->conf.remote_addr.aid] != -1)
				curpeer->conf.capabilities.mp[
				    curpeer->conf.remote_addr.aid] = 1;
			for (aid = AID_MIN; aid < AID_MAX; aid++) {
				if (curpeer->conf.capabilities.mp[aid] == -1)
					curpeer->conf.capabilities.mp[aid] = 0;
			}

			if (neighbor_consistent(curpeer) == -1) {
				free(curpeer);
				curpeer = curgroup;
				YYERROR;
			}
			if (RB_INSERT(peer_head, new_peers, curpeer) != NULL)
				fatalx("%s: peer tree is corrupt", __func__);
			curpeer = curgroup;
		}
break;
case 198:
#line 1769 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			curgroup = curpeer = new_group();
			if (strlcpy(curgroup->conf.group, yyvsp[0].v.string,
			    sizeof(curgroup->conf.group)) >=
			    sizeof(curgroup->conf.group)) {
				yyerror("group name \"%s\" too long: max %zu",
				    yyvsp[0].v.string, sizeof(curgroup->conf.group) - 1);
				free(yyvsp[0].v.string);
				free(curgroup);
				curgroup = NULL;
				YYERROR;
			}
			free(yyvsp[0].v.string);
			if (get_id(curgroup)) {
				yyerror("get_id failed");
				free(curgroup);
				curgroup = NULL;
				YYERROR;
			}
		}
break;
case 199:
#line 1788 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (curgroup_filter[0] != NULL)
				TAILQ_INSERT_TAIL(groupfilter_l,
				    curgroup_filter[0], entry);
			if (curgroup_filter[1] != NULL)
				TAILQ_INSERT_TAIL(groupfilter_l,
				    curgroup_filter[1], entry);
			curgroup_filter[0] = NULL;
			curgroup_filter[1] = NULL;

			free(curgroup);
			curgroup = NULL;
		}
break;
case 205:
#line 1810 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.number = 0; }
break;
case 206:
#line 1811 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.number < 1 || yyvsp[0].v.number > MAX_ADDPATH_COUNT) {
				yyerror("additional paths must be between "
				    "%u and %u", 1, MAX_ADDPATH_COUNT);
				YYERROR;
			}
			yyval.v.number = yyvsp[0].v.number;
		}
break;
case 207:
#line 1821 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.number = 0; }
break;
case 208:
#line 1822 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.number < 1 || yyvsp[0].v.number > MAX_ADDPATH_COUNT) {
				yyerror("maximum additional paths must be "
				    "between %u and %u", 1, MAX_ADDPATH_COUNT);
				YYERROR;
			}
			yyval.v.number = yyvsp[0].v.number;
		}
break;
case 216:
#line 1843 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			curpeer->conf.remote_as = yyvsp[0].v.number;
		}
break;
case 217:
#line 1846 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			curpeer->conf.local_as = yyvsp[0].v.number;
			if (yyvsp[0].v.number > USHRT_MAX)
				curpeer->conf.local_short_as = AS_TRANS;
			else
				curpeer->conf.local_short_as = yyvsp[0].v.number;
		}
break;
case 218:
#line 1853 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			curpeer->conf.local_as = yyvsp[-1].v.number;
			curpeer->conf.local_short_as = yyvsp[0].v.number;
		}
break;
case 219:
#line 1857 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (strlcpy(curpeer->conf.descr, yyvsp[0].v.string,
			    sizeof(curpeer->conf.descr)) >=
			    sizeof(curpeer->conf.descr)) {
				yyerror("descr \"%s\" too long: max %zu",
				    yyvsp[0].v.string, sizeof(curpeer->conf.descr) - 1);
				free(yyvsp[0].v.string);
				YYERROR;
			}
			free(yyvsp[0].v.string);
		}
break;
case 220:
#line 1868 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.addr.aid == AID_INET)
				memcpy(&curpeer->conf.local_addr_v4, &yyvsp[0].v.addr,
				    sizeof(curpeer->conf.local_addr_v4));
			else if (yyvsp[0].v.addr.aid == AID_INET6)
				memcpy(&curpeer->conf.local_addr_v6, &yyvsp[0].v.addr,
				    sizeof(curpeer->conf.local_addr_v6));
			else {
				yyerror("Unsupported address family %s for "
				    "local-addr", aid2str(yyvsp[0].v.addr.aid));
				YYERROR;
			}
		}
break;
case 221:
#line 1881 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[-1].v.number) {
				yyerror("bad local-address definition");
				YYERROR;
			}
			memset(&curpeer->conf.local_addr_v4, 0,
			    sizeof(curpeer->conf.local_addr_v4));
			memset(&curpeer->conf.local_addr_v6, 0,
			    sizeof(curpeer->conf.local_addr_v6));
		}
break;
case 222:
#line 1891 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.number < 2 || yyvsp[0].v.number > 255) {
				yyerror("invalid multihop distance %lld", yyvsp[0].v.number);
				YYERROR;
			}
			curpeer->conf.distance = yyvsp[0].v.number;
		}
break;
case 223:
#line 1898 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			curpeer->conf.passive = 1;
		}
break;
case 224:
#line 1901 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			curpeer->conf.down = 1;
		}
break;
case 225:
#line 1904 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			curpeer->conf.down = 1;
			if (strlcpy(curpeer->conf.reason, yyvsp[0].v.string,
				sizeof(curpeer->conf.reason)) >=
				sizeof(curpeer->conf.reason)) {
				    yyerror("shutdown reason too long");
				    free(yyvsp[0].v.string);
				    YYERROR;
			}
			free(yyvsp[0].v.string);
		}
break;
case 226:
#line 1915 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (!find_rib(yyvsp[0].v.string)) {
				yyerror("rib \"%s\" does not exist.", yyvsp[0].v.string);
				free(yyvsp[0].v.string);
				YYERROR;
			}
			if (strlcpy(curpeer->conf.rib, yyvsp[0].v.string,
			    sizeof(curpeer->conf.rib)) >=
			    sizeof(curpeer->conf.rib)) {
				yyerror("rib name \"%s\" too long: max %zu",
				    yyvsp[0].v.string, sizeof(curpeer->conf.rib) - 1);
				free(yyvsp[0].v.string);
				YYERROR;
			}
			free(yyvsp[0].v.string);
		}
break;
case 227:
#line 1931 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.number < MIN_HOLDTIME || yyvsp[0].v.number > USHRT_MAX) {
				yyerror("holdtime must be between %u and %u",
				    MIN_HOLDTIME, USHRT_MAX);
				YYERROR;
			}
			curpeer->conf.holdtime = yyvsp[0].v.number;
		}
break;
case 228:
#line 1939 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.number < MIN_HOLDTIME || yyvsp[0].v.number > USHRT_MAX) {
				yyerror("holdtime must be between %u and %u",
				    MIN_HOLDTIME, USHRT_MAX);
				YYERROR;
			}
			curpeer->conf.min_holdtime = yyvsp[0].v.number;
		}
break;
case 229:
#line 1947 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.number < MIN_HOLDTIME || yyvsp[0].v.number > CAPA_GR_TIMEMASK) {
				yyerror("staletime must be between %u and %u",
				    MIN_HOLDTIME, CAPA_GR_TIMEMASK);
				YYERROR;
			}
			curpeer->conf.staletime = yyvsp[0].v.number;
		}
break;
case 230:
#line 1955 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[-1].v.number == SAFI_NONE) {
				u_int		aid;
				uint8_t		safi;
				uint16_t	afi;

				for (aid = AID_MIN; aid < AID_MAX; aid++) {
					if (aid2afi(aid, &afi, &safi) == -1 ||
					    afi != yyvsp[-2].v.number)
						continue;
					curpeer->conf.capabilities.mp[aid] = -1;
				}
			} else {
				uint8_t aid;

				if (afi2aid(yyvsp[-2].v.number, yyvsp[-1].v.number, &aid) == -1) {
					yyerror("unknown AFI/SAFI pair");
					YYERROR;
				}
				if (yyvsp[0].v.number)
					curpeer->conf.capabilities.mp[aid] = 2;
				else
					curpeer->conf.capabilities.mp[aid] = 1;
			}
		}
break;
case 231:
#line 1980 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.number)
				curpeer->conf.capabilities.mp[AID_EVPN] = 2;
			else
				curpeer->conf.capabilities.mp[AID_EVPN] = 1;
		}
break;
case 232:
#line 1986 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			curpeer->conf.capabilities.refresh = yyvsp[0].v.number;
		}
break;
case 233:
#line 1989 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			curpeer->conf.capabilities.enhanced_rr = yyvsp[0].v.number;
		}
break;
case 234:
#line 1992 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			curpeer->conf.capabilities.grestart.restart = yyvsp[0].v.number;
		}
break;
case 235:
#line 1995 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			curpeer->conf.capabilities.grestart.grnotification = yyvsp[0].v.number;
		}
break;
case 236:
#line 1998 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			curpeer->conf.capabilities.as4byte = yyvsp[0].v.number;
		}
break;
case 237:
#line 2001 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			int8_t *ap = curpeer->conf.capabilities.add_path;
			u_int i;

			for (i = AID_MIN; i < AID_MAX; i++) {
				if (yyvsp[0].v.number) {
					if (yyvsp[0].v.number == 2)
						ap[i] |= CAPA_AP_RECV_ENFORCE;
					ap[i] |= CAPA_AP_RECV;
				} else
					ap[i] &= ~CAPA_AP_RECV;
			}
		}
break;
case 238:
#line 2014 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			int8_t *ap = curpeer->conf.capabilities.add_path;
			enum addpath_mode mode;
			u_int i;

			if (!strcmp(yyvsp[-3].v.string, "no")) {
				free(yyvsp[-3].v.string);
				if (yyvsp[-2].v.number != 0 || yyvsp[-1].v.number != 0 || yyvsp[0].v.number != 0) {
					yyerror("cannot use additional options "
					    "for 'add-path send no'");
					YYERROR;
				}
				mode = ADDPATH_EVAL_NONE;
			} else if (!strcmp(yyvsp[-3].v.string, "all")) {
				free(yyvsp[-3].v.string);
				if (yyvsp[-2].v.number != 0 || yyvsp[-1].v.number != 0) {
					yyerror("cannot use additional options "
					    "for 'add-path send all'");
					YYERROR;
				}
				mode = ADDPATH_EVAL_ALL;
			} else if (!strcmp(yyvsp[-3].v.string, "best")) {
				free(yyvsp[-3].v.string);
				if (yyvsp[-1].v.number != 0) {
					yyerror("cannot use max option "
					    "for 'add-path send best'");
					YYERROR;
				}
				mode = ADDPATH_EVAL_BEST;
			} else if (!strcmp(yyvsp[-3].v.string, "ecmp")) {
				free(yyvsp[-3].v.string);
				mode = ADDPATH_EVAL_ECMP;
			} else if (!strcmp(yyvsp[-3].v.string, "as-wide-best")) {
				free(yyvsp[-3].v.string);
				mode = ADDPATH_EVAL_AS_WIDE;
			} else {
				yyerror("announce add-path send: "
				    "unknown mode \"%s\"", yyvsp[-3].v.string);
				free(yyvsp[-3].v.string);
				YYERROR;
			}
			for (i = AID_MIN; i < AID_MAX; i++) {
				if (mode != ADDPATH_EVAL_NONE) {
					if (yyvsp[0].v.number)
						ap[i] |= CAPA_AP_SEND_ENFORCE;
					ap[i] |= CAPA_AP_SEND;
				} else
					ap[i] &= ~CAPA_AP_SEND;
			}
			curpeer->conf.eval.mode = mode;
			curpeer->conf.eval.extrapaths = yyvsp[-2].v.number;
			curpeer->conf.eval.maxpaths = yyvsp[-1].v.number;
		}
break;
case 239:
#line 2067 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			curpeer->conf.capabilities.policy = yyvsp[0].v.number;
		}
break;
case 240:
#line 2070 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			curpeer->conf.capabilities.ext_msg = yyvsp[0].v.number;
		}
break;
case 241:
#line 2073 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.number != 0) {
				struct rde_rib *rr;

				rr = find_rib("Loc-RIB");
				if (rr == NULL)
					fatalx("cannot find the main RIB!");

				if ((rr->flags & F_RIB_NOFIBSYNC) == 0) {
					yyerror("announce extended nexthop "
					    "requires 'fib-update no'");
					YYERROR;
				}
			}
			curpeer->conf.capabilities.ext_nh[AID_VPN_IPv4] =
			    curpeer->conf.capabilities.ext_nh[AID_INET] = yyvsp[0].v.number;
		}
break;
case 242:
#line 2090 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (strcmp(yyvsp[0].v.string, "provider") == 0) {
				curpeer->conf.role = ROLE_PROVIDER;
			} else if (strcmp(yyvsp[0].v.string, "rs") == 0) {
				curpeer->conf.role = ROLE_RS;
			} else if (strcmp(yyvsp[0].v.string, "rs-client") == 0) {
				curpeer->conf.role = ROLE_RS_CLIENT;
			} else if (strcmp(yyvsp[0].v.string, "customer") == 0) {
				curpeer->conf.role = ROLE_CUSTOMER;
			} else if (strcmp(yyvsp[0].v.string, "peer") == 0) {
				curpeer->conf.role = ROLE_PEER;
			} else {
				yyerror("syntax error, one of none, provider, "
				    "rs, rs-client, customer, peer expected");
				free(yyvsp[0].v.string);
				YYERROR;
			}
			free(yyvsp[0].v.string);
		}
break;
case 243:
#line 2109 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			curpeer->conf.role = ROLE_NONE;
		}
break;
case 244:
#line 2112 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			curpeer->conf.export_type = EXPORT_NONE;
		}
break;
case 245:
#line 2115 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			curpeer->conf.export_type = EXPORT_DEFAULT_ROUTE;
		}
break;
case 246:
#line 2118 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.number)
				curpeer->conf.enforce_as = ENFORCE_AS_ON;
			else
				curpeer->conf.enforce_as = ENFORCE_AS_OFF;
		}
break;
case 247:
#line 2124 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.number)
				curpeer->conf.enforce_local_as = ENFORCE_AS_ON;
			else
				curpeer->conf.enforce_local_as = ENFORCE_AS_OFF;
		}
break;
case 248:
#line 2130 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.number) {
				struct filter_rule	*r;
				struct filter_set	*s;

				if ((s = calloc(1, sizeof(struct filter_set)))
				    == NULL)
					fatal(NULL);
				s->type = ACTION_SET_AS_OVERRIDE;

				r = get_rule(s->type);
				if (merge_filterset(&r->set, s) == -1)
					YYERROR;
			}
		}
break;
case 249:
#line 2145 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[-1].v.number < 0 || yyvsp[-1].v.number > UINT_MAX) {
				yyerror("bad maximum number of prefixes");
				YYERROR;
			}
			curpeer->conf.max_prefix = yyvsp[-1].v.number;
			curpeer->conf.max_prefix_restart = yyvsp[0].v.number;
		}
break;
case 250:
#line 2153 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[-2].v.number < 0 || yyvsp[-2].v.number > UINT_MAX) {
				yyerror("bad maximum number of prefixes");
				YYERROR;
			}
			curpeer->conf.max_out_prefix = yyvsp[-2].v.number;
			curpeer->conf.max_out_prefix_restart = yyvsp[0].v.number;
		}
break;
case 251:
#line 2161 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (merge_auth_conf(&curpeer->auth_conf, &yyvsp[0].v.authconf) == 0)
				YYERROR;
		}
break;
case 252:
#line 2165 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			curpeer->conf.ttlsec = yyvsp[0].v.number;
		}
break;
case 253:
#line 2168 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			struct filter_rule	*r;

			r = get_rule(yyvsp[0].v.filter_set->type);
			if (merge_filterset(&r->set, yyvsp[0].v.filter_set) == -1)
				YYERROR;
		}
break;
case 254:
#line 2175 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			struct filter_rule	*r;
			struct filter_set	*s;

			while ((s = TAILQ_FIRST(yyvsp[-2].v.filter_set_head)) != NULL) {
				TAILQ_REMOVE(yyvsp[-2].v.filter_set_head, s, entry);
				r = get_rule(s->type);
				if (merge_filterset(&r->set, s) == -1)
					YYERROR;
			}
			free(yyvsp[-2].v.filter_set_head);
		}
break;
case 256:
#line 2188 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if ((conf->flags & BGPD_FLAG_REFLECTOR) &&
			    conf->clusterid != 0) {
				yyerror("only one route reflector "
				    "cluster allowed");
				YYERROR;
			}
			conf->flags |= BGPD_FLAG_REFLECTOR;
			curpeer->conf.reflector_client = 1;
		}
break;
case 257:
#line 2198 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.addr.aid != AID_INET) {
				yyerror("route reflector cluster-id must be "
				    "an IPv4 address");
				YYERROR;
			}
			if ((conf->flags & BGPD_FLAG_REFLECTOR) &&
			    conf->clusterid != ntohl(yyvsp[0].v.addr.v4.s_addr)) {
				yyerror("only one route reflector "
				    "cluster allowed");
				YYERROR;
			}
			conf->flags |= BGPD_FLAG_REFLECTOR;
			curpeer->conf.reflector_client = 1;
			conf->clusterid = ntohl(yyvsp[0].v.addr.v4.s_addr);
		}
break;
case 258:
#line 2214 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (strlcpy(curpeer->conf.if_depend, yyvsp[0].v.string,
			    sizeof(curpeer->conf.if_depend)) >=
			    sizeof(curpeer->conf.if_depend)) {
				yyerror("interface name \"%s\" too long: "
				    "max %zu", yyvsp[0].v.string,
				    sizeof(curpeer->conf.if_depend) - 1);
				free(yyvsp[0].v.string);
				YYERROR;
			}
			free(yyvsp[0].v.string);
		}
break;
case 259:
#line 2226 "../../../openbgpd-portable/src/bgpd/parse.y"
{
#ifdef HAVE_CARP
			if (strlcpy(curpeer->conf.demote_group, yyvsp[0].v.string,
			    sizeof(curpeer->conf.demote_group)) >=
			    sizeof(curpeer->conf.demote_group)) {
				yyerror("demote group name \"%s\" too long: "
				    "max %zu", yyvsp[0].v.string,
				    sizeof(curpeer->conf.demote_group) - 1);
				free(yyvsp[0].v.string);
				YYERROR;
			}
			free(yyvsp[0].v.string);
			if (carp_demote_init(curpeer->conf.demote_group,
			    cmd_opts & BGPD_OPT_FORCE_DEMOTE) == -1) {
				yyerror("error initializing group \"%s\"",
				    curpeer->conf.demote_group);
				YYERROR;
			}
#else
			yyerror("carp demote not supported");
			free(yyvsp[0].v.string);
			YYERROR;
#endif
		}
break;
case 260:
#line 2250 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.number == 1)
				curpeer->conf.flags |= PEERFLAG_TRANS_AS;
			else
				curpeer->conf.flags &= ~PEERFLAG_TRANS_AS;
		}
break;
case 261:
#line 2256 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (!strcmp(yyvsp[0].v.string, "updates"))
				curpeer->conf.flags |= PEERFLAG_LOG_UPDATES;
			else if (!strcmp(yyvsp[0].v.string, "no"))
				curpeer->conf.flags &= ~PEERFLAG_LOG_UPDATES;
			else {
				free(yyvsp[0].v.string);
				YYERROR;
			}
			free(yyvsp[0].v.string);
		}
break;
case 262:
#line 2267 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.number == 1)
				curpeer->conf.flags &= ~PEERFLAG_PERMIT_AS_SET;
			else
				curpeer->conf.flags |= PEERFLAG_PERMIT_AS_SET;
		}
break;
case 263:
#line 2273 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			curpeer->conf.remote_port = yyvsp[0].v.number;
		}
break;
case 264:
#line 2276 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (!strcmp(yyvsp[0].v.string, "all"))
				curpeer->conf.flags |= PEERFLAG_EVALUATE_ALL;
			else if (!strcmp(yyvsp[0].v.string, "default"))
				curpeer->conf.flags &= ~PEERFLAG_EVALUATE_ALL;
			else {
				yyerror("rde evaluate: "
				    "unknown setting \"%s\"", yyvsp[0].v.string);
				free(yyvsp[0].v.string);
				YYERROR;
			}
			free(yyvsp[0].v.string);
		}
break;
case 265:
#line 2291 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.number = 0; }
break;
case 266:
#line 2292 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.number < 1 || yyvsp[0].v.number > USHRT_MAX) {
				yyerror("restart out of range. 1 to %u minutes",
				    USHRT_MAX);
				YYERROR;
			}
			yyval.v.number = yyvsp[0].v.number;
		}
break;
case 267:
#line 2302 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.number = AFI_IPv4; }
break;
case 268:
#line 2303 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.number = AFI_IPv6; }
break;
case 269:
#line 2306 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.number = SAFI_NONE; }
break;
case 270:
#line 2307 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.number = SAFI_UNICAST; }
break;
case 271:
#line 2308 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.number = SAFI_MPLSVPN; }
break;
case 272:
#line 2309 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.number = SAFI_FLOWSPEC; }
break;
case 273:
#line 2312 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.number = 1; }
break;
case 274:
#line 2313 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.number = 0; }
break;
case 275:
#line 2316 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			memset(&yyval.v.authconf, 0, sizeof(yyval.v.authconf));
			if (strlcpy(yyval.v.authconf.md5key, yyvsp[0].v.string, sizeof(yyval.v.authconf.md5key)) >=
			    sizeof(yyval.v.authconf.md5key)) {
				yyerror("tcp md5sig password too long: max %zu",
				    sizeof(yyval.v.authconf.md5key) - 1);
				free(yyvsp[0].v.string);
				YYERROR;
			}
			yyval.v.authconf.method = AUTH_MD5SIG;
			yyval.v.authconf.md5key_len = strlen(yyvsp[0].v.string);
			free(yyvsp[0].v.string);
		}
break;
case 276:
#line 2329 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			memset(&yyval.v.authconf, 0, sizeof(yyval.v.authconf));
			if (str2key(yyvsp[0].v.string, yyval.v.authconf.md5key, sizeof(yyval.v.authconf.md5key)) == -1) {
				free(yyvsp[0].v.string);
				YYERROR;
			}
			yyval.v.authconf.method = AUTH_MD5SIG;
			yyval.v.authconf.md5key_len = strlen(yyvsp[0].v.string) / 2;
			free(yyvsp[0].v.string);
		}
break;
case 277:
#line 2339 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			memset(&yyval.v.authconf, 0, sizeof(yyval.v.authconf));
			if (yyvsp[-1].v.number)
				yyval.v.authconf.method = AUTH_IPSEC_IKE_ESP;
			else
				yyval.v.authconf.method = AUTH_IPSEC_IKE_AH;
		}
break;
case 278:
#line 2346 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			enum auth_alg	auth_alg;
			uint8_t		keylen;

			memset(&yyval.v.authconf, 0, sizeof(yyval.v.authconf));
			if (!strcmp(yyvsp[-2].v.string, "sha1")) {
				auth_alg = AUTH_AALG_SHA1HMAC;
				keylen = 20;
			} else if (!strcmp(yyvsp[-2].v.string, "md5")) {
				auth_alg = AUTH_AALG_MD5HMAC;
				keylen = 16;
			} else {
				yyerror("unknown auth algorithm \"%s\"", yyvsp[-2].v.string);
				free(yyvsp[-2].v.string);
				free(yyvsp[-1].v.string);
				YYERROR;
			}
			free(yyvsp[-2].v.string);

			if (strlen(yyvsp[-1].v.string) / 2 != keylen) {
				yyerror("auth key len: must be %u bytes, "
				    "is %zu bytes", keylen, strlen(yyvsp[-1].v.string) / 2);
				free(yyvsp[-1].v.string);
				YYERROR;
			}

			if (yyvsp[-6].v.number)
				yyval.v.authconf.method = AUTH_IPSEC_MANUAL_ESP;
			else {
				if (yyvsp[0].v.encspec.enc_alg) {
					yyerror("\"ipsec ah\" doesn't take "
					    "encryption keys");
					free(yyvsp[-1].v.string);
					YYERROR;
				}
				yyval.v.authconf.method = AUTH_IPSEC_MANUAL_AH;
			}

			if (yyvsp[-3].v.number <= SPI_RESERVED_MAX || yyvsp[-3].v.number > UINT_MAX) {
				yyerror("bad spi number %lld", yyvsp[-3].v.number);
				free(yyvsp[-1].v.string);
				YYERROR;
			}

			if (yyvsp[-5].v.number == 1) {
				if (str2key(yyvsp[-1].v.string, yyval.v.authconf.auth_key_in,
				    sizeof(yyval.v.authconf.auth_key_in)) == -1) {
					free(yyvsp[-1].v.string);
					YYERROR;
				}
				yyval.v.authconf.spi_in = yyvsp[-3].v.number;
				yyval.v.authconf.auth_alg_in = auth_alg;
				yyval.v.authconf.enc_alg_in = yyvsp[0].v.encspec.enc_alg;
				memcpy(&yyval.v.authconf.enc_key_in, &yyvsp[0].v.encspec.enc_key,
				    sizeof(yyval.v.authconf.enc_key_in));
				yyval.v.authconf.enc_keylen_in = yyvsp[0].v.encspec.enc_key_len;
				yyval.v.authconf.auth_keylen_in = keylen;
			} else {
				if (str2key(yyvsp[-1].v.string, yyval.v.authconf.auth_key_out,
				    sizeof(yyval.v.authconf.auth_key_out)) == -1) {
					free(yyvsp[-1].v.string);
					YYERROR;
				}
				yyval.v.authconf.spi_out = yyvsp[-3].v.number;
				yyval.v.authconf.auth_alg_out = auth_alg;
				yyval.v.authconf.enc_alg_out = yyvsp[0].v.encspec.enc_alg;
				memcpy(&yyval.v.authconf.enc_key_out, &yyvsp[0].v.encspec.enc_key,
				    sizeof(yyval.v.authconf.enc_key_out));
				yyval.v.authconf.enc_keylen_out = yyvsp[0].v.encspec.enc_key_len;
				yyval.v.authconf.auth_keylen_out = keylen;
			}
			free(yyvsp[-1].v.string);
		}
break;
case 279:
#line 2421 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.number = 1; }
break;
case 280:
#line 2422 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.number = 0; }
break;
case 281:
#line 2425 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			memset(&yyval.v.encspec, 0, sizeof(yyval.v.encspec));
		}
break;
case 282:
#line 2428 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			memset(&yyval.v.encspec, 0, sizeof(yyval.v.encspec));
			if (!strcmp(yyvsp[-1].v.string, "3des") || !strcmp(yyvsp[-1].v.string, "3des-cbc")) {
				yyval.v.encspec.enc_alg = AUTH_EALG_3DESCBC;
				yyval.v.encspec.enc_key_len = 21; /* XXX verify */
			} else if (!strcmp(yyvsp[-1].v.string, "aes") ||
			    !strcmp(yyvsp[-1].v.string, "aes-128-cbc")) {
				yyval.v.encspec.enc_alg = AUTH_EALG_AES;
				yyval.v.encspec.enc_key_len = 16;
			} else {
				yyerror("unknown enc algorithm \"%s\"", yyvsp[-1].v.string);
				free(yyvsp[-1].v.string);
				free(yyvsp[0].v.string);
				YYERROR;
			}
			free(yyvsp[-1].v.string);

			if (strlen(yyvsp[0].v.string) / 2 != yyval.v.encspec.enc_key_len) {
				yyerror("enc key length wrong: should be %u "
				    "bytes, is %zu bytes",
				    yyval.v.encspec.enc_key_len * 2, strlen(yyvsp[0].v.string));
				free(yyvsp[0].v.string);
				YYERROR;
			}

			if (str2key(yyvsp[0].v.string, yyval.v.encspec.enc_key, sizeof(yyval.v.encspec.enc_key)) == -1) {
				free(yyvsp[0].v.string);
				YYERROR;
			}
			free(yyvsp[0].v.string);
		}
break;
case 283:
#line 2463 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			struct filter_rule	 r;
			struct filter_rib_l	 *rb, *rbnext;

			memset(&r, 0, sizeof(r));
			r.action = yyvsp[-6].v.u8;
			r.quick = yyvsp[-5].v.u8;
			r.dir = yyvsp[-3].v.u8;
			if (yyvsp[-4].v.filter_rib) {
				if (r.dir != DIR_IN) {
					yyerror("rib only allowed on \"from\" "
					    "rules.");

					for (rb = yyvsp[-4].v.filter_rib; rb != NULL; rb = rbnext) {
						rbnext = rb->next;
						free(rb);
					}
					YYERROR;
				}
			}
			if (expand_rule(&r, yyvsp[-4].v.filter_rib, yyvsp[-2].v.filter_peers, &yyvsp[-1].v.filter_match, yyvsp[0].v.filter_set_head) == -1)
				YYERROR;
		}
break;
case 284:
#line 2488 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.u8 = ACTION_ALLOW; }
break;
case 285:
#line 2489 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.u8 = ACTION_DENY; }
break;
case 286:
#line 2490 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.u8 = ACTION_NONE; }
break;
case 287:
#line 2493 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.u8 = 0; }
break;
case 288:
#line 2494 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.u8 = 1; }
break;
case 289:
#line 2497 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.u8 = DIR_IN; }
break;
case 290:
#line 2498 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.u8 = DIR_OUT; }
break;
case 291:
#line 2501 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.filter_rib = NULL; }
break;
case 292:
#line 2502 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.filter_rib = yyvsp[0].v.filter_rib; }
break;
case 293:
#line 2503 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.filter_rib = yyvsp[-2].v.filter_rib; }
break;
case 294:
#line 2505 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.filter_rib = yyvsp[0].v.filter_rib; }
break;
case 295:
#line 2506 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			yyvsp[0].v.filter_rib->next = yyvsp[-2].v.filter_rib;
			yyval.v.filter_rib = yyvsp[0].v.filter_rib;
		}
break;
case 296:
#line 2512 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (!find_rib(yyvsp[0].v.string)) {
				yyerror("rib \"%s\" does not exist.", yyvsp[0].v.string);
				free(yyvsp[0].v.string);
				YYERROR;
			}
			if ((yyval.v.filter_rib = calloc(1, sizeof(struct filter_rib_l))) ==
			    NULL)
				fatal(NULL);
			yyval.v.filter_rib->next = NULL;
			if (strlcpy(yyval.v.filter_rib->name, yyvsp[0].v.string, sizeof(yyval.v.filter_rib->name)) >=
			    sizeof(yyval.v.filter_rib->name)) {
				yyerror("rib name \"%s\" too long: "
				    "max %zu", yyvsp[0].v.string, sizeof(yyval.v.filter_rib->name) - 1);
				free(yyvsp[0].v.string);
				free(yyval.v.filter_rib);
				YYERROR;
			}
			free(yyvsp[0].v.string);
		}
break;
case 298:
#line 2535 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.filter_peers = yyvsp[-2].v.filter_peers; }
break;
case 299:
#line 2538 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.filter_peers = yyvsp[0].v.filter_peers; }
break;
case 300:
#line 2539 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			yyvsp[0].v.filter_peers->next = yyvsp[-2].v.filter_peers;
			yyval.v.filter_peers = yyvsp[0].v.filter_peers;
		}
break;
case 301:
#line 2545 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if ((yyval.v.filter_peers = calloc(1, sizeof(struct filter_peers_l))) ==
			    NULL)
				fatal(NULL);
			yyval.v.filter_peers->p.peerid = yyval.v.filter_peers->p.groupid = 0;
			yyval.v.filter_peers->next = NULL;
		}
break;
case 302:
#line 2552 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			struct peer *p;

			if ((yyval.v.filter_peers = calloc(1, sizeof(struct filter_peers_l))) ==
			    NULL)
				fatal(NULL);
			yyval.v.filter_peers->p.remote_as = yyval.v.filter_peers->p.groupid = yyval.v.filter_peers->p.peerid = 0;
			yyval.v.filter_peers->next = NULL;
			RB_FOREACH(p, peer_head, new_peers)
				if (!memcmp(&p->conf.remote_addr,
				    &yyvsp[0].v.addr, sizeof(p->conf.remote_addr))) {
					yyval.v.filter_peers->p.peerid = p->conf.id;
					break;
				}
			if (yyval.v.filter_peers->p.peerid == 0) {
				yyerror("no such peer: %s", log_addr(&yyvsp[0].v.addr));
				free(yyval.v.filter_peers);
				YYERROR;
			}
		}
break;
case 303:
#line 2572 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if ((yyval.v.filter_peers = calloc(1, sizeof(struct filter_peers_l))) ==
			    NULL)
				fatal(NULL);
			yyval.v.filter_peers->p.groupid = yyval.v.filter_peers->p.peerid = 0;
			yyval.v.filter_peers->p.remote_as = yyvsp[0].v.number;
		}
break;
case 304:
#line 2579 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			struct peer *p;

			if ((yyval.v.filter_peers = calloc(1, sizeof(struct filter_peers_l))) ==
			    NULL)
				fatal(NULL);
			yyval.v.filter_peers->p.remote_as = yyval.v.filter_peers->p.peerid = 0;
			yyval.v.filter_peers->next = NULL;
			RB_FOREACH(p, peer_head, new_peers)
				if (!strcmp(p->conf.group, yyvsp[0].v.string)) {
					yyval.v.filter_peers->p.groupid = p->conf.groupid;
					break;
				}
			if (yyval.v.filter_peers->p.groupid == 0) {
				yyerror("no such group: \"%s\"", yyvsp[0].v.string);
				free(yyvsp[0].v.string);
				free(yyval.v.filter_peers);
				YYERROR;
			}
			free(yyvsp[0].v.string);
		}
break;
case 305:
#line 2600 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if ((yyval.v.filter_peers = calloc(1, sizeof(struct filter_peers_l))) ==
			    NULL)
				fatal(NULL);
			yyval.v.filter_peers->p.ebgp = 1;
		}
break;
case 306:
#line 2606 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if ((yyval.v.filter_peers = calloc(1, sizeof(struct filter_peers_l))) ==
			    NULL)
				fatal(NULL);
			yyval.v.filter_peers->p.ibgp = 1;
		}
break;
case 307:
#line 2614 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.prefixlen.op == OP_NONE) {
				yyvsp[0].v.prefixlen.op = OP_RANGE;
				yyvsp[0].v.prefixlen.len_min = 0;
				yyvsp[0].v.prefixlen.len_max = -1;
			}
			if ((yyval.v.filter_prefix = calloc(1, sizeof(struct filter_prefix_l))) ==
			    NULL)
				fatal(NULL);
			yyval.v.filter_prefix->p.addr.aid = AID_INET;
			if (merge_prefixspec(&yyval.v.filter_prefix->p, &yyvsp[0].v.prefixlen) == -1) {
				free(yyval.v.filter_prefix);
				YYERROR;
			}
		}
break;
case 308:
#line 2629 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.prefixlen.op == OP_NONE) {
				yyvsp[0].v.prefixlen.op = OP_RANGE;
				yyvsp[0].v.prefixlen.len_min = 0;
				yyvsp[0].v.prefixlen.len_max = -1;
			}
			if ((yyval.v.filter_prefix = calloc(1, sizeof(struct filter_prefix_l))) ==
			    NULL)
				fatal(NULL);
			yyval.v.filter_prefix->p.addr.aid = AID_INET6;
			if (merge_prefixspec(&yyval.v.filter_prefix->p, &yyvsp[0].v.prefixlen) == -1) {
				free(yyval.v.filter_prefix);
				YYERROR;
			}
		}
break;
case 309:
#line 2644 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.filter_prefix = yyvsp[0].v.filter_prefix; }
break;
case 310:
#line 2645 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.filter_prefix = yyvsp[-1].v.filter_prefix; }
break;
case 312:
#line 2649 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.filter_prefix = yyvsp[-1].v.filter_prefix; }
break;
case 313:
#line 2651 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			struct filter_prefix_l	*p;

			/* merge, both can be lists */
			for (p = yyvsp[-2].v.filter_prefix; p != NULL && p->next != NULL; p = p->next)
				;	/* nothing */
			if (p != NULL)
				p->next = yyvsp[0].v.filter_prefix;
			yyval.v.filter_prefix = yyvsp[-2].v.filter_prefix;
		}
break;
case 314:
#line 2662 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.filter_prefix = yyvsp[0].v.filter_prefix; }
break;
case 315:
#line 2663 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			yyvsp[0].v.filter_prefix->next = yyvsp[-2].v.filter_prefix;
			yyval.v.filter_prefix = yyvsp[0].v.filter_prefix;
		}
break;
case 316:
#line 2669 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if ((yyval.v.filter_prefix = calloc(1, sizeof(struct filter_prefix_l))) ==
			    NULL)
				fatal(NULL);
			memcpy(&yyval.v.filter_prefix->p.addr, &yyvsp[-1].v.prefix.prefix,
			    sizeof(yyval.v.filter_prefix->p.addr));
			yyval.v.filter_prefix->p.len = yyvsp[-1].v.prefix.len;

			if (merge_prefixspec(&yyval.v.filter_prefix->p, &yyvsp[0].v.prefixlen) == -1) {
				free(yyval.v.filter_prefix);
				YYERROR;
			}
		}
break;
case 318:
#line 2685 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.filter_as = yyvsp[-1].v.filter_as; }
break;
case 320:
#line 2689 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			struct filter_as_l	*a;

			/* merge, both can be lists */
			for (a = yyvsp[-2].v.filter_as; a != NULL && a->next != NULL; a = a->next)
				;	/* nothing */
			if (a != NULL)
				a->next = yyvsp[0].v.filter_as;
			yyval.v.filter_as = yyvsp[-2].v.filter_as;
		}
break;
case 321:
#line 2701 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			yyval.v.filter_as = yyvsp[0].v.filter_as;
			yyval.v.filter_as->a.type = yyvsp[-1].v.u8;
		}
break;
case 322:
#line 2705 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			struct filter_as_l	*a;

			yyval.v.filter_as = yyvsp[-1].v.filter_as;
			for (a = yyval.v.filter_as; a != NULL; a = a->next)
				a->a.type = yyvsp[-3].v.u8;
		}
break;
case 323:
#line 2712 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (as_sets_lookup(&conf->as_sets, yyvsp[0].v.string) == NULL) {
				yyerror("as-set \"%s\" not defined", yyvsp[0].v.string);
				free(yyvsp[0].v.string);
				YYERROR;
			}
			if ((yyval.v.filter_as = calloc(1, sizeof(struct filter_as_l))) ==
			    NULL)
				fatal(NULL);
			yyval.v.filter_as->a.type = yyvsp[-2].v.u8;
			yyval.v.filter_as->a.flags = AS_FLAG_AS_SET_NAME;
			if (strlcpy(yyval.v.filter_as->a.name, yyvsp[0].v.string, sizeof(yyval.v.filter_as->a.name)) >=
			    sizeof(yyval.v.filter_as->a.name)) {
				yyerror("as-set name \"%s\" too long: "
				    "max %zu", yyvsp[0].v.string, sizeof(yyval.v.filter_as->a.name) - 1);
				free(yyvsp[0].v.string);
				free(yyval.v.filter_as);
				YYERROR;
			}
			free(yyvsp[0].v.string);
		}
break;
case 325:
#line 2736 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.filter_as = yyvsp[-1].v.filter_as; }
break;
case 326:
#line 2738 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			struct filter_as_l	*a;

			/* merge, both can be lists */
			for (a = yyvsp[-2].v.filter_as; a != NULL && a->next != NULL; a = a->next)
				;	/* nothing */
			if (a != NULL)
				a->next = yyvsp[0].v.filter_as;
			yyval.v.filter_as = yyvsp[-2].v.filter_as;
		}
break;
case 328:
#line 2751 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			yyvsp[0].v.filter_as->next = yyvsp[-2].v.filter_as;
			yyval.v.filter_as = yyvsp[0].v.filter_as;
		}
break;
case 329:
#line 2757 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if ((yyval.v.filter_as = calloc(1, sizeof(struct filter_as_l))) ==
			    NULL)
				fatal(NULL);
			yyval.v.filter_as->a.as_min = yyvsp[0].v.number;
			yyval.v.filter_as->a.as_max = yyvsp[0].v.number;
			yyval.v.filter_as->a.op = OP_EQ;
		}
break;
case 330:
#line 2765 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if ((yyval.v.filter_as = calloc(1, sizeof(struct filter_as_l))) ==
			    NULL)
				fatal(NULL);
			yyval.v.filter_as->a.flags = AS_FLAG_NEIGHBORAS;
		}
break;
case 331:
#line 2771 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if ((yyval.v.filter_as = calloc(1, sizeof(struct filter_as_l))) ==
			    NULL)
				fatal(NULL);
			yyval.v.filter_as->a.op = yyvsp[-1].v.u8;
			yyval.v.filter_as->a.as_min = yyvsp[0].v.number;
			yyval.v.filter_as->a.as_max = yyvsp[0].v.number;
		}
break;
case 332:
#line 2779 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if ((yyval.v.filter_as = calloc(1, sizeof(struct filter_as_l))) ==
			    NULL)
				fatal(NULL);
			if (yyvsp[-2].v.number >= yyvsp[0].v.number) {
				yyerror("start AS is bigger than end");
				YYERROR;
			}
			yyval.v.filter_as->a.op = yyvsp[-1].v.u8;
			yyval.v.filter_as->a.as_min = yyvsp[-2].v.number;
			yyval.v.filter_as->a.as_max = yyvsp[0].v.number;
		}
break;
case 333:
#line 2793 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			memset(&yyval.v.filter_match, 0, sizeof(yyval.v.filter_match));
		}
break;
case 334:
#line 2796 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			memset(&fmopts, 0, sizeof(fmopts));
		}
break;
case 335:
#line 2799 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			memcpy(&yyval.v.filter_match, &fmopts, sizeof(yyval.v.filter_match));
		}
break;
case 338:
#line 2808 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (fmopts.prefix_l != NULL) {
				yyerror("\"prefix\" already specified");
				YYERROR;
			}
			if (fmopts.m.prefixset.name[0] != '\0') {
				yyerror("\"prefix-set\" already specified, "
				    "cannot be used with \"prefix\" in the "
				    "same filter rule");
				YYERROR;
			}
			fmopts.prefix_l = yyvsp[0].v.filter_prefix;
		}
break;
case 339:
#line 2821 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (fmopts.as_l != NULL) {
				yyerror("AS filters already specified");
				YYERROR;
			}
			fmopts.as_l = yyvsp[0].v.filter_as;
		}
break;
case 340:
#line 2828 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (fmopts.m.aslen.type != ASLEN_NONE) {
				yyerror("AS length filters already specified");
				YYERROR;
			}
			if (yyvsp[0].v.number < 0 || yyvsp[0].v.number > UINT_MAX) {
				yyerror("bad max-as-len %lld", yyvsp[0].v.number);
				YYERROR;
			}
			fmopts.m.aslen.type = ASLEN_MAX;
			fmopts.m.aslen.aslen = yyvsp[0].v.number;
		}
break;
case 341:
#line 2840 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (fmopts.m.aslen.type != ASLEN_NONE) {
				yyerror("AS length filters already specified");
				YYERROR;
			}
			if (yyvsp[0].v.number < 0 || yyvsp[0].v.number > UINT_MAX) {
				yyerror("bad max-as-seq %lld", yyvsp[0].v.number);
				YYERROR;
			}
			fmopts.m.aslen.type = ASLEN_SEQ;
			fmopts.m.aslen.aslen = yyvsp[0].v.number;
		}
break;
case 342:
#line 2852 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			int i;
			for (i = 0; i < MAX_COMM_MATCH; i++) {
				if (fmopts.m.community[i].flags == 0)
					break;
			}
			if (i >= MAX_COMM_MATCH) {
				yyerror("too many \"community\" filters "
				    "specified");
				free(yyvsp[0].v.string);
				YYERROR;
			}
			if (parsecommunity(&fmopts.m.community[i], yyvsp[-1].v.u8, yyvsp[0].v.string) ==
			    -1) {
				free(yyvsp[0].v.string);
				YYERROR;
			}
			free(yyvsp[0].v.string);
		}
break;
case 343:
#line 2871 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			int i;
			for (i = 0; i < MAX_COMM_MATCH; i++) {
				if (fmopts.m.community[i].flags == 0)
					break;
			}
			if (i >= MAX_COMM_MATCH) {
				yyerror("too many \"community\" filters "
				    "specified");
				free(yyvsp[-1].v.string);
				free(yyvsp[0].v.string);
				YYERROR;
			}
			if (parseextcommunity(&fmopts.m.community[i],
			    yyvsp[-1].v.string, yyvsp[0].v.string) == -1) {
				free(yyvsp[-1].v.string);
				free(yyvsp[0].v.string);
				YYERROR;
			}
			free(yyvsp[-1].v.string);
			free(yyvsp[0].v.string);
		}
break;
case 344:
#line 2893 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			int i;
			for (i = 0; i < MAX_COMM_MATCH; i++) {
				if (fmopts.m.community[i].flags == 0)
					break;
			}
			if (i >= MAX_COMM_MATCH) {
				yyerror("too many \"community\" filters "
				    "specified");
				free(yyvsp[0].v.string);
				YYERROR;
			}
			if (parseextcommunity(&fmopts.m.community[i],
			    "ovs", yyvsp[0].v.string) == -1) {
				free(yyvsp[0].v.string);
				YYERROR;
			}
			free(yyvsp[0].v.string);
		}
break;
case 345:
#line 2912 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.number < 0 || yyvsp[0].v.number > INT16_MAX) {
				yyerror("bad max-comunities %lld", yyvsp[0].v.number);
				YYERROR;
			}
			if (fmopts.m.maxcomm != 0) {
				yyerror("%s already specified",
				    "max-communities");
				YYERROR;
			}
			/*
			 * Offset by 1 since 0 means not used.
			 * The match function then uses >= to compensate.
			 */
			fmopts.m.maxcomm = yyvsp[0].v.number + 1;
		}
break;
case 346:
#line 2928 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.number < 0 || yyvsp[0].v.number > INT16_MAX) {
				yyerror("bad max-ext-communities %lld", yyvsp[0].v.number);
				YYERROR;
			}
			if (fmopts.m.maxextcomm != 0) {
				yyerror("%s already specified",
				    "max-ext-communities");
				YYERROR;
			}
			fmopts.m.maxextcomm = yyvsp[0].v.number + 1;
		}
break;
case 347:
#line 2940 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.number < 0 || yyvsp[0].v.number > INT16_MAX) {
				yyerror("bad max-large-communities %lld", yyvsp[0].v.number);
				YYERROR;
			}
			if (fmopts.m.maxlargecomm != 0) {
				yyerror("%s already specified",
				    "max-large-communities");
				YYERROR;
			}
			fmopts.m.maxlargecomm = yyvsp[0].v.number + 1;
		}
break;
case 348:
#line 2952 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (fmopts.m.nexthop.flags) {
				yyerror("nexthop already specified");
				YYERROR;
			}
			fmopts.m.nexthop.addr = yyvsp[0].v.addr;
			fmopts.m.nexthop.flags = FILTER_NEXTHOP_ADDR;
		}
break;
case 349:
#line 2960 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (fmopts.m.nexthop.flags) {
				yyerror("nexthop already specified");
				YYERROR;
			}
			fmopts.m.nexthop.flags = FILTER_NEXTHOP_NEIGHBOR;
		}
break;
case 350:
#line 2967 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			struct prefixset *ps;
			if (fmopts.prefix_l != NULL) {
				yyerror("\"prefix\" already specified, cannot "
				    "be used with \"prefix-set\" in the same "
				    "filter rule");
				free(yyvsp[-1].v.string);
				YYERROR;
			}
			if (fmopts.m.prefixset.name[0] != '\0') {
				yyerror("prefix-set filter already specified");
				free(yyvsp[-1].v.string);
				YYERROR;
			}
			if ((ps = find_prefixset(yyvsp[-1].v.string, &conf->prefixsets))
			    == NULL) {
				yyerror("prefix-set '%s' not defined", yyvsp[-1].v.string);
				free(yyvsp[-1].v.string);
				YYERROR;
			}
			if (strlcpy(fmopts.m.prefixset.name, yyvsp[-1].v.string,
			    sizeof(fmopts.m.prefixset.name)) >=
			    sizeof(fmopts.m.prefixset.name)) {
				yyerror("prefix-set name too long");
				free(yyvsp[-1].v.string);
				YYERROR;
			}
			if (!(yyvsp[0].v.prefixlen.op == OP_NONE ||
			    (yyvsp[0].v.prefixlen.op == OP_RANGE &&
			     yyvsp[0].v.prefixlen.len_min == -1 && yyvsp[0].v.prefixlen.len_max == -1))) {
				yyerror("prefix-sets can only use option "
				    "or-longer");
				free(yyvsp[-1].v.string);
				YYERROR;
			}
			if (yyvsp[0].v.prefixlen.op == OP_RANGE &&
			    ps->sflags & PREFIXSET_FLAG_OPS) {
				yyerror("prefix-set %s contains prefixlen "
				    "operators and cannot be used with an "
				    "or-longer filter", yyvsp[-1].v.string);
				free(yyvsp[-1].v.string);
				YYERROR;
			}
			if (yyvsp[0].v.prefixlen.op == OP_RANGE && yyvsp[0].v.prefixlen.len_min == -1 &&
			    yyvsp[0].v.prefixlen.len_min == -1)
				fmopts.m.prefixset.flags |=
				    PREFIXSET_FLAG_LONGER;
			fmopts.m.prefixset.flags |= PREFIXSET_FLAG_FILTER;
			free(yyvsp[-1].v.string);
		}
break;
case 351:
#line 3017 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (fmopts.m.originset.name[0] != '\0') {
				yyerror("origin-set filter already specified");
				free(yyvsp[0].v.string);
				YYERROR;
			}
			if (find_prefixset(yyvsp[0].v.string, &conf->originsets) == NULL) {
				yyerror("origin-set '%s' not defined", yyvsp[0].v.string);
				free(yyvsp[0].v.string);
				YYERROR;
			}
			if (strlcpy(fmopts.m.originset.name, yyvsp[0].v.string,
			    sizeof(fmopts.m.originset.name)) >=
			    sizeof(fmopts.m.originset.name)) {
				yyerror("origin-set name too long");
				free(yyvsp[0].v.string);
				YYERROR;
			}
			free(yyvsp[0].v.string);
		}
break;
case 352:
#line 3037 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (fmopts.m.ovs.is_set) {
				yyerror("ovs filter already specified");
				YYERROR;
			}
			fmopts.m.ovs.validity = yyvsp[0].v.number;
			fmopts.m.ovs.is_set = 1;
		}
break;
case 353:
#line 3045 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (fmopts.m.avs.is_set) {
				yyerror("avs filter already specified");
				YYERROR;
			}
			fmopts.m.avs.validity = yyvsp[0].v.number;
			fmopts.m.avs.is_set = 1;
		}
break;
case 354:
#line 3055 "../../../openbgpd-portable/src/bgpd/parse.y"
{ memset(&yyval.v.prefixlen, 0, sizeof(yyval.v.prefixlen)); }
break;
case 355:
#line 3056 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			memset(&yyval.v.prefixlen, 0, sizeof(yyval.v.prefixlen));
			yyval.v.prefixlen.op = OP_RANGE;
			yyval.v.prefixlen.len_min = -1;
			yyval.v.prefixlen.len_max = -1;
		}
break;
case 356:
#line 3062 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			memset(&yyval.v.prefixlen, 0, sizeof(yyval.v.prefixlen));
			if (yyvsp[0].v.number < 0 || yyvsp[0].v.number > 128) {
				yyerror("prefixlen must be >= 0 and <= 128");
				YYERROR;
			}

			yyval.v.prefixlen.op = OP_RANGE;
			yyval.v.prefixlen.len_min = -1;
			yyval.v.prefixlen.len_max = yyvsp[0].v.number;
		}
break;
case 357:
#line 3073 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			int min, max;

			memset(&yyval.v.prefixlen, 0, sizeof(yyval.v.prefixlen));
			if (yyvsp[0].v.number < 0 || yyvsp[0].v.number > 128) {
				yyerror("prefixlen must be >= 0 and <= 128");
				YYERROR;
			}
			/*
			 * convert the unary operation into the equivalent
			 * range check
			 */
			yyval.v.prefixlen.op = OP_RANGE;

			switch (yyvsp[-1].v.u8) {
			case OP_NE:
				yyval.v.prefixlen.op = yyvsp[-1].v.u8;
			case OP_EQ:
				min = max = yyvsp[0].v.number;
				break;
			case OP_LT:
				if (yyvsp[0].v.number == 0) {
					yyerror("prefixlen must be > 0");
					YYERROR;
				}
				yyvsp[0].v.number -= 1;
			case OP_LE:
				min = -1;
				max = yyvsp[0].v.number;
				break;
			case OP_GT:
				yyvsp[0].v.number += 1;
			case OP_GE:
				min = yyvsp[0].v.number;
				max = -1;
				break;
			default:
				yyerror("unknown prefixlen operation");
				YYERROR;
			}
			yyval.v.prefixlen.len_min = min;
			yyval.v.prefixlen.len_max = max;
		}
break;
case 358:
#line 3116 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			memset(&yyval.v.prefixlen, 0, sizeof(yyval.v.prefixlen));
			if (yyvsp[-2].v.number < 0 || yyvsp[-2].v.number > 128 || yyvsp[0].v.number < 0 || yyvsp[0].v.number > 128) {
				yyerror("prefixlen must be < 128");
				YYERROR;
			}
			if (yyvsp[-2].v.number > yyvsp[0].v.number) {
				yyerror("start prefixlen is bigger than end");
				YYERROR;
			}
			yyval.v.prefixlen.op = yyvsp[-1].v.u8;
			yyval.v.prefixlen.len_min = yyvsp[-2].v.number;
			yyval.v.prefixlen.len_max = yyvsp[0].v.number;
		}
break;
case 359:
#line 3132 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.u8 = AS_ALL; }
break;
case 360:
#line 3133 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.u8 = AS_SOURCE; }
break;
case 361:
#line 3134 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.u8 = AS_TRANSIT; }
break;
case 362:
#line 3135 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.u8 = AS_PEER; }
break;
case 363:
#line 3138 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.filter_set_head = NULL; }
break;
case 364:
#line 3139 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if ((yyval.v.filter_set_head = calloc(1, sizeof(struct filter_set_head))) ==
			    NULL)
				fatal(NULL);
			TAILQ_INIT(yyval.v.filter_set_head);
			TAILQ_INSERT_TAIL(yyval.v.filter_set_head, yyvsp[0].v.filter_set, entry);
		}
break;
case 365:
#line 3146 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.filter_set_head = yyvsp[-2].v.filter_set_head; }
break;
case 366:
#line 3149 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			yyval.v.filter_set_head = yyvsp[-2].v.filter_set_head;
			if (merge_filterset(yyval.v.filter_set_head, yyvsp[0].v.filter_set) == 1)
				YYERROR;
		}
break;
case 367:
#line 3154 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if ((yyval.v.filter_set_head = calloc(1, sizeof(struct filter_set_head))) ==
			    NULL)
				fatal(NULL);
			TAILQ_INIT(yyval.v.filter_set_head);
			TAILQ_INSERT_TAIL(yyval.v.filter_set_head, yyvsp[0].v.filter_set, entry);
		}
break;
case 368:
#line 3163 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.u8 = COMMUNITY_TYPE_BASIC; }
break;
case 369:
#line 3164 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.u8 = COMMUNITY_TYPE_LARGE; }
break;
case 370:
#line 3167 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.u8 = 0; }
break;
case 371:
#line 3168 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.u8 = 1; }
break;
case 372:
#line 3171 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.number = 0; }
break;
case 373:
#line 3172 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.number = 2; }
break;
case 374:
#line 3175 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.number = yyvsp[0].v.number; }
break;
case 375:
#line 3176 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.number = 2; }
break;
case 376:
#line 3179 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.number < -INT_MAX || yyvsp[0].v.number > UINT_MAX) {
				yyerror("bad localpref %lld", yyvsp[0].v.number);
				YYERROR;
			}
			if ((yyval.v.filter_set = calloc(1, sizeof(struct filter_set))) == NULL)
				fatal(NULL);
			if (yyvsp[0].v.number >= 0) {
				yyval.v.filter_set->type = ACTION_SET_LOCALPREF;
				yyval.v.filter_set->action.metric = yyvsp[0].v.number;
			} else {
				yyval.v.filter_set->type = ACTION_SET_RELATIVE_LOCALPREF;
				yyval.v.filter_set->action.relative = yyvsp[0].v.number;
			}
		}
break;
case 377:
#line 3194 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.number < 0 || yyvsp[0].v.number > INT_MAX) {
				yyerror("bad localpref +%lld", yyvsp[0].v.number);
				YYERROR;
			}
			if ((yyval.v.filter_set = calloc(1, sizeof(struct filter_set))) == NULL)
				fatal(NULL);
			yyval.v.filter_set->type = ACTION_SET_RELATIVE_LOCALPREF;
			yyval.v.filter_set->action.relative = yyvsp[0].v.number;
		}
break;
case 378:
#line 3204 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.number < 0 || yyvsp[0].v.number > INT_MAX) {
				yyerror("bad localpref -%lld", yyvsp[0].v.number);
				YYERROR;
			}
			if ((yyval.v.filter_set = calloc(1, sizeof(struct filter_set))) == NULL)
				fatal(NULL);
			yyval.v.filter_set->type = ACTION_SET_RELATIVE_LOCALPREF;
			yyval.v.filter_set->action.relative = -yyvsp[0].v.number;
		}
break;
case 379:
#line 3214 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.number < -INT_MAX || yyvsp[0].v.number > UINT_MAX) {
				yyerror("bad metric %lld", yyvsp[0].v.number);
				YYERROR;
			}
			if ((yyval.v.filter_set = calloc(1, sizeof(struct filter_set))) == NULL)
				fatal(NULL);
			if (yyvsp[0].v.number >= 0) {
				yyval.v.filter_set->type = ACTION_SET_MED;
				yyval.v.filter_set->action.metric = yyvsp[0].v.number;
			} else {
				yyval.v.filter_set->type = ACTION_SET_RELATIVE_MED;
				yyval.v.filter_set->action.relative = yyvsp[0].v.number;
			}
		}
break;
case 380:
#line 3229 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.number < 0 || yyvsp[0].v.number > INT_MAX) {
				yyerror("bad metric +%lld", yyvsp[0].v.number);
				YYERROR;
			}
			if ((yyval.v.filter_set = calloc(1, sizeof(struct filter_set))) == NULL)
				fatal(NULL);
			yyval.v.filter_set->type = ACTION_SET_RELATIVE_MED;
			yyval.v.filter_set->action.relative = yyvsp[0].v.number;
		}
break;
case 381:
#line 3239 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.number < 0 || yyvsp[0].v.number > INT_MAX) {
				yyerror("bad metric -%lld", yyvsp[0].v.number);
				YYERROR;
			}
			if ((yyval.v.filter_set = calloc(1, sizeof(struct filter_set))) == NULL)
				fatal(NULL);
			yyval.v.filter_set->type = ACTION_SET_RELATIVE_MED;
			yyval.v.filter_set->action.relative = -yyvsp[0].v.number;
		}
break;
case 382:
#line 3249 "../../../openbgpd-portable/src/bgpd/parse.y"
{	/* alias for MED */
			if (yyvsp[0].v.number < -INT_MAX || yyvsp[0].v.number > UINT_MAX) {
				yyerror("bad metric %lld", yyvsp[0].v.number);
				YYERROR;
			}
			if ((yyval.v.filter_set = calloc(1, sizeof(struct filter_set))) == NULL)
				fatal(NULL);
			if (yyvsp[0].v.number >= 0) {
				yyval.v.filter_set->type = ACTION_SET_MED;
				yyval.v.filter_set->action.metric = yyvsp[0].v.number;
			} else {
				yyval.v.filter_set->type = ACTION_SET_RELATIVE_MED;
				yyval.v.filter_set->action.relative = yyvsp[0].v.number;
			}
		}
break;
case 383:
#line 3264 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.number < 0 || yyvsp[0].v.number > INT_MAX) {
				yyerror("bad metric +%lld", yyvsp[0].v.number);
				YYERROR;
			}
			if ((yyval.v.filter_set = calloc(1, sizeof(struct filter_set))) == NULL)
				fatal(NULL);
			yyval.v.filter_set->type = ACTION_SET_RELATIVE_MED;
			yyval.v.filter_set->action.metric = yyvsp[0].v.number;
		}
break;
case 384:
#line 3274 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.number < 0 || yyvsp[0].v.number > INT_MAX) {
				yyerror("bad metric -%lld", yyvsp[0].v.number);
				YYERROR;
			}
			if ((yyval.v.filter_set = calloc(1, sizeof(struct filter_set))) == NULL)
				fatal(NULL);
			yyval.v.filter_set->type = ACTION_SET_RELATIVE_MED;
			yyval.v.filter_set->action.relative = -yyvsp[0].v.number;
		}
break;
case 385:
#line 3284 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.number < -INT_MAX || yyvsp[0].v.number > UINT_MAX) {
				yyerror("bad weight %lld", yyvsp[0].v.number);
				YYERROR;
			}
			if ((yyval.v.filter_set = calloc(1, sizeof(struct filter_set))) == NULL)
				fatal(NULL);
			if (yyvsp[0].v.number > 0) {
				yyval.v.filter_set->type = ACTION_SET_WEIGHT;
				yyval.v.filter_set->action.metric = yyvsp[0].v.number;
			} else {
				yyval.v.filter_set->type = ACTION_SET_RELATIVE_WEIGHT;
				yyval.v.filter_set->action.relative = yyvsp[0].v.number;
			}
		}
break;
case 386:
#line 3299 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.number < 0 || yyvsp[0].v.number > INT_MAX) {
				yyerror("bad weight +%lld", yyvsp[0].v.number);
				YYERROR;
			}
			if ((yyval.v.filter_set = calloc(1, sizeof(struct filter_set))) == NULL)
				fatal(NULL);
			yyval.v.filter_set->type = ACTION_SET_RELATIVE_WEIGHT;
			yyval.v.filter_set->action.relative = yyvsp[0].v.number;
		}
break;
case 387:
#line 3309 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.number < 0 || yyvsp[0].v.number > INT_MAX) {
				yyerror("bad weight -%lld", yyvsp[0].v.number);
				YYERROR;
			}
			if ((yyval.v.filter_set = calloc(1, sizeof(struct filter_set))) == NULL)
				fatal(NULL);
			yyval.v.filter_set->type = ACTION_SET_RELATIVE_WEIGHT;
			yyval.v.filter_set->action.relative = -yyvsp[0].v.number;
		}
break;
case 388:
#line 3319 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if ((yyval.v.filter_set = calloc(1, sizeof(struct filter_set))) == NULL)
				fatal(NULL);
			yyval.v.filter_set->type = ACTION_SET_NEXTHOP;
			memcpy(&yyval.v.filter_set->action.nexthop, &yyvsp[0].v.addr,
			    sizeof(yyval.v.filter_set->action.nexthop));
		}
break;
case 389:
#line 3326 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if ((yyval.v.filter_set = calloc(1, sizeof(struct filter_set))) == NULL)
				fatal(NULL);
			yyval.v.filter_set->type = ACTION_SET_NEXTHOP_BLACKHOLE;
		}
break;
case 390:
#line 3331 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if ((yyval.v.filter_set = calloc(1, sizeof(struct filter_set))) == NULL)
				fatal(NULL);
			yyval.v.filter_set->type = ACTION_SET_NEXTHOP_REJECT;
		}
break;
case 391:
#line 3336 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if ((yyval.v.filter_set = calloc(1, sizeof(struct filter_set))) == NULL)
				fatal(NULL);
			yyval.v.filter_set->type = ACTION_SET_NEXTHOP_NOMODIFY;
		}
break;
case 392:
#line 3341 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if ((yyval.v.filter_set = calloc(1, sizeof(struct filter_set))) == NULL)
				fatal(NULL);
			yyval.v.filter_set->type = ACTION_SET_NEXTHOP_SELF;
		}
break;
case 393:
#line 3346 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.number < 0 || yyvsp[0].v.number > 128) {
				yyerror("bad number of prepends");
				YYERROR;
			}
			if ((yyval.v.filter_set = calloc(1, sizeof(struct filter_set))) == NULL)
				fatal(NULL);
			yyval.v.filter_set->type = ACTION_SET_PREPEND_SELF;
			yyval.v.filter_set->action.prepend = yyvsp[0].v.number;
		}
break;
case 394:
#line 3356 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (yyvsp[0].v.number < 0 || yyvsp[0].v.number > 128) {
				yyerror("bad number of prepends");
				YYERROR;
			}
			if ((yyval.v.filter_set = calloc(1, sizeof(struct filter_set))) == NULL)
				fatal(NULL);
			yyval.v.filter_set->type = ACTION_SET_PREPEND_PEER;
			yyval.v.filter_set->action.prepend = yyvsp[0].v.number;
		}
break;
case 395:
#line 3366 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if ((yyval.v.filter_set = calloc(1, sizeof(struct filter_set))) == NULL)
				fatal(NULL);
			yyval.v.filter_set->type = ACTION_SET_AS_OVERRIDE;
		}
break;
case 396:
#line 3371 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if ((yyval.v.filter_set = calloc(1, sizeof(struct filter_set))) == NULL)
				fatal(NULL);
			yyval.v.filter_set->type = ACTION_PFTABLE;
			if (!(cmd_opts & BGPD_OPT_NOACTION) &&
			    pftable_exists(yyvsp[0].v.string) != 0) {
				yyerror("pftable name does not exist");
				free(yyvsp[0].v.string);
				free(yyval.v.filter_set);
				YYERROR;
			}
			if (strlcpy(yyval.v.filter_set->action.pftable, yyvsp[0].v.string,
			    sizeof(yyval.v.filter_set->action.pftable)) >=
			    sizeof(yyval.v.filter_set->action.pftable)) {
				yyerror("pftable name too long");
				free(yyvsp[0].v.string);
				free(yyval.v.filter_set);
				YYERROR;
			}
			if (pftable_add(yyvsp[0].v.string) != 0) {
				yyerror("Couldn't register table");
				free(yyvsp[0].v.string);
				free(yyval.v.filter_set);
				YYERROR;
			}
			free(yyvsp[0].v.string);
		}
break;
case 397:
#line 3398 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if ((yyval.v.filter_set = calloc(1, sizeof(struct filter_set))) == NULL)
				fatal(NULL);
			yyval.v.filter_set->type = ACTION_RTLABEL;
			if (strlcpy(yyval.v.filter_set->action.rtlabel, yyvsp[0].v.string,
			    sizeof(yyval.v.filter_set->action.rtlabel)) >=
			    sizeof(yyval.v.filter_set->action.rtlabel)) {
				yyerror("rtlabel name too long");
				free(yyvsp[0].v.string);
				free(yyval.v.filter_set);
				YYERROR;
			}
			free(yyvsp[0].v.string);
		}
break;
case 398:
#line 3412 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			uint8_t f1, f2, f3;

			if ((yyval.v.filter_set = calloc(1, sizeof(struct filter_set))) == NULL)
				fatal(NULL);
			if (yyvsp[-1].v.u8)
				yyval.v.filter_set->type = ACTION_DEL_COMMUNITY;
			else
				yyval.v.filter_set->type = ACTION_SET_COMMUNITY;

			if (parsecommunity(&yyval.v.filter_set->action.community, yyvsp[-2].v.u8, yyvsp[0].v.string) ==
			    -1) {
				free(yyvsp[0].v.string);
				free(yyval.v.filter_set);
				YYERROR;
			}
			free(yyvsp[0].v.string);
			/* Don't allow setting of any match */
			f1 = yyval.v.filter_set->action.community.flags >> 8;
			f2 = yyval.v.filter_set->action.community.flags >> 16;
			f3 = yyval.v.filter_set->action.community.flags >> 24;
			if (!yyvsp[-1].v.u8 && (f1 == COMMUNITY_ANY ||
			    f2 == COMMUNITY_ANY || f3 == COMMUNITY_ANY)) {
				yyerror("'*' is not allowed in set community");
				free(yyval.v.filter_set);
				YYERROR;
			}
		}
break;
case 399:
#line 3440 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if ((yyval.v.filter_set = calloc(1, sizeof(struct filter_set))) == NULL)
				fatal(NULL);
			if (yyvsp[-2].v.u8)
				yyval.v.filter_set->type = ACTION_DEL_COMMUNITY;
			else
				yyval.v.filter_set->type = ACTION_SET_COMMUNITY;

			if (parseextcommunity(&yyval.v.filter_set->action.community,
			    yyvsp[-1].v.string, yyvsp[0].v.string) == -1) {
				free(yyvsp[-1].v.string);
				free(yyvsp[0].v.string);
				free(yyval.v.filter_set);
				YYERROR;
			}
			free(yyvsp[-1].v.string);
			free(yyvsp[0].v.string);
		}
break;
case 400:
#line 3458 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if ((yyval.v.filter_set = calloc(1, sizeof(struct filter_set))) == NULL)
				fatal(NULL);
			if (yyvsp[-2].v.u8)
				yyval.v.filter_set->type = ACTION_DEL_COMMUNITY;
			else
				yyval.v.filter_set->type = ACTION_SET_COMMUNITY;

			if (parseextcommunity(&yyval.v.filter_set->action.community,
			    "ovs", yyvsp[0].v.string) == -1) {
				free(yyvsp[0].v.string);
				free(yyval.v.filter_set);
				YYERROR;
			}
			free(yyvsp[0].v.string);
		}
break;
case 401:
#line 3474 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if ((yyval.v.filter_set = calloc(1, sizeof(struct filter_set))) == NULL)
				fatal(NULL);
			yyval.v.filter_set->type = ACTION_SET_ORIGIN;
			yyval.v.filter_set->action.origin = yyvsp[0].v.number;
		}
break;
case 402:
#line 3482 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (!strcmp(yyvsp[0].v.string, "egp"))
				yyval.v.number = ORIGIN_EGP;
			else if (!strcmp(yyvsp[0].v.string, "igp"))
				yyval.v.number = ORIGIN_IGP;
			else if (!strcmp(yyvsp[0].v.string, "incomplete"))
				yyval.v.number = ORIGIN_INCOMPLETE;
			else {
				yyerror("unknown origin \"%s\"", yyvsp[0].v.string);
				free(yyvsp[0].v.string);
				YYERROR;
			}
			free(yyvsp[0].v.string);
		}
break;
case 403:
#line 3497 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (!strcmp(yyvsp[0].v.string, "not-found"))
				yyval.v.number = ROA_NOTFOUND;
			else if (!strcmp(yyvsp[0].v.string, "invalid"))
				yyval.v.number = ROA_INVALID;
			else if (!strcmp(yyvsp[0].v.string, "valid"))
				yyval.v.number = ROA_VALID;
			else {
				yyerror("unknown roa validity \"%s\"", yyvsp[0].v.string);
				free(yyvsp[0].v.string);
				YYERROR;
			}
			free(yyvsp[0].v.string);
		}
break;
case 404:
#line 3512 "../../../openbgpd-portable/src/bgpd/parse.y"
{
			if (!strcmp(yyvsp[0].v.string, "unknown"))
				yyval.v.number = ASPA_UNKNOWN;
			else if (!strcmp(yyvsp[0].v.string, "invalid"))
				yyval.v.number = ASPA_INVALID;
			else if (!strcmp(yyvsp[0].v.string, "valid"))
				yyval.v.number = ASPA_VALID;
			else {
				yyerror("unknown aspa validity \"%s\"", yyvsp[0].v.string);
				free(yyvsp[0].v.string);
				YYERROR;
			}
			free(yyvsp[0].v.string);
		}
break;
case 411:
#line 3537 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.u8 = OP_EQ; }
break;
case 412:
#line 3538 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.u8 = OP_NE; }
break;
case 413:
#line 3539 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.u8 = OP_LE; }
break;
case 414:
#line 3540 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.u8 = OP_LT; }
break;
case 415:
#line 3541 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.u8 = OP_GE; }
break;
case 416:
#line 3542 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.u8 = OP_GT; }
break;
case 417:
#line 3545 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.u8 = OP_EQ; }
break;
case 418:
#line 3546 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.u8 = OP_NE; }
break;
case 419:
#line 3549 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.u8 = OP_RANGE; }
break;
case 420:
#line 3550 "../../../openbgpd-portable/src/bgpd/parse.y"
{ yyval.v.u8 = OP_XRANGE; }
break;
#line 8285 "parse.c"
    }
    yyssp -= yym;
    yystate = *yyssp;
    yyvsp -= yym;
    yym = yylhs[yyn];
    if (yystate == 0 && yym == 0)
    {
#if YYDEBUG
        if (yydebug)
            printf("%sdebug: after reduction, shifting from state 0 to\
 state %d\n", YYPREFIX, YYFINAL);
#endif
        yystate = YYFINAL;
        *++yyssp = YYFINAL;
        *++yyvsp = yyval;
        if (yychar < 0)
        {
            if ((yychar = yylex()) < 0) yychar = 0;
#if YYDEBUG
            if (yydebug)
            {
                yys = 0;
                if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
                if (!yys) yys = "illegal-symbol";
                printf("%sdebug: state %d, reading %d (%s)\n",
                        YYPREFIX, YYFINAL, yychar, yys);
            }
#endif
        }
        if (yychar == 0) goto yyaccept;
        goto yyloop;
    }
    if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 &&
            yyn <= YYTABLESIZE && yycheck[yyn] == yystate)
        yystate = yytable[yyn];
    else
        yystate = yydgoto[yym];
#if YYDEBUG
    if (yydebug)
        printf("%sdebug: after reduction, shifting from state %d \
to state %d\n", YYPREFIX, *yyssp, yystate);
#endif
    if (yyssp >= yysslim && yygrowstack())
    {
        goto yyoverflow;
    }
    *++yyssp = yystate;
    *++yyvsp = yyval;
    goto yyloop;
yyoverflow:
    yyerror("yacc stack overflow");
yyabort:
    if (yyss)
            free(yyss);
    if (yyvs)
            free(yyvs);
    yyss = yyssp = NULL;
    yyvs = yyvsp = NULL;
    yystacksize = 0;
    return (1);
yyaccept:
    if (yyss)
            free(yyss);
    if (yyvs)
            free(yyvs);
    yyss = yyssp = NULL;
    yyvs = yyvsp = NULL;
    yystacksize = 0;
    return (0);
}
