1*08f6ba19Snaddy /* $OpenBSD: parse.y,v 1.48 2021/10/15 15:01:28 naddy Exp $ */
2ddeeec14Snorby
3ddeeec14Snorby /*
4ddeeec14Snorby * Copyright (c) 2006 Michele Marchetto <mydecay@openbeer.it>
5ddeeec14Snorby * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
6ddeeec14Snorby * Copyright (c) 2004 Ryan McBride <mcbride@openbsd.org>
7ddeeec14Snorby * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
8ddeeec14Snorby * Copyright (c) 2001 Markus Friedl. All rights reserved.
9ddeeec14Snorby * Copyright (c) 2001 Daniel Hartmeier. All rights reserved.
10ddeeec14Snorby * Copyright (c) 2001 Theo de Raadt. All rights reserved.
11ddeeec14Snorby *
12ddeeec14Snorby * Permission to use, copy, modify, and distribute this software for any
13ddeeec14Snorby * purpose with or without fee is hereby granted, provided that the above
14ddeeec14Snorby * copyright notice and this permission notice appear in all copies.
15ddeeec14Snorby *
16ddeeec14Snorby * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
17ddeeec14Snorby * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
18ddeeec14Snorby * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
19ddeeec14Snorby * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20ddeeec14Snorby * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
21ddeeec14Snorby * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
22ddeeec14Snorby * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23ddeeec14Snorby */
24ddeeec14Snorby
25ddeeec14Snorby %{
26ddeeec14Snorby #include <sys/types.h>
27ddeeec14Snorby #include <sys/socket.h>
2820741916Sderaadt #include <sys/stat.h>
291acb5c27Sremi #include <net/route.h>
30ddeeec14Snorby #include <netinet/in.h>
31ddeeec14Snorby #include <arpa/inet.h>
32ddeeec14Snorby #include <ctype.h>
33ddeeec14Snorby #include <err.h>
34ddeeec14Snorby #include <errno.h>
3520741916Sderaadt #include <unistd.h>
36ddeeec14Snorby #include <limits.h>
37ddeeec14Snorby #include <stdarg.h>
38ddeeec14Snorby #include <stdio.h>
39ddeeec14Snorby #include <string.h>
404a1d3eaaSsthen #include <syslog.h>
41ddeeec14Snorby
42ddeeec14Snorby #include "ripd.h"
43ddeeec14Snorby #include "rip.h"
44ddeeec14Snorby #include "ripe.h"
45ddeeec14Snorby #include "log.h"
46ddeeec14Snorby
4720741916Sderaadt TAILQ_HEAD(files, file) files = TAILQ_HEAD_INITIALIZER(files);
4820741916Sderaadt static struct file {
4920741916Sderaadt TAILQ_ENTRY(file) entry;
5020741916Sderaadt FILE *stream;
5120741916Sderaadt char *name;
5220741916Sderaadt int lineno;
5320741916Sderaadt int errors;
54c6004ab9Smpf } *file, *topfile;
5520741916Sderaadt struct file *pushfile(const char *, int);
5620741916Sderaadt int popfile(void);
57ddeeec14Snorby int yyparse(void);
5820741916Sderaadt int yylex(void);
597fe19e9cSdoug int yyerror(const char *, ...)
607fe19e9cSdoug __attribute__((__format__ (printf, 1, 2)))
617fe19e9cSdoug __attribute__((__nonnull__ (1)));
62ddeeec14Snorby int kw_cmp(const void *, const void *);
63ddeeec14Snorby int lookup(char *);
64d5d66eaeSderaadt int lgetc(int);
65ddeeec14Snorby int lungetc(int);
66ddeeec14Snorby int findeol(void);
6720741916Sderaadt
6820741916Sderaadt TAILQ_HEAD(symhead, sym) symhead = TAILQ_HEAD_INITIALIZER(symhead);
6920741916Sderaadt struct sym {
7020741916Sderaadt TAILQ_ENTRY(sym) entry;
7120741916Sderaadt int used;
7220741916Sderaadt int persist;
7320741916Sderaadt char *nam;
7420741916Sderaadt char *val;
7520741916Sderaadt };
7620741916Sderaadt int symset(const char *, const char *, int);
7720741916Sderaadt char *symget(const char *);
78ddeeec14Snorby
79ddeeec14Snorby static struct {
80d1c9c145Sclaudio u_int8_t auth_key[MAX_SIMPLE_AUTH_LEN];
81ddeeec14Snorby struct auth_md_head md_list;
82ddeeec14Snorby enum auth_type auth_type;
83ddeeec14Snorby u_int8_t auth_keyid;
84ddeeec14Snorby u_int8_t cost;
85ddeeec14Snorby } *defs, globaldefs, ifacedefs;
86ddeeec14Snorby
8720741916Sderaadt struct iface *iface = NULL;
8820741916Sderaadt static struct ripd_conf *conf;
8920741916Sderaadt static int errors = 0;
90ddeeec14Snorby
91ddeeec14Snorby struct iface *conf_get_if(struct kif *);
9220741916Sderaadt void clear_config(struct ripd_conf *);
9320741916Sderaadt int check_file_secrecy(int, const char *);
9420741916Sderaadt u_int32_t get_rtr_id(void);
9520741916Sderaadt int host(const char *, struct in_addr *, struct in_addr *);
96ddeeec14Snorby
97ddeeec14Snorby typedef struct {
98ddeeec14Snorby union {
9906f703ebSderaadt int64_t number;
100ddeeec14Snorby char *string;
101ddeeec14Snorby } v;
102ddeeec14Snorby int lineno;
103ddeeec14Snorby } YYSTYPE;
104ddeeec14Snorby
105ddeeec14Snorby %}
106ddeeec14Snorby
1071acb5c27Sremi %token SPLIT_HORIZON TRIGGERED_UPDATES FIBPRIORITY FIBUPDATE
1081acb5c27Sremi %token REDISTRIBUTE RDOMAIN
109ddeeec14Snorby %token AUTHKEY AUTHTYPE AUTHMD AUTHMDKEYID
1109bb9ec63Sclaudio %token INTERFACE RTLABEL
111ddeeec14Snorby %token COST PASSIVE
1129bb9ec63Sclaudio %token YES NO
1134d8b14b6Smichele %token DEMOTE
114ddeeec14Snorby %token ERROR
115ddeeec14Snorby %token <v.string> STRING
11606f703ebSderaadt %token <v.number> NUMBER
11706f703ebSderaadt %type <v.number> yesno no
118ddeeec14Snorby %type <v.string> string
119ddeeec14Snorby
120ddeeec14Snorby %%
121ddeeec14Snorby
122ddeeec14Snorby grammar : /* empty */
123ddeeec14Snorby | grammar '\n'
124ddeeec14Snorby | grammar conf_main '\n'
125ddeeec14Snorby | grammar varset '\n'
126ddeeec14Snorby | grammar interface '\n'
12720741916Sderaadt | grammar error '\n' { file->errors++; }
128ddeeec14Snorby ;
129ddeeec14Snorby
130ddeeec14Snorby string : string STRING {
131ddeeec14Snorby if (asprintf(&$$, "%s %s", $1, $2) == -1) {
132ddeeec14Snorby free($1);
133ddeeec14Snorby free($2);
134ddeeec14Snorby yyerror("string: asprintf");
135ddeeec14Snorby YYERROR;
136ddeeec14Snorby }
137ddeeec14Snorby free($1);
138ddeeec14Snorby free($2);
139ddeeec14Snorby }
140ddeeec14Snorby | STRING
141ddeeec14Snorby ;
142ddeeec14Snorby
1439bb9ec63Sclaudio yesno : YES { $$ = 1; }
1449bb9ec63Sclaudio | NO { $$ = 0; }
145ddeeec14Snorby ;
146ddeeec14Snorby
1479bb9ec63Sclaudio no : /* empty */ { $$ = 0; }
1489bb9ec63Sclaudio | NO { $$ = 1; }
1499bb9ec63Sclaudio
150ddeeec14Snorby varset : STRING '=' string {
1510c7b4ca6Sbenno char *s = $1;
152ddeeec14Snorby if (conf->opts & RIPD_OPT_VERBOSE)
153ddeeec14Snorby printf("%s = \"%s\"\n", $1, $3);
1540c7b4ca6Sbenno while (*s++) {
1550c7b4ca6Sbenno if (isspace((unsigned char)*s)) {
1560c7b4ca6Sbenno yyerror("macro name cannot contain "
1570c7b4ca6Sbenno "whitespace");
15816a0a906Skrw free($1);
15916a0a906Skrw free($3);
1600c7b4ca6Sbenno YYERROR;
1610c7b4ca6Sbenno }
1620c7b4ca6Sbenno }
163ddeeec14Snorby if (symset($1, $3, 0) == -1)
164ddeeec14Snorby fatal("cannot store variable");
165ddeeec14Snorby free($1);
166ddeeec14Snorby free($3);
167ddeeec14Snorby }
168ddeeec14Snorby ;
169ddeeec14Snorby
170ddeeec14Snorby conf_main : SPLIT_HORIZON STRING {
171ddeeec14Snorby /* clean flags first */
172ddeeec14Snorby conf->options &= ~(OPT_SPLIT_HORIZON |
173ddeeec14Snorby OPT_SPLIT_POISONED);
174ddeeec14Snorby if (!strcmp($2, "none"))
175ddeeec14Snorby /* nothing */ ;
17646802160Smichele else if (!strcmp($2, "simple"))
177ddeeec14Snorby conf->options |= OPT_SPLIT_HORIZON;
178ddeeec14Snorby else if (!strcmp($2, "poisoned"))
179ddeeec14Snorby conf->options |= OPT_SPLIT_POISONED;
180ddeeec14Snorby else {
1818fb80d1cSmichele yyerror("unknown split horizon type");
182ddeeec14Snorby free($2);
183ddeeec14Snorby YYERROR;
184ddeeec14Snorby }
185ddeeec14Snorby free($2);
186ddeeec14Snorby }
187ddeeec14Snorby | TRIGGERED_UPDATES yesno {
188ddeeec14Snorby if ($2 == 1)
189ddeeec14Snorby conf->options |= OPT_TRIGGERED_UPDATES;
190ddeeec14Snorby else
191ddeeec14Snorby conf->options &= ~OPT_TRIGGERED_UPDATES;
192ddeeec14Snorby }
1930ab89b34Smichele | RDOMAIN NUMBER {
1940ab89b34Smichele if ($2 < 0 || $2 > RT_TABLEID_MAX) {
1950ab89b34Smichele yyerror("invalid rdomain");
1960ab89b34Smichele YYERROR;
1970ab89b34Smichele }
1980ab89b34Smichele conf->rdomain = $2;
1990ab89b34Smichele }
2001acb5c27Sremi | FIBPRIORITY NUMBER {
2011acb5c27Sremi if ($2 <= RTP_NONE || $2 > RTP_MAX) {
2021acb5c27Sremi yyerror("invalid fib-priority");
2031acb5c27Sremi YYERROR;
2041acb5c27Sremi }
2051acb5c27Sremi conf->fib_priority = $2;
2061acb5c27Sremi }
207ddeeec14Snorby | FIBUPDATE yesno {
208ddeeec14Snorby if ($2 == 0)
209ddeeec14Snorby conf->flags |= RIPD_FLAG_NO_FIB_UPDATE;
210ddeeec14Snorby else
211ddeeec14Snorby conf->flags &= ~RIPD_FLAG_NO_FIB_UPDATE;
212ddeeec14Snorby }
2139bb9ec63Sclaudio | no REDISTRIBUTE STRING {
2149bb9ec63Sclaudio struct redistribute *r;
2159bb9ec63Sclaudio
2169bb9ec63Sclaudio if ((r = calloc(1, sizeof(*r))) == NULL)
2179bb9ec63Sclaudio fatal(NULL);
2189bb9ec63Sclaudio if (!strcmp($3, "static"))
2199bb9ec63Sclaudio r->type = REDIST_STATIC;
2209bb9ec63Sclaudio else if (!strcmp($3, "connected"))
2219bb9ec63Sclaudio r->type = REDIST_CONNECTED;
22239c227bcSmichele else if (!strcmp($3, "default"))
22339c227bcSmichele r->type = REDIST_DEFAULT;
2249bb9ec63Sclaudio else if (host($3, &r->addr, &r->mask))
2259bb9ec63Sclaudio r->type = REDIST_ADDR;
226ddeeec14Snorby else {
227ddeeec14Snorby yyerror("unknown redistribute type");
2289bb9ec63Sclaudio free($3);
2299bb9ec63Sclaudio free(r);
230ddeeec14Snorby YYERROR;
231ddeeec14Snorby }
2329bb9ec63Sclaudio
2339bb9ec63Sclaudio if ($1)
2349bb9ec63Sclaudio r->type |= REDIST_NO;
2359bb9ec63Sclaudio
2369bb9ec63Sclaudio SIMPLEQ_INSERT_TAIL(&conf->redist_list, r,
2379bb9ec63Sclaudio entry);
23839c227bcSmichele
2399bb9ec63Sclaudio conf->redistribute |= REDISTRIBUTE_ON;
2409bb9ec63Sclaudio free($3);
2419bb9ec63Sclaudio }
2429bb9ec63Sclaudio | no REDISTRIBUTE RTLABEL STRING {
2439bb9ec63Sclaudio struct redistribute *r;
2449bb9ec63Sclaudio
2459bb9ec63Sclaudio if ((r = calloc(1, sizeof(*r))) == NULL)
2469bb9ec63Sclaudio fatal(NULL);
2479bb9ec63Sclaudio r->type = REDIST_LABEL;
2489bb9ec63Sclaudio r->label = rtlabel_name2id($4);
2499bb9ec63Sclaudio if ($1)
2509bb9ec63Sclaudio r->type |= REDIST_NO;
2519bb9ec63Sclaudio free($4);
2529bb9ec63Sclaudio
2539bb9ec63Sclaudio SIMPLEQ_INSERT_TAIL(&conf->redist_list, r, entry);
2549bb9ec63Sclaudio conf->redistribute |= REDISTRIBUTE_ON;
255ddeeec14Snorby }
2560d0a18a3Smichele | defaults
257ddeeec14Snorby ;
258ddeeec14Snorby
25906f703ebSderaadt authmd : AUTHMD NUMBER STRING {
260ddeeec14Snorby if ($2 < MIN_MD_ID || $2 > MAX_MD_ID) {
261ddeeec14Snorby yyerror("auth-md key-id out of range "
262ddeeec14Snorby "(%d-%d)", MIN_MD_ID, MAX_MD_ID);
263ddeeec14Snorby free($3);
264ddeeec14Snorby YYERROR;
265ddeeec14Snorby }
266d1c9c145Sclaudio if (md_list_add(&defs->md_list, $2, $3) == -1) {
267ddeeec14Snorby yyerror("auth-md key length out of range "
268d1c9c145Sclaudio "(max length %d)", MD5_DIGEST_LENGTH);
269ddeeec14Snorby free($3);
270ddeeec14Snorby YYERROR;
271ddeeec14Snorby }
272ddeeec14Snorby free($3);
273ddeeec14Snorby }
274ddeeec14Snorby
27506f703ebSderaadt authmdkeyid : AUTHMDKEYID NUMBER {
276ddeeec14Snorby if ($2 < MIN_MD_ID || $2 > MAX_MD_ID) {
277ddeeec14Snorby yyerror("auth-md-keyid out of range "
278ddeeec14Snorby "(%d-%d)", MIN_MD_ID, MAX_MD_ID);
279ddeeec14Snorby YYERROR;
280ddeeec14Snorby }
281ddeeec14Snorby defs->auth_keyid = $2;
282ddeeec14Snorby }
283ddeeec14Snorby
284ddeeec14Snorby authtype : AUTHTYPE STRING {
285ddeeec14Snorby enum auth_type type;
286ddeeec14Snorby
287ddeeec14Snorby if (!strcmp($2, "none"))
288ddeeec14Snorby type = AUTH_NONE;
289ddeeec14Snorby else if (!strcmp($2, "simple"))
290ddeeec14Snorby type = AUTH_SIMPLE;
291ddeeec14Snorby else if (!strcmp($2, "crypt"))
292ddeeec14Snorby type = AUTH_CRYPT;
293ddeeec14Snorby else {
294ddeeec14Snorby yyerror("unknown auth-type");
295ddeeec14Snorby free($2);
296ddeeec14Snorby YYERROR;
297ddeeec14Snorby }
298ddeeec14Snorby free($2);
299ddeeec14Snorby defs->auth_type = type;
300ddeeec14Snorby }
301ddeeec14Snorby ;
302ddeeec14Snorby
303ddeeec14Snorby authkey : AUTHKEY STRING {
304ddeeec14Snorby if (strlen($2) > MAX_SIMPLE_AUTH_LEN) {
305b8bbf4e7Sdavid yyerror("auth-key too long (max length %d)",
306ddeeec14Snorby MAX_SIMPLE_AUTH_LEN);
307ddeeec14Snorby free($2);
308ddeeec14Snorby YYERROR;
309ddeeec14Snorby }
310d1c9c145Sclaudio bzero(defs->auth_key, MAX_SIMPLE_AUTH_LEN);
311d1c9c145Sclaudio memcpy(defs->auth_key, $2, strlen($2));
312ddeeec14Snorby free($2);
313ddeeec14Snorby }
314ddeeec14Snorby ;
315ddeeec14Snorby
31606f703ebSderaadt defaults : COST NUMBER {
317ddeeec14Snorby if ($2 < 1 || $2 > INFINITY) {
318ddeeec14Snorby yyerror("cost out of range (%d-%d)", 1,
319ddeeec14Snorby INFINITY);
320ddeeec14Snorby YYERROR;
321ddeeec14Snorby }
322ddeeec14Snorby defs->cost = $2;
323ddeeec14Snorby }
324ddeeec14Snorby | authtype
325ddeeec14Snorby | authkey
326ddeeec14Snorby | authmdkeyid
327ddeeec14Snorby | authmd
328ddeeec14Snorby ;
329ddeeec14Snorby
330ddeeec14Snorby optnl : '\n' optnl
331ddeeec14Snorby |
332ddeeec14Snorby ;
333ddeeec14Snorby
334ddeeec14Snorby nl : '\n' optnl
335ddeeec14Snorby ;
336ddeeec14Snorby
337ddeeec14Snorby interface : INTERFACE STRING {
338ddeeec14Snorby struct kif *kif;
339ddeeec14Snorby
340ddeeec14Snorby if ((kif = kif_findname($2)) == NULL) {
341ddeeec14Snorby yyerror("unknown interface %s", $2);
342ddeeec14Snorby free($2);
343ddeeec14Snorby YYERROR;
344ddeeec14Snorby }
345ddeeec14Snorby free($2);
346ddeeec14Snorby iface = conf_get_if(kif);
347ddeeec14Snorby if (iface == NULL)
348ddeeec14Snorby YYERROR;
349ddeeec14Snorby LIST_INSERT_HEAD(&conf->iface_list, iface, entry);
350ddeeec14Snorby memcpy(&ifacedefs, defs, sizeof(ifacedefs));
3510d0a18a3Smichele md_list_copy(&ifacedefs.md_list, &defs->md_list);
352ddeeec14Snorby defs = &ifacedefs;
353ddeeec14Snorby } interface_block {
354ddeeec14Snorby iface->cost = defs->cost;
355ddeeec14Snorby iface->auth_type = defs->auth_type;
356ddeeec14Snorby iface->auth_keyid = defs->auth_keyid;
357ddeeec14Snorby memcpy(iface->auth_key, defs->auth_key,
358ddeeec14Snorby sizeof(iface->auth_key));
359ddeeec14Snorby md_list_copy(&iface->auth_md_list, &defs->md_list);
360ddeeec14Snorby md_list_clr(&defs->md_list);
361ddeeec14Snorby defs = &globaldefs;
362ddeeec14Snorby }
363ddeeec14Snorby ;
364ddeeec14Snorby
3657bc1b36bSremi interface_block : /* empty */
3667bc1b36bSremi | '{' optnl interfaceopts_l '}'
367ddeeec14Snorby | '{' optnl '}'
368ddeeec14Snorby ;
369ddeeec14Snorby
3704d8b14b6Smichele interfaceopts_l : interfaceopts_l interfaceoptsl nl
3714d8b14b6Smichele | interfaceoptsl optnl
372ddeeec14Snorby ;
373ddeeec14Snorby
3744d8b14b6Smichele interfaceoptsl : PASSIVE { iface->passive = 1; }
3754d8b14b6Smichele | DEMOTE STRING {
3764d8b14b6Smichele if (strlcpy(iface->demote_group, $2,
3774d8b14b6Smichele sizeof(iface->demote_group)) >=
3784d8b14b6Smichele sizeof(iface->demote_group)) {
3797fe19e9cSdoug yyerror("demote group name \"%s\" too long",
3807fe19e9cSdoug $2);
3814d8b14b6Smichele free($2);
3824d8b14b6Smichele YYERROR;
3834d8b14b6Smichele }
3844d8b14b6Smichele free($2);
3854d8b14b6Smichele if (carp_demote_init(iface->demote_group,
3864d8b14b6Smichele conf->opts & RIPD_OPT_FORCE_DEMOTE) == -1) {
3874d8b14b6Smichele yyerror("error initializing group \"%s\"",
3884d8b14b6Smichele iface->demote_group);
3894d8b14b6Smichele YYERROR;
3904d8b14b6Smichele }
3914d8b14b6Smichele }
3924d8b14b6Smichele | defaults
393ddeeec14Snorby ;
394ddeeec14Snorby %%
395ddeeec14Snorby
396ddeeec14Snorby struct keywords {
397ddeeec14Snorby const char *k_name;
398ddeeec14Snorby int k_val;
399ddeeec14Snorby };
400ddeeec14Snorby
401ddeeec14Snorby int
yyerror(const char * fmt,...)402ddeeec14Snorby yyerror(const char *fmt, ...)
403ddeeec14Snorby {
404ddeeec14Snorby va_list ap;
405cd8337bcSbluhm char *msg;
406ddeeec14Snorby
40720741916Sderaadt file->errors++;
408ddeeec14Snorby va_start(ap, fmt);
409cd8337bcSbluhm if (vasprintf(&msg, fmt, ap) == -1)
410cd8337bcSbluhm fatalx("yyerror vasprintf");
411ddeeec14Snorby va_end(ap);
412cd8337bcSbluhm logit(LOG_CRIT, "%s:%d: %s", file->name, yylval.lineno, msg);
413cd8337bcSbluhm free(msg);
414ddeeec14Snorby return (0);
415ddeeec14Snorby }
416ddeeec14Snorby
417ddeeec14Snorby int
kw_cmp(const void * k,const void * e)418ddeeec14Snorby kw_cmp(const void *k, const void *e)
419ddeeec14Snorby {
420ddeeec14Snorby return (strcmp(k, ((const struct keywords *)e)->k_name));
421ddeeec14Snorby }
422ddeeec14Snorby
423ddeeec14Snorby int
lookup(char * s)424ddeeec14Snorby lookup(char *s)
425ddeeec14Snorby {
426ddeeec14Snorby /* this has to be sorted always */
427ddeeec14Snorby static const struct keywords keywords[] = {
428ddeeec14Snorby {"auth-key", AUTHKEY},
429ddeeec14Snorby {"auth-md", AUTHMD},
430ddeeec14Snorby {"auth-md-keyid", AUTHMDKEYID},
431ddeeec14Snorby {"auth-type", AUTHTYPE},
432ddeeec14Snorby {"cost", COST},
4334d8b14b6Smichele {"demote", DEMOTE},
4341acb5c27Sremi {"fib-priority", FIBPRIORITY},
435ddeeec14Snorby {"fib-update", FIBUPDATE},
436ddeeec14Snorby {"interface", INTERFACE},
4379bb9ec63Sclaudio {"no", NO},
438ddeeec14Snorby {"passive", PASSIVE},
4390ab89b34Smichele {"rdomain", RDOMAIN},
440ddeeec14Snorby {"redistribute", REDISTRIBUTE},
4419bb9ec63Sclaudio {"rtlabel", RTLABEL},
442ddeeec14Snorby {"split-horizon", SPLIT_HORIZON},
4439bb9ec63Sclaudio {"triggered-updates", TRIGGERED_UPDATES},
4449bb9ec63Sclaudio {"yes", YES}
445ddeeec14Snorby };
446ddeeec14Snorby const struct keywords *p;
447ddeeec14Snorby
448ddeeec14Snorby p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
449ddeeec14Snorby sizeof(keywords[0]), kw_cmp);
450ddeeec14Snorby
451c186cac6Shenning if (p)
452ddeeec14Snorby return (p->k_val);
453c186cac6Shenning else
454ddeeec14Snorby return (STRING);
455ddeeec14Snorby }
456ddeeec14Snorby
457ddeeec14Snorby #define MAXPUSHBACK 128
458ddeeec14Snorby
459*08f6ba19Snaddy char *parsebuf;
460ddeeec14Snorby int parseindex;
461*08f6ba19Snaddy char pushback_buffer[MAXPUSHBACK];
462ddeeec14Snorby int pushback_index = 0;
463ddeeec14Snorby
464ddeeec14Snorby int
lgetc(int quotec)46520741916Sderaadt lgetc(int quotec)
466ddeeec14Snorby {
467ddeeec14Snorby int c, next;
468ddeeec14Snorby
469ddeeec14Snorby if (parsebuf) {
470ddeeec14Snorby /* Read character from the parsebuffer instead of input. */
471ddeeec14Snorby if (parseindex >= 0) {
472*08f6ba19Snaddy c = (unsigned char)parsebuf[parseindex++];
473ddeeec14Snorby if (c != '\0')
474ddeeec14Snorby return (c);
475ddeeec14Snorby parsebuf = NULL;
476ddeeec14Snorby } else
477ddeeec14Snorby parseindex++;
478ddeeec14Snorby }
479ddeeec14Snorby
480ddeeec14Snorby if (pushback_index)
481*08f6ba19Snaddy return ((unsigned char)pushback_buffer[--pushback_index]);
482ddeeec14Snorby
48320741916Sderaadt if (quotec) {
48420741916Sderaadt if ((c = getc(file->stream)) == EOF) {
485c6004ab9Smpf yyerror("reached end of file while parsing "
486c6004ab9Smpf "quoted string");
487c6004ab9Smpf if (file == topfile || popfile() == EOF)
48820741916Sderaadt return (EOF);
48920741916Sderaadt return (quotec);
49020741916Sderaadt }
491d5d66eaeSderaadt return (c);
492d5d66eaeSderaadt }
493d5d66eaeSderaadt
49420741916Sderaadt while ((c = getc(file->stream)) == '\\') {
49520741916Sderaadt next = getc(file->stream);
496ddeeec14Snorby if (next != '\n') {
497d5d66eaeSderaadt c = next;
498ddeeec14Snorby break;
499ddeeec14Snorby }
50020741916Sderaadt yylval.lineno = file->lineno;
50120741916Sderaadt file->lineno++;
502ddeeec14Snorby }
503ddeeec14Snorby
50420741916Sderaadt while (c == EOF) {
505c6004ab9Smpf if (file == topfile || popfile() == EOF)
50620741916Sderaadt return (EOF);
50720741916Sderaadt c = getc(file->stream);
50820741916Sderaadt }
509ddeeec14Snorby return (c);
510ddeeec14Snorby }
511ddeeec14Snorby
512ddeeec14Snorby int
lungetc(int c)513ddeeec14Snorby lungetc(int c)
514ddeeec14Snorby {
515ddeeec14Snorby if (c == EOF)
516ddeeec14Snorby return (EOF);
517ddeeec14Snorby if (parsebuf) {
518ddeeec14Snorby parseindex--;
519ddeeec14Snorby if (parseindex >= 0)
520ddeeec14Snorby return (c);
521ddeeec14Snorby }
522*08f6ba19Snaddy if (pushback_index + 1 >= MAXPUSHBACK)
523ddeeec14Snorby return (EOF);
524*08f6ba19Snaddy pushback_buffer[pushback_index++] = c;
525*08f6ba19Snaddy return (c);
526ddeeec14Snorby }
527ddeeec14Snorby
528ddeeec14Snorby int
findeol(void)529ddeeec14Snorby findeol(void)
530ddeeec14Snorby {
531ddeeec14Snorby int c;
532ddeeec14Snorby
533ddeeec14Snorby parsebuf = NULL;
534ddeeec14Snorby
535ddeeec14Snorby /* skip to either EOF or the first real EOL */
536ddeeec14Snorby while (1) {
5371a28f514Shenning if (pushback_index)
538*08f6ba19Snaddy c = (unsigned char)pushback_buffer[--pushback_index];
5391a28f514Shenning else
540d5d66eaeSderaadt c = lgetc(0);
541ddeeec14Snorby if (c == '\n') {
54220741916Sderaadt file->lineno++;
543ddeeec14Snorby break;
544ddeeec14Snorby }
545ddeeec14Snorby if (c == EOF)
546ddeeec14Snorby break;
547ddeeec14Snorby }
548ddeeec14Snorby return (ERROR);
549ddeeec14Snorby }
550ddeeec14Snorby
551ddeeec14Snorby int
yylex(void)552ddeeec14Snorby yylex(void)
553ddeeec14Snorby {
554*08f6ba19Snaddy char buf[8096];
555*08f6ba19Snaddy char *p, *val;
55620741916Sderaadt int quotec, next, c;
557ddeeec14Snorby int token;
558ddeeec14Snorby
559ddeeec14Snorby top:
560ddeeec14Snorby p = buf;
5612053f12aSmpf while ((c = lgetc(0)) == ' ' || c == '\t')
562ddeeec14Snorby ; /* nothing */
563ddeeec14Snorby
56420741916Sderaadt yylval.lineno = file->lineno;
565ddeeec14Snorby if (c == '#')
566d5d66eaeSderaadt while ((c = lgetc(0)) != '\n' && c != EOF)
567ddeeec14Snorby ; /* nothing */
568ddeeec14Snorby if (c == '$' && parsebuf == NULL) {
569ddeeec14Snorby while (1) {
570d5d66eaeSderaadt if ((c = lgetc(0)) == EOF)
571ddeeec14Snorby return (0);
572ddeeec14Snorby
573ddeeec14Snorby if (p + 1 >= buf + sizeof(buf) - 1) {
574ddeeec14Snorby yyerror("string too long");
575ddeeec14Snorby return (findeol());
576ddeeec14Snorby }
577ddeeec14Snorby if (isalnum(c) || c == '_') {
578015d7b4dSbenno *p++ = c;
579ddeeec14Snorby continue;
580ddeeec14Snorby }
581ddeeec14Snorby *p = '\0';
582ddeeec14Snorby lungetc(c);
583ddeeec14Snorby break;
584ddeeec14Snorby }
585ddeeec14Snorby val = symget(buf);
586ddeeec14Snorby if (val == NULL) {
587ddeeec14Snorby yyerror("macro '%s' not defined", buf);
588ddeeec14Snorby return (findeol());
589ddeeec14Snorby }
590ddeeec14Snorby parsebuf = val;
591ddeeec14Snorby parseindex = 0;
592ddeeec14Snorby goto top;
593ddeeec14Snorby }
594ddeeec14Snorby
595ddeeec14Snorby switch (c) {
596ddeeec14Snorby case '\'':
597ddeeec14Snorby case '"':
59820741916Sderaadt quotec = c;
599ddeeec14Snorby while (1) {
60020741916Sderaadt if ((c = lgetc(quotec)) == EOF)
601ddeeec14Snorby return (0);
602ddeeec14Snorby if (c == '\n') {
60320741916Sderaadt file->lineno++;
604ddeeec14Snorby continue;
605d5d66eaeSderaadt } else if (c == '\\') {
60620741916Sderaadt if ((next = lgetc(quotec)) == EOF)
607d5d66eaeSderaadt return (0);
608a1533359Ssashan if (next == quotec || next == ' ' ||
609a1533359Ssashan next == '\t')
610d5d66eaeSderaadt c = next;
611daf24110Shenning else if (next == '\n') {
612daf24110Shenning file->lineno++;
613ea014f46Sderaadt continue;
614daf24110Shenning } else
615d5d66eaeSderaadt lungetc(next);
61620741916Sderaadt } else if (c == quotec) {
617d5d66eaeSderaadt *p = '\0';
618d5d66eaeSderaadt break;
61941eef22fSjsg } else if (c == '\0') {
62041eef22fSjsg yyerror("syntax error");
62141eef22fSjsg return (findeol());
622ddeeec14Snorby }
623ddeeec14Snorby if (p + 1 >= buf + sizeof(buf) - 1) {
624ddeeec14Snorby yyerror("string too long");
625ddeeec14Snorby return (findeol());
626ddeeec14Snorby }
627015d7b4dSbenno *p++ = c;
628ddeeec14Snorby }
629ddeeec14Snorby yylval.v.string = strdup(buf);
630ddeeec14Snorby if (yylval.v.string == NULL)
631a062aa9dSkrw err(1, "%s", __func__);
632ddeeec14Snorby return (STRING);
633ddeeec14Snorby }
634ddeeec14Snorby
63506f703ebSderaadt #define allowed_to_end_number(x) \
6360cf2c9c3Smpf (isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=')
63706f703ebSderaadt
63806f703ebSderaadt if (c == '-' || isdigit(c)) {
63906f703ebSderaadt do {
64006f703ebSderaadt *p++ = c;
641915c3f33Sderaadt if ((size_t)(p-buf) >= sizeof(buf)) {
64206f703ebSderaadt yyerror("string too long");
64306f703ebSderaadt return (findeol());
64406f703ebSderaadt }
645d5d66eaeSderaadt } while ((c = lgetc(0)) != EOF && isdigit(c));
64606f703ebSderaadt lungetc(c);
64706f703ebSderaadt if (p == buf + 1 && buf[0] == '-')
64806f703ebSderaadt goto nodigits;
64906f703ebSderaadt if (c == EOF || allowed_to_end_number(c)) {
65006f703ebSderaadt const char *errstr = NULL;
65106f703ebSderaadt
65206f703ebSderaadt *p = '\0';
65306f703ebSderaadt yylval.v.number = strtonum(buf, LLONG_MIN,
65406f703ebSderaadt LLONG_MAX, &errstr);
65506f703ebSderaadt if (errstr) {
65606f703ebSderaadt yyerror("\"%s\" invalid number: %s",
65706f703ebSderaadt buf, errstr);
65806f703ebSderaadt return (findeol());
65906f703ebSderaadt }
66006f703ebSderaadt return (NUMBER);
66106f703ebSderaadt } else {
66206f703ebSderaadt nodigits:
66306f703ebSderaadt while (p > buf + 1)
664*08f6ba19Snaddy lungetc((unsigned char)*--p);
665*08f6ba19Snaddy c = (unsigned char)*--p;
66606f703ebSderaadt if (c == '-')
66706f703ebSderaadt return (c);
66806f703ebSderaadt }
66906f703ebSderaadt }
67006f703ebSderaadt
671ddeeec14Snorby #define allowed_in_string(x) \
672ddeeec14Snorby (isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
673ddeeec14Snorby x != '{' && x != '}' && \
674ddeeec14Snorby x != '!' && x != '=' && x != '#' && \
675ddeeec14Snorby x != ','))
676ddeeec14Snorby
677ddeeec14Snorby if (isalnum(c) || c == ':' || c == '_') {
678ddeeec14Snorby do {
679ddeeec14Snorby *p++ = c;
680915c3f33Sderaadt if ((size_t)(p-buf) >= sizeof(buf)) {
681ddeeec14Snorby yyerror("string too long");
682ddeeec14Snorby return (findeol());
683ddeeec14Snorby }
684d5d66eaeSderaadt } while ((c = lgetc(0)) != EOF && (allowed_in_string(c)));
685ddeeec14Snorby lungetc(c);
686ddeeec14Snorby *p = '\0';
687ddeeec14Snorby if ((token = lookup(buf)) == STRING)
688ddeeec14Snorby if ((yylval.v.string = strdup(buf)) == NULL)
689a062aa9dSkrw err(1, "%s", __func__);
690ddeeec14Snorby return (token);
691ddeeec14Snorby }
692ddeeec14Snorby if (c == '\n') {
69320741916Sderaadt yylval.lineno = file->lineno;
69420741916Sderaadt file->lineno++;
695ddeeec14Snorby }
696ddeeec14Snorby if (c == EOF)
697ddeeec14Snorby return (0);
698ddeeec14Snorby return (c);
699ddeeec14Snorby }
700ddeeec14Snorby
70120741916Sderaadt int
check_file_secrecy(int fd,const char * fname)70220741916Sderaadt check_file_secrecy(int fd, const char *fname)
70320741916Sderaadt {
70420741916Sderaadt struct stat st;
70520741916Sderaadt
70620741916Sderaadt if (fstat(fd, &st)) {
70720741916Sderaadt log_warn("cannot stat %s", fname);
70820741916Sderaadt return (-1);
70920741916Sderaadt }
71020741916Sderaadt if (st.st_uid != 0 && st.st_uid != getuid()) {
71120741916Sderaadt log_warnx("%s: owner not root or current user", fname);
71220741916Sderaadt return (-1);
71320741916Sderaadt }
7147140c133Shenning if (st.st_mode & (S_IWGRP | S_IXGRP | S_IRWXO)) {
7157140c133Shenning log_warnx("%s: group writable or world read/writable", fname);
71620741916Sderaadt return (-1);
71720741916Sderaadt }
71820741916Sderaadt return (0);
71920741916Sderaadt }
72020741916Sderaadt
72120741916Sderaadt struct file *
pushfile(const char * name,int secret)72220741916Sderaadt pushfile(const char *name, int secret)
72320741916Sderaadt {
72420741916Sderaadt struct file *nfile;
72520741916Sderaadt
7267fc93de0Stobias if ((nfile = calloc(1, sizeof(struct file))) == NULL) {
7276a3d55f9Skrw log_warn("%s", __func__);
72820741916Sderaadt return (NULL);
7296fa930c9Spyr }
7307fc93de0Stobias if ((nfile->name = strdup(name)) == NULL) {
7316a3d55f9Skrw log_warn("%s", __func__);
7327fc93de0Stobias free(nfile);
7337fc93de0Stobias return (NULL);
7347fc93de0Stobias }
73520741916Sderaadt if ((nfile->stream = fopen(nfile->name, "r")) == NULL) {
7366a3d55f9Skrw log_warn("%s: %s", __func__, nfile->name);
73720741916Sderaadt free(nfile->name);
73820741916Sderaadt free(nfile);
73920741916Sderaadt return (NULL);
74020741916Sderaadt } else if (secret &&
74120741916Sderaadt check_file_secrecy(fileno(nfile->stream), nfile->name)) {
74220741916Sderaadt fclose(nfile->stream);
74320741916Sderaadt free(nfile->name);
74420741916Sderaadt free(nfile);
74520741916Sderaadt return (NULL);
74620741916Sderaadt }
74720741916Sderaadt nfile->lineno = 1;
74820741916Sderaadt TAILQ_INSERT_TAIL(&files, nfile, entry);
74920741916Sderaadt return (nfile);
75020741916Sderaadt }
75120741916Sderaadt
75220741916Sderaadt int
popfile(void)75320741916Sderaadt popfile(void)
75420741916Sderaadt {
75520741916Sderaadt struct file *prev;
75620741916Sderaadt
757c6004ab9Smpf if ((prev = TAILQ_PREV(file, files, entry)) != NULL)
75820741916Sderaadt prev->errors += file->errors;
759c6004ab9Smpf
76020741916Sderaadt TAILQ_REMOVE(&files, file, entry);
76120741916Sderaadt fclose(file->stream);
76220741916Sderaadt free(file->name);
76320741916Sderaadt free(file);
76420741916Sderaadt file = prev;
765c6004ab9Smpf return (file ? 0 : EOF);
76620741916Sderaadt }
76720741916Sderaadt
768ddeeec14Snorby struct ripd_conf *
parse_config(char * filename,int opts)769ddeeec14Snorby parse_config(char *filename, int opts)
770ddeeec14Snorby {
771ddeeec14Snorby struct sym *sym, *next;
772ddeeec14Snorby
773ddeeec14Snorby if ((conf = calloc(1, sizeof(struct ripd_conf))) == NULL)
774ddeeec14Snorby fatal("parse_config");
775ddeeec14Snorby
776ddeeec14Snorby bzero(&globaldefs, sizeof(globaldefs));
777ddeeec14Snorby defs = &globaldefs;
778ddeeec14Snorby TAILQ_INIT(&defs->md_list);
7790d0a18a3Smichele defs->cost = DEFAULT_COST;
780ddeeec14Snorby defs->auth_type = AUTH_NONE;
781ddeeec14Snorby conf->opts = opts;
78246802160Smichele conf->options = OPT_SPLIT_POISONED;
7831acb5c27Sremi conf->fib_priority = RTP_RIP;
7849bb9ec63Sclaudio SIMPLEQ_INIT(&conf->redist_list);
785ddeeec14Snorby
78620741916Sderaadt if ((file = pushfile(filename, !(conf->opts & RIPD_OPT_NOACTION))) == NULL) {
787ddeeec14Snorby free(conf);
788ddeeec14Snorby return (NULL);
789ddeeec14Snorby }
790d6fc1e53Smpf topfile = file;
791ddeeec14Snorby
792ddeeec14Snorby yyparse();
79320741916Sderaadt errors = file->errors;
79420741916Sderaadt popfile();
795ddeeec14Snorby
796ddeeec14Snorby /* Free macros and check which have not been used. */
79746bca67bSkrw TAILQ_FOREACH_SAFE(sym, &symhead, entry, next) {
798ddeeec14Snorby if ((conf->opts & RIPD_OPT_VERBOSE2) && !sym->used)
799ddeeec14Snorby fprintf(stderr, "warning: macro '%s' not "
800ddeeec14Snorby "used\n", sym->nam);
801ddeeec14Snorby if (!sym->persist) {
802ddeeec14Snorby free(sym->nam);
803ddeeec14Snorby free(sym->val);
80420741916Sderaadt TAILQ_REMOVE(&symhead, sym, entry);
805ddeeec14Snorby free(sym);
806ddeeec14Snorby }
807ddeeec14Snorby }
808ddeeec14Snorby
809ddeeec14Snorby /* free global config defaults */
810ddeeec14Snorby md_list_clr(&globaldefs.md_list);
811ddeeec14Snorby
812ddeeec14Snorby if (errors) {
813ddeeec14Snorby clear_config(conf);
814ddeeec14Snorby return (NULL);
815ddeeec14Snorby }
816ddeeec14Snorby
817ddeeec14Snorby return (conf);
818ddeeec14Snorby }
819ddeeec14Snorby
820ddeeec14Snorby int
symset(const char * nam,const char * val,int persist)821ddeeec14Snorby symset(const char *nam, const char *val, int persist)
822ddeeec14Snorby {
823ddeeec14Snorby struct sym *sym;
824ddeeec14Snorby
82554c95b7aSkrw TAILQ_FOREACH(sym, &symhead, entry) {
82654c95b7aSkrw if (strcmp(nam, sym->nam) == 0)
82754c95b7aSkrw break;
82854c95b7aSkrw }
829ddeeec14Snorby
830ddeeec14Snorby if (sym != NULL) {
831ddeeec14Snorby if (sym->persist == 1)
832ddeeec14Snorby return (0);
833ddeeec14Snorby else {
834ddeeec14Snorby free(sym->nam);
835ddeeec14Snorby free(sym->val);
83620741916Sderaadt TAILQ_REMOVE(&symhead, sym, entry);
837ddeeec14Snorby free(sym);
838ddeeec14Snorby }
839ddeeec14Snorby }
840ddeeec14Snorby if ((sym = calloc(1, sizeof(*sym))) == NULL)
841ddeeec14Snorby return (-1);
842ddeeec14Snorby
843ddeeec14Snorby sym->nam = strdup(nam);
844ddeeec14Snorby if (sym->nam == NULL) {
845ddeeec14Snorby free(sym);
846ddeeec14Snorby return (-1);
847ddeeec14Snorby }
848ddeeec14Snorby sym->val = strdup(val);
849ddeeec14Snorby if (sym->val == NULL) {
850ddeeec14Snorby free(sym->nam);
851ddeeec14Snorby free(sym);
852ddeeec14Snorby return (-1);
853ddeeec14Snorby }
854ddeeec14Snorby sym->used = 0;
855ddeeec14Snorby sym->persist = persist;
85620741916Sderaadt TAILQ_INSERT_TAIL(&symhead, sym, entry);
857ddeeec14Snorby return (0);
858ddeeec14Snorby }
859ddeeec14Snorby
860ddeeec14Snorby int
cmdline_symset(char * s)861ddeeec14Snorby cmdline_symset(char *s)
862ddeeec14Snorby {
863ddeeec14Snorby char *sym, *val;
864ddeeec14Snorby int ret;
865ddeeec14Snorby
866ddeeec14Snorby if ((val = strrchr(s, '=')) == NULL)
867ddeeec14Snorby return (-1);
868ed1b9eb8Smiko sym = strndup(s, val - s);
869ed1b9eb8Smiko if (sym == NULL)
870ed1b9eb8Smiko errx(1, "%s: strndup", __func__);
871ddeeec14Snorby ret = symset(sym, val + 1, 1);
872ddeeec14Snorby free(sym);
873ddeeec14Snorby
874ddeeec14Snorby return (ret);
875ddeeec14Snorby }
876ddeeec14Snorby
877ddeeec14Snorby char *
symget(const char * nam)878ddeeec14Snorby symget(const char *nam)
879ddeeec14Snorby {
880ddeeec14Snorby struct sym *sym;
881ddeeec14Snorby
88254c95b7aSkrw TAILQ_FOREACH(sym, &symhead, entry) {
883ddeeec14Snorby if (strcmp(nam, sym->nam) == 0) {
884ddeeec14Snorby sym->used = 1;
885ddeeec14Snorby return (sym->val);
886ddeeec14Snorby }
88754c95b7aSkrw }
888ddeeec14Snorby return (NULL);
889ddeeec14Snorby }
890ddeeec14Snorby
891ddeeec14Snorby struct iface *
conf_get_if(struct kif * kif)892ddeeec14Snorby conf_get_if(struct kif *kif)
893ddeeec14Snorby {
894ddeeec14Snorby struct iface *i;
895ddeeec14Snorby
896ddeeec14Snorby LIST_FOREACH(i, &conf->iface_list, entry)
897ddeeec14Snorby if (i->ifindex == kif->ifindex) {
898ddeeec14Snorby yyerror("interface %s already configured",
899ddeeec14Snorby kif->ifname);
900ddeeec14Snorby return (NULL);
901ddeeec14Snorby }
902ddeeec14Snorby
903ddeeec14Snorby i = if_new(kif);
904ddeeec14Snorby i->auth_keyid = 1;
905ddeeec14Snorby i->passive = 0;
906ddeeec14Snorby
907ddeeec14Snorby return (i);
908ddeeec14Snorby }
909ddeeec14Snorby
910ddeeec14Snorby void
clear_config(struct ripd_conf * xconf)911ddeeec14Snorby clear_config(struct ripd_conf *xconf)
912ddeeec14Snorby {
913ddeeec14Snorby struct iface *i;
914ddeeec14Snorby
915ddeeec14Snorby while ((i = LIST_FIRST(&conf->iface_list)) != NULL) {
916ddeeec14Snorby LIST_REMOVE(i, entry);
917ddeeec14Snorby if_del(i);
918ddeeec14Snorby }
919ddeeec14Snorby
920ddeeec14Snorby free(xconf);
921ddeeec14Snorby }
9229bb9ec63Sclaudio
9239bb9ec63Sclaudio int
host(const char * s,struct in_addr * addr,struct in_addr * mask)9249bb9ec63Sclaudio host(const char *s, struct in_addr *addr, struct in_addr *mask)
9259bb9ec63Sclaudio {
9269bb9ec63Sclaudio struct in_addr ina;
9279bb9ec63Sclaudio int bits = 32;
9289bb9ec63Sclaudio
9299bb9ec63Sclaudio bzero(&ina, sizeof(struct in_addr));
9309bb9ec63Sclaudio if (strrchr(s, '/') != NULL) {
9319bb9ec63Sclaudio if ((bits = inet_net_pton(AF_INET, s, &ina, sizeof(ina))) == -1)
9329bb9ec63Sclaudio return (0);
9339bb9ec63Sclaudio } else {
9349bb9ec63Sclaudio if (inet_pton(AF_INET, s, &ina) != 1)
9359bb9ec63Sclaudio return (0);
9369bb9ec63Sclaudio }
9379bb9ec63Sclaudio
9389bb9ec63Sclaudio addr->s_addr = ina.s_addr;
9399bb9ec63Sclaudio mask->s_addr = prefixlen2mask(bits);
9409bb9ec63Sclaudio
9419bb9ec63Sclaudio return (1);
9429bb9ec63Sclaudio }
943