Merge branch 'master' into int-new

This commit is contained in:
Ondrej Zajicek (work) 2016-11-08 19:27:58 +01:00
commit 8860e991f6
89 changed files with 2693 additions and 1625 deletions

View file

@ -125,7 +125,7 @@ more_end(void)
} }
static void static void
sig_handler(int signal) sig_handler(int signal UNUSED)
{ {
cleanup(); cleanup();
exit(0); exit(0);

View file

@ -24,7 +24,7 @@ vlog(const char *msg, va_list args)
int n = vsnprintf(buf, sizeof(buf), msg, args); int n = vsnprintf(buf, sizeof(buf), msg, args);
if (n < 0) if (n < 0)
snprintf(buf, sizeof(buf), "???"); snprintf(buf, sizeof(buf), "???");
if (n >= sizeof(buf)) else if (n >= (int) sizeof(buf))
snprintf(buf + sizeof(buf) - 100, 100, " ... <too long>"); snprintf(buf + sizeof(buf) - 100, 100, " ... <too long>");
fputs(buf, stderr); fputs(buf, stderr);
fputc('\n', stderr); fputc('\n', stderr);

View file

@ -24,6 +24,7 @@ $(o)cf-lex.c: $(s)cf-lex.l
$(FLEX) $(FLEX_DEBUG) -s -B -8 -Pcf_ -o$@ $< $(FLEX) $(FLEX_DEBUG) -s -B -8 -Pcf_ -o$@ $<
$(o)cf-lex.o: $(o)cf-parse.tab.h $(o)keywords.h $(o)cf-lex.o: $(o)cf-parse.tab.h $(o)keywords.h
$(o)cf-lex.o: CFLAGS+=-Wno-sign-compare -Wno-unused-function
$(addprefix $(o), cf-parse.y keywords.h commands.h cf-parse.tab.h cf-parse.tab.c cf-lex.c): $(objdir)/.dir-stamp $(addprefix $(o), cf-parse.y keywords.h commands.h cf-parse.tab.h cf-parse.tab.c cf-lex.c): $(objdir)/.dir-stamp

View file

@ -85,7 +85,7 @@ int undo_available; /* Undo was not requested from last reconfiguration */
* further use. Returns a pointer to the structure. * further use. Returns a pointer to the structure.
*/ */
struct config * struct config *
config_alloc(byte *name) config_alloc(const byte *name)
{ {
pool *p = rp_new(&root_pool, "Config"); pool *p = rp_new(&root_pool, "Config");
linpool *l = lp_new(p, 4080); linpool *l = lp_new(p, 4080);
@ -450,7 +450,7 @@ config_undo(void)
extern void cmd_reconfig_undo_notify(void); extern void cmd_reconfig_undo_notify(void);
static void static void
config_timeout(struct timer *t) config_timeout(struct timer *t UNUSED)
{ {
log(L_INFO "Config timeout expired, starting undo"); log(L_INFO "Config timeout expired, starting undo");
cmd_reconfig_undo_notify(); cmd_reconfig_undo_notify();
@ -530,7 +530,7 @@ cf_error(const char *msg, ...)
* and we want to preserve it for further use. * and we want to preserve it for further use.
*/ */
char * char *
cfg_strdup(char *c) cfg_strdup(const char *c)
{ {
int l = strlen(c) + 1; int l = strlen(c) + 1;
char *z = cfg_allocu(l); char *z = cfg_allocu(l);

View file

@ -20,7 +20,7 @@ struct config {
linpool *mem; /* Linear pool containing configuration data */ linpool *mem; /* Linear pool containing configuration data */
list protos; /* Configured protocol instances (struct proto_config) */ list protos; /* Configured protocol instances (struct proto_config) */
list tables; /* Configured routing tables (struct rtable_config) */ list tables; /* Configured routing tables (struct rtable_config) */
list logfiles; /* Configured log fils (sysdep) */ list logfiles; /* Configured log files (sysdep) */
int mrtdump_file; /* Configured MRTDump file (sysdep, fd in unix) */ int mrtdump_file; /* Configured MRTDump file (sysdep, fd in unix) */
char *syslog_name; /* Name used for syslog (NULL -> no syslog) */ char *syslog_name; /* Name used for syslog (NULL -> no syslog) */
@ -60,7 +60,7 @@ struct config {
extern struct config *config; /* Currently active configuration */ extern struct config *config; /* Currently active configuration */
extern struct config *new_config; /* Configuration being parsed */ extern struct config *new_config; /* Configuration being parsed */
struct config *config_alloc(byte *name); struct config *config_alloc(const byte *name);
int config_parse(struct config *); int config_parse(struct config *);
int cli_parse(struct config *); int cli_parse(struct config *);
void config_free(struct config *); void config_free(struct config *);
@ -94,7 +94,7 @@ extern linpool *cfg_mem;
#define cfg_alloc(size) lp_alloc(cfg_mem, size) #define cfg_alloc(size) lp_alloc(cfg_mem, size)
#define cfg_allocu(size) lp_allocu(cfg_mem, size) #define cfg_allocu(size) lp_allocu(cfg_mem, size)
#define cfg_allocz(size) lp_allocz(cfg_mem, size) #define cfg_allocz(size) lp_allocz(cfg_mem, size)
char *cfg_strdup(char *c); char *cfg_strdup(const char *c);
void cfg_copy_list(list *dest, list *src, unsigned node_size); void cfg_copy_list(list *dest, list *src, unsigned node_size);
/* Lexer */ /* Lexer */

View file

@ -143,7 +143,7 @@ expr_us:
/* Switches */ /* Switches */
bool: bool:
expr {$$ = !!$1; } expr { $$ = !!$1; }
| ON { $$ = 1; } | ON { $$ = 1; }
| YES { $$ = 1; } | YES { $$ = 1; }
| OFF { $$ = 0; } | OFF { $$ = 0; }
@ -202,7 +202,7 @@ net_roa4_: net_ip4_ MAX NUM AS NUM
{ {
$$ = cfg_alloc(sizeof(net_addr_roa4)); $$ = cfg_alloc(sizeof(net_addr_roa4));
net_fill_roa4($$, net4_prefix(&$1), net4_pxlen(&$1), $3, $5); net_fill_roa4($$, net4_prefix(&$1), net4_pxlen(&$1), $3, $5);
if ($3 < net4_pxlen(&$1) || $3 > IP4_MAX_PREFIX_LENGTH) if ($3 < (int) net4_pxlen(&$1) || $3 > IP4_MAX_PREFIX_LENGTH)
cf_error("Invalid max prefix length %d", $3); cf_error("Invalid max prefix length %d", $3);
}; };
@ -210,7 +210,7 @@ net_roa6_: net_ip6_ MAX NUM AS NUM
{ {
$$ = cfg_alloc(sizeof(net_addr_roa6)); $$ = cfg_alloc(sizeof(net_addr_roa6));
net_fill_roa6($$, net6_prefix(&$1), net6_pxlen(&$1), $3, $5); net_fill_roa6($$, net6_prefix(&$1), net6_pxlen(&$1), $3, $5);
if ($3 < net6_pxlen(&$1) || $3 > IP6_MAX_PREFIX_LENGTH) if ($3 < (int) net6_pxlen(&$1) || $3 > IP6_MAX_PREFIX_LENGTH)
cf_error("Invalid max prefix length %d", $3); cf_error("Invalid max prefix length %d", $3);
}; };

View file

@ -88,11 +88,13 @@ fi
if test "$bird_cflags_default" = yes ; then if test "$bird_cflags_default" = yes ; then
BIRD_CHECK_GCC_OPTION(bird_cv_c_option_wno_pointer_sign, -Wno-pointer-sign, -Wall) BIRD_CHECK_GCC_OPTION(bird_cv_c_option_wno_pointer_sign, -Wno-pointer-sign, -Wall)
BIRD_CHECK_GCC_OPTION(bird_cv_c_option_wno_missing_init, -Wno-missing-field-initializers, -Wall -Wextra)
BIRD_CHECK_GCC_OPTION(bird_cv_c_option_fno_strict_aliasing, -fno-strict-aliasing) BIRD_CHECK_GCC_OPTION(bird_cv_c_option_fno_strict_aliasing, -fno-strict-aliasing)
BIRD_CHECK_GCC_OPTION(bird_cv_c_option_fno_strict_overflow, -fno-strict-overflow) BIRD_CHECK_GCC_OPTION(bird_cv_c_option_fno_strict_overflow, -fno-strict-overflow)
CFLAGS="$CFLAGS -Wall -Wstrict-prototypes -Wno-parentheses" CFLAGS="$CFLAGS -Wall -Wextra -Wstrict-prototypes -Wno-parentheses"
BIRD_ADD_GCC_OPTION(bird_cv_c_option_wno_pointer_sign, -Wno-pointer-sign) BIRD_ADD_GCC_OPTION(bird_cv_c_option_wno_pointer_sign, -Wno-pointer-sign)
BIRD_ADD_GCC_OPTION(bird_cv_c_option_wno_missing_init, -Wno-missing-field-initializers)
BIRD_ADD_GCC_OPTION(bird_cv_c_option_fno_strict_aliasing, -fno-strict-aliasing) BIRD_ADD_GCC_OPTION(bird_cv_c_option_fno_strict_aliasing, -fno-strict-aliasing)
BIRD_ADD_GCC_OPTION(bird_cv_c_option_fno_strict_overflow, -fno-strict-overflow) BIRD_ADD_GCC_OPTION(bird_cv_c_option_fno_strict_overflow, -fno-strict-overflow)
fi fi

View file

@ -25,6 +25,9 @@ $(o)%.sgml: $(s)%.sgml $(objdir)/.dir-stamp
$(o)%.html: $(o)%.sgml $(o)%.html: $(o)%.sgml
cd $(dir $@) && $(sgml2)html $(notdir $<) cd $(dir $@) && $(sgml2)html $(notdir $<)
$(o)%.tex: $(o)%.sgml
cd $(dir $@) && $(sgml2)latex --output=tex $(notdir $<)
$(o)%.dvi: $(o)%.tex $(o)%.dvi: $(o)%.tex
cd $(dir $@) && TEXINPUTS=$(TEXINPUTS):$(doc-srcdir)/tex latex $(notdir $<) cd $(dir $@) && TEXINPUTS=$(TEXINPUTS):$(doc-srcdir)/tex latex $(notdir $<)
cd $(dir $@) && TEXINPUTS=$(TEXINPUTS):$(doc-srcdir)/tex latex $(notdir $<) cd $(dir $@) && TEXINPUTS=$(TEXINPUTS):$(doc-srcdir)/tex latex $(notdir $<)
@ -32,11 +35,9 @@ $(o)%.dvi: $(o)%.tex
$(o)%.ps: $(o)%.dvi $(o)%.ps: $(o)%.dvi
dvips -D600 -ta4 -o $@ $< dvips -D600 -ta4 -o $@ $<
$(o)%.pdf: $(o)%.ps $(o)%.pdf: $(o)%.tex
ps2pdf $< $@ pdflatex -output-directory=$(dir $@) $<
pdflatex -output-directory=$(dir $@) $<
$(o)%.tex: $(o)%.sgml
cd $(dir $@) && $(sgml2)latex --output=tex $(notdir $<)
$(o)%.txt: $(o)%.sgml $(o)%.txt: $(o)%.sgml
cd $(dir $@) && $(sgml2)txt $(notdir $<) cd $(dir $@) && $(sgml2)txt $(notdir $<)

File diff suppressed because it is too large Load diff

View file

@ -56,6 +56,7 @@
<newline> "<BR>" <newline> "<BR>"
<label> + "<@@label>[ID]" + <label> + "<@@label>[ID]" +
</label>
<header> <header>
</header> </header>
@ -134,6 +135,9 @@
<ncite> "[<I>[NOTE] ([ID])</I>]" <ncite> "[<I>[NOTE] ([ID])</I>]"
</ncite> </ncite>
<file> "<CODE>"
</file> "</CODE>"
<footnote> + "<BLOCKQUOTE>" <footnote> + "<BLOCKQUOTE>"
</footnote> "</BLOCKQUOTE>" + </footnote> "</BLOCKQUOTE>" +
@ -198,11 +202,13 @@
"<@@endurl>" + "<@@endurl>" +
</url> </url>
<htmlurl> + "<@@url>[URL]\n" <htmlurl> "<A HREF=\"[URL]\">[NAME]</A>"
"[NAME]</A>\n"
"<@@endurl>" +
</htmlurl> </htmlurl>
<rfc> "<A HREF=\"http://www.rfc-editor.org/info/rfc[ID]\">RFC [ID]</A>"
</rfc>
% ref modified to have an optional name field % ref modified to have an optional name field
<ref> + "<@@ref>[ID]\n" <ref> + "<@@ref>[ID]\n"
"[NAME]</A>\n" "[NAME]</A>\n"

View file

@ -2,7 +2,9 @@
% birddoc to LaTeX replacement file % birddoc to LaTeX replacement file
% The \relax is there to avoid sgml2latex rewriting the class % The \relax is there to avoid sgml2latex rewriting the class
<book> + "\\relax\\documentclass\[a4paper,10pt,openany\]{book}\n" <book> + "\\relax\\documentclass\[a4paper,10pt,openany,oneside\]{book}\n"
"\\usepackage\[colorlinks=true,linkcolor=blue,pdftitle={BIRD User's Guide}\]{hyperref}\n"
"\\usepackage{enumitem}\n"
"\\usepackage{birddoc}\n" "\\usepackage{birddoc}\n"
"\\usepackage{qwertz}\n" "\\usepackage{qwertz}\n"
"\\usepackage{url}\n" "\\usepackage{url}\n"
@ -109,7 +111,7 @@
<heading> "{" <heading> "{"
</heading> "}\n\n" </heading> "}\n\n"
<p> <p> "\\phantomsection{}"
</p> "\n\n" </p> "\n\n"
<itemize> + "\\begin{itemize}" + <itemize> + "\\begin{itemize}" +
@ -121,13 +123,13 @@
<list> + "\\begin{list}{}{}\n" + <list> + "\\begin{list}{}{}\n" +
</list> + "\\end{list}" + </list> + "\\end{list}" +
<descrip> + "\\begin{description}" + <descrip> + "\\begin{description}\[style=unboxed\]" +
</descrip> + "\\end{description}" + </descrip> + "\\end{description}" +
<item> + "\\item " <item> + "\\item "
</item> </item>
<tag> + "\\item\[{\\ttfamily " <tag> + "\\phantomsection\\item\[{\\ttfamily "
</tag> "}\] \\hfil\\break\n" + </tag> "}\] \\hfil\\break\n" +
<tagp> + "\\item\[ " <tagp> + "\\item\[ "
@ -154,7 +156,7 @@
% The idea here is to automatically insert soft hyphens after every slash in % The idea here is to automatically insert soft hyphens after every slash in
% the filename, so long filenames will break naturally. The url{} macro is % the filename, so long filenames will break naturally. The url{} macro is
% a kluge but it works, % a kluge but it works,
<file> "\\url{" <file> "{\\tt "
</file> "}" </file> "}"
<footnote> "\\footnote{" <footnote> "\\footnote{"
@ -223,19 +225,22 @@
<cparam> "\\cparam{" <cparam> "\\cparam{"
</cparam> "}" </cparam> "}"
<ref> "\\ref{[ID]} {([NAME])}" <ref> "\\hyperref\[[ID]\]{[NAME]} (p.\\,\\getpagerefnumber{[ID]})"
</ref> </ref>
<pageref> "\\pageref{[ID]}" <pageref> "\\pageref{[ID]}"
</pageref> </pageref>
%url added by HG %url added by HG
<url> "\\nameurl{[URL]}{[NAME]}" <url> "\\href{[URL]}{[NAME]}"
</url> </url>
<htmlurl> "\\onlynameurl{[NAME]}" <htmlurl> "\\href{[URL]}{[NAME]}"
</htmlurl> </htmlurl>
<rfc> "\\href{http://www.rfc-editor.org/info/rfc[ID]}{RFC [ID]}"
</rfc>
<x> <x>
</x> </x>

View file

@ -284,11 +284,11 @@ $latex2e->{postASP} = sub
# for nameurl # for nameurl
if ( /\\nameurl/ ) if ( /\\nameurl/ )
{ {
($urlid, $urlnam) = ($_ =~ /\\nameurl{(.*)}{(.*)}/); ($urlid, $urlnam) = ($_ =~ /\\nameurl\{(.*)\}\{(.*)\}/);
print $urlnum . ": " . $urlid . "\n" if ( $global->{debug} ); print $urlnum . ": " . $urlid . "\n" if ( $global->{debug} );
$urldef = latex2e_defnam($urlnum) . "url"; $urldef = latex2e_defnam($urlnum) . "url";
s/\\nameurl{.*}{.*}/{\\em $urlnam} {\\tt \\$urldef}/; s/\\nameurl\{.*\}\{.*\}/{\\em $urlnam} {\\tt \\$urldef}/;
push @urlnames, $_; push @urlnames, $_;
push @urldefines, "\\urldef{\\$urldef} \\url{$urlid}\n"; push @urldefines, "\\urldef{\\$urldef} \\url{$urlid}\n";
$urlnum++; $urlnum++;

View file

@ -99,7 +99,7 @@ anywhere else. <pavel@ucw.cz>
<!-- url added by HG; htmlurl added by esr --> <!-- url added by HG; htmlurl added by esr -->
<!entity % xref <!entity % xref
" label|ref|pageref|cite|url|htmlurl|ncite " > " label|ref|pageref|cite|url|htmlurl|rfc|ncite " >
<!entity % inline <!entity % inline
" (#pcdata | f| x| %emph; |sq| %xref | %index | file )* " > " (#pcdata | f| x| %emph; |sq| %xref | %index | file )* " >
@ -501,6 +501,10 @@ anywhere else. <pavel@ucw.cz>
url cdata #required url cdata #required
name cdata "&urlnam" > name cdata "&urlnam" >
<!element rfc - o empty>
<!attlist rfc
id cdata #required>
<!element pageref - o empty> <!element pageref - o empty>
<!attlist pageref <!attlist pageref
id cdata #required> id cdata #required>
@ -566,7 +570,7 @@ anywhere else. <pavel@ucw.cz>
<!element heading o o (%inline)> <!element heading o o (%inline)>
<!element chapt - o (%sect, sect*) +(footnote)> <!element chapt - o (%sect, sect*) +(footnote)>
<!element sect - o (%sect, sect1*) +(footnote)> <!element sect - o (%sect, sect1*) +(footnote)>
<!element sect1 - o (%sect, sect2*)> <!element sect1 - o (%sect, sect2*) +(footnote)>
<!element sect2 - o (%sect, sect3*)> <!element sect2 - o (%sect, sect3*)>
<!element sect3 - o (%sect, sect4*)> <!element sect3 - o (%sect, sect4*)>
<!element sect4 - o (%sect)> <!element sect4 - o (%sect)>

View file

@ -36,6 +36,7 @@ f_valid_set_type(int type)
case T_ENUM: case T_ENUM:
case T_IP: case T_IP:
case T_EC: case T_EC:
case T_LC:
return 1; return 1;
default: default:
@ -66,6 +67,14 @@ f_merge_items(struct f_tree *a, struct f_tree *b)
static inline struct f_tree * static inline struct f_tree *
f_new_pair_item(int fa, int ta, int fb, int tb) f_new_pair_item(int fa, int ta, int fb, int tb)
{ {
check_u16(fa);
check_u16(ta);
check_u16(fb);
check_u16(tb);
if ((ta < fa) || (tb < fb))
cf_error( "From value cannot be higher that To value in pair sets");
struct f_tree *t = f_new_tree(); struct f_tree *t = f_new_tree();
t->right = t; t->right = t;
t->from.type = t->to.type = T_PAIR; t->from.type = t->to.type = T_PAIR;
@ -77,22 +86,26 @@ f_new_pair_item(int fa, int ta, int fb, int tb)
static inline struct f_tree * static inline struct f_tree *
f_new_pair_set(int fa, int ta, int fb, int tb) f_new_pair_set(int fa, int ta, int fb, int tb)
{ {
struct f_tree *lst = NULL; check_u16(fa);
int i; check_u16(ta);
check_u16(fb);
if ((fa == ta) || ((fb == 0) && (tb == 0xFFFF))) check_u16(tb);
return f_new_pair_item(fa, ta, fb, tb);
if ((ta < fa) || (tb < fb)) if ((ta < fa) || (tb < fb))
cf_error( "From value cannot be higher that To value in pair sets"); cf_error( "From value cannot be higher that To value in pair sets");
struct f_tree *lst = NULL;
int i;
for (i = fa; i <= ta; i++) for (i = fa; i <= ta; i++)
lst = f_merge_items(lst, f_new_pair_item(i, i, fb, tb)); lst = f_merge_items(lst, f_new_pair_item(i, i, fb, tb));
return lst; return lst;
} }
#define CC_ALL 0xFFFF
#define EC_ALL 0xFFFFFFFF #define EC_ALL 0xFFFFFFFF
#define LC_ALL 0xFFFFFFFF
static struct f_tree * static struct f_tree *
f_new_ec_item(u32 kind, u32 ipv4_used, u32 key, u32 vf, u32 vt) f_new_ec_item(u32 kind, u32 ipv4_used, u32 key, u32 vf, u32 vt)
@ -132,6 +145,17 @@ f_new_ec_item(u32 kind, u32 ipv4_used, u32 key, u32 vf, u32 vt)
return t; return t;
} }
static struct f_tree *
f_new_lc_item(u32 f1, u32 t1, u32 f2, u32 t2, u32 f3, u32 t3)
{
struct f_tree *t = f_new_tree();
t->right = t;
t->from.type = t->to.type = T_LC;
t->from.val.lc = (lcomm) {f1, f2, f3};
t->to.val.lc = (lcomm) {t1, t2, t3};
return t;
}
static inline struct f_inst * static inline struct f_inst *
f_generate_empty(struct f_inst *dyn) f_generate_empty(struct f_inst *dyn)
{ {
@ -148,6 +172,9 @@ f_generate_empty(struct f_inst *dyn)
case EAF_TYPE_EC_SET: case EAF_TYPE_EC_SET:
e->aux = T_ECLIST; e->aux = T_ECLIST;
break; break;
case EAF_TYPE_LC_SET:
e->aux = T_LCLIST;
break;
default: default:
cf_error("Can't empty that attribute"); cf_error("Can't empty that attribute");
} }
@ -266,14 +293,44 @@ f_generate_ec(u16 kind, struct f_inst *tk, struct f_inst *tv)
return rv; return rv;
} }
static inline struct f_inst *
f_generate_lc(struct f_inst *t1, struct f_inst *t2, struct f_inst *t3)
{
struct f_inst *rv;
if ((t1->code == 'c') && (t2->code == 'c') && (t3->code == 'c')) {
if ((t1->aux != T_INT) || (t2->aux != T_INT) || (t3->aux != T_INT))
cf_error( "LC - Can't operate with value of non-integer type in tuple constructor");
rv = f_new_inst();
rv->code = 'C';
NEW_F_VAL;
rv->a1.p = val;
val->type = T_LC;
val->val.lc = (lcomm) { t1->a2.i, t2->a2.i, t3->a2.i };
}
else
{
rv = cfg_allocz(sizeof(struct f_inst3));
rv->lineno = ifs->lino;
rv->code = P('m','l');
rv->a1.p = t1;
rv->a2.p = t2;
INST3(rv).p = t3;
}
return rv;
}
CF_DECLS CF_DECLS
CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN, CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
ACCEPT, REJECT, ERROR, QUITBIRD, ACCEPT, REJECT, ERROR, QUITBIRD,
INT, BOOL, IP, PREFIX, PAIR, QUAD, EC, INT, BOOL, IP, PREFIX, PAIR, QUAD, EC, LC,
SET, STRING, BGPMASK, BGPPATH, CLIST, ECLIST, SET, STRING, BGPMASK, BGPPATH, CLIST, ECLIST, LCLIST,
IF, THEN, ELSE, CASE, IF, THEN, ELSE, CASE,
TRUE, FALSE, RT, RO, UNKNOWN, GENERIC, TRUE, FALSE, RT, RO, UNKNOWN, GENERIC,
FROM, GW, NET, MASK, PROTO, SOURCE, SCOPE, CAST, DEST, IFNAME, IFINDEX, FROM, GW, NET, MASK, PROTO, SOURCE, SCOPE, CAST, DEST, IFNAME, IFINDEX,
@ -291,9 +348,9 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
%type <x> term block cmds cmds_int cmd function_body constant constructor print_one print_list var_list var_listn dynamic_attr static_attr function_call symbol bgp_path_expr %type <x> term block cmds cmds_int cmd function_body constant constructor print_one print_list var_list var_listn dynamic_attr static_attr function_call symbol bgp_path_expr
%type <f> filter filter_body where_filter %type <f> filter filter_body where_filter
%type <i> type break_command pair_expr ec_kind %type <i> type break_command ec_kind
%type <i32> pair_atom ec_expr %type <i32> cnum
%type <e> pair_item ec_item set_item switch_item set_items switch_items switch_body %type <e> pair_item ec_item lc_item set_item switch_item set_items switch_items switch_body
%type <trie> fprefix_set %type <trie> fprefix_set
%type <v> set_atom switch_atom fipa %type <v> set_atom switch_atom fipa
%type <px> fprefix %type <px> fprefix
@ -326,17 +383,20 @@ type:
| PAIR { $$ = T_PAIR; } | PAIR { $$ = T_PAIR; }
| QUAD { $$ = T_QUAD; } | QUAD { $$ = T_QUAD; }
| EC { $$ = T_EC; } | EC { $$ = T_EC; }
| LC { $$ = T_LC; }
| STRING { $$ = T_STRING; } | STRING { $$ = T_STRING; }
| BGPMASK { $$ = T_PATH_MASK; } | BGPMASK { $$ = T_PATH_MASK; }
| BGPPATH { $$ = T_PATH; } | BGPPATH { $$ = T_PATH; }
| CLIST { $$ = T_CLIST; } | CLIST { $$ = T_CLIST; }
| ECLIST { $$ = T_ECLIST; } | ECLIST { $$ = T_ECLIST; }
| LCLIST { $$ = T_LCLIST; }
| type SET { | type SET {
switch ($1) { switch ($1) {
case T_INT: case T_INT:
case T_PAIR: case T_PAIR:
case T_QUAD: case T_QUAD:
case T_EC: case T_EC:
case T_LC:
case T_IP: case T_IP:
$$ = T_SET; $$ = T_SET;
break; break;
@ -511,30 +571,23 @@ switch_atom:
| ENUM { $$.type = pair_a($1); $$.val.i = pair_b($1); } | ENUM { $$.type = pair_a($1); $$.val.i = pair_b($1); }
; ;
pair_expr: cnum:
term { $$ = f_eval_int($1); check_u16($$); } term { $$ = f_eval_int($1); }
pair_atom:
pair_expr { $$ = pair($1, $1); }
| pair_expr DDOT pair_expr { $$ = pair($1, $3); }
| '*' { $$ = 0xFFFF; }
;
pair_item: pair_item:
'(' pair_atom ',' pair_atom ')' { '(' cnum ',' cnum ')' { $$ = f_new_pair_item($2, $2, $4, $4); }
$$ = f_new_pair_set(pair_a($2), pair_b($2), pair_a($4), pair_b($4)); | '(' cnum ',' cnum DDOT cnum ')' { $$ = f_new_pair_item($2, $2, $4, $6); }
} | '(' cnum ',' '*' ')' { $$ = f_new_pair_item($2, $2, 0, CC_ALL); }
| '(' pair_atom ',' pair_atom ')' DDOT '(' pair_expr ',' pair_expr ')' { | '(' cnum DDOT cnum ',' cnum ')' { $$ = f_new_pair_set($2, $4, $6, $6); }
/* Hack: $2 and $4 should be pair_expr, but that would cause shift/reduce conflict */ | '(' cnum DDOT cnum ',' cnum DDOT cnum ')' { $$ = f_new_pair_set($2, $4, $6, $8); }
if ((pair_a($2) != pair_b($2)) || (pair_a($4) != pair_b($4))) | '(' cnum DDOT cnum ',' '*' ')' { $$ = f_new_pair_item($2, $4, 0, CC_ALL); }
cf_error("syntax error"); | '(' '*' ',' cnum ')' { $$ = f_new_pair_set(0, CC_ALL, $4, $4); }
$$ = f_new_pair_item(pair_b($2), $8, pair_b($4), $10); | '(' '*' ',' cnum DDOT cnum ')' { $$ = f_new_pair_set(0, CC_ALL, $4, $6); }
} | '(' '*' ',' '*' ')' { $$ = f_new_pair_item(0, CC_ALL, 0, CC_ALL); }
| '(' cnum ',' cnum ')' DDOT '(' cnum ',' cnum ')'
{ $$ = f_new_pair_item($2, $8, $4, $10); }
; ;
ec_expr:
term { $$ = f_eval_int($1); }
ec_kind: ec_kind:
RT { $$ = EC_RT; } RT { $$ = EC_RT; }
| RO { $$ = EC_RO; } | RO { $$ = EC_RO; }
@ -543,14 +596,27 @@ ec_kind:
; ;
ec_item: ec_item:
'(' ec_kind ',' ec_expr ',' ec_expr ')' { $$ = f_new_ec_item($2, 0, $4, $6, $6); } '(' ec_kind ',' cnum ',' cnum ')' { $$ = f_new_ec_item($2, 0, $4, $6, $6); }
| '(' ec_kind ',' ec_expr ',' ec_expr DDOT ec_expr ')' { $$ = f_new_ec_item($2, 0, $4, $6, $8); } | '(' ec_kind ',' cnum ',' cnum DDOT cnum ')' { $$ = f_new_ec_item($2, 0, $4, $6, $8); }
| '(' ec_kind ',' ec_expr ',' '*' ')' { $$ = f_new_ec_item($2, 0, $4, 0, EC_ALL); } | '(' ec_kind ',' cnum ',' '*' ')' { $$ = f_new_ec_item($2, 0, $4, 0, EC_ALL); }
; ;
lc_item:
'(' cnum ',' cnum ',' cnum ')' { $$ = f_new_lc_item($2, $2, $4, $4, $6, $6); }
| '(' cnum ',' cnum ',' cnum DDOT cnum ')' { $$ = f_new_lc_item($2, $2, $4, $4, $6, $8); }
| '(' cnum ',' cnum ',' '*' ')' { $$ = f_new_lc_item($2, $2, $4, $4, 0, LC_ALL); }
| '(' cnum ',' cnum DDOT cnum ',' '*' ')' { $$ = f_new_lc_item($2, $2, $4, $6, 0, LC_ALL); }
| '(' cnum ',' '*' ',' '*' ')' { $$ = f_new_lc_item($2, $2, 0, LC_ALL, 0, LC_ALL); }
| '(' cnum DDOT cnum ',' '*' ',' '*' ')' { $$ = f_new_lc_item($2, $4, 0, LC_ALL, 0, LC_ALL); }
| '(' '*' ',' '*' ',' '*' ')' { $$ = f_new_lc_item(0, LC_ALL, 0, LC_ALL, 0, LC_ALL); }
| '(' cnum ',' cnum ',' cnum ')' DDOT '(' cnum ',' cnum ',' cnum ')'
{ $$ = f_new_lc_item($2, $10, $4, $12, $6, $14); }
;
set_item: set_item:
pair_item pair_item
| ec_item | ec_item
| lc_item
| set_atom { $$ = f_new_item($1, $1); } | set_atom { $$ = f_new_item($1, $1); }
| set_atom DDOT set_atom { $$ = f_new_item($1, $3); } | set_atom DDOT set_atom { $$ = f_new_item($1, $3); }
; ;
@ -558,6 +624,7 @@ set_item:
switch_item: switch_item:
pair_item pair_item
| ec_item | ec_item
| lc_item
| switch_atom { $$ = f_new_item($1, $1); } | switch_atom { $$ = f_new_item($1, $1); }
| switch_atom DDOT switch_atom { $$ = f_new_item($1, $3); } | switch_atom DDOT switch_atom { $$ = f_new_item($1, $3); }
; ;
@ -648,6 +715,7 @@ constant:
constructor: constructor:
'(' term ',' term ')' { $$ = f_generate_dpair($2, $4); } '(' term ',' term ')' { $$ = f_generate_dpair($2, $4); }
| '(' ec_kind ',' term ',' term ')' { $$ = f_generate_ec($2, $4, $6); } | '(' ec_kind ',' term ',' term ')' { $$ = f_generate_ec($2, $4, $6); }
| '(' term ',' term ',' term ')' { $$ = f_generate_lc($2, $4, $6); }
; ;
@ -758,6 +826,7 @@ term:
| '+' EMPTY '+' { $$ = f_new_inst(); $$->code = 'E'; $$->aux = T_PATH; } | '+' EMPTY '+' { $$ = f_new_inst(); $$->code = 'E'; $$->aux = T_PATH; }
| '-' EMPTY '-' { $$ = f_new_inst(); $$->code = 'E'; $$->aux = T_CLIST; } | '-' EMPTY '-' { $$ = f_new_inst(); $$->code = 'E'; $$->aux = T_CLIST; }
| '-' '-' EMPTY '-' '-' { $$ = f_new_inst(); $$->code = 'E'; $$->aux = T_ECLIST; } | '-' '-' EMPTY '-' '-' { $$ = f_new_inst(); $$->code = 'E'; $$->aux = T_ECLIST; }
| '-' '-' '-' EMPTY '-' '-' '-' { $$ = f_new_inst(); $$->code = 'E'; $$->aux = T_LCLIST; }
| PREPEND '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('A','p'); $$->a1.p = $3; $$->a2.p = $5; } | PREPEND '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('A','p'); $$->a1.p = $3; $$->a2.p = $5; }
| ADD '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('C','a'); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'a'; } | ADD '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('C','a'); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'a'; }
| DELETE '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('C','a'); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'd'; } | DELETE '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('C','a'); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'd'; }

View file

@ -99,6 +99,18 @@ pm_format(struct f_path_mask *p, buffer *buf)
static inline int val_is_ip4(const struct f_val v) static inline int val_is_ip4(const struct f_val v)
{ return (v.type == T_IP) && ipa_is_ip4(v.val.ip); } { return (v.type == T_IP) && ipa_is_ip4(v.val.ip); }
static inline int
lcomm_cmp(lcomm v1, lcomm v2)
{
if (v1.asn != v2.asn)
return (v1.asn > v2.asn) ? 1 : -1;
if (v1.ldp1 != v2.ldp1)
return (v1.ldp1 > v2.ldp1) ? 1 : -1;
if (v1.ldp2 != v2.ldp2)
return (v1.ldp2 > v2.ldp2) ? 1 : -1;
return 0;
}
/** /**
* val_compare - compare two values * val_compare - compare two values
* @v1: first value * @v1: first value
@ -138,6 +150,8 @@ val_compare(struct f_val v1, struct f_val v2)
return uint_cmp(v1.val.i, v2.val.i); return uint_cmp(v1.val.i, v2.val.i);
case T_EC: case T_EC:
return u64_cmp(v1.val.ec, v2.val.ec); return u64_cmp(v1.val.ec, v2.val.ec);
case T_LC:
return lcomm_cmp(v1.val.lc, v2.val.lc);
case T_IP: case T_IP:
return ipa_compare(v1.val.ip, v2.val.ip); return ipa_compare(v1.val.ip, v2.val.ip);
case T_NET: case T_NET:
@ -201,6 +215,7 @@ val_same(struct f_val v1, struct f_val v2)
case T_PATH: case T_PATH:
case T_CLIST: case T_CLIST:
case T_ECLIST: case T_ECLIST:
case T_LCLIST:
return adata_same(v1.val.ad, v2.val.ad); return adata_same(v1.val.ad, v2.val.ad);
case T_SET: case T_SET:
return same_tree(v1.val.t, v2.val.t); return same_tree(v1.val.t, v2.val.t);
@ -241,6 +256,10 @@ static inline int
eclist_set_type(struct f_tree *set) eclist_set_type(struct f_tree *set)
{ return set->from.type == T_EC; } { return set->from.type == T_EC; }
static inline int
lclist_set_type(struct f_tree *set)
{ return set->from.type == T_LC; }
static int static int
clist_match_set(struct adata *clist, struct f_tree *set) clist_match_set(struct adata *clist, struct f_tree *set)
{ {
@ -286,6 +305,30 @@ eclist_match_set(struct adata *list, struct f_tree *set)
return 0; return 0;
} }
static int
lclist_match_set(struct adata *list, struct f_tree *set)
{
if (!list)
return 0;
if (!lclist_set_type(set))
return CMP_ERROR;
struct f_val v;
u32 *l = int_set_get_data(list);
int len = int_set_get_size(list);
int i;
v.type = T_LC;
for (i = 0; i < len; i += 3) {
v.val.lc = lc_get(l, i);
if (find_tree(set, v))
return 1;
}
return 0;
}
static struct adata * static struct adata *
clist_filter(struct linpool *pool, struct adata *list, struct f_val set, int pos) clist_filter(struct linpool *pool, struct adata *list, struct f_val set, int pos)
{ {
@ -312,7 +355,7 @@ clist_filter(struct linpool *pool, struct adata *list, struct f_val set, int pos
*k++ = v.val.i; *k++ = v.val.i;
} }
int nl = (k - tmp) * 4; uint nl = (k - tmp) * sizeof(u32);
if (nl == list->length) if (nl == list->length)
return list; return list;
@ -346,7 +389,39 @@ eclist_filter(struct linpool *pool, struct adata *list, struct f_val set, int po
} }
} }
int nl = (k - tmp) * 4; uint nl = (k - tmp) * sizeof(u32);
if (nl == list->length)
return list;
struct adata *res = adata_empty(pool, nl);
memcpy(res->data, tmp, nl);
return res;
}
static struct adata *
lclist_filter(struct linpool *pool, struct adata *list, struct f_val set, int pos)
{
if (!list)
return NULL;
int tree = (set.type == T_SET); /* 1 -> set is T_SET, 0 -> set is T_CLIST */
struct f_val v;
int len = int_set_get_size(list);
u32 *l = int_set_get_data(list);
u32 tmp[len];
u32 *k = tmp;
int i;
v.type = T_LC;
for (i = 0; i < len; i += 3) {
v.val.lc = lc_get(l, i);
/* pos && member(val, set) || !pos && !member(val, set), member() depends on tree */
if ((tree ? !!find_tree(set.val.t, v) : lc_set_contains(set.val.ad, v.val.lc)) == pos)
k = lc_copy(k, l+i);
}
uint nl = (k - tmp) * sizeof(u32);
if (nl == list->length) if (nl == list->length)
return list; return list;
@ -381,6 +456,9 @@ val_in_range(struct f_val v1, struct f_val v2)
if ((v1.type == T_EC) && (v2.type == T_ECLIST)) if ((v1.type == T_EC) && (v2.type == T_ECLIST))
return ec_set_contains(v2.val.ad, v1.val.ec); return ec_set_contains(v2.val.ad, v1.val.ec);
if ((v1.type == T_LC) && (v2.type == T_LCLIST))
return lc_set_contains(v2.val.ad, v1.val.lc);
if ((v1.type == T_STRING) && (v2.type == T_STRING)) if ((v1.type == T_STRING) && (v2.type == T_STRING))
return patmatch(v2.val.s, v1.val.s); return patmatch(v2.val.s, v1.val.s);
@ -407,6 +485,9 @@ val_in_range(struct f_val v1, struct f_val v2)
if (v1.type == T_ECLIST) if (v1.type == T_ECLIST)
return eclist_match_set(v1.val.ad, v2.val.t); return eclist_match_set(v1.val.ad, v2.val.t);
if (v1.type == T_LCLIST)
return lclist_match_set(v1.val.ad, v2.val.t);
if (v1.type == T_PATH) if (v1.type == T_PATH)
return as_path_match_set(v1.val.ad, v2.val.t); return as_path_match_set(v1.val.ad, v2.val.t);
@ -431,12 +512,14 @@ val_format(struct f_val v, buffer *buf)
case T_PAIR: buffer_print(buf, "(%u,%u)", v.val.i >> 16, v.val.i & 0xffff); return; case T_PAIR: buffer_print(buf, "(%u,%u)", v.val.i >> 16, v.val.i & 0xffff); return;
case T_QUAD: buffer_print(buf, "%R", v.val.i); return; case T_QUAD: buffer_print(buf, "%R", v.val.i); return;
case T_EC: ec_format(buf2, v.val.ec); buffer_print(buf, "%s", buf2); return; case T_EC: ec_format(buf2, v.val.ec); buffer_print(buf, "%s", buf2); return;
case T_LC: lc_format(buf2, v.val.lc); buffer_print(buf, "%s", buf2); return;
case T_PREFIX_SET: trie_format(v.val.ti, buf); return; case T_PREFIX_SET: trie_format(v.val.ti, buf); return;
case T_SET: tree_format(v.val.t, buf); return; case T_SET: tree_format(v.val.t, buf); return;
case T_ENUM: buffer_print(buf, "(enum %x)%u", v.type, v.val.i); return; case T_ENUM: buffer_print(buf, "(enum %x)%u", v.type, v.val.i); return;
case T_PATH: as_path_format(v.val.ad, buf2, 1000); buffer_print(buf, "(path %s)", buf2); return; case T_PATH: as_path_format(v.val.ad, buf2, 1000); buffer_print(buf, "(path %s)", buf2); return;
case T_CLIST: int_set_format(v.val.ad, 1, -1, buf2, 1000); buffer_print(buf, "(clist %s)", buf2); return; case T_CLIST: int_set_format(v.val.ad, 1, -1, buf2, 1000); buffer_print(buf, "(clist %s)", buf2); return;
case T_ECLIST: ec_set_format(v.val.ad, -1, buf2, 1000); buffer_print(buf, "(eclist %s)", buf2); return; case T_ECLIST: ec_set_format(v.val.ad, -1, buf2, 1000); buffer_print(buf, "(eclist %s)", buf2); return;
case T_LCLIST: lc_set_format(v.val.ad, -1, buf2, 1000); buffer_print(buf, "(lclist %s)", buf2); return;
case T_PATH_MASK: pm_format(v.val.path_mask, buf); return; case T_PATH_MASK: pm_format(v.val.path_mask, buf); return;
default: buffer_print(buf, "[unknown type %x]", v.type); return; default: buffer_print(buf, "[unknown type %x]", v.type); return;
} }
@ -628,6 +711,7 @@ interpret(struct f_inst *what)
runtime("Can't operate with value of non-integer type in EC constructor"); runtime("Can't operate with value of non-integer type in EC constructor");
val = v2.val.i; val = v2.val.i;
/* XXXX */
res.type = T_EC; res.type = T_EC;
if (what->aux == EC_GENERIC) { if (what->aux == EC_GENERIC) {
@ -649,6 +733,24 @@ interpret(struct f_inst *what)
break; break;
} }
case P('m','l'):
{
TWOARGS;
/* Third argument hack */
struct f_val v3 = interpret(INST3(what).p);
if (v3.type & T_RETURN)
return v3;
if ((v1.type != T_INT) || (v2.type != T_INT) || (v3.type != T_INT))
runtime( "Can't operate with value of non-integer type in LC constructor" );
res.type = T_LC;
res.val.lc = (lcomm) { v1.val.i, v2.val.i, v3.val.i };
break;
}
/* Relational operators */ /* Relational operators */
#define COMPARE(x) \ #define COMPARE(x) \
@ -883,6 +985,13 @@ interpret(struct f_inst *what)
break; break;
} }
/* The same special case for lc_set */
if ((what->aux & EAF_TYPE_MASK) == EAF_TYPE_LC_SET) {
res.type = T_LCLIST;
res.val.ad = adata_empty(f_pool, 0);
break;
}
/* Undefined value */ /* Undefined value */
res.type = T_VOID; res.type = T_VOID;
break; break;
@ -922,6 +1031,10 @@ interpret(struct f_inst *what)
res.type = T_ECLIST; res.type = T_ECLIST;
res.val.ad = e->u.ptr; res.val.ad = e->u.ptr;
break; break;
case EAF_TYPE_LC_SET:
res.type = T_LCLIST;
res.val.ad = e->u.ptr;
break;
case EAF_TYPE_UNDEF: case EAF_TYPE_UNDEF:
res.type = T_VOID; res.type = T_VOID;
break; break;
@ -1010,6 +1123,11 @@ interpret(struct f_inst *what)
runtime( "Setting eclist attribute to non-eclist value" ); runtime( "Setting eclist attribute to non-eclist value" );
l->attrs[0].u.ptr = v1.val.ad; l->attrs[0].u.ptr = v1.val.ad;
break; break;
case EAF_TYPE_LC_SET:
if (v1.type != T_LCLIST)
runtime( "Setting lclist attribute to non-lclist value" );
l->attrs[0].u.ptr = v1.val.ad;
break;
case EAF_TYPE_UNDEF: case EAF_TYPE_UNDEF:
if (v1.type != T_VOID) if (v1.type != T_VOID)
runtime( "Setting void attribute to non-void value" ); runtime( "Setting void attribute to non-void value" );
@ -1051,6 +1169,7 @@ interpret(struct f_inst *what)
case T_PATH: res.val.i = as_path_getlen(v1.val.ad); break; case T_PATH: res.val.i = as_path_getlen(v1.val.ad); break;
case T_CLIST: res.val.i = int_set_get_size(v1.val.ad); break; case T_CLIST: res.val.i = int_set_get_size(v1.val.ad); break;
case T_ECLIST: res.val.i = ec_set_get_size(v1.val.ad); break; case T_ECLIST: res.val.i = ec_set_get_size(v1.val.ad); break;
case T_LCLIST: res.val.i = lc_set_get_size(v1.val.ad); break;
default: runtime( "Prefix, path, clist or eclist expected" ); default: runtime( "Prefix, path, clist or eclist expected" );
} }
break; break;
@ -1240,7 +1359,7 @@ interpret(struct f_inst *what)
else if (v2.type == T_ECLIST) else if (v2.type == T_ECLIST)
arg_set = 2; arg_set = 2;
else if (v2.type != T_EC) else if (v2.type != T_EC)
runtime("Can't add/delete non-pair"); runtime("Can't add/delete non-ec");
res.type = T_ECLIST; res.type = T_ECLIST;
switch (what->aux) switch (what->aux)
@ -1271,8 +1390,50 @@ interpret(struct f_inst *what)
bug("unknown Ca operation"); bug("unknown Ca operation");
} }
} }
else if (v1.type == T_LCLIST)
{
/* Large community list */
int arg_set = 0;
/* v2.val is either LC or LC-set */
if ((v2.type == T_SET) && lclist_set_type(v2.val.t))
arg_set = 1;
else if (v2.type == T_LCLIST)
arg_set = 2;
else if (v2.type != T_LC)
runtime("Can't add/delete non-lc");
res.type = T_LCLIST;
switch (what->aux)
{
case 'a':
if (arg_set == 1)
runtime("Can't add set");
else if (!arg_set)
res.val.ad = lc_set_add(f_pool, v1.val.ad, v2.val.lc);
else else
runtime("Can't add/delete to non-(e)clist"); res.val.ad = lc_set_union(f_pool, v1.val.ad, v2.val.ad);
break;
case 'd':
if (!arg_set)
res.val.ad = lc_set_del(f_pool, v1.val.ad, v2.val.lc);
else
res.val.ad = lclist_filter(f_pool, v1.val.ad, v2, 0);
break;
case 'f':
if (!arg_set)
runtime("Can't filter lc");
res.val.ad = lclist_filter(f_pool, v1.val.ad, v2, 1);
break;
default:
bug("unknown Ca operation");
}
}
else
runtime("Can't add/delete to non-[e|l]clist");
break; break;
@ -1370,6 +1531,12 @@ i_same(struct f_inst *f1, struct f_inst *f2)
case '~': TWOARGS; break; case '~': TWOARGS; break;
case P('d','e'): ONEARG; break; case P('d','e'): ONEARG; break;
case P('m','l'):
TWOARGS;
if (!i_same(INST3(f1).p, INST3(f2).p))
return 0;
break;
case 's': case 's':
ARG(v2, a2.p); ARG(v2, a2.p);
{ {

View file

@ -38,6 +38,17 @@ struct f_inst_roa_check {
struct rtable_config *rtc; struct rtable_config *rtc;
}; };
struct f_inst3 {
struct f_inst i;
union {
int i;
void *p;
} a3;
};
#define INST3(x) (((struct f_inst3 *) x)->a3)
struct f_prefix { struct f_prefix {
net_addr net; net_addr net;
u8 lo, hi; u8 lo, hi;
@ -48,6 +59,7 @@ struct f_val {
union { union {
uint i; uint i;
u64 ec; u64 ec;
lcomm lc;
ip_addr ip; ip_addr ip;
const net_addr *net; const net_addr *net;
char *s; char *s;
@ -146,8 +158,10 @@ void val_format(struct f_val v, buffer *buf);
#define T_PATH_MASK 0x23 /* mask for BGP path */ #define T_PATH_MASK 0x23 /* mask for BGP path */
#define T_PATH 0x24 /* BGP path */ #define T_PATH 0x24 /* BGP path */
#define T_CLIST 0x25 /* Community list */ #define T_CLIST 0x25 /* Community list */
#define T_ECLIST 0x26 /* Extended community list */ #define T_EC 0x26 /* Extended community value, u64 */
#define T_EC 0x27 /* Extended community value, u64 */ #define T_ECLIST 0x27 /* Extended community list */
#define T_LC 0x28 /* Large community value, lcomm */
#define T_LCLIST 0x29 /* Large community list */
#define T_RETURN 0x40 #define T_RETURN 0x40
#define T_SET 0x80 #define T_SET 0x80
@ -175,7 +189,7 @@ struct f_tree {
struct f_trie_node struct f_trie_node
{ {
ip_addr addr, mask, accept; ip_addr addr, mask, accept;
int plen; uint plen;
struct f_trie_node *c[2]; struct f_trie_node *c[2];
}; };

View file

@ -31,6 +31,11 @@ function 'mkpair-a'(int a)
return (1, a); return (1, a);
} }
function mktrip(int a)
{
return (a, 2*a, 3*a);
}
function mkpath(int a; int b) function mkpath(int a; int b)
{ {
return [= a b 3 2 1 =]; return [= a b 3 2 1 =];
@ -95,6 +100,8 @@ clist l;
clist l2; clist l2;
eclist el; eclist el;
eclist el2; eclist el2;
lclist ll;
lclist ll2;
{ {
print "Entering path test..."; print "Entering path test...";
pm1 = / 4 3 2 1 /; pm1 = / 4 3 2 1 /;
@ -160,7 +167,7 @@ eclist el2;
print "Community list (1,2) (3,1) (3,5) ", l, " len: ", l.len; print "Community list (1,2) (3,1) (3,5) ", l, " len: ", l.len;
l = add( l, (3,2) ); l = add( l, (3,2) );
l = add( l, (4,5) ); l = add( l, (4,5) );
print "Community list (1,2) (3,1) (3,2) (3,5) (4,5) ", l, " len: ", l.len; print "Community list (1,2) (3,1) (3,5) (3,2) (4,5) ", l, " len: ", l.len;
print "Should be true: ", l ~ [(*,2)], " ", l ~ [(*,5)], " ", l ~ [(*, one)]; print "Should be true: ", l ~ [(*,2)], " ", l ~ [(*,5)], " ", l ~ [(*, one)];
print "Should be false: ", l ~ [(*,3)], " ", l ~ [(*,(one+6))], " ", l ~ [(*, (one+one+one))]; print "Should be false: ", l ~ [(*,3)], " ", l ~ [(*,(one+6))], " ", l ~ [(*, (one+one+one))];
l = delete( l, [(*,(one+onef(3)))] ); l = delete( l, [(*,(one+onef(3)))] );
@ -209,6 +216,33 @@ eclist el2;
print "eclist A isect B: ", filter( el, el2 ); print "eclist A isect B: ", filter( el, el2 );
print "eclist A \ B: ", delete( el, el2 ); print "eclist A \ B: ", delete( el, el2 );
ll = --- empty ---;
ll = add(ll, (ten, 20, 30));
ll = add(ll, (1000, 2000, 3000));
ll = add(ll, mktrip(100000));
print "LC list (10, 20, 30) (1000, 2000, 3000) (100000, 200000, 300000):";
print ll;
print "LC len: ", el.len;
print "Should be true: ", mktrip(1000) ~ ll, " ", ll ~ [(5,10,15), (10,20,30)], " ", ll ~ [(10,15..25,*)], " ", ll ~ [(ten, *, *)];
print "Should be false: ", mktrip(100) ~ ll, " ", ll ~ [(5,10,15), (10,21,30)], " ", ll ~ [(10,21..25,*)], " ", ll ~ [(11, *, *)];
print "LC filtered: ", filter(ll, [(5..15, *, *), (100000, 500..500000, *)]);
ll = --- empty ---;
ll = add(ll, (10, 10, 10));
ll = add(ll, (20, 20, 20));
ll = add(ll, (30, 30, 30));
ll2 = --- empty ---;
ll2 = add(ll2, (20, 20, 20));
ll2 = add(ll2, (30, 30, 30));
ll2 = add(ll2, (40, 40, 40));
print "lclist A (10,20,30): ", ll;
print "lclist B (20,30,40): ", ll2;
print "lclist A union B: ", add(ll, ll2);
print "lclist A isect B: ", filter(ll, ll2);
print "lclist A \ B: ", delete(ll, ll2);
# test_roa(); # test_roa();
} }

View file

@ -63,7 +63,7 @@ tree_compare(const void *p1, const void *p2)
* build_tree * build_tree
* @from: degenerated tree (linked by @tree->left) to be transformed into form suitable for find_tree() * @from: degenerated tree (linked by @tree->left) to be transformed into form suitable for find_tree()
* *
* Transforms denerated tree into balanced tree. * Transforms degenerated tree into balanced tree.
*/ */
struct f_tree * struct f_tree *
build_tree(struct f_tree *from) build_tree(struct f_tree *from)
@ -165,6 +165,9 @@ tree_format(struct f_tree *t, buffer *buf)
tree_node_format(t, buf); tree_node_format(t, buf);
if (buf->pos == buf->end)
return;
/* Undo last separator */ /* Undo last separator */
if (buf->pos[-1] != '[') if (buf->pos[-1] != '[')
buf->pos -= 2; buf->pos -= 2;

View file

@ -220,7 +220,7 @@ trie_add_prefix(struct f_trie *t, const net_addr *net, uint l, uint h)
} }
static int static int
trie_match_prefix(struct f_trie *t, ip_addr px, int plen) trie_match_prefix(struct f_trie *t, ip_addr px, uint plen)
{ {
ip_addr pmask = ipa_mkmask(plen); ip_addr pmask = ipa_mkmask(plen);
ip_addr paddr = ipa_and(px, pmask); ip_addr paddr = ipa_and(px, pmask);
@ -266,7 +266,8 @@ trie_match_prefix(struct f_trie *t, ip_addr px, int plen)
int int
trie_match_net(struct f_trie *t, const net_addr *n) trie_match_net(struct f_trie *t, const net_addr *n)
{ {
int add = 0; uint add = 0;
switch (n->type) { switch (n->type) {
case NET_IP4: case NET_IP4:
case NET_VPN4: case NET_VPN4:
@ -333,9 +334,12 @@ trie_format(struct f_trie *t, buffer *buf)
buffer_puts(buf, "["); buffer_puts(buf, "[");
if (t->zero) if (t->zero)
buffer_print(buf, "%I/%d", IPA_NONE, 0); buffer_print(buf, "%I/%d, ", IPA_NONE, 0);
trie_node_format(t->root, buf); trie_node_format(t->root, buf);
if (buf->pos == buf->end)
return;
/* Undo last separator */ /* Undo last separator */
if (buf->pos[-1] != '[') if (buf->pos[-1] != '[')
buf->pos -= 2; buf->pos -= 2;

View file

@ -2,6 +2,7 @@ H Library functions
S ip.c S ip.c
S lists.c S lists.c
S checksum.c bitops.c patmatch.c printf.c xmalloc.c tbf.c S checksum.c bitops.c patmatch.c printf.c xmalloc.c tbf.c
S mac.c
D resource.sgml D resource.sgml
S resource.c S resource.c
S mempool.c S mempool.c

View file

@ -1,3 +1,3 @@
src := bitops.c checksum.c event.c idm.c ip.c lists.c md5.c mempool.c net.c patmatch.c printf.c resource.c sha1.c sha256.c sha512.c slab.c slists.c tbf.c xmalloc.c src := bitops.c checksum.c event.c idm.c ip.c lists.c mac.c md5.c mempool.c net.c patmatch.c printf.c resource.c sha1.c sha256.c sha512.c slab.c slists.c tbf.c xmalloc.c
obj := $(src-o-files) obj := $(src-o-files)
$(all-daemon) $(all-daemon)

View file

@ -63,7 +63,6 @@ static inline int u64_cmp(u64 i1, u64 i2)
#define UNUSED __attribute__((unused)) #define UNUSED __attribute__((unused))
#define PACKED __attribute__((packed)) #define PACKED __attribute__((packed))
/* Microsecond time */ /* Microsecond time */
typedef s64 btime; typedef s64 btime;

View file

@ -1,3 +1,17 @@
/*
* BIRD Library -- Generic Buffer Structure
*
* (c) 2013 Ondrej Zajicek <santiago@crfreenet.org>
* (c) 2013 CZ.NIC z.s.p.o.
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
#ifndef _BIRD_BUFFER_H_
#define _BIRD_BUFFER_H_
#include "lib/resource.h"
#include "sysdep/config.h"
#define BUFFER(type) struct { type *data; uint used, size; } #define BUFFER(type) struct { type *data; uint used, size; }
@ -32,4 +46,4 @@
#define BUFFER_FLUSH(v) ({ (v).used = 0; }) #define BUFFER_FLUSH(v) ({ (v).used = 0; })
#endif /* _BIRD_BUFFER_H_ */

View file

@ -1,8 +1,18 @@
/*
* BIRD Library -- Generic Hash Table
*
* (c) 2013 Ondrej Zajicek <santiago@crfreenet.org>
* (c) 2013 CZ.NIC z.s.p.o.
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
#ifndef _BIRD_HASH_H_
#define _BIRD_HASH_H_
#define HASH(type) struct { type **data; uint count, order; } #define HASH(type) struct { type **data; uint count, order; }
#define HASH_TYPE(v) typeof(** (v).data) #define HASH_TYPE(v) typeof(** (v).data)
#define HASH_SIZE(v) (1 << (v).order) #define HASH_SIZE(v) (1U << (v).order)
#define HASH_EQ(v,id,k1,k2...) (id##_EQ(k1, k2)) #define HASH_EQ(v,id,k1,k2...) (id##_EQ(k1, k2))
#define HASH_FN(v,id,key...) ((u32) (id##_FN(key)) >> (32 - (v).order)) #define HASH_FN(v,id,key...) ((u32) (id##_FN(key)) >> (32 - (v).order))
@ -116,12 +126,12 @@
#define HASH_MAY_RESIZE_DOWN_(v,pool,rehash_fn,args) \ #define HASH_MAY_RESIZE_DOWN_(v,pool,rehash_fn,args) \
({ \ ({ \
int _o = (v).order; \ uint _o = (v).order; \
while (((v).count < ((1 << _o) REHASH_LO_MARK(args))) && \ while (((v).count < ((1U << _o) REHASH_LO_MARK(args))) && \
(_o > (REHASH_LO_BOUND(args)))) \ (_o > (REHASH_LO_BOUND(args)))) \
_o -= (REHASH_LO_STEP(args)); \ _o -= (REHASH_LO_STEP(args)); \
if (_o < (v).order) \ if (_o < (v).order) \
rehash_fn(&(v), pool, _o - (int) (v).order); \ rehash_fn(&(v), pool, _o - (v).order); \
}) })
@ -178,6 +188,7 @@
#define HASH_WALK_FILTER_END } while (0) #define HASH_WALK_FILTER_END } while (0)
static inline void static inline void
mem_hash_init(u64 *h) mem_hash_init(u64 *h)
{ {
@ -185,11 +196,12 @@ mem_hash_init(u64 *h)
} }
static inline void static inline void
mem_hash_mix(u64 *h, void *p, int s) mem_hash_mix(u64 *h, void *p, uint s)
{ {
const u64 multiplier = 0xb38bc09a61202731ULL; const u64 multiplier = 0xb38bc09a61202731ULL;
const char *pp = p; const char *pp = p;
uint i; uint i;
for (i=0; i<s/4; i++) for (i=0; i<s/4; i++)
*h = *h * multiplier + ((const u32 *)pp)[i]; *h = *h * multiplier + ((const u32 *)pp)[i];
@ -204,7 +216,7 @@ mem_hash_value(u64 *h)
} }
static inline uint static inline uint
mem_hash(void *p, int s) mem_hash(void *p, uint s)
{ {
static u64 h; static u64 h;
mem_hash_init(&h); mem_hash_init(&h);
@ -212,3 +224,4 @@ mem_hash(void *p, int s)
return mem_hash_value(&h); return mem_hash_value(&h);
} }
#endif

View file

@ -53,7 +53,7 @@ idm_alloc(struct idm *m)
ASSERT(0); ASSERT(0);
found: found:
ASSERT(i < 0x8000000); ASSERT(i < 0x8000000);
m->pos = i; m->pos = i;

289
lib/mac.c Normal file
View file

@ -0,0 +1,289 @@
/*
* BIRD Library -- Message Authentication Codes
*
* (c) 2016 Ondrej Zajicek <santiago@crfreenet.org>
* (c) 2016 CZ.NIC z.s.p.o.
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
/**
* DOC: Message authentication codes
*
* MAC algorithms are simple cryptographic tools for message authentication.
* They use shared a secret key a and message text to generate authentication
* code, which is then passed with the message to the other side, where the code
* is verified. There are multiple families of MAC algorithms based on different
* cryptographic primitives, BIRD implements two MAC families which use hash
* functions.
*
* The first family is simply a cryptographic hash camouflaged as MAC algorithm.
* Originally supposed to be (m|k)-hash (message is concatenated with key, and
* that is hashed), but later it turned out that a raw hash is more practical.
* This is used for cryptographic authentication in OSPFv2, RIP and BFD.
*
* The second family is the standard HMAC (RFC 2104), using inner and outer hash
* to process key and message. HMAC (with SHA) is used in advanced OSPF and RIP
* authentication (RFC 5709, RFC 4822).
*/
#include "lib/mac.h"
#include "lib/md5.h"
#include "lib/sha1.h"
#include "lib/sha256.h"
#include "lib/sha512.h"
/*
* Internal hash calls
*/
static inline void
hash_init(struct mac_context *mctx, struct hash_context *hctx)
{ mctx->type->hash_init(hctx); }
static inline void
hash_update(struct mac_context *mctx, struct hash_context *hctx, const byte *buf, uint len)
{ mctx->type->hash_update(hctx, buf, len); }
static inline byte *
hash_final(struct mac_context *mctx, struct hash_context *hctx)
{ return mctx->type->hash_final(hctx); }
static inline void
hash_buffer(struct mac_context *mctx, byte *outbuf, const byte *buffer, uint length)
{
struct hash_context hctx;
hash_init(mctx, &hctx);
hash_update(mctx, &hctx, buffer, length);
memcpy(outbuf, hash_final(mctx, &hctx), mctx->type->hash_size);
}
/*
* (not-really-MAC) Hash
*/
static void
nrmh_init(struct mac_context *ctx, const byte *key UNUSED, uint keylen UNUSED)
{
struct nrmh_context *ct = (void *) ctx;
hash_init(ctx, &ct->ictx);
}
static void
nrmh_update(struct mac_context *ctx, const byte *data, uint datalen)
{
struct nrmh_context *ct = (void *) ctx;
hash_update(ctx, &ct->ictx, data, datalen);
}
static byte *
nrmh_final(struct mac_context *ctx)
{
struct nrmh_context *ct = (void *) ctx;
return hash_final(ctx, &ct->ictx);
}
/*
* HMAC
*/
static void
hmac_init(struct mac_context *ctx, const byte *key, uint keylen)
{
struct hmac_context *ct = (void *) ctx;
uint block_size = ctx->type->block_size;
uint hash_size = ctx->type->hash_size;
byte *keybuf = alloca(block_size);
byte *buf = alloca(block_size);
uint i;
/* Hash the key if necessary */
if (keylen <= block_size)
{
memcpy(keybuf, key, keylen);
memset(keybuf + keylen, 0, block_size - keylen);
}
else
{
hash_buffer(ctx, keybuf, key, keylen);
memset(keybuf + hash_size, 0, block_size - hash_size);
}
/* Initialize the inner digest */
hash_init(ctx, &ct->ictx);
for (i = 0; i < block_size; i++)
buf[i] = keybuf[i] ^ 0x36;
hash_update(ctx, &ct->ictx, buf, block_size);
/* Initialize the outer digest */
hash_init(ctx, &ct->octx);
for (i = 0; i < block_size; i++)
buf[i] = keybuf[i] ^ 0x5c;
hash_update(ctx, &ct->octx, buf, block_size);
}
static void
hmac_update(struct mac_context *ctx, const byte *data, uint datalen)
{
struct hmac_context *ct = (void *) ctx;
/* Just update the inner digest */
hash_update(ctx, &ct->ictx, data, datalen);
}
static byte *
hmac_final(struct mac_context *ctx)
{
struct hmac_context *ct = (void *) ctx;
/* Finish the inner digest */
byte *isha = hash_final(ctx, &ct->ictx);
/* Finish the outer digest */
hash_update(ctx, &ct->octx, isha, ctx->type->hash_size);
return hash_final(ctx, &ct->octx);
}
/*
* Common code
*/
#define HASH_DESC(name, px, PX) \
{ name, PX##_SIZE, sizeof(struct nrmh_context), nrmh_init, nrmh_update, nrmh_final, \
PX##_SIZE, PX##_BLOCK_SIZE, px##_init, px##_update, px##_final }
#define HMAC_DESC(name, px, PX) \
{ name, PX##_SIZE, sizeof(struct hmac_context), hmac_init, hmac_update, hmac_final, \
PX##_SIZE, PX##_BLOCK_SIZE, px##_init, px##_update, px##_final }
const struct mac_desc mac_table[ALG_MAX] = {
[ALG_MD5] = HASH_DESC("Keyed MD5", md5, MD5),
[ALG_SHA1] = HASH_DESC("Keyed SHA-1", sha1, SHA1),
[ALG_SHA224] = HASH_DESC("Keyed SHA-224", sha224, SHA224),
[ALG_SHA256] = HASH_DESC("Keyed SHA-256", sha256, SHA256),
[ALG_SHA384] = HASH_DESC("Keyed SHA-384", sha384, SHA384),
[ALG_SHA512] = HASH_DESC("Keyed SHA-512", sha512, SHA512),
[ALG_HMAC_MD5] = HMAC_DESC("HMAC-MD5", md5, MD5),
[ALG_HMAC_SHA1] = HMAC_DESC("HMAC-SHA-1", sha1, SHA1),
[ALG_HMAC_SHA224] = HMAC_DESC("HMAC-SHA-224", sha224, SHA224),
[ALG_HMAC_SHA256] = HMAC_DESC("HMAC-SHA-256", sha256, SHA256),
[ALG_HMAC_SHA384] = HMAC_DESC("HMAC-SHA-384", sha384, SHA384),
[ALG_HMAC_SHA512] = HMAC_DESC("HMAC-SHA-512", sha512, SHA512),
};
/**
* mac_init - initialize MAC algorithm
* @ctx: context to initialize
* @id: MAC algorithm ID
* @key: MAC key
* @keylen: MAC key length
*
* Initialize MAC context @ctx for algorithm @id (e.g., %ALG_HMAC_SHA1), with
* key @key of length @keylen. After that, message data could be added using
* mac_update() function.
*/
void
mac_init(struct mac_context *ctx, uint id, const byte *key, uint keylen)
{
ctx->type = &mac_table[id];
ctx->type->init(ctx, key, keylen);
}
#if 0
/**
* mac_update - add more data to MAC algorithm
* @ctx: MAC context
* @data: data to add
* @datalen: length of data
*
* Push another @datalen bytes of data pointed to by @data into the MAC
* algorithm currently in @ctx. Can be called multiple times for the same MAC
* context. It has the same effect as concatenating all the data together and
* passing them at once.
*/
void mac_update(struct mac_context *ctx, const byte *data, uint datalen)
{ DUMMY; }
/**
* mac_final - finalize MAC algorithm
* @ctx: MAC context
*
* Finish MAC computation and return a pointer to the result. No more
* @mac_update() calls could be done, but the context may be reinitialized
* later.
*
* Note that the returned pointer points into data in the @ctx context. If it
* ceases to exist, the pointer becomes invalid.
*/
byte *mac_final(struct mac_context *ctx)
{ DUMMY; }
/**
* mac_cleanup - cleanup MAC context
* @ctx: MAC context
*
* Cleanup MAC context after computation (by filling with zeros). Not strictly
* necessary, just to erase sensitive data from stack. This also invalidates the
* pointer returned by @mac_final().
*/
void mac_cleanup(struct mac_context *ctx)
{ DUMMY; }
#endif
/**
* mac_fill - compute and fill MAC
* @id: MAC algorithm ID
* @key: secret key
* @keylen: key length
* @data: message data
* @datalen: message length
* @mac: place to fill MAC
*
* Compute MAC for specified key @key and message @data using algorithm @id and
* copy it to buffer @mac. mac_fill() is a shortcut function doing all usual
* steps for transmitted messages.
*/
void
mac_fill(uint id, const byte *key, uint keylen, const byte *data, uint datalen, byte *mac)
{
struct mac_context ctx;
mac_init(&ctx, id, key, keylen);
mac_update(&ctx, data, datalen);
memcpy(mac, mac_final(&ctx), mac_get_length(&ctx));
mac_cleanup(&ctx);
}
/**
* mac_verify - compute and verify MAC
* @id: MAC algorithm ID
* @key: secret key
* @keylen: key length
* @data: message data
* @datalen: message length
* @mac: received MAC
*
* Compute MAC for specified key @key and message @data using algorithm @id and
* compare it with received @mac, return whether they are the same. mac_verify()
* is a shortcut function doing all usual steps for received messages.
*/
int
mac_verify(uint id, const byte *key, uint keylen, const byte *data, uint datalen, const byte *mac)
{
struct mac_context ctx;
mac_init(&ctx, id, key, keylen);
mac_update(&ctx, data, datalen);
int res = !memcmp(mac, mac_final(&ctx), mac_get_length(&ctx));
mac_cleanup(&ctx);
return res;
}

121
lib/mac.h Normal file
View file

@ -0,0 +1,121 @@
/*
* BIRD Library -- Message Authentication Codes
*
* (c) 2016 Ondrej Zajicek <santiago@crfreenet.org>
* (c) 2016 CZ.NIC z.s.p.o.
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
#ifndef _BIRD_MAC_H_
#define _BIRD_MAC_H_
#include "nest/bird.h"
#include "lib/sha512.h"
#define ALG_UNDEFINED 0
#define ALG_MD5 0x01
#define ALG_SHA1 0x02
#define ALG_SHA224 0x03
#define ALG_SHA256 0x04
#define ALG_SHA384 0x05
#define ALG_SHA512 0x06
#define ALG_HMAC 0x10
#define ALG_HMAC_MD5 0x11
#define ALG_HMAC_SHA1 0x12
#define ALG_HMAC_SHA224 0x13
#define ALG_HMAC_SHA256 0x14
#define ALG_HMAC_SHA384 0x15
#define ALG_HMAC_SHA512 0x16
#define ALG_MAX 0x17
/* These are maximums for HASH/MAC lengths and required context space */
#define MAX_HASH_SIZE SHA512_SIZE
#define HASH_STORAGE sizeof(struct sha512_context)
#define MAC_STORAGE sizeof(struct hmac_context)
/* This value is used by several IETF protocols for padding */
#define HMAC_MAGIC htonl(0x878FE1F3)
/* Generic context used by hash functions */
struct hash_context
{
u8 data[HASH_STORAGE];
u64 align[0];
};
/* Context for embedded hash (not-really-MAC hash) */
struct nrmh_context {
const struct mac_desc *type;
struct hash_context ictx;
};
/* Context for hash based HMAC */
struct hmac_context {
const struct mac_desc *type;
struct hash_context ictx;
struct hash_context octx;
};
/* Generic context used by MAC functions */
struct mac_context
{
const struct mac_desc *type;
u8 data[MAC_STORAGE - sizeof(void *)];
u64 align[0];
};
/* Union to satisfy C aliasing rules */
union mac_context_union {
struct mac_context mac;
struct nrmh_context nrmh;
struct hmac_context hmac;
};
struct mac_desc {
const char *name; /* Name of MAC algorithm */
uint mac_length; /* Length of authentication code */
uint ctx_length; /* Length of algorithm context */
void (*init)(struct mac_context *ctx, const byte *key, uint keylen);
void (*update)(struct mac_context *ctx, const byte *data, uint datalen);
byte *(*final)(struct mac_context *ctx);
uint hash_size; /* Hash length, for hash-based MACs */
uint block_size; /* Hash block size, for hash-based MACs */
void (*hash_init)(struct hash_context *ctx);
void (*hash_update)(struct hash_context *ctx, const byte *data, uint datalen);
byte *(*hash_final)(struct hash_context *ctx);
};
extern const struct mac_desc mac_table[ALG_MAX];
static inline const char *mac_type_name(uint id)
{ return mac_table[id].name; }
static inline uint mac_type_length(uint id)
{ return mac_table[id].mac_length; }
static inline const char *mac_get_name(struct mac_context *ctx)
{ return ctx->type->name; }
static inline uint mac_get_length(struct mac_context *ctx)
{ return ctx->type->mac_length; }
void mac_init(struct mac_context *ctx, uint id, const byte *key, uint keylen);
static inline void mac_update(struct mac_context *ctx, const byte *data, uint datalen)
{ ctx->type->update(ctx, data, datalen); }
static inline byte *mac_final(struct mac_context *ctx)
{ return ctx->type->final(ctx); }
static inline void mac_cleanup(struct mac_context *ctx)
{ memset(ctx, 0, ctx->type->ctx_length); }
void mac_fill(uint id, const byte *key, uint keylen, const byte *data, uint datalen, byte *mac);
int mac_verify(uint id, const byte *key, uint keylen, const byte *data, uint datalen, const byte *mac);
#endif /* _BIRD_MAC_H_ */

View file

@ -39,8 +39,10 @@ static void md5_transform(u32 buf[4], u32 const in[16]);
* initialization constants. * initialization constants.
*/ */
void void
md5_init(struct md5_context *ctx) md5_init(struct hash_context *CTX)
{ {
struct md5_context *ctx = (void *) CTX;
ctx->buf[0] = 0x67452301; ctx->buf[0] = 0x67452301;
ctx->buf[1] = 0xefcdab89; ctx->buf[1] = 0xefcdab89;
ctx->buf[2] = 0x98badcfe; ctx->buf[2] = 0x98badcfe;
@ -55,8 +57,9 @@ md5_init(struct md5_context *ctx)
* of bytes. * of bytes.
*/ */
void void
md5_update(struct md5_context *ctx, const byte *buf, uint len) md5_update(struct hash_context *CTX, const byte *buf, uint len)
{ {
struct md5_context *ctx = (void *) CTX;
u32 t; u32 t;
/* Update bitcount */ /* Update bitcount */
@ -105,8 +108,9 @@ md5_update(struct md5_context *ctx, const byte *buf, uint len)
* 1 0* (64-bit count of bits processed, MSB-first) * 1 0* (64-bit count of bits processed, MSB-first)
*/ */
byte * byte *
md5_final(struct md5_context *ctx) md5_final(struct hash_context *CTX)
{ {
struct md5_context *ctx = (void *) CTX;
uint count; uint count;
byte *p; byte *p;
@ -149,13 +153,6 @@ md5_final(struct md5_context *ctx)
return (byte*) ctx->buf; return (byte*) ctx->buf;
} }
/* I am a hard paranoid */
void
md5_erase_ctx(struct md5_context *ctx)
{
memset((char *) ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
}
/* The four core functions - F1 is optimized somewhat */ /* The four core functions - F1 is optimized somewhat */
/* #define F1(x, y, z) (x & y | ~x & z) */ /* #define F1(x, y, z) (x & y | ~x & z) */
@ -256,67 +253,3 @@ md5_transform(u32 buf[4], u32 const in[16])
buf[2] += c; buf[2] += c;
buf[3] += d; buf[3] += d;
} }
/*
* MD5-HMAC
*/
static void
md5_hash_buffer(byte *outbuf, const byte *buffer, size_t length)
{
struct md5_context hd_tmp;
md5_init(&hd_tmp);
md5_update(&hd_tmp, buffer, length);
memcpy(outbuf, md5_final(&hd_tmp), MD5_SIZE);
}
void
md5_hmac_init(struct md5_hmac_context *ctx, const byte *key, size_t keylen)
{
byte keybuf[MD5_BLOCK_SIZE], buf[MD5_BLOCK_SIZE];
/* Hash the key if necessary */
if (keylen <= MD5_BLOCK_SIZE)
{
memcpy(keybuf, key, keylen);
bzero(keybuf + keylen, MD5_BLOCK_SIZE - keylen);
}
else
{
md5_hash_buffer(keybuf, key, keylen);
bzero(keybuf + MD5_SIZE, MD5_BLOCK_SIZE - MD5_SIZE);
}
/* Initialize the inner digest */
md5_init(&ctx->ictx);
int i;
for (i = 0; i < MD5_BLOCK_SIZE; i++)
buf[i] = keybuf[i] ^ 0x36;
md5_update(&ctx->ictx, buf, MD5_BLOCK_SIZE);
/* Initialize the outer digest */
md5_init(&ctx->octx);
for (i = 0; i < MD5_BLOCK_SIZE; i++)
buf[i] = keybuf[i] ^ 0x5c;
md5_update(&ctx->octx, buf, MD5_BLOCK_SIZE);
}
void
md5_hmac_update(struct md5_hmac_context *ctx, const byte *buf, size_t buflen)
{
/* Just update the inner digest */
md5_update(&ctx->ictx, buf, buflen);
}
byte *
md5_hmac_final(struct md5_hmac_context *ctx)
{
/* Finish the inner digest */
byte *isha = md5_final(&ctx->ictx);
/* Finish the outer digest */
md5_update(&ctx->octx, isha, MD5_SIZE);
return md5_final(&ctx->octx);
}

View file

@ -19,29 +19,18 @@
#define MD5_BLOCK_SIZE 64 #define MD5_BLOCK_SIZE 64
struct hash_context;
struct md5_context { struct md5_context {
u32 buf[4]; u32 buf[4];
u32 bits[2]; u32 bits[2];
byte in[64]; byte in[64];
}; };
void md5_init(struct md5_context *ctx);
void md5_update(struct md5_context *ctx, const byte *buf, uint len);
byte *md5_final(struct md5_context *ctx);
void md5_init(struct hash_context *ctx);
/* void md5_update(struct hash_context *ctx, const byte *buf, uint len);
* HMAC-MD5 byte *md5_final(struct hash_context *ctx);
*/
struct md5_hmac_context {
struct md5_context ictx;
struct md5_context octx;
};
void md5_hmac_init(struct md5_hmac_context *ctx, const byte *key, size_t keylen);
void md5_hmac_update(struct md5_hmac_context *ctx, const byte *buf, size_t buflen);
byte *md5_hmac_final(struct md5_hmac_context *ctx);
#endif /* _BIRD_MD5_H_ */ #endif /* _BIRD_MD5_H_ */

View file

@ -1,5 +1,5 @@
/* /*
* BIRD Library -- SHA-1 Hash Function (FIPS 180-1, RFC 3174) and HMAC-SHA-1 * BIRD Library -- SHA-1 Hash Function (FIPS 180-1, RFC 3174)
* *
* (c) 2015 CZ.NIC z.s.p.o. * (c) 2015 CZ.NIC z.s.p.o.
* *
@ -17,8 +17,10 @@
void void
sha1_init(struct sha1_context *ctx) sha1_init(struct hash_context *CTX)
{ {
struct sha1_context *ctx = (void *) CTX;
ctx->h0 = 0x67452301; ctx->h0 = 0x67452301;
ctx->h1 = 0xefcdab89; ctx->h1 = 0xefcdab89;
ctx->h2 = 0x98badcfe; ctx->h2 = 0x98badcfe;
@ -167,8 +169,10 @@ sha1_transform(struct sha1_context *ctx, const byte *data)
* Update the message digest with the contents of BUF with length LEN. * Update the message digest with the contents of BUF with length LEN.
*/ */
void void
sha1_update(struct sha1_context *ctx, const byte *buf, uint len) sha1_update(struct hash_context *CTX, const byte *buf, uint len)
{ {
struct sha1_context *ctx = (void *) CTX;
if (ctx->count) if (ctx->count)
{ {
/* Fill rest of internal buffer */ /* Fill rest of internal buffer */
@ -209,11 +213,12 @@ sha1_update(struct sha1_context *ctx, const byte *buf, uint len)
* Returns: 20 bytes representing the digest. * Returns: 20 bytes representing the digest.
*/ */
byte * byte *
sha1_final(struct sha1_context *ctx) sha1_final(struct hash_context *CTX)
{ {
struct sha1_context *ctx = (void *) CTX;
u32 t, msb, lsb; u32 t, msb, lsb;
sha1_update(ctx, NULL, 0); /* flush */ sha1_update(CTX, NULL, 0); /* flush */
t = ctx->nblocks; t = ctx->nblocks;
/* multiply by 64 to make a byte count */ /* multiply by 64 to make a byte count */
@ -242,7 +247,7 @@ sha1_final(struct sha1_context *ctx)
ctx->buf[ctx->count++] = 0x80; /* pad character */ ctx->buf[ctx->count++] = 0x80; /* pad character */
while (ctx->count < 64) while (ctx->count < 64)
ctx->buf[ctx->count++] = 0; ctx->buf[ctx->count++] = 0;
sha1_update(ctx, NULL, 0); /* flush */ sha1_update(CTX, NULL, 0); /* flush */
memset(ctx->buf, 0, 56); /* fill next block with zeroes */ memset(ctx->buf, 0, 56); /* fill next block with zeroes */
} }
@ -268,81 +273,3 @@ sha1_final(struct sha1_context *ctx)
return ctx->buf; return ctx->buf;
} }
/*
* SHA1-HMAC
*/
/*
* Shortcut function which puts the hash value of the supplied buffer
* into outbuf which must have a size of 20 bytes.
*/
void
sha1_hash_buffer(byte *outbuf, const byte *buffer, uint length)
{
struct sha1_context ctx;
sha1_init(&ctx);
sha1_update(&ctx, buffer, length);
memcpy(outbuf, sha1_final(&ctx), SHA1_SIZE);
}
void
sha1_hmac_init(struct sha1_hmac_context *ctx, const byte *key, uint keylen)
{
byte keybuf[SHA1_BLOCK_SIZE], buf[SHA1_BLOCK_SIZE];
/* Hash the key if necessary */
if (keylen <= SHA1_BLOCK_SIZE)
{
memcpy(keybuf, key, keylen);
memset(keybuf + keylen, 0, SHA1_BLOCK_SIZE - keylen);
}
else
{
sha1_hash_buffer(keybuf, key, keylen);
memset(keybuf + SHA1_SIZE, 0, SHA1_BLOCK_SIZE - SHA1_SIZE);
}
/* Initialize the inner digest */
sha1_init(&ctx->ictx);
int i;
for (i = 0; i < SHA1_BLOCK_SIZE; i++)
buf[i] = keybuf[i] ^ 0x36;
sha1_update(&ctx->ictx, buf, SHA1_BLOCK_SIZE);
/* Initialize the outer digest */
sha1_init(&ctx->octx);
for (i = 0; i < SHA1_BLOCK_SIZE; i++)
buf[i] = keybuf[i] ^ 0x5c;
sha1_update(&ctx->octx, buf, SHA1_BLOCK_SIZE);
}
void
sha1_hmac_update(struct sha1_hmac_context *ctx, const byte *data, uint datalen)
{
/* Just update the inner digest */
sha1_update(&ctx->ictx, data, datalen);
}
byte *
sha1_hmac_final(struct sha1_hmac_context *ctx)
{
/* Finish the inner digest */
byte *isha = sha1_final(&ctx->ictx);
/* Finish the outer digest */
sha1_update(&ctx->octx, isha, SHA1_SIZE);
return sha1_final(&ctx->octx);
}
void
sha1_hmac(byte *outbuf, const byte *key, uint keylen, const byte *data, uint datalen)
{
struct sha1_hmac_context ctx;
sha1_hmac_init(&ctx, key, keylen);
sha1_hmac_update(&ctx, data, datalen);
memcpy(outbuf, sha1_hmac_final(&ctx), SHA1_SIZE);
}

View file

@ -1,5 +1,5 @@
/* /*
* BIRD Library -- SHA-1 Hash Function (FIPS 180-1, RFC 3174) and HMAC-SHA-1 * BIRD Library -- SHA-1 Hash Function (FIPS 180-1, RFC 3174)
* *
* (c) 2015 CZ.NIC z.s.p.o. * (c) 2015 CZ.NIC z.s.p.o.
* *
@ -27,6 +27,8 @@
* Internal SHA1 state. * Internal SHA1 state.
* You should use it just as an opaque handle only. * You should use it just as an opaque handle only.
*/ */
struct hash_context;
struct sha1_context { struct sha1_context {
u32 h0, h1, h2, h3, h4; u32 h0, h1, h2, h3, h4;
byte buf[SHA1_BLOCK_SIZE]; byte buf[SHA1_BLOCK_SIZE];
@ -34,15 +36,14 @@ struct sha1_context {
uint count; uint count;
}; };
void sha1_init(struct hash_context *ctx); /* Initialize new algorithm run in the @ctx context. **/
void sha1_init(struct sha1_context *ctx); /* Initialize new algorithm run in the @ctx context. **/
/* /*
* Push another @len bytes of data pointed to by @buf onto the SHA1 hash * Push another @len bytes of data pointed to by @buf onto the SHA1 hash
* currently in @ctx. You can call this any times you want on the same hash (and * currently in @ctx. You can call this any times you want on the same hash (and
* you do not need to reinitialize it by @sha1_init()). It has the same effect * you do not need to reinitialize it by @sha1_init()). It has the same effect
* as concatenating all the data together and passing them at once. * as concatenating all the data together and passing them at once.
*/ */
void sha1_update(struct sha1_context *ctx, const byte *buf, uint len); void sha1_update(struct hash_context *ctx, const byte *buf, uint len);
/* /*
* No more @sha1_update() calls will be done. This terminates the hash and * No more @sha1_update() calls will be done. This terminates the hash and
* returns a pointer to it. * returns a pointer to it.
@ -50,7 +51,7 @@ void sha1_update(struct sha1_context *ctx, const byte *buf, uint len);
* Note that the pointer points into data in the @ctx context. If it ceases to * Note that the pointer points into data in the @ctx context. If it ceases to
* exist, the pointer becomes invalid. * exist, the pointer becomes invalid.
*/ */
byte *sha1_final(struct sha1_context *ctx); byte *sha1_final(struct hash_context *ctx);
/* /*
* A convenience one-shot function for SHA1 hash. It is equivalent to this * A convenience one-shot function for SHA1 hash. It is equivalent to this
@ -63,24 +64,5 @@ byte *sha1_final(struct sha1_context *ctx);
*/ */
void sha1_hash_buffer(byte *outbuf, const byte *buffer, uint length); void sha1_hash_buffer(byte *outbuf, const byte *buffer, uint length);
/*
* SHA1 HMAC message authentication. If you provide @key and @data, the result
* will be stored in @outbuf.
*/
void sha1_hmac(byte *outbuf, const byte *key, uint keylen, const byte *data, uint datalen);
/*
* The HMAC also exists in a stream version in a way analogous to the plain
* SHA1. Pass this as a context.
*/
struct sha1_hmac_context {
struct sha1_context ictx;
struct sha1_context octx;
};
void sha1_hmac_init(struct sha1_hmac_context *ctx, const byte *key, uint keylen); /* Initialize HMAC with context @ctx and the given key. See sha1_init(). */
void sha1_hmac_update(struct sha1_hmac_context *ctx, const byte *data, uint datalen); /* Hash another @datalen bytes of data. See sha1_update(). */
byte *sha1_hmac_final(struct sha1_hmac_context *ctx); /* Terminate the HMAC and return a pointer to the allocated hash. See sha1_final(). */
#endif /* _BIRD_SHA1_H_ */ #endif /* _BIRD_SHA1_H_ */

View file

@ -1,6 +1,5 @@
/* /*
* BIRD Library -- SHA-256 and SHA-224 Hash Functions, * BIRD Library -- SHA-256 and SHA-224 Hash Functions
* HMAC-SHA-256 and HMAC-SHA-224 Functions
* *
* (c) 2015 CZ.NIC z.s.p.o. * (c) 2015 CZ.NIC z.s.p.o.
* *
@ -17,8 +16,10 @@
// #define SHA256_UNROLLED // #define SHA256_UNROLLED
void void
sha256_init(struct sha256_context *ctx) sha256_init(struct hash_context *CTX)
{ {
struct sha256_context *ctx = (void *) CTX;
ctx->h0 = 0x6a09e667; ctx->h0 = 0x6a09e667;
ctx->h1 = 0xbb67ae85; ctx->h1 = 0xbb67ae85;
ctx->h2 = 0x3c6ef372; ctx->h2 = 0x3c6ef372;
@ -33,8 +34,10 @@ sha256_init(struct sha256_context *ctx)
} }
void void
sha224_init(struct sha224_context *ctx) sha224_init(struct hash_context *CTX)
{ {
struct sha224_context *ctx = (void *) CTX;
ctx->h0 = 0xc1059ed8; ctx->h0 = 0xc1059ed8;
ctx->h1 = 0x367cd507; ctx->h1 = 0x367cd507;
ctx->h2 = 0x3070dd17; ctx->h2 = 0x3070dd17;
@ -219,8 +222,10 @@ sha256_transform(struct sha256_context *ctx, const byte *data)
not have any meaning but writing after finalize is sometimes not have any meaning but writing after finalize is sometimes
helpful to mitigate timing attacks. */ helpful to mitigate timing attacks. */
void void
sha256_update(struct sha256_context *ctx, const byte *buf, size_t len) sha256_update(struct hash_context *CTX, const byte *buf, uint len)
{ {
struct sha256_context *ctx = (void *) CTX;
if (ctx->count) if (ctx->count)
{ {
/* Fill rest of internal buffer */ /* Fill rest of internal buffer */
@ -261,11 +266,12 @@ sha256_update(struct sha256_context *ctx, const byte *buf, size_t len)
* Returns: 32 bytes with the message the digest. 28 bytes for SHA-224. * Returns: 32 bytes with the message the digest. 28 bytes for SHA-224.
*/ */
byte * byte *
sha256_final(struct sha256_context *ctx) sha256_final(struct hash_context *CTX)
{ {
struct sha256_context *ctx = (void *) CTX;
u32 t, th, msb, lsb; u32 t, th, msb, lsb;
sha256_update(ctx, NULL, 0); /* flush */ sha256_update(CTX, NULL, 0); /* flush */
t = ctx->nblocks; t = ctx->nblocks;
th = 0; th = 0;
@ -296,7 +302,7 @@ sha256_final(struct sha256_context *ctx)
ctx->buf[ctx->count++] = 0x80; /* pad character */ ctx->buf[ctx->count++] = 0x80; /* pad character */
while (ctx->count < 64) while (ctx->count < 64)
ctx->buf[ctx->count++] = 0; ctx->buf[ctx->count++] = 0;
sha256_update(ctx, NULL, 0); /* flush */; sha256_update(CTX, NULL, 0); /* flush */;
memset(ctx->buf, 0, 56 ); /* fill next block with zeroes */ memset(ctx->buf, 0, 56 ); /* fill next block with zeroes */
} }
@ -319,131 +325,3 @@ sha256_final(struct sha256_context *ctx)
return ctx->buf; return ctx->buf;
} }
/*
* SHA256-HMAC
*/
static void
sha256_hash_buffer(byte *outbuf, const byte *buffer, size_t length)
{
struct sha256_context ctx;
sha256_init(&ctx);
sha256_update(&ctx, buffer, length);
memcpy(outbuf, sha256_final(&ctx), SHA256_SIZE);
}
void
sha256_hmac_init(struct sha256_hmac_context *ctx, const byte *key, size_t keylen)
{
byte keybuf[SHA256_BLOCK_SIZE], buf[SHA256_BLOCK_SIZE];
/* Hash the key if necessary */
if (keylen <= SHA256_BLOCK_SIZE)
{
memcpy(keybuf, key, keylen);
memset(keybuf + keylen, 0, SHA256_BLOCK_SIZE - keylen);
}
else
{
sha256_hash_buffer(keybuf, key, keylen);
memset(keybuf + SHA256_SIZE, 0, SHA256_BLOCK_SIZE - SHA256_SIZE);
}
/* Initialize the inner digest */
sha256_init(&ctx->ictx);
int i;
for (i = 0; i < SHA256_BLOCK_SIZE; i++)
buf[i] = keybuf[i] ^ 0x36;
sha256_update(&ctx->ictx, buf, SHA256_BLOCK_SIZE);
/* Initialize the outer digest */
sha256_init(&ctx->octx);
for (i = 0; i < SHA256_BLOCK_SIZE; i++)
buf[i] = keybuf[i] ^ 0x5c;
sha256_update(&ctx->octx, buf, SHA256_BLOCK_SIZE);
}
void
sha256_hmac_update(struct sha256_hmac_context *ctx, const byte *buf, size_t buflen)
{
/* Just update the inner digest */
sha256_update(&ctx->ictx, buf, buflen);
}
byte *
sha256_hmac_final(struct sha256_hmac_context *ctx)
{
/* Finish the inner digest */
byte *isha = sha256_final(&ctx->ictx);
/* Finish the outer digest */
sha256_update(&ctx->octx, isha, SHA256_SIZE);
return sha256_final(&ctx->octx);
}
/*
* SHA224-HMAC
*/
static void
sha224_hash_buffer(byte *outbuf, const byte *buffer, size_t length)
{
struct sha224_context ctx;
sha224_init(&ctx);
sha224_update(&ctx, buffer, length);
memcpy(outbuf, sha224_final(&ctx), SHA224_SIZE);
}
void
sha224_hmac_init(struct sha224_hmac_context *ctx, const byte *key, size_t keylen)
{
byte keybuf[SHA224_BLOCK_SIZE], buf[SHA224_BLOCK_SIZE];
/* Hash the key if necessary */
if (keylen <= SHA224_BLOCK_SIZE)
{
memcpy(keybuf, key, keylen);
memset(keybuf + keylen, 0, SHA224_BLOCK_SIZE - keylen);
}
else
{
sha224_hash_buffer(keybuf, key, keylen);
memset(keybuf + SHA224_SIZE, 0, SHA224_BLOCK_SIZE - SHA224_SIZE);
}
/* Initialize the inner digest */
sha224_init(&ctx->ictx);
int i;
for (i = 0; i < SHA224_BLOCK_SIZE; i++)
buf[i] = keybuf[i] ^ 0x36;
sha224_update(&ctx->ictx, buf, SHA224_BLOCK_SIZE);
/* Initialize the outer digest */
sha224_init(&ctx->octx);
for (i = 0; i < SHA224_BLOCK_SIZE; i++)
buf[i] = keybuf[i] ^ 0x5c;
sha224_update(&ctx->octx, buf, SHA224_BLOCK_SIZE);
}
void
sha224_hmac_update(struct sha224_hmac_context *ctx, const byte *buf, size_t buflen)
{
/* Just update the inner digest */
sha256_update(&ctx->ictx, buf, buflen);
}
byte *
sha224_hmac_final(struct sha224_hmac_context *ctx)
{
/* Finish the inner digest */
byte *isha = sha224_final(&ctx->ictx);
/* Finish the outer digest */
sha224_update(&ctx->octx, isha, SHA224_SIZE);
return sha224_final(&ctx->octx);
}

View file

@ -1,6 +1,5 @@
/* /*
* BIRD Library -- SHA-256 and SHA-224 Hash Functions, * BIRD Library -- SHA-256 and SHA-224 Hash Functions
* HMAC-SHA-256 and HMAC-SHA-224 Functions
* *
* (c) 2015 CZ.NIC z.s.p.o. * (c) 2015 CZ.NIC z.s.p.o.
* *
@ -25,6 +24,8 @@
#define SHA256_BLOCK_SIZE 64 #define SHA256_BLOCK_SIZE 64
struct hash_context;
struct sha256_context { struct sha256_context {
u32 h0, h1, h2, h3, h4, h5, h6, h7; u32 h0, h1, h2, h3, h4, h5, h6, h7;
byte buf[SHA256_BLOCK_SIZE]; byte buf[SHA256_BLOCK_SIZE];
@ -35,39 +36,14 @@ struct sha256_context {
#define sha224_context sha256_context #define sha224_context sha256_context
void sha256_init(struct sha256_context *ctx); void sha256_init(struct hash_context *ctx);
void sha224_init(struct sha224_context *ctx); void sha224_init(struct hash_context *ctx);
void sha256_update(struct sha256_context *ctx, const byte *buf, size_t len); void sha256_update(struct hash_context *ctx, const byte *buf, uint len);
static inline void sha224_update(struct sha224_context *ctx, const byte *buf, size_t len) #define sha224_update sha256_update
{ sha256_update(ctx, buf, len); }
byte *sha256_final(struct sha256_context *ctx); byte *sha256_final(struct hash_context *ctx);
static inline byte *sha224_final(struct sha224_context *ctx) #define sha224_final sha256_final
{ return sha256_final(ctx); }
/*
* HMAC-SHA256, HMAC-SHA224
*/
struct sha256_hmac_context
{
struct sha256_context ictx;
struct sha256_context octx;
};
#define sha224_hmac_context sha256_hmac_context
void sha256_hmac_init(struct sha256_hmac_context *ctx, const byte *key, size_t keylen);
void sha224_hmac_init(struct sha224_hmac_context *ctx, const byte *key, size_t keylen);
void sha256_hmac_update(struct sha256_hmac_context *ctx, const byte *buf, size_t buflen);
void sha224_hmac_update(struct sha224_hmac_context *ctx, const byte *buf, size_t buflen);
byte *sha256_hmac_final(struct sha256_hmac_context *ctx);
byte *sha224_hmac_final(struct sha224_hmac_context *ctx);
#endif /* _BIRD_SHA256_H_ */ #endif /* _BIRD_SHA256_H_ */

View file

@ -1,6 +1,5 @@
/* /*
* BIRD Library -- SHA-512 and SHA-384 Hash Functions, * BIRD Library -- SHA-512 and SHA-384 Hash Functions
* HMAC-SHA-512 and HMAC-SHA-384 Functions
* *
* (c) 2015 CZ.NIC z.s.p.o. * (c) 2015 CZ.NIC z.s.p.o.
* *
@ -17,8 +16,10 @@
// #define SHA512_UNROLLED // #define SHA512_UNROLLED
void void
sha512_init(struct sha512_context *ctx) sha512_init(struct hash_context *CTX)
{ {
struct sha512_context *ctx = (void *) CTX;
ctx->h0 = U64(0x6a09e667f3bcc908); ctx->h0 = U64(0x6a09e667f3bcc908);
ctx->h1 = U64(0xbb67ae8584caa73b); ctx->h1 = U64(0xbb67ae8584caa73b);
ctx->h2 = U64(0x3c6ef372fe94f82b); ctx->h2 = U64(0x3c6ef372fe94f82b);
@ -33,8 +34,10 @@ sha512_init(struct sha512_context *ctx)
} }
void void
sha384_init(struct sha384_context *ctx) sha384_init(struct hash_context *CTX)
{ {
struct sha384_context *ctx = (void *) CTX;
ctx->h0 = U64(0xcbbb9d5dc1059ed8); ctx->h0 = U64(0xcbbb9d5dc1059ed8);
ctx->h1 = U64(0x629a292a367cd507); ctx->h1 = U64(0x629a292a367cd507);
ctx->h2 = U64(0x9159015a3070dd17); ctx->h2 = U64(0x9159015a3070dd17);
@ -389,8 +392,10 @@ sha512_transform(struct sha512_context *ctx, const byte *data)
} }
void void
sha512_update(struct sha512_context *ctx, const byte *buf, size_t len) sha512_update(struct hash_context *CTX, const byte *buf, uint len)
{ {
struct sha512_context *ctx = (void *) CTX;
if (ctx->count) if (ctx->count)
{ {
/* Fill rest of internal buffer */ /* Fill rest of internal buffer */
@ -432,11 +437,12 @@ sha512_update(struct sha512_context *ctx, const byte *buf, size_t len)
* first 48 of those bytes. * first 48 of those bytes.
*/ */
byte * byte *
sha512_final(struct sha512_context *ctx) sha512_final(struct hash_context *CTX)
{ {
struct sha512_context *ctx = (void *) CTX;
u64 t, th, msb, lsb; u64 t, th, msb, lsb;
sha512_update(ctx, NULL, 0); /* flush */ sha512_update(CTX, NULL, 0); /* flush */
t = ctx->nblocks; t = ctx->nblocks;
th = 0; th = 0;
@ -467,7 +473,7 @@ sha512_final(struct sha512_context *ctx)
ctx->buf[ctx->count++] = 0x80; /* pad character */ ctx->buf[ctx->count++] = 0x80; /* pad character */
while(ctx->count < 128) while(ctx->count < 128)
ctx->buf[ctx->count++] = 0; ctx->buf[ctx->count++] = 0;
sha512_update(ctx, NULL, 0); /* flush */ sha512_update(CTX, NULL, 0); /* flush */
memset(ctx->buf, 0, 112); /* fill next block with zeroes */ memset(ctx->buf, 0, 112); /* fill next block with zeroes */
} }
@ -490,131 +496,3 @@ sha512_final(struct sha512_context *ctx)
return ctx->buf; return ctx->buf;
} }
/*
* SHA512-HMAC
*/
static void
sha512_hash_buffer(byte *outbuf, const byte *buffer, size_t length)
{
struct sha512_context ctx;
sha512_init(&ctx);
sha512_update(&ctx, buffer, length);
memcpy(outbuf, sha512_final(&ctx), SHA512_SIZE);
}
void
sha512_hmac_init(struct sha512_hmac_context *ctx, const byte *key, size_t keylen)
{
byte keybuf[SHA512_BLOCK_SIZE], buf[SHA512_BLOCK_SIZE];
/* Hash the key if necessary */
if (keylen <= SHA512_BLOCK_SIZE)
{
memcpy(keybuf, key, keylen);
memset(keybuf + keylen, 0, SHA512_BLOCK_SIZE - keylen);
}
else
{
sha512_hash_buffer(keybuf, key, keylen);
memset(keybuf + SHA512_SIZE, 0, SHA512_BLOCK_SIZE - SHA512_SIZE);
}
/* Initialize the inner digest */
sha512_init(&ctx->ictx);
int i;
for (i = 0; i < SHA512_BLOCK_SIZE; i++)
buf[i] = keybuf[i] ^ 0x36;
sha512_update(&ctx->ictx, buf, SHA512_BLOCK_SIZE);
/* Initialize the outer digest */
sha512_init(&ctx->octx);
for (i = 0; i < SHA512_BLOCK_SIZE; i++)
buf[i] = keybuf[i] ^ 0x5c;
sha512_update(&ctx->octx, buf, SHA512_BLOCK_SIZE);
}
void
sha512_hmac_update(struct sha512_hmac_context *ctx, const byte *buf, size_t buflen)
{
/* Just update the inner digest */
sha512_update(&ctx->ictx, buf, buflen);
}
byte *
sha512_hmac_final(struct sha512_hmac_context *ctx)
{
/* Finish the inner digest */
byte *isha = sha512_final(&ctx->ictx);
/* Finish the outer digest */
sha512_update(&ctx->octx, isha, SHA512_SIZE);
return sha512_final(&ctx->octx);
}
/*
* SHA384-HMAC
*/
static void
sha384_hash_buffer(byte *outbuf, const byte *buffer, size_t length)
{
struct sha384_context ctx;
sha384_init(&ctx);
sha384_update(&ctx, buffer, length);
memcpy(outbuf, sha384_final(&ctx), SHA384_SIZE);
}
void
sha384_hmac_init(struct sha384_hmac_context *ctx, const byte *key, size_t keylen)
{
byte keybuf[SHA384_BLOCK_SIZE], buf[SHA384_BLOCK_SIZE];
/* Hash the key if necessary */
if (keylen <= SHA384_BLOCK_SIZE)
{
memcpy(keybuf, key, keylen);
memset(keybuf + keylen, 0, SHA384_BLOCK_SIZE - keylen);
}
else
{
sha384_hash_buffer(keybuf, key, keylen);
memset(keybuf + SHA384_SIZE, 0, SHA384_BLOCK_SIZE - SHA384_SIZE);
}
/* Initialize the inner digest */
sha384_init(&ctx->ictx);
int i;
for (i = 0; i < SHA384_BLOCK_SIZE; i++)
buf[i] = keybuf[i] ^ 0x36;
sha384_update(&ctx->ictx, buf, SHA384_BLOCK_SIZE);
/* Initialize the outer digest */
sha384_init(&ctx->octx);
for (i = 0; i < SHA384_BLOCK_SIZE; i++)
buf[i] = keybuf[i] ^ 0x5c;
sha384_update(&ctx->octx, buf, SHA384_BLOCK_SIZE);
}
void
sha384_hmac_update(struct sha384_hmac_context *ctx, const byte *buf, size_t buflen)
{
/* Just update the inner digest */
sha384_update(&ctx->ictx, buf, buflen);
}
byte *
sha384_hmac_final(struct sha384_hmac_context *ctx)
{
/* Finish the inner digest */
byte *isha = sha384_final(&ctx->ictx);
/* Finish the outer digest */
sha384_update(&ctx->octx, isha, SHA384_SIZE);
return sha384_final(&ctx->octx);
}

View file

@ -1,6 +1,5 @@
/* /*
* BIRD Library -- SHA-512 and SHA-384 Hash Functions, * BIRD Library -- SHA-512 and SHA-384 Hash Functions
* HMAC-SHA-512 and HMAC-SHA-384 Functions
* *
* (c) 2015 CZ.NIC z.s.p.o. * (c) 2015 CZ.NIC z.s.p.o.
* *
@ -25,6 +24,8 @@
#define SHA512_BLOCK_SIZE 128 #define SHA512_BLOCK_SIZE 128
struct hash_context;
struct sha512_context { struct sha512_context {
u64 h0, h1, h2, h3, h4, h5, h6, h7; u64 h0, h1, h2, h3, h4, h5, h6, h7;
byte buf[SHA512_BLOCK_SIZE]; byte buf[SHA512_BLOCK_SIZE];
@ -35,39 +36,14 @@ struct sha512_context {
#define sha384_context sha512_context #define sha384_context sha512_context
void sha512_init(struct sha512_context *ctx); void sha512_init(struct hash_context *ctx);
void sha384_init(struct sha384_context *ctx); void sha384_init(struct hash_context *ctx);
void sha512_update(struct sha512_context *ctx, const byte *buf, size_t len); void sha512_update(struct hash_context *ctx, const byte *buf, uint len);
static inline void sha384_update(struct sha384_context *ctx, const byte *buf, size_t len) #define sha384_update sha512_update
{ sha512_update(ctx, buf, len); }
byte *sha512_final(struct sha512_context *ctx); byte *sha512_final(struct hash_context *ctx);
static inline byte *sha384_final(struct sha384_context *ctx) #define sha384_final sha512_final
{ return sha512_final(ctx); }
/*
* HMAC-SHA512, HMAC-SHA384
*/
struct sha512_hmac_context
{
struct sha512_context ictx;
struct sha512_context octx;
};
#define sha384_hmac_context sha512_hmac_context
void sha512_hmac_init(struct sha512_hmac_context *ctx, const byte *key, size_t keylen);
void sha384_hmac_init(struct sha384_hmac_context *ctx, const byte *key, size_t keylen);
void sha512_hmac_update(struct sha512_hmac_context *ctx, const byte *buf, size_t buflen);
void sha384_hmac_update(struct sha384_hmac_context *ctx, const byte *buf, size_t buflen);
byte *sha512_hmac_final(struct sha512_hmac_context *ctx);
byte *sha384_hmac_final(struct sha384_hmac_context *ctx);
#endif /* _BIRD_SHA512_H_ */ #endif /* _BIRD_SHA512_H_ */

View file

@ -30,7 +30,7 @@ typedef struct birdsock {
byte *rbuf, *rpos; /* NULL=allocate automatically */ byte *rbuf, *rpos; /* NULL=allocate automatically */
uint fast_rx; /* RX has higher priority in event loop */ uint fast_rx; /* RX has higher priority in event loop */
uint rbsize; uint rbsize;
int (*rx_hook)(struct birdsock *, int size); /* NULL=receiving turned off, returns 1 to clear rx buffer */ int (*rx_hook)(struct birdsock *, uint size); /* NULL=receiving turned off, returns 1 to clear rx buffer */
byte *tbuf, *tpos; /* NULL=allocate automatically */ byte *tbuf, *tpos; /* NULL=allocate automatically */
byte *ttx; /* Internal */ byte *ttx; /* Internal */

View file

@ -30,6 +30,25 @@ static inline char *xbasename(const char *str)
return s ? s+1 : (char *) str; return s ? s+1 : (char *) str;
} }
static inline char *
xstrdup(const char *c)
{
size_t l = strlen(c) + 1;
char *z = xmalloc(l);
memcpy(z, c, l);
return z;
}
static inline void
memset32(void *D, u32 val, uint n)
{
u32 *dst = D;
uint i;
for (i = 0; i < n; i++)
dst[i] = val;
}
#define ROUTER_ID_64_LENGTH 23 #define ROUTER_ID_64_LENGTH 23
#endif #endif

View file

@ -370,7 +370,7 @@ as_path_filter(struct linpool *pool, struct adata *path, struct f_tree *set, u32
} }
} }
int nl = d - buf; uint nl = d - buf;
if (nl == path->length) if (nl == path->length)
return path; return path;

View file

@ -116,7 +116,7 @@ int
ec_set_format(struct adata *set, int from, byte *buf, uint size) ec_set_format(struct adata *set, int from, byte *buf, uint size)
{ {
u32 *z = int_set_get_data(set); u32 *z = int_set_get_data(set);
byte *end = buf + size - 24; byte *end = buf + size - 64;
int from2 = MAX(from, 0); int from2 = MAX(from, 0);
int to = int_set_get_size(set); int to = int_set_get_size(set);
int i; int i;
@ -141,6 +141,43 @@ ec_set_format(struct adata *set, int from, byte *buf, uint size)
return 0; return 0;
} }
int
lc_format(byte *buf, lcomm lc)
{
return bsprintf(buf, "(%u, %u, %u)", lc.asn, lc.ldp1, lc.ldp2);
}
int
lc_set_format(struct adata *set, int from, byte *buf, uint bufsize)
{
u32 *d = (u32 *) set->data;
byte *end = buf + bufsize - 64;
int from2 = MAX(from, 0);
int to = set->length / 4;
int i;
for (i = from2; i < to; i += 3)
{
if (buf > end)
{
if (from < 0)
strcpy(buf, "...");
else
buf[-1] = 0;
return i;
}
buf += bsprintf(buf, "(%u, %u, %u)", d[i], d[i+1], d[i+2]);
*buf++ = ' ';
}
if (i != from2)
buf--;
*buf = 0;
return 0;
}
int int
int_set_contains(struct adata *list, u32 val) int_set_contains(struct adata *list, u32 val)
{ {
@ -177,6 +214,24 @@ ec_set_contains(struct adata *list, u64 val)
return 0; return 0;
} }
int
lc_set_contains(struct adata *list, lcomm val)
{
if (!list)
return 0;
u32 *l = int_set_get_data(list);
int len = int_set_get_size(list);
int i;
for (i = 0; i < len; i += 3)
if (lc_match(l, i, val))
return 1;
return 0;
}
struct adata * struct adata *
int_set_add(struct linpool *pool, struct adata *list, u32 val) int_set_add(struct linpool *pool, struct adata *list, u32 val)
{ {
@ -189,9 +244,13 @@ int_set_add(struct linpool *pool, struct adata *list, u32 val)
len = list ? list->length : 0; len = list ? list->length : 0;
res = lp_alloc(pool, sizeof(struct adata) + len + 4); res = lp_alloc(pool, sizeof(struct adata) + len + 4);
res->length = len + 4; res->length = len + 4;
* (u32 *) res->data = val;
if (list) if (list)
memcpy((char *) res->data + 4, list->data, list->length); memcpy(res->data, list->data, list->length);
u32 *c = (u32 *) (res->data + len);
*c = val;
return res; return res;
} }
@ -208,13 +267,30 @@ ec_set_add(struct linpool *pool, struct adata *list, u64 val)
if (list) if (list)
memcpy(res->data, list->data, list->length); memcpy(res->data, list->data, list->length);
u32 *l = (u32 *) (res->data + res->length - 8); u32 *l = (u32 *) (res->data + olen);
l[0] = ec_hi(val); l[0] = ec_hi(val);
l[1] = ec_lo(val); l[1] = ec_lo(val);
return res; return res;
} }
struct adata *
lc_set_add(struct linpool *pool, struct adata *list, lcomm val)
{
if (lc_set_contains(list, val))
return list;
int olen = list ? list->length : 0;
struct adata *res = lp_alloc(pool, sizeof(struct adata) + olen + LCOMM_LENGTH);
res->length = olen + LCOMM_LENGTH;
if (list)
memcpy(res->data, list->data, list->length);
lc_put((u32 *) (res->data + olen), val);
return res;
}
struct adata * struct adata *
int_set_del(struct linpool *pool, struct adata *list, u32 val) int_set_del(struct linpool *pool, struct adata *list, u32 val)
@ -265,6 +341,27 @@ ec_set_del(struct linpool *pool, struct adata *list, u64 val)
return res; return res;
} }
struct adata *
lc_set_del(struct linpool *pool, struct adata *list, lcomm val)
{
if (!lc_set_contains(list, val))
return list;
struct adata *res;
res = lp_alloc(pool, sizeof(struct adata) + list->length - LCOMM_LENGTH);
res->length = list->length - LCOMM_LENGTH;
u32 *l = int_set_get_data(list);
u32 *k = int_set_get_data(res);
int len = int_set_get_size(list);
int i;
for (i=0; i < len; i += 3)
if (! lc_match(l, i, val))
k = lc_copy(k, l+i);
return res;
}
struct adata * struct adata *
int_set_union(struct linpool *pool, struct adata *l1, struct adata *l2) int_set_union(struct linpool *pool, struct adata *l1, struct adata *l2)
@ -328,3 +425,33 @@ ec_set_union(struct linpool *pool, struct adata *l1, struct adata *l2)
memcpy(res->data + l1->length, tmp, len); memcpy(res->data + l1->length, tmp, len);
return res; return res;
} }
struct adata *
lc_set_union(struct linpool *pool, struct adata *l1, struct adata *l2)
{
if (!l1)
return l2;
if (!l2)
return l1;
struct adata *res;
int len = int_set_get_size(l2);
u32 *l = int_set_get_data(l2);
u32 tmp[len];
u32 *k = tmp;
int i;
for (i = 0; i < len; i += 3)
if (!lc_set_contains(l1, lc_get(l, i)))
k = lc_copy(k, l+i);
if (k == tmp)
return l1;
len = (k - tmp) * 4;
res = lp_alloc(pool, sizeof(struct adata) + l1->length + len);
res->length = l1->length + len;
memcpy(res->data, l1->data, l1->length);
memcpy(res->data + l1->length, tmp, len);
return res;
}

View file

@ -68,6 +68,7 @@ int as_path_match(struct adata *path, struct f_path_mask *mask);
/* Transitive bit (for first u32 half of EC) */ /* Transitive bit (for first u32 half of EC) */
#define EC_TBIT 0x40000000 #define EC_TBIT 0x40000000
#define ECOMM_LENGTH 8
static inline int int_set_get_size(struct adata *list) static inline int int_set_get_size(struct adata *list)
{ return list->length / 4; } { return list->length / 4; }
@ -75,6 +76,9 @@ static inline int int_set_get_size(struct adata *list)
static inline int ec_set_get_size(struct adata *list) static inline int ec_set_get_size(struct adata *list)
{ return list->length / 8; } { return list->length / 8; }
static inline int lc_set_get_size(struct adata *list)
{ return list->length / 12; }
static inline u32 *int_set_get_data(struct adata *list) static inline u32 *int_set_get_data(struct adata *list)
{ return (u32 *) list->data; } { return (u32 *) list->data; }
@ -98,17 +102,45 @@ static inline u64 ec_ip4(u64 kind, u64 key, u64 val)
static inline u64 ec_generic(u64 key, u64 val) static inline u64 ec_generic(u64 key, u64 val)
{ return (key << 32) | val; } { return (key << 32) | val; }
/* Large community value */
typedef struct lcomm {
u32 asn;
u32 ldp1;
u32 ldp2;
} lcomm;
#define LCOMM_LENGTH 12
static inline lcomm lc_get(const u32 *l, int i)
{ return (lcomm) { l[i], l[i+1], l[i+2] }; }
static inline void lc_put(u32 *l, lcomm v)
{ l[0] = v.asn; l[1] = v.ldp1; l[2] = v.ldp2; }
static inline int lc_match(const u32 *l, int i, lcomm v)
{ return (l[i] == v.asn && l[i+1] == v.ldp1 && l[i+2] == v.ldp2); }
static inline u32 *lc_copy(u32 *dst, const u32 *src)
{ memcpy(dst, src, LCOMM_LENGTH); return dst + 3; }
int int_set_format(struct adata *set, int way, int from, byte *buf, uint size); int int_set_format(struct adata *set, int way, int from, byte *buf, uint size);
int ec_format(byte *buf, u64 ec); int ec_format(byte *buf, u64 ec);
int ec_set_format(struct adata *set, int from, byte *buf, uint size); int ec_set_format(struct adata *set, int from, byte *buf, uint size);
int lc_format(byte *buf, lcomm lc);
int lc_set_format(struct adata *set, int from, byte *buf, uint size);
int int_set_contains(struct adata *list, u32 val); int int_set_contains(struct adata *list, u32 val);
int ec_set_contains(struct adata *list, u64 val); int ec_set_contains(struct adata *list, u64 val);
int lc_set_contains(struct adata *list, lcomm val);
struct adata *int_set_add(struct linpool *pool, struct adata *list, u32 val); struct adata *int_set_add(struct linpool *pool, struct adata *list, u32 val);
struct adata *ec_set_add(struct linpool *pool, struct adata *list, u64 val); struct adata *ec_set_add(struct linpool *pool, struct adata *list, u64 val);
struct adata *lc_set_add(struct linpool *pool, struct adata *list, lcomm val);
struct adata *int_set_del(struct linpool *pool, struct adata *list, u32 val); struct adata *int_set_del(struct linpool *pool, struct adata *list, u32 val);
struct adata *ec_set_del(struct linpool *pool, struct adata *list, u64 val); struct adata *ec_set_del(struct linpool *pool, struct adata *list, u64 val);
struct adata *lc_set_del(struct linpool *pool, struct adata *list, lcomm val);
struct adata *int_set_union(struct linpool *pool, struct adata *l1, struct adata *l2); struct adata *int_set_union(struct linpool *pool, struct adata *l1, struct adata *l2);
struct adata *ec_set_union(struct linpool *pool, struct adata *l1, struct adata *l2); struct adata *ec_set_union(struct linpool *pool, struct adata *l1, struct adata *l2);
struct adata *lc_set_union(struct linpool *pool, struct adata *l1, struct adata *l2);
#endif #endif

View file

@ -42,7 +42,7 @@ struct bfd_request {
struct bfd_request * bfd_request_session(pool *p, ip_addr addr, ip_addr local, struct iface *iface, void (*hook)(struct bfd_request *), void *data); struct bfd_request * bfd_request_session(pool *p, ip_addr addr, ip_addr local, struct iface *iface, void (*hook)(struct bfd_request *), void *data);
static inline void cf_check_bfd(int use) { } static inline void cf_check_bfd(int use UNUSED) { }
#else #else

View file

@ -13,6 +13,7 @@ CF_HDR
#include "nest/password.h" #include "nest/password.h"
#include "nest/cmds.h" #include "nest/cmds.h"
#include "lib/lists.h" #include "lib/lists.h"
#include "lib/mac.h"
CF_DEFINES CF_DEFINES
@ -68,7 +69,8 @@ CF_KEYWORDS(INTERFACE, IMPORT, EXPORT, FILTER, NONE, TABLE, STATES, ROUTES, FILT
CF_KEYWORDS(IPV4, IPV6, VPN4, VPN6, ROA4, ROA6) CF_KEYWORDS(IPV4, IPV6, VPN4, VPN6, ROA4, ROA6)
CF_KEYWORDS(RECEIVE, LIMIT, ACTION, WARN, BLOCK, RESTART, DISABLE, KEEP, FILTERED) CF_KEYWORDS(RECEIVE, LIMIT, ACTION, WARN, BLOCK, RESTART, DISABLE, KEEP, FILTERED)
CF_KEYWORDS(PASSWORD, FROM, PASSIVE, TO, ID, EVENTS, PACKETS, PROTOCOLS, INTERFACES) CF_KEYWORDS(PASSWORD, FROM, PASSIVE, TO, ID, EVENTS, PACKETS, PROTOCOLS, INTERFACES)
CF_KEYWORDS(PRIMARY, STATS, COUNT, FOR, COMMANDS, PREEXPORT, NOEXPORT, GENERATE) /* ,ROA */ CF_KEYWORDS(ALGORITHM, KEYED, HMAC, MD5, SHA1, SHA256, SHA384, SHA512)
CF_KEYWORDS(PRIMARY, STATS, COUNT, FOR, COMMANDS, PREEXPORT, NOEXPORT, GENERATE)
CF_KEYWORDS(LISTEN, BGP, V6ONLY, DUAL, ADDRESS, PORT, PASSWORDS, DESCRIPTION, SORTED) CF_KEYWORDS(LISTEN, BGP, V6ONLY, DUAL, ADDRESS, PORT, PASSWORDS, DESCRIPTION, SORTED)
CF_KEYWORDS(RELOAD, IN, OUT, MRTDUMP, MESSAGES, RESTRICT, MEMORY, IGP_METRIC, CLASS, DSCP) CF_KEYWORDS(RELOAD, IN, OUT, MRTDUMP, MESSAGES, RESTRICT, MEMORY, IGP_METRIC, CLASS, DSCP)
CF_KEYWORDS(GRACEFUL, RESTART, WAIT, MAX, FLUSH, AS) CF_KEYWORDS(GRACEFUL, RESTART, WAIT, MAX, FLUSH, AS)
@ -86,7 +88,7 @@ CF_ENUM(T_ENUM_ROA, ROA_, UNKNOWN, VALID, INVALID)
%type <s> optsym %type <s> optsym
%type <ra> r_args %type <ra> r_args
%type <sd> sym_args %type <sd> sym_args
%type <i> proto_start echo_mask echo_size debug_mask debug_list debug_flag mrtdump_mask mrtdump_list mrtdump_flag export_mode limit_action net_type table_sorted tos %type <i> proto_start echo_mask echo_size debug_mask debug_list debug_flag mrtdump_mask mrtdump_list mrtdump_flag export_mode limit_action net_type table_sorted tos password_algorithm
%type <ps> proto_patt proto_patt2 %type <ps> proto_patt proto_patt2
%type <cc> channel_start proto_channel %type <cc> channel_start proto_channel
%type <cl> limit_spec %type <cl> limit_spec
@ -438,11 +440,13 @@ password_item_begin:
} }
this_p_item = cfg_alloc(sizeof (struct password_item)); this_p_item = cfg_alloc(sizeof (struct password_item));
this_p_item->password = $2; this_p_item->password = $2;
this_p_item->length = strlen($2);
this_p_item->genfrom = 0; this_p_item->genfrom = 0;
this_p_item->gento = TIME_INFINITY; this_p_item->gento = TIME_INFINITY;
this_p_item->accfrom = 0; this_p_item->accfrom = 0;
this_p_item->accto = TIME_INFINITY; this_p_item->accto = TIME_INFINITY;
this_p_item->id = password_id++; this_p_item->id = password_id++;
this_p_item->alg = ALG_UNDEFINED;
add_tail(this_p_list, &this_p_item->n); add_tail(this_p_list, &this_p_item->n);
} }
; ;
@ -453,10 +457,24 @@ password_item_params:
| GENERATE TO datetime ';' password_item_params { this_p_item->gento = $3; } | GENERATE TO datetime ';' password_item_params { this_p_item->gento = $3; }
| ACCEPT FROM datetime ';' password_item_params { this_p_item->accfrom = $3; } | ACCEPT FROM datetime ';' password_item_params { this_p_item->accfrom = $3; }
| ACCEPT TO datetime ';' password_item_params { this_p_item->accto = $3; } | ACCEPT TO datetime ';' password_item_params { this_p_item->accto = $3; }
| FROM datetime ';' password_item_params { this_p_item->genfrom = this_p_item->accfrom = $2; }
| TO datetime ';' password_item_params { this_p_item->gento = this_p_item->accto = $2; }
| ID expr ';' password_item_params { this_p_item->id = $2; if ($2 <= 0) cf_error("Password ID has to be greated than zero."); } | ID expr ';' password_item_params { this_p_item->id = $2; if ($2 <= 0) cf_error("Password ID has to be greated than zero."); }
| ALGORITHM password_algorithm ';' password_item_params { this_p_item->alg = $2; }
; ;
password_algorithm:
KEYED MD5 { $$ = ALG_MD5; }
| KEYED SHA1 { $$ = ALG_SHA1; }
| KEYED SHA256 { $$ = ALG_SHA256; }
| KEYED SHA384 { $$ = ALG_SHA384; }
| KEYED SHA512 { $$ = ALG_SHA512; }
| HMAC MD5 { $$ = ALG_HMAC_MD5; }
| HMAC SHA1 { $$ = ALG_HMAC_SHA1; }
| HMAC SHA256 { $$ = ALG_HMAC_SHA256; }
| HMAC SHA384 { $$ = ALG_HMAC_SHA384; }
| HMAC SHA512 { $$ = ALG_HMAC_SHA512; }
;
/* Core commands */ /* Core commands */
CF_CLI_HELP(SHOW, ..., [[Show status information]]) CF_CLI_HELP(SHOW, ..., [[Show status information]])
@ -605,7 +623,7 @@ CF_CLI(EVAL, term, <expr>, [[Evaluate an expression]])
{ cmd_eval($2); } ; { cmd_eval($2); } ;
CF_CLI_HELP(ECHO, ..., [[Control echoing of log messages]]) CF_CLI_HELP(ECHO, ..., [[Control echoing of log messages]])
CF_CLI(ECHO, echo_mask echo_size, (all | off | { debug | trace | info | remote | warning | error | auth }) [<buffer-size>], [[Control echoing of log messages]]) { CF_CLI(ECHO, echo_mask echo_size, (all | off | { debug|trace|info|remote|warning|error|auth [, ...] }) [<buffer-size>], [[Control echoing of log messages]]) {
cli_set_log_echo(this_cli, $2, $3); cli_set_log_echo(this_cli, $2, $3);
cli_msg(0, ""); cli_msg(0, "");
} ; } ;
@ -638,11 +656,11 @@ CF_CLI(RELOAD OUT, proto_patt, <protocol> | \"<pattern>\" | all, [[Reload protoc
{ proto_apply_cmd($3, proto_cmd_reload, 1, CMD_RELOAD_OUT); } ; { proto_apply_cmd($3, proto_cmd_reload, 1, CMD_RELOAD_OUT); } ;
CF_CLI_HELP(DEBUG, ..., [[Control protocol debugging via BIRD logs]]) CF_CLI_HELP(DEBUG, ..., [[Control protocol debugging via BIRD logs]])
CF_CLI(DEBUG, proto_patt debug_mask, (<protocol> | <pattern> | all) (all | off | { states | routes | filters | interfaces | events | packets }), [[Control protocol debugging via BIRD logs]]) CF_CLI(DEBUG, proto_patt debug_mask, (<protocol> | \"<pattern>\" | all) (all | off | { states|routes|filters|interfaces|events|packets [, ...] }), [[Control protocol debugging via BIRD logs]])
{ proto_apply_cmd($2, proto_cmd_debug, 1, $3); } ; { proto_apply_cmd($2, proto_cmd_debug, 1, $3); } ;
CF_CLI_HELP(MRTDUMP, ..., [[Control protocol debugging via MRTdump files]]) CF_CLI_HELP(MRTDUMP, ..., [[Control protocol debugging via MRTdump files]])
CF_CLI(MRTDUMP, proto_patt mrtdump_mask, (<protocol> | <pattern> | all) (all | off | { states | messages }), [[Control protocol debugging via MRTdump format]]) CF_CLI(MRTDUMP, proto_patt mrtdump_mask, (<protocol> | \"<pattern>\" | all) (all | off | { states|messages [, ...] }), [[Control protocol debugging via MRTdump format]])
{ proto_apply_cmd($2, proto_cmd_mrtdump, 1, $3); } ; { proto_apply_cmd($2, proto_cmd_mrtdump, 1, $3); } ;
CF_CLI(RESTRICT,,,[[Restrict current CLI session to safe commands]]) CF_CLI(RESTRICT,,,[[Restrict current CLI session to safe commands]])

View file

@ -100,7 +100,8 @@ static struct resclass olock_class = {
sizeof(struct object_lock), sizeof(struct object_lock),
olock_free, olock_free,
olock_dump, olock_dump,
NULL NULL,
NULL,
}; };
/** /**

View file

@ -10,6 +10,7 @@
#include "nest/bird.h" #include "nest/bird.h"
#include "nest/password.h" #include "nest/password.h"
#include "lib/string.h" #include "lib/string.h"
#include "lib/mac.h"
struct password_item *last_password_item = NULL; struct password_item *last_password_item = NULL;
@ -37,7 +38,7 @@ password_find(list *l, int first_fit)
} }
struct password_item * struct password_item *
password_find_by_id(list *l, int id) password_find_by_id(list *l, uint id)
{ {
struct password_item *pi; struct password_item *pi;
@ -66,3 +67,17 @@ password_find_by_value(list *l, char *pass, uint size)
return NULL; return NULL;
} }
uint
max_mac_length(list *l)
{
struct password_item *pi;
uint val = 0;
if (!l)
return 0;
WALK_LIST(pi, *l)
val = MAX(val, mac_type_length(pi->alg));
return val;
}

View file

@ -9,19 +9,22 @@
#ifndef PASSWORD_H #ifndef PASSWORD_H
#define PASSWORD_H #define PASSWORD_H
#include "sysdep/unix/timer.h" #include "sysdep/unix/timer.h"
struct password_item { struct password_item {
node n; node n;
char *password; char *password; /* Key data, null terminated */
int id; uint length; /* Key length, without null */
uint id; /* Key ID */
uint alg; /* MAC algorithm */
bird_clock_t accfrom, accto, genfrom, gento; bird_clock_t accfrom, accto, genfrom, gento;
}; };
extern struct password_item *last_password_item; extern struct password_item *last_password_item;
struct password_item *password_find(list *l, int first_fit); struct password_item *password_find(list *l, int first_fit);
struct password_item *password_find_by_id(list *l, int id); struct password_item *password_find_by_id(list *l, uint id);
struct password_item *password_find_by_value(list *l, char *pass, uint size); struct password_item *password_find_by_value(list *l, char *pass, uint size);
static inline int password_verify(struct password_item *p1, char *p2, uint size) static inline int password_verify(struct password_item *p1, char *p2, uint size)
@ -31,4 +34,6 @@ static inline int password_verify(struct password_item *p1, char *p2, uint size)
return !memcmp(buf, p2, size); return !memcmp(buf, p2, size);
} }
uint max_mac_length(list *l);
#endif #endif

View file

@ -285,7 +285,6 @@ rte *rte_find(net *net, struct rte_src *src);
rte *rte_get_temp(struct rta *); rte *rte_get_temp(struct rta *);
void rte_update2(struct channel *c, net_addr *n, rte *new, struct rte_src *src); void rte_update2(struct channel *c, net_addr *n, rte *new, struct rte_src *src);
/* rte_update() moved to protocol.h to avoid dependency conflicts */ /* rte_update() moved to protocol.h to avoid dependency conflicts */
void rte_discard(rtable *tab, rte *old);
int rt_examine(rtable *t, net_addr *a, struct proto *p, struct filter *filter); int rt_examine(rtable *t, net_addr *a, struct proto *p, struct filter *filter);
rte *rt_export_merged(struct channel *c, net *net, rte **rt_free, struct ea_list **tmpa, linpool *pool, int silent); rte *rt_export_merged(struct channel *c, net *net, rte **rt_free, struct ea_list **tmpa, linpool *pool, int silent);
void rt_refresh_begin(rtable *t, struct channel *c); void rt_refresh_begin(rtable *t, struct channel *c);
@ -445,7 +444,7 @@ typedef struct eattr {
#define EA_ALLOW_UNDEF 0x10000 /* ea_find: allow EAF_TYPE_UNDEF */ #define EA_ALLOW_UNDEF 0x10000 /* ea_find: allow EAF_TYPE_UNDEF */
#define EA_BIT(n) ((n) << 24) /* Used in bitfield accessors */ #define EA_BIT(n) ((n) << 24) /* Used in bitfield accessors */
#define EAF_TYPE_MASK 0x0f /* Mask with this to get type */ #define EAF_TYPE_MASK 0x1f /* Mask with this to get type */
#define EAF_TYPE_INT 0x01 /* 32-bit unsigned integer number */ #define EAF_TYPE_INT 0x01 /* 32-bit unsigned integer number */
#define EAF_TYPE_OPAQUE 0x02 /* Opaque byte string (not filterable) */ #define EAF_TYPE_OPAQUE 0x02 /* Opaque byte string (not filterable) */
#define EAF_TYPE_IP_ADDRESS 0x04 /* IP address */ #define EAF_TYPE_IP_ADDRESS 0x04 /* IP address */
@ -454,7 +453,8 @@ typedef struct eattr {
#define EAF_TYPE_BITFIELD 0x09 /* 32-bit embedded bitfield */ #define EAF_TYPE_BITFIELD 0x09 /* 32-bit embedded bitfield */
#define EAF_TYPE_INT_SET 0x0a /* Set of u32's (e.g., a community list) */ #define EAF_TYPE_INT_SET 0x0a /* Set of u32's (e.g., a community list) */
#define EAF_TYPE_EC_SET 0x0e /* Set of pairs of u32's - ext. community list */ #define EAF_TYPE_EC_SET 0x0e /* Set of pairs of u32's - ext. community list */
#define EAF_TYPE_UNDEF 0x0f /* `force undefined' entry */ #define EAF_TYPE_LC_SET 0x12 /* Set of triplets of u32's - large community list */
#define EAF_TYPE_UNDEF 0x1f /* `force undefined' entry */
#define EAF_EMBEDDED 0x01 /* Data stored in eattr.u.data (part of type spec) */ #define EAF_EMBEDDED 0x01 /* Data stored in eattr.u.data (part of type spec) */
#define EAF_VAR_LENGTH 0x02 /* Attribute length is variable (part of type spec) */ #define EAF_VAR_LENGTH 0x02 /* Attribute length is variable (part of type spec) */
#define EAF_ORIGINATED 0x40 /* The attribute has originated locally */ #define EAF_ORIGINATED 0x40 /* The attribute has originated locally */

View file

@ -733,7 +733,7 @@ static inline void
opaque_format(struct adata *ad, byte *buf, uint size) opaque_format(struct adata *ad, byte *buf, uint size)
{ {
byte *bound = buf + size - 10; byte *bound = buf + size - 10;
int i; uint i;
for(i = 0; i < ad->length; i++) for(i = 0; i < ad->length; i++)
{ {
@ -776,6 +776,18 @@ ea_show_ec_set(struct cli *c, struct adata *ad, byte *pos, byte *buf, byte *end)
} }
} }
static inline void
ea_show_lc_set(struct cli *c, struct adata *ad, byte *pos, byte *buf, byte *end)
{
int i = lc_set_format(ad, 0, pos, end - pos);
cli_printf(c, -1012, "\t%s", buf);
while (i)
{
i = lc_set_format(ad, i, buf, end - buf - 1);
cli_printf(c, -1012, "\t\t%s", buf);
}
}
/** /**
* ea_show - print an &eattr to CLI * ea_show - print an &eattr to CLI
* @c: destination CLI * @c: destination CLI
@ -840,6 +852,9 @@ ea_show(struct cli *c, eattr *e)
case EAF_TYPE_EC_SET: case EAF_TYPE_EC_SET:
ea_show_ec_set(c, ad, pos, buf, end); ea_show_ec_set(c, ad, pos, buf, end);
return; return;
case EAF_TYPE_LC_SET:
ea_show_lc_set(c, ad, pos, buf, end);
return;
case EAF_TYPE_UNDEF: case EAF_TYPE_UNDEF:
default: default:
bsprintf(pos, "<type %02x>", e->type); bsprintf(pos, "<type %02x>", e->type);

View file

@ -63,7 +63,7 @@ make_tmp_attrs(struct rte *rt, struct linpool *pool)
{ {
struct ea_list *(*mta)(struct rte *rt, struct linpool *pool); struct ea_list *(*mta)(struct rte *rt, struct linpool *pool);
mta = rt->attrs->src->proto->make_tmp_attrs; mta = rt->attrs->src->proto->make_tmp_attrs;
return mta ? mta(rt, rte_update_pool) : NULL; return mta ? mta(rt, pool) : NULL;
} }
@ -713,7 +713,7 @@ mpnh_merge_rta(struct mpnh *nhs, rta *a, linpool *pool, int max)
{ {
struct mpnh nh = { .gw = a->gw, .iface = a->iface }; struct mpnh nh = { .gw = a->gw, .iface = a->iface };
struct mpnh *nh2 = (a->dest == RTD_MULTIPATH) ? a->nexthops : &nh; struct mpnh *nh2 = (a->dest == RTD_MULTIPATH) ? a->nexthops : &nh;
return mpnh_merge(nhs, nh2, 1, 0, max, rte_update_pool); return mpnh_merge(nhs, nh2, 1, 0, max, pool);
} }
rte * rte *
@ -1403,8 +1403,8 @@ rte_announce_i(rtable *tab, unsigned type, net *net, rte *new, rte *old,
rte_update_unlock(); rte_update_unlock();
} }
void static inline void
rte_discard(rtable *t, rte *old) /* Non-filtered route deletion, used during garbage collection */ rte_discard(rte *old) /* Non-filtered route deletion, used during garbage collection */
{ {
rte_update_lock(); rte_update_lock();
rte_recalculate(old->sender, old->net, NULL, old->attrs->src); rte_recalculate(old->sender, old->net, NULL, old->attrs->src);
@ -1695,7 +1695,7 @@ again:
return; return;
} }
rte_discard(tab, e); rte_discard(e);
limit--; limit--;
goto rescan; goto rescan;
@ -1780,7 +1780,7 @@ rta_apply_hostentry(rta *a, struct hostentry *he)
} }
static inline rte * static inline rte *
rt_next_hop_update_rte(rtable *tab, rte *old) rt_next_hop_update_rte(rtable *tab UNUSED, rte *old)
{ {
rta a; rta a;
memcpy(&a, old->attrs, sizeof(rta)); memcpy(&a, old->attrs, sizeof(rta));
@ -2166,11 +2166,11 @@ hc_remove(struct hostcache *hc, struct hostentry *he)
static void static void
hc_alloc_table(struct hostcache *hc, unsigned order) hc_alloc_table(struct hostcache *hc, unsigned order)
{ {
unsigned hsize = 1 << order; uint hsize = 1 << order;
hc->hash_order = order; hc->hash_order = order;
hc->hash_shift = 32 - order; hc->hash_shift = 32 - order;
hc->hash_max = (order >= HC_HI_ORDER) ? ~0 : (hsize HC_HI_MARK); hc->hash_max = (order >= HC_HI_ORDER) ? ~0U : (hsize HC_HI_MARK);
hc->hash_min = (order <= HC_LO_ORDER) ? 0 : (hsize HC_LO_MARK); hc->hash_min = (order <= HC_LO_ORDER) ? 0U : (hsize HC_LO_MARK);
hc->hash_table = mb_allocz(rt_table_pool, hsize * sizeof(struct hostentry *)); hc->hash_table = mb_allocz(rt_table_pool, hsize * sizeof(struct hostentry *));
} }
@ -2178,10 +2178,10 @@ hc_alloc_table(struct hostcache *hc, unsigned order)
static void static void
hc_resize(struct hostcache *hc, unsigned new_order) hc_resize(struct hostcache *hc, unsigned new_order)
{ {
unsigned old_size = 1 << hc->hash_order;
struct hostentry **old_table = hc->hash_table; struct hostentry **old_table = hc->hash_table;
struct hostentry *he, *hen; struct hostentry *he, *hen;
int i; uint old_size = 1 << hc->hash_order;
uint i;
hc_alloc_table(hc, new_order); hc_alloc_table(hc, new_order);
for (i = 0; i < old_size; i++) for (i = 0; i < old_size; i++)

View file

@ -1723,7 +1723,7 @@ babel_dump(struct proto *P)
} }
static void static void
babel_get_route_info(rte *rte, byte *buf, ea_list *attrs) babel_get_route_info(rte *rte, byte *buf, ea_list *attrs UNUSED)
{ {
buf += bsprintf(buf, " (%d/%d) [%lR]", rte->pref, rte->u.babel.metric, rte->u.babel.router_id); buf += bsprintf(buf, " (%d/%d) [%lR]", rte->pref, rte->u.babel.metric, rte->u.babel.router_id);
} }
@ -1965,7 +1965,7 @@ babel_store_tmp_attrs(struct rte *rt, struct ea_list *attrs)
*/ */
static void static void
babel_rt_notify(struct proto *P, struct rtable *table UNUSED, struct network *net, babel_rt_notify(struct proto *P, struct rtable *table UNUSED, struct network *net,
struct rte *new, struct rte *old, struct ea_list *attrs) struct rte *new, struct rte *old UNUSED, struct ea_list *attrs UNUSED)
{ {
struct babel_proto *p = (void *) P; struct babel_proto *p = (void *) P;
struct babel_entry *e; struct babel_entry *e;

View file

@ -111,7 +111,7 @@ struct babel_iface_config {
u16 rxcost; u16 rxcost;
u8 type; u8 type;
u8 check_link; u8 check_link;
int port; uint port;
u16 hello_interval; u16 hello_interval;
u16 ihu_interval; u16 ihu_interval;
u16 update_interval; u16 update_interval;

View file

@ -146,6 +146,7 @@ struct babel_write_state {
#define TLV_HDR(tlv,t,l) ({ tlv->type = t; tlv->length = l - sizeof(struct babel_tlv); }) #define TLV_HDR(tlv,t,l) ({ tlv->type = t; tlv->length = l - sizeof(struct babel_tlv); })
#define TLV_HDR0(tlv,t) TLV_HDR(tlv, t, tlv_data[t].min_length) #define TLV_HDR0(tlv,t) TLV_HDR(tlv, t, tlv_data[t].min_length)
#define BYTES(n) ((((uint) n) + 7) / 8)
static inline u16 static inline u16
get_time16(const void *p) get_time16(const void *p)
@ -161,18 +162,18 @@ put_time16(void *p, u16 v)
} }
static inline ip6_addr static inline ip6_addr
get_ip6_px(const void *p, int plen) get_ip6_px(const void *p, uint plen)
{ {
ip6_addr addr = IPA_NONE; ip6_addr addr = IPA_NONE;
memcpy(&addr, p, (plen + 7) / 8); memcpy(&addr, p, BYTES(plen));
return ip6_ntoh(addr); return ip6_ntoh(addr);
} }
static inline void static inline void
put_ip6_px(void *p, ip6_addr addr, int plen) put_ip6_px(void *p, ip6_addr addr, uint plen)
{ {
addr = ip6_hton(addr); addr = ip6_hton(addr);
memcpy(p, &addr, (plen + 7) / 8); memcpy(p, &addr, BYTES(plen));
} }
static inline ip6_addr static inline ip6_addr
@ -202,21 +203,21 @@ static int babel_read_update(struct babel_tlv *hdr, union babel_msg *msg, struct
static int babel_read_route_request(struct babel_tlv *hdr, union babel_msg *msg, struct babel_parse_state *state); static int babel_read_route_request(struct babel_tlv *hdr, union babel_msg *msg, struct babel_parse_state *state);
static int babel_read_seqno_request(struct babel_tlv *hdr, union babel_msg *msg, struct babel_parse_state *state); static int babel_read_seqno_request(struct babel_tlv *hdr, union babel_msg *msg, struct babel_parse_state *state);
static int babel_write_ack(struct babel_tlv *hdr, union babel_msg *msg, struct babel_write_state *state, int max_len); static uint babel_write_ack(struct babel_tlv *hdr, union babel_msg *msg, struct babel_write_state *state, uint max_len);
static int babel_write_hello(struct babel_tlv *hdr, union babel_msg *msg, struct babel_write_state *state, int max_len); static uint babel_write_hello(struct babel_tlv *hdr, union babel_msg *msg, struct babel_write_state *state, uint max_len);
static int babel_write_ihu(struct babel_tlv *hdr, union babel_msg *msg, struct babel_write_state *state, int max_len); static uint babel_write_ihu(struct babel_tlv *hdr, union babel_msg *msg, struct babel_write_state *state, uint max_len);
static int babel_write_update(struct babel_tlv *hdr, union babel_msg *msg, struct babel_write_state *state, int max_len); static uint babel_write_update(struct babel_tlv *hdr, union babel_msg *msg, struct babel_write_state *state, uint max_len);
static int babel_write_route_request(struct babel_tlv *hdr, union babel_msg *msg, struct babel_write_state *state, int max_len); static uint babel_write_route_request(struct babel_tlv *hdr, union babel_msg *msg, struct babel_write_state *state, uint max_len);
static int babel_write_seqno_request(struct babel_tlv *hdr, union babel_msg *msg, struct babel_write_state *state, int max_len); static uint babel_write_seqno_request(struct babel_tlv *hdr, union babel_msg *msg, struct babel_write_state *state, uint max_len);
struct babel_tlv_data { struct babel_tlv_data {
u8 min_length; u8 min_length;
int (*read_tlv)(struct babel_tlv *hdr, union babel_msg *m, struct babel_parse_state *state); int (*read_tlv)(struct babel_tlv *hdr, union babel_msg *m, struct babel_parse_state *state);
int (*write_tlv)(struct babel_tlv *hdr, union babel_msg *m, struct babel_write_state *state, int max_len); uint (*write_tlv)(struct babel_tlv *hdr, union babel_msg *m, struct babel_write_state *state, uint max_len);
void (*handle_tlv)(union babel_msg *m, struct babel_iface *ifa); void (*handle_tlv)(union babel_msg *m, struct babel_iface *ifa);
}; };
const static struct babel_tlv_data tlv_data[BABEL_TLV_MAX] = { static const struct babel_tlv_data tlv_data[BABEL_TLV_MAX] = {
[BABEL_TLV_ACK_REQ] = { [BABEL_TLV_ACK_REQ] = {
sizeof(struct babel_tlv_ack_req), sizeof(struct babel_tlv_ack_req),
babel_read_ack_req, babel_read_ack_req,
@ -291,9 +292,9 @@ babel_read_ack_req(struct babel_tlv *hdr, union babel_msg *m,
return PARSE_SUCCESS; return PARSE_SUCCESS;
} }
static int static uint
babel_write_ack(struct babel_tlv *hdr, union babel_msg *m, babel_write_ack(struct babel_tlv *hdr, union babel_msg *m,
struct babel_write_state *state, int max_len) struct babel_write_state *state UNUSED, uint max_len UNUSED)
{ {
struct babel_tlv_ack *tlv = (void *) hdr; struct babel_tlv_ack *tlv = (void *) hdr;
struct babel_msg_ack *msg = &m->ack; struct babel_msg_ack *msg = &m->ack;
@ -319,9 +320,9 @@ babel_read_hello(struct babel_tlv *hdr, union babel_msg *m,
return PARSE_SUCCESS; return PARSE_SUCCESS;
} }
static int static uint
babel_write_hello(struct babel_tlv *hdr, union babel_msg *m, babel_write_hello(struct babel_tlv *hdr, union babel_msg *m,
struct babel_write_state *state, int max_len) struct babel_write_state *state UNUSED, uint max_len UNUSED)
{ {
struct babel_tlv_hello *tlv = (void *) hdr; struct babel_tlv_hello *tlv = (void *) hdr;
struct babel_msg_hello *msg = &m->hello; struct babel_msg_hello *msg = &m->hello;
@ -363,9 +364,9 @@ babel_read_ihu(struct babel_tlv *hdr, union babel_msg *m,
return PARSE_SUCCESS; return PARSE_SUCCESS;
} }
static int static uint
babel_write_ihu(struct babel_tlv *hdr, union babel_msg *m, babel_write_ihu(struct babel_tlv *hdr, union babel_msg *m,
struct babel_write_state *state, int max_len) struct babel_write_state *state UNUSED, uint max_len)
{ {
struct babel_tlv_ihu *tlv = (void *) hdr; struct babel_tlv_ihu *tlv = (void *) hdr;
struct babel_msg_ihu *msg = &m->ihu; struct babel_msg_ihu *msg = &m->ihu;
@ -401,9 +402,9 @@ babel_read_router_id(struct babel_tlv *hdr, union babel_msg *m UNUSED,
} }
/* This is called directly from babel_write_update() */ /* This is called directly from babel_write_update() */
static int static uint
babel_write_router_id(struct babel_tlv *hdr, u64 router_id, babel_write_router_id(struct babel_tlv *hdr, u64 router_id,
struct babel_write_state *state, int max_len UNUSED) struct babel_write_state *state, uint max_len UNUSED)
{ {
struct babel_tlv_router_id *tlv = (void *) hdr; struct babel_tlv_router_id *tlv = (void *) hdr;
@ -467,10 +468,10 @@ babel_read_update(struct babel_tlv *hdr, union babel_msg *m,
msg->metric = get_u16(&tlv->metric); msg->metric = get_u16(&tlv->metric);
/* Length of received prefix data without omitted part */ /* Length of received prefix data without omitted part */
int len = (tlv->plen + 7)/8 - (int) tlv->omitted; int len = BYTES(tlv->plen) - (int) tlv->omitted;
u8 buf[16] = {}; u8 buf[16] = {};
if ((len < 0) || (len > TLV_OPT_LENGTH(tlv))) if ((len < 0) || ((uint) len > TLV_OPT_LENGTH(tlv)))
return PARSE_ERROR; return PARSE_ERROR;
switch (tlv->ae) switch (tlv->ae)
@ -536,13 +537,13 @@ babel_read_update(struct babel_tlv *hdr, union babel_msg *m,
return PARSE_SUCCESS; return PARSE_SUCCESS;
} }
static int static uint
babel_write_update(struct babel_tlv *hdr, union babel_msg *m, babel_write_update(struct babel_tlv *hdr, union babel_msg *m,
struct babel_write_state *state, int max_len) struct babel_write_state *state, uint max_len)
{ {
struct babel_tlv_update *tlv = (void *) hdr; struct babel_tlv_update *tlv = (void *) hdr;
struct babel_msg_update *msg = &m->update; struct babel_msg_update *msg = &m->update;
int len0 = 0; uint len0 = 0;
/* /*
* When needed, we write Router-ID TLV before Update TLV and return size of * When needed, we write Router-ID TLV before Update TLV and return size of
@ -558,7 +559,7 @@ babel_write_update(struct babel_tlv *hdr, union babel_msg *m,
tlv = (struct babel_tlv_update *) NEXT_TLV(tlv); tlv = (struct babel_tlv_update *) NEXT_TLV(tlv);
} }
int len = sizeof(struct babel_tlv_update) + (msg->plen + 7)/8; uint len = sizeof(struct babel_tlv_update) + BYTES(msg->plen);
if (len0 + len > max_len) if (len0 + len > max_len)
return 0; return 0;
@ -587,7 +588,7 @@ babel_write_update(struct babel_tlv *hdr, union babel_msg *m,
static int static int
babel_read_route_request(struct babel_tlv *hdr, union babel_msg *m, babel_read_route_request(struct babel_tlv *hdr, union babel_msg *m,
struct babel_parse_state *state) struct babel_parse_state *state UNUSED)
{ {
struct babel_tlv_route_request *tlv = (void *) hdr; struct babel_tlv_route_request *tlv = (void *) hdr;
struct babel_msg_route_request *msg = &m->route_request; struct babel_msg_route_request *msg = &m->route_request;
@ -612,7 +613,7 @@ babel_read_route_request(struct babel_tlv *hdr, union babel_msg *m,
if (tlv->plen > MAX_PREFIX_LENGTH) if (tlv->plen > MAX_PREFIX_LENGTH)
return PARSE_ERROR; return PARSE_ERROR;
if (TLV_OPT_LENGTH(tlv) < (tlv->plen + 7)/8) if (TLV_OPT_LENGTH(tlv) < BYTES(tlv->plen))
return PARSE_ERROR; return PARSE_ERROR;
msg->plen = tlv->plen; msg->plen = tlv->plen;
@ -629,14 +630,14 @@ babel_read_route_request(struct babel_tlv *hdr, union babel_msg *m,
return PARSE_IGNORE; return PARSE_IGNORE;
} }
static int static uint
babel_write_route_request(struct babel_tlv *hdr, union babel_msg *m, babel_write_route_request(struct babel_tlv *hdr, union babel_msg *m,
struct babel_write_state *state, int max_len) struct babel_write_state *state UNUSED, uint max_len)
{ {
struct babel_tlv_route_request *tlv = (void *) hdr; struct babel_tlv_route_request *tlv = (void *) hdr;
struct babel_msg_route_request *msg = &m->route_request; struct babel_msg_route_request *msg = &m->route_request;
int len = sizeof(struct babel_tlv_route_request) + (msg->plen + 7)/8; uint len = sizeof(struct babel_tlv_route_request) + BYTES(msg->plen);
if (len > max_len) if (len > max_len)
return 0; return 0;
@ -687,7 +688,7 @@ babel_read_seqno_request(struct babel_tlv *hdr, union babel_msg *m,
if (tlv->plen > MAX_PREFIX_LENGTH) if (tlv->plen > MAX_PREFIX_LENGTH)
return PARSE_ERROR; return PARSE_ERROR;
if (TLV_OPT_LENGTH(tlv) < (tlv->plen + 7)/8) if (TLV_OPT_LENGTH(tlv) < BYTES(tlv->plen))
return PARSE_ERROR; return PARSE_ERROR;
msg->plen = tlv->plen; msg->plen = tlv->plen;
@ -704,14 +705,14 @@ babel_read_seqno_request(struct babel_tlv *hdr, union babel_msg *m,
return PARSE_IGNORE; return PARSE_IGNORE;
} }
static int static uint
babel_write_seqno_request(struct babel_tlv *hdr, union babel_msg *m, babel_write_seqno_request(struct babel_tlv *hdr, union babel_msg *m,
struct babel_write_state *state, int max_len) struct babel_write_state *state UNUSED, uint max_len)
{ {
struct babel_tlv_seqno_request *tlv = (void *) hdr; struct babel_tlv_seqno_request *tlv = (void *) hdr;
struct babel_msg_seqno_request *msg = &m->seqno_request; struct babel_msg_seqno_request *msg = &m->seqno_request;
int len = sizeof(struct babel_tlv_seqno_request) + (msg->plen + 7)/8; uint len = sizeof(struct babel_tlv_seqno_request) + BYTES(msg->plen);
if (len > max_len) if (len > max_len)
return 0; return 0;
@ -744,11 +745,11 @@ babel_read_tlv(struct babel_tlv *hdr,
return tlv_data[hdr->type].read_tlv(hdr, msg, state); return tlv_data[hdr->type].read_tlv(hdr, msg, state);
} }
static int static uint
babel_write_tlv(struct babel_tlv *hdr, babel_write_tlv(struct babel_tlv *hdr,
union babel_msg *msg, union babel_msg *msg,
struct babel_write_state *state, struct babel_write_state *state,
int max_len) uint max_len)
{ {
if ((msg->type <= BABEL_TLV_PADN) || if ((msg->type <= BABEL_TLV_PADN) ||
(msg->type >= BABEL_TLV_MAX) || (msg->type >= BABEL_TLV_MAX) ||
@ -792,7 +793,7 @@ babel_send_to(struct babel_iface *ifa, ip_addr dest)
* *
* The TLVs in the queue are freed after they are written to the buffer. * The TLVs in the queue are freed after they are written to the buffer.
*/ */
static int static uint
babel_write_queue(struct babel_iface *ifa, list *queue) babel_write_queue(struct babel_iface *ifa, list *queue)
{ {
struct babel_proto *p = ifa->proto; struct babel_proto *p = ifa->proto;
@ -813,6 +814,9 @@ babel_write_queue(struct babel_iface *ifa, list *queue)
struct babel_msg_node *msg; struct babel_msg_node *msg;
WALK_LIST_FIRST(msg, *queue) WALK_LIST_FIRST(msg, *queue)
{ {
if (pos >= end)
break;
int len = babel_write_tlv((struct babel_tlv *) pos, &msg->msg, &state, end - pos); int len = babel_write_tlv((struct babel_tlv *) pos, &msg->msg, &state, end - pos);
if (!len) if (!len)
@ -823,7 +827,7 @@ babel_write_queue(struct babel_iface *ifa, list *queue)
sl_free(p->msg_slab, msg); sl_free(p->msg_slab, msg);
} }
int plen = pos - (byte *) pkt; uint plen = pos - (byte *) pkt;
put_u16(&pkt->length, plen - sizeof(struct babel_pkt_header)); put_u16(&pkt->length, plen - sizeof(struct babel_pkt_header));
return plen; return plen;
@ -1027,7 +1031,7 @@ babel_tx_hook(sock *sk)
static int static int
babel_rx_hook(sock *sk, int len) babel_rx_hook(sock *sk, uint len)
{ {
struct babel_iface *ifa = sk->data; struct babel_iface *ifa = sk->data;
struct babel_proto *p = ifa->proto; struct babel_proto *p = ifa->proto;

View file

@ -316,6 +316,7 @@ bfd_session_timeout(struct bfd_session *s)
s->rem_min_rx_int = 1; s->rem_min_rx_int = 1;
s->rem_demand_mode = 0; s->rem_demand_mode = 0;
s->rem_detect_mult = 0; s->rem_detect_mult = 0;
s->rx_csn_known = 0;
s->poll_active = 0; s->poll_active = 0;
s->poll_scheduled = 0; s->poll_scheduled = 0;
@ -429,6 +430,7 @@ bfd_add_session(struct bfd_proto *p, ip_addr addr, ip_addr local, struct iface *
s->rem_min_rx_int = 1; s->rem_min_rx_int = 1;
s->detect_mult = ifa->cf->multiplier; s->detect_mult = ifa->cf->multiplier;
s->passive = ifa->cf->passive; s->passive = ifa->cf->passive;
s->tx_csn = random_u32();
s->tx_timer = tm2_new_init(p->tpool, bfd_tx_timer_hook, s, 0, 0); s->tx_timer = tm2_new_init(p->tpool, bfd_tx_timer_hook, s, 0, 0);
s->hold_timer = tm2_new_init(p->tpool, bfd_hold_timer_hook, s, 0, 0); s->hold_timer = tm2_new_init(p->tpool, bfd_hold_timer_hook, s, 0, 0);
@ -796,7 +798,7 @@ bfd_start_neighbor(struct bfd_proto *p, struct bfd_neighbor *n)
} }
static void static void
bfd_stop_neighbor(struct bfd_proto *p, struct bfd_neighbor *n) bfd_stop_neighbor(struct bfd_proto *p UNUSED, struct bfd_neighbor *n)
{ {
if (n->neigh) if (n->neigh)
n->neigh->data = NULL; n->neigh->data = NULL;
@ -853,7 +855,7 @@ void pipe_drain(int fd);
void pipe_kick(int fd); void pipe_kick(int fd);
static int static int
bfd_notify_hook(sock *sk, int len) bfd_notify_hook(sock *sk, uint len UNUSED)
{ {
struct bfd_proto *p = sk->data; struct bfd_proto *p = sk->data;
struct bfd_session *s; struct bfd_session *s;
@ -1062,7 +1064,7 @@ bfd_preconfig(struct protocol *P UNUSED, struct config *c UNUSED)
} }
static void static void
bfd_copy_config(struct proto_config *dest, struct proto_config *src) bfd_copy_config(struct proto_config *dest, struct proto_config *src UNUSED)
{ {
struct bfd_config *d = (struct bfd_config *) dest; struct bfd_config *d = (struct bfd_config *) dest;
// struct bfd_config *s = (struct bfd_config *) src; // struct bfd_config *s = (struct bfd_config *) src;

View file

@ -14,6 +14,7 @@
#include "nest/iface.h" #include "nest/iface.h"
#include "nest/protocol.h" #include "nest/protocol.h"
#include "nest/route.h" #include "nest/route.h"
#include "nest/password.h"
#include "conf/conf.h" #include "conf/conf.h"
#include "lib/hash.h" #include "lib/hash.h"
#include "lib/resource.h" #include "lib/resource.h"
@ -52,6 +53,8 @@ struct bfd_iface_config
u32 idle_tx_int; u32 idle_tx_int;
u8 multiplier; u8 multiplier;
u8 passive; u8 passive;
u8 auth_type; /* Authentication type (BFD_AUTH_*) */
list *passwords; /* Passwords for authentication */
}; };
struct bfd_neighbor struct bfd_neighbor
@ -143,6 +146,11 @@ struct bfd_session
list request_list; /* List of client requests (struct bfd_request) */ list request_list; /* List of client requests (struct bfd_request) */
bird_clock_t last_state_change; /* Time of last state change */ bird_clock_t last_state_change; /* Time of last state change */
u8 notify_running; /* 1 if notify hooks are running */ u8 notify_running; /* 1 if notify hooks are running */
u8 rx_csn_known; /* Received crypto sequence number is known */
u32 rx_csn; /* Last received crypto sequence number */
u32 tx_csn; /* Last transmitted crypto sequence number */
u32 tx_csn_time; /* Timestamp of last tx_csn change */
}; };
@ -174,6 +182,15 @@ extern const char *bfd_state_names[];
#define BFD_FLAG_DEMAND (1 << 1) #define BFD_FLAG_DEMAND (1 << 1)
#define BFD_FLAG_MULTIPOINT (1 << 0) #define BFD_FLAG_MULTIPOINT (1 << 0)
#define BFD_AUTH_NONE 0
#define BFD_AUTH_SIMPLE 1
#define BFD_AUTH_KEYED_MD5 2
#define BFD_AUTH_METICULOUS_KEYED_MD5 3
#define BFD_AUTH_KEYED_SHA1 4
#define BFD_AUTH_METICULOUS_KEYED_SHA1 5
extern const u8 bfd_auth_type_to_hash_alg[];
static inline void bfd_lock_sessions(struct bfd_proto *p) { pthread_spin_lock(&p->lock); } static inline void bfd_lock_sessions(struct bfd_proto *p) { pthread_spin_lock(&p->lock); }
static inline void bfd_unlock_sessions(struct bfd_proto *p) { pthread_spin_unlock(&p->lock); } static inline void bfd_unlock_sessions(struct bfd_proto *p) { pthread_spin_unlock(&p->lock); }

View file

@ -22,11 +22,12 @@ extern struct bfd_config *bfd_cf;
CF_DECLS CF_DECLS
CF_KEYWORDS(BFD, MIN, IDLE, RX, TX, INTERVAL, MULTIPLIER, PASSIVE, CF_KEYWORDS(BFD, MIN, IDLE, RX, TX, INTERVAL, MULTIPLIER, PASSIVE,
INTERFACE, MULTIHOP, NEIGHBOR, DEV, LOCAL) INTERFACE, MULTIHOP, NEIGHBOR, DEV, LOCAL, AUTHENTICATION,
NONE, SIMPLE, METICULOUS, KEYED, MD5, SHA1)
%type <iface> bfd_neigh_iface %type <iface> bfd_neigh_iface
%type <a> bfd_neigh_local %type <a> bfd_neigh_local
%type <i> bfd_neigh_multihop %type <i> bfd_neigh_multihop bfd_auth_type
CF_GRAMMAR CF_GRAMMAR
@ -62,12 +63,35 @@ bfd_proto:
bfd_iface_start: bfd_iface_start:
{ {
this_ipatt = cfg_allocz(sizeof(struct bfd_iface_config)); this_ipatt = cfg_allocz(sizeof(struct bfd_iface_config));
add_tail(&BFD_CFG->patt_list, NODE this_ipatt);
init_list(&this_ipatt->ipn_list); init_list(&this_ipatt->ipn_list);
BFD_IFACE->min_rx_int = BFD_DEFAULT_MIN_RX_INT; BFD_IFACE->min_rx_int = BFD_DEFAULT_MIN_RX_INT;
BFD_IFACE->min_tx_int = BFD_DEFAULT_MIN_TX_INT; BFD_IFACE->min_tx_int = BFD_DEFAULT_MIN_TX_INT;
BFD_IFACE->idle_tx_int = BFD_DEFAULT_IDLE_TX_INT; BFD_IFACE->idle_tx_int = BFD_DEFAULT_IDLE_TX_INT;
BFD_IFACE->multiplier = BFD_DEFAULT_MULTIPLIER; BFD_IFACE->multiplier = BFD_DEFAULT_MULTIPLIER;
reset_passwords();
};
bfd_iface_finish:
{
BFD_IFACE->passwords = get_passwords();
if (!BFD_IFACE->auth_type != !BFD_IFACE->passwords)
log(L_WARN "Authentication and password options should be used together");
if (BFD_IFACE->passwords)
{
struct password_item *pass;
WALK_LIST(pass, *BFD_IFACE->passwords)
{
if (pass->alg)
cf_error("Password algorithm option not available in BFD protocol");
pass->alg = bfd_auth_type_to_hash_alg[BFD_IFACE->auth_type];
}
}
}; };
bfd_iface_item: bfd_iface_item:
@ -77,6 +101,17 @@ bfd_iface_item:
| IDLE TX INTERVAL expr_us { BFD_IFACE->idle_tx_int = $4; } | IDLE TX INTERVAL expr_us { BFD_IFACE->idle_tx_int = $4; }
| MULTIPLIER expr { BFD_IFACE->multiplier = $2; } | MULTIPLIER expr { BFD_IFACE->multiplier = $2; }
| PASSIVE bool { BFD_IFACE->passive = $2; } | PASSIVE bool { BFD_IFACE->passive = $2; }
| AUTHENTICATION bfd_auth_type { BFD_IFACE->auth_type = $2; }
| password_list {}
;
bfd_auth_type:
NONE { $$ = BFD_AUTH_NONE; }
| SIMPLE { $$ = BFD_AUTH_SIMPLE; }
| KEYED MD5 { $$ = BFD_AUTH_KEYED_MD5; }
| KEYED SHA1 { $$ = BFD_AUTH_KEYED_SHA1; }
| METICULOUS KEYED MD5 { $$ = BFD_AUTH_METICULOUS_KEYED_MD5; }
| METICULOUS KEYED SHA1 { $$ = BFD_AUTH_METICULOUS_KEYED_SHA1; }
; ;
bfd_iface_opts: bfd_iface_opts:
@ -89,10 +124,11 @@ bfd_iface_opt_list:
| '{' bfd_iface_opts '}' | '{' bfd_iface_opts '}'
; ;
bfd_iface: bfd_iface_start iface_patt_list_nopx bfd_iface_opt_list bfd_iface:
{ add_tail(&BFD_CFG->patt_list, NODE this_ipatt); }; bfd_iface_start iface_patt_list_nopx bfd_iface_opt_list bfd_iface_finish;
bfd_multihop: bfd_iface_start bfd_iface_opt_list bfd_multihop:
bfd_iface_start bfd_iface_opt_list bfd_iface_finish
{ BFD_CFG->multihop = BFD_IFACE; }; { BFD_CFG->multihop = BFD_IFACE; };

View file

@ -5,24 +5,60 @@
*/ */
#include "bfd.h" #include "bfd.h"
#include "lib/mac.h"
struct bfd_ctl_packet struct bfd_ctl_packet
{ {
u8 vdiag; /* version and diagnostic */ u8 vdiag; /* Version and diagnostic */
u8 flags; /* state and flags */ u8 flags; /* State and flags */
u8 detect_mult; u8 detect_mult;
u8 length; u8 length; /* Whole packet length */
u32 snd_id; /* sender ID, aka 'my discriminator' */ u32 snd_id; /* Sender ID, aka 'my discriminator' */
u32 rcv_id; /* receiver ID, aka 'your discriminator' */ u32 rcv_id; /* Receiver ID, aka 'your discriminator' */
u32 des_min_tx_int; u32 des_min_tx_int;
u32 req_min_rx_int; u32 req_min_rx_int;
u32 req_min_echo_rx_int; u32 req_min_echo_rx_int;
}; };
struct bfd_auth
{
u8 type; /* Authentication type (BFD_AUTH_*) */
u8 length; /* Authentication section length */
};
struct bfd_simple_auth
{
u8 type; /* BFD_AUTH_SIMPLE */
u8 length; /* Length of bfd_simple_auth + pasword length */
u8 key_id; /* Key ID */
byte password[0]; /* Password itself, variable length */
};
#define BFD_MAX_PASSWORD_LENGTH 16
struct bfd_crypto_auth
{
u8 type; /* BFD_AUTH_*_MD5 or BFD_AUTH_*_SHA1 */
u8 length; /* Length of bfd_crypto_auth + hash length */
u8 key_id; /* Key ID */
u8 zero; /* Reserved, zero on transmit */
u32 csn; /* Cryptographic sequence number */
byte data[0]; /* Authentication key/hash, length 16 or 20 */
};
#define BFD_BASE_LEN sizeof(struct bfd_ctl_packet) #define BFD_BASE_LEN sizeof(struct bfd_ctl_packet)
#define BFD_MAX_LEN 64 #define BFD_MAX_LEN 64
#define DROP(DSC,VAL) do { err_dsc = DSC; err_val = VAL; goto drop; } while(0)
#define LOG_PKT(msg, args...) \
log(L_REMOTE "%s: " msg, p->p.name, args)
#define LOG_PKT_AUTH(msg, args...) \
log(L_AUTH "%s: " msg, p->p.name, args)
static inline u8 bfd_pack_vdiag(u8 version, u8 diag) static inline u8 bfd_pack_vdiag(u8 version, u8 diag)
{ return (version << 5) | diag; } { return (version << 5) | diag; }
@ -39,7 +75,7 @@ static inline u8 bfd_pkt_get_diag(struct bfd_ctl_packet *pkt)
static inline u8 bfd_pkt_get_state(struct bfd_ctl_packet *pkt) static inline u8 bfd_pkt_get_state(struct bfd_ctl_packet *pkt)
{ return pkt->flags >> 6; } { return pkt->flags >> 6; }
static inline void bfd_pkt_set_state(struct bfd_ctl_packet *pkt, u8 val) static inline void UNUSED bfd_pkt_set_state(struct bfd_ctl_packet *pkt, u8 val)
{ pkt->flags = val << 6; } { pkt->flags = val << 6; }
@ -59,6 +95,189 @@ bfd_format_flags(u8 flags, char *buf)
return buf; return buf;
} }
const u8 bfd_auth_type_to_hash_alg[] = {
[BFD_AUTH_NONE] = ALG_UNDEFINED,
[BFD_AUTH_SIMPLE] = ALG_UNDEFINED,
[BFD_AUTH_KEYED_MD5] = ALG_MD5,
[BFD_AUTH_METICULOUS_KEYED_MD5] = ALG_MD5,
[BFD_AUTH_KEYED_SHA1] = ALG_SHA1,
[BFD_AUTH_METICULOUS_KEYED_SHA1] = ALG_SHA1,
};
/* Fill authentication section and modifies final length in control section packet */
static void
bfd_fill_authentication(struct bfd_proto *p, struct bfd_session *s, struct bfd_ctl_packet *pkt)
{
struct bfd_iface_config *cf = s->ifa->cf;
struct password_item *pass = password_find(cf->passwords, 0);
uint meticulous = 0;
if (!pass)
{
/* FIXME: This should not happen */
log(L_ERR "%s: No suitable password found for authentication", p->p.name);
return;
}
switch (cf->auth_type)
{
case BFD_AUTH_SIMPLE:
{
struct bfd_simple_auth *auth = (void *) (pkt + 1);
uint pass_len = MIN(pass->length, BFD_MAX_PASSWORD_LENGTH);
auth->type = BFD_AUTH_SIMPLE;
auth->length = sizeof(struct bfd_simple_auth) + pass_len;
auth->key_id = pass->id;
pkt->flags |= BFD_FLAG_AP;
pkt->length += auth->length;
memcpy(auth->password, pass->password, pass_len);
return;
}
case BFD_AUTH_METICULOUS_KEYED_MD5:
case BFD_AUTH_METICULOUS_KEYED_SHA1:
meticulous = 1;
case BFD_AUTH_KEYED_MD5:
case BFD_AUTH_KEYED_SHA1:
{
struct bfd_crypto_auth *auth = (void *) (pkt + 1);
uint hash_alg = bfd_auth_type_to_hash_alg[cf->auth_type];
uint hash_len = mac_type_length(pass->alg);
/* Increase CSN about one time per second */
u32 new_time = (u64) current_time() >> 20;
if ((new_time != s->tx_csn_time) || meticulous)
{
s->tx_csn++;
s->tx_csn_time = new_time;
}
DBG("[%I] CSN: %u\n", s->addr, s->last_tx_csn);
auth->type = cf->auth_type;
auth->length = sizeof(struct bfd_crypto_auth) + hash_len;
auth->key_id = pass->id;
auth->zero = 0;
auth->csn = htonl(s->tx_csn);
pkt->flags |= BFD_FLAG_AP;
pkt->length += auth->length;
strncpy(auth->data, pass->password, hash_len);
mac_fill(hash_alg, NULL, 0, (byte *) pkt, pkt->length, auth->data);
return;
}
}
}
static int
bfd_check_authentication(struct bfd_proto *p, struct bfd_session *s, struct bfd_ctl_packet *pkt)
{
struct bfd_iface_config *cf = s->ifa->cf;
const char *err_dsc = NULL;
uint err_val = 0;
uint auth_type = 0;
uint meticulous = 0;
if (pkt->flags & BFD_FLAG_AP)
{
struct bfd_auth *auth = (void *) (pkt + 1);
if ((pkt->length < (BFD_BASE_LEN + sizeof(struct bfd_auth))) ||
(pkt->length < (BFD_BASE_LEN + auth->length)))
DROP("packet length mismatch", pkt->length);
/* Zero is reserved, we use it as BFD_AUTH_NONE internally */
if (auth->type == 0)
DROP("reserved authentication type", 0);
auth_type = auth->type;
}
if (auth_type != cf->auth_type)
DROP("authentication method mismatch", auth_type);
switch (auth_type)
{
case BFD_AUTH_NONE:
return 1;
case BFD_AUTH_SIMPLE:
{
struct bfd_simple_auth *auth = (void *) (pkt + 1);
if (auth->length < sizeof(struct bfd_simple_auth))
DROP("wrong authentication length", auth->length);
struct password_item *pass = password_find_by_id(cf->passwords, auth->key_id);
if (!pass)
DROP("no suitable password found", auth->key_id);
uint pass_len = MIN(pass->length, BFD_MAX_PASSWORD_LENGTH);
uint auth_len = sizeof(struct bfd_simple_auth) + pass_len;
if ((auth->length != auth_len) || memcmp(auth->password, pass->password, pass_len))
DROP("wrong password", pass->id);
return 1;
}
case BFD_AUTH_METICULOUS_KEYED_MD5:
case BFD_AUTH_METICULOUS_KEYED_SHA1:
meticulous = 1;
case BFD_AUTH_KEYED_MD5:
case BFD_AUTH_KEYED_SHA1:
{
struct bfd_crypto_auth *auth = (void *) (pkt + 1);
uint hash_alg = bfd_auth_type_to_hash_alg[cf->auth_type];
uint hash_len = mac_type_length(hash_alg);
if (auth->length != (sizeof(struct bfd_crypto_auth) + hash_len))
DROP("wrong authentication length", auth->length);
struct password_item *pass = password_find_by_id(cf->passwords, auth->key_id);
if (!pass)
DROP("no suitable password found", auth->key_id);
/* BFD CSNs are in 32-bit circular number space */
u32 csn = ntohl(auth->csn);
if (s->rx_csn_known &&
(((csn - s->rx_csn) > (3 * s->detect_mult)) ||
(meticulous && (csn == s->rx_csn))))
{
/* We want to report both new and old CSN */
LOG_PKT_AUTH("Authentication failed for %I - "
"wrong sequence number (rcv %u, old %u)",
s->addr, csn, s->rx_csn);
return 0;
}
byte *auth_data = alloca(hash_len);
memcpy(auth_data, auth->data, hash_len);
strncpy(auth->data, pass->password, hash_len);
if (!mac_verify(hash_alg, NULL, 0, (byte *) pkt, pkt->length, auth_data))
DROP("wrong authentication code", pass->id);
s->rx_csn = csn;
s->rx_csn_known = 1;
return 1;
}
}
drop:
LOG_PKT_AUTH("Authentication failed for %I - %s (%u)",
s->addr, err_dsc, err_val);
return 0;
}
void void
bfd_send_ctl(struct bfd_proto *p, struct bfd_session *s, int final) bfd_send_ctl(struct bfd_proto *p, struct bfd_session *s, int final)
{ {
@ -85,6 +304,9 @@ bfd_send_ctl(struct bfd_proto *p, struct bfd_session *s, int final)
else if (s->poll_active) else if (s->poll_active)
pkt->flags |= BFD_FLAG_POLL; pkt->flags |= BFD_FLAG_POLL;
if (s->ifa->cf->auth_type)
bfd_fill_authentication(p, s, pkt);
if (sk->tbuf != sk->tpos) if (sk->tbuf != sk->tpos)
log(L_WARN "%s: Old packet overwritten in TX buffer", p->p.name); log(L_WARN "%s: Old packet overwritten in TX buffer", p->p.name);
@ -94,10 +316,8 @@ bfd_send_ctl(struct bfd_proto *p, struct bfd_session *s, int final)
sk_send_to(sk, pkt->length, s->addr, sk->dport); sk_send_to(sk, pkt->length, s->addr, sk->dport);
} }
#define DROP(DSC,VAL) do { err_dsc = DSC; err_val = VAL; goto drop; } while(0)
static int static int
bfd_rx_hook(sock *sk, int len) bfd_rx_hook(sock *sk, uint len)
{ {
struct bfd_proto *p = sk->data; struct bfd_proto *p = sk->data;
struct bfd_ctl_packet *pkt = (struct bfd_ctl_packet *) sk->rbuf; struct bfd_ctl_packet *pkt = (struct bfd_ctl_packet *) sk->rbuf;
@ -151,10 +371,9 @@ bfd_rx_hook(sock *sk, int len)
return 1; return 1;
} }
/* FIXME: better authentication handling and message */ /* bfd_check_authentication() has its own error logging */
if (pkt->flags & BFD_FLAG_AP) if (!bfd_check_authentication(p, s, pkt))
DROP("authentication not supported", 0); return 1;
u32 old_tx_int = s->des_min_tx_int; u32 old_tx_int = s->des_min_tx_int;
u32 old_rx_int = s->rem_min_rx_int; u32 old_rx_int = s->rem_min_rx_int;
@ -173,8 +392,8 @@ bfd_rx_hook(sock *sk, int len)
bfd_session_process_ctl(s, pkt->flags, old_tx_int, old_rx_int); bfd_session_process_ctl(s, pkt->flags, old_tx_int, old_rx_int);
return 1; return 1;
drop: drop:
log(L_REMOTE "%s: Bad packet from %I - %s (%u)", p->p.name, sk->faddr, err_dsc, err_val); LOG_PKT("Bad packet from %I - %s (%u)", sk->faddr, err_dsc, err_val);
return 1; return 1;
} }

View file

@ -191,7 +191,7 @@ validate_as4_path(struct bgp_proto *p, struct adata *path)
} }
static int static int
bgp_check_next_hop(struct bgp_proto *p UNUSED, byte *a, int len) bgp_check_next_hop(struct bgp_proto *p UNUSED, byte *a UNUSED6, int len UNUSED6)
{ {
#ifdef IPV6 #ifdef IPV6
return IGNORE; return IGNORE;
@ -289,6 +289,12 @@ bgp_check_ext_community(struct bgp_proto *p UNUSED, byte *a UNUSED, int len)
return ((len % 8) == 0) ? 0 : WITHDRAW; return ((len % 8) == 0) ? 0 : WITHDRAW;
} }
static int
bgp_check_large_community(struct bgp_proto *p UNUSED, byte *a UNUSED, int len)
{
return ((len % 12) == 0) ? 0 : WITHDRAW;
}
static struct attr_desc bgp_attr_table[] = { static struct attr_desc bgp_attr_table[] = {
{ NULL, -1, 0, 0, 0, /* Undefined */ { NULL, -1, 0, 0, 0, /* Undefined */
@ -325,7 +331,10 @@ static struct attr_desc bgp_attr_table[] = {
{ "as4_path", -1, BAF_OPTIONAL | BAF_TRANSITIVE, EAF_TYPE_OPAQUE, 1, /* BA_AS4_PATH */ { "as4_path", -1, BAF_OPTIONAL | BAF_TRANSITIVE, EAF_TYPE_OPAQUE, 1, /* BA_AS4_PATH */
NULL, NULL }, NULL, NULL },
{ "as4_aggregator", -1, BAF_OPTIONAL | BAF_TRANSITIVE, EAF_TYPE_OPAQUE, 1, /* BA_AS4_PATH */ { "as4_aggregator", -1, BAF_OPTIONAL | BAF_TRANSITIVE, EAF_TYPE_OPAQUE, 1, /* BA_AS4_PATH */
NULL, NULL } NULL, NULL },
[BA_LARGE_COMMUNITY] =
{ "large_community", -1, BAF_OPTIONAL | BAF_TRANSITIVE, EAF_TYPE_LC_SET, 1,
bgp_check_large_community, NULL }
}; };
/* BA_AS4_PATH is type EAF_TYPE_OPAQUE and not type EAF_TYPE_AS_PATH. /* BA_AS4_PATH is type EAF_TYPE_OPAQUE and not type EAF_TYPE_AS_PATH.
@ -575,7 +584,7 @@ bgp_encode_attrs(struct bgp_proto *p, byte *w, ea_list *attrs, int remains)
len = bgp_get_attr_len(a); len = bgp_get_attr_len(a);
/* Skip empty sets */ /* Skip empty sets */
if (((type == EAF_TYPE_INT_SET) || (type == EAF_TYPE_EC_SET)) && (len == 0)) if (((type == EAF_TYPE_INT_SET) || (type == EAF_TYPE_EC_SET) || (type == EAF_TYPE_LC_SET)) && (len == 0))
continue; continue;
if (remains < len + 4) if (remains < len + 4)
@ -601,6 +610,7 @@ bgp_encode_attrs(struct bgp_proto *p, byte *w, ea_list *attrs, int remains)
break; break;
} }
case EAF_TYPE_INT_SET: case EAF_TYPE_INT_SET:
case EAF_TYPE_LC_SET:
case EAF_TYPE_EC_SET: case EAF_TYPE_EC_SET:
{ {
u32 *z = int_set_get_data(a->u.ptr); u32 *z = int_set_get_data(a->u.ptr);
@ -683,6 +693,25 @@ bgp_normalize_ec_set(struct adata *ad, u32 *src, int internal)
qsort(dst, ad->length / 8, 8, (int(*)(const void *, const void *)) bgp_compare_ec); qsort(dst, ad->length / 8, 8, (int(*)(const void *, const void *)) bgp_compare_ec);
} }
static int
bgp_compare_lc(const u32 *x, const u32 *y)
{
if (x[0] != y[0])
return (x[0] > y[0]) ? 1 : -1;
if (x[1] != y[1])
return (x[1] > y[1]) ? 1 : -1;
if (x[2] != y[2])
return (x[2] > y[2]) ? 1 : -1;
return 0;
}
static inline void
bgp_normalize_lc_set(u32 *dest, u32 *src, unsigned cnt)
{
memcpy(dest, src, LCOMM_LENGTH * cnt);
qsort(dest, cnt, LCOMM_LENGTH, (int(*)(const void *, const void *)) bgp_compare_lc);
}
static void static void
bgp_rehash_buckets(struct bgp_proto *p) bgp_rehash_buckets(struct bgp_proto *p)
{ {
@ -827,6 +856,14 @@ bgp_get_bucket(struct bgp_proto *p, net *n, ea_list *attrs, int originate)
d->u.ptr = z; d->u.ptr = z;
break; break;
} }
case EAF_TYPE_LC_SET:
{
struct adata *z = alloca(sizeof(struct adata) + d->u.ptr->length);
z->length = d->u.ptr->length;
bgp_normalize_lc_set((u32 *) z->data, (u32 *) d->u.ptr->data, z->length / LCOMM_LENGTH);
d->u.ptr = z;
break;
}
default: ; default: ;
} }
d++; d++;
@ -1797,6 +1834,7 @@ bgp_decode_attrs(struct bgp_conn *conn, byte *attr, uint len, struct linpool *po
ipa_ntoh(*(ip_addr *)ad->data); ipa_ntoh(*(ip_addr *)ad->data);
break; break;
case EAF_TYPE_INT_SET: case EAF_TYPE_INT_SET:
case EAF_TYPE_LC_SET:
case EAF_TYPE_EC_SET: case EAF_TYPE_EC_SET:
{ {
u32 *z = (u32 *) ad->data; u32 *z = (u32 *) ad->data;

View file

@ -807,7 +807,7 @@ bgp_find_proto(sock *sk)
* closes the new connection by sending a Notification message. * closes the new connection by sending a Notification message.
*/ */
static int static int
bgp_incoming_connection(sock *sk, int dummy UNUSED) bgp_incoming_connection(sock *sk, uint dummy UNUSED)
{ {
struct bgp_proto *p; struct bgp_proto *p;
int acc, hops; int acc, hops;

View file

@ -191,7 +191,7 @@ struct bgp_bucket {
#define BGP_RX_BUFFER_EXT_SIZE 65535 #define BGP_RX_BUFFER_EXT_SIZE 65535
#define BGP_TX_BUFFER_EXT_SIZE 65535 #define BGP_TX_BUFFER_EXT_SIZE 65535
static inline int bgp_max_packet_length(struct bgp_proto *p) static inline uint bgp_max_packet_length(struct bgp_proto *p)
{ return p->ext_messages ? BGP_MAX_EXT_MSG_LENGTH : BGP_MAX_MESSAGE_LENGTH; } { return p->ext_messages ? BGP_MAX_EXT_MSG_LENGTH : BGP_MAX_MESSAGE_LENGTH; }
extern struct linpool *bgp_linpool; extern struct linpool *bgp_linpool;
@ -268,7 +268,7 @@ void mrt_dump_bgp_state_change(struct bgp_conn *conn, unsigned old, unsigned new
void bgp_schedule_packet(struct bgp_conn *conn, int type); void bgp_schedule_packet(struct bgp_conn *conn, int type);
void bgp_kick_tx(void *vconn); void bgp_kick_tx(void *vconn);
void bgp_tx(struct birdsock *sk); void bgp_tx(struct birdsock *sk);
int bgp_rx(struct birdsock *sk, int size); int bgp_rx(struct birdsock *sk, uint size);
const char * bgp_error_dsc(unsigned code, unsigned subcode); const char * bgp_error_dsc(unsigned code, unsigned subcode);
void bgp_log_error(struct bgp_proto *p, u8 class, char *msg, unsigned code, unsigned subcode, byte *data, unsigned len); void bgp_log_error(struct bgp_proto *p, u8 class, char *msg, unsigned code, unsigned subcode, byte *data, unsigned len);
@ -308,6 +308,7 @@ void bgp_log_error(struct bgp_proto *p, u8 class, char *msg, unsigned code, unsi
#define BA_EXT_COMMUNITY 0x10 /* [RFC4360] */ #define BA_EXT_COMMUNITY 0x10 /* [RFC4360] */
#define BA_AS4_PATH 0x11 /* [RFC4893] */ #define BA_AS4_PATH 0x11 /* [RFC4893] */
#define BA_AS4_AGGREGATOR 0x12 #define BA_AS4_AGGREGATOR 0x12
#define BA_LARGE_COMMUNITY 0x20 /* [draft-ietf-idr-large-community] */
/* BGP connection states */ /* BGP connection states */

View file

@ -27,7 +27,7 @@ CF_KEYWORDS(BGP, LOCAL, NEIGHBOR, AS, HOLD, TIME, CONNECT, RETRY,
INTERPRET, COMMUNITIES, BGP_ORIGINATOR_ID, BGP_CLUSTER_LIST, IGP, INTERPRET, COMMUNITIES, BGP_ORIGINATOR_ID, BGP_CLUSTER_LIST, IGP,
TABLE, GATEWAY, DIRECT, RECURSIVE, MED, TTL, SECURITY, DETERMINISTIC, TABLE, GATEWAY, DIRECT, RECURSIVE, MED, TTL, SECURITY, DETERMINISTIC,
SECONDARY, ALLOW, BFD, ADD, PATHS, RX, TX, GRACEFUL, RESTART, AWARE, SECONDARY, ALLOW, BFD, ADD, PATHS, RX, TX, GRACEFUL, RESTART, AWARE,
CHECK, LINK, PORT, EXTENDED, MESSAGES, SETKEY) CHECK, LINK, PORT, EXTENDED, MESSAGES, SETKEY, BGP_LARGE_COMMUNITY)
CF_GRAMMAR CF_GRAMMAR
@ -153,6 +153,8 @@ CF_ADDTO(dynamic_attr, BGP_CLUSTER_LIST
{ $$ = f_new_dynamic_attr(EAF_TYPE_INT_SET, T_CLIST, EA_CODE(EAP_BGP, BA_CLUSTER_LIST)); }) { $$ = f_new_dynamic_attr(EAF_TYPE_INT_SET, T_CLIST, EA_CODE(EAP_BGP, BA_CLUSTER_LIST)); })
CF_ADDTO(dynamic_attr, BGP_EXT_COMMUNITY CF_ADDTO(dynamic_attr, BGP_EXT_COMMUNITY
{ $$ = f_new_dynamic_attr(EAF_TYPE_EC_SET, T_ECLIST, EA_CODE(EAP_BGP, BA_EXT_COMMUNITY)); }) { $$ = f_new_dynamic_attr(EAF_TYPE_EC_SET, T_ECLIST, EA_CODE(EAP_BGP, BA_EXT_COMMUNITY)); })
CF_ADDTO(dynamic_attr, BGP_LARGE_COMMUNITY
{ $$ = f_new_dynamic_attr(EAF_TYPE_LC_SET, T_LCLIST, EA_CODE(EAP_BGP, BA_LARGE_COMMUNITY)); })

View file

@ -191,7 +191,7 @@ bgp_put_cap_gr1(struct bgp_proto *p, byte *buf)
} }
static byte * static byte *
bgp_put_cap_gr2(struct bgp_proto *p, byte *buf) bgp_put_cap_gr2(struct bgp_proto *p UNUSED, byte *buf)
{ {
*buf++ = 64; /* Capability 64: Support for graceful restart */ *buf++ = 64; /* Capability 64: Support for graceful restart */
*buf++ = 2; /* Capability data length */ *buf++ = 2; /* Capability data length */
@ -931,7 +931,7 @@ bgp_parse_options(struct bgp_conn *conn, byte *opt, int len)
} }
static void static void
bgp_rx_open(struct bgp_conn *conn, byte *pkt, int len) bgp_rx_open(struct bgp_conn *conn, byte *pkt, uint len)
{ {
struct bgp_conn *other; struct bgp_conn *other;
struct bgp_proto *p = conn->bgp; struct bgp_proto *p = conn->bgp;
@ -944,7 +944,7 @@ bgp_rx_open(struct bgp_conn *conn, byte *pkt, int len)
{ bgp_error(conn, 5, fsm_err_subcode[conn->state], NULL, 0); return; } { bgp_error(conn, 5, fsm_err_subcode[conn->state], NULL, 0); return; }
/* Check message contents */ /* Check message contents */
if (len < 29 || len != 29 + pkt[28]) if (len < 29 || len != 29U + pkt[28])
{ bgp_error(conn, 1, 2, pkt+16, 2); return; } { bgp_error(conn, 1, 2, pkt+16, 2); return; }
if (pkt[19] != BGP_VERSION) if (pkt[19] != BGP_VERSION)
{ bgp_error(conn, 2, 1, pkt+19, 1); return; } /* RFC 1771 says 16 bits, draft-09 tells to use 8 */ { bgp_error(conn, 2, 1, pkt+19, 1); return; } /* RFC 1771 says 16 bits, draft-09 tells to use 8 */
@ -1256,16 +1256,15 @@ bgp_do_rx_update(struct bgp_conn *conn,
#else /* IPv6 version */ #else /* IPv6 version */
#define DO_NLRI(name) \ #define DO_NLRI(name) \
start = x = p->name##_start; \ x = p->name##_start; \
len = len0 = p->name##_len; \ len = len0 = p->name##_len; \
if (len) \ if (len) \
{ \ { \
if (len < 3) { err=9; goto done; } \ if (len < 3) { err=9; goto done; } \
af = get_u16(x); \ af = get_u16(x); \
sub = x[2]; \
x += 3; \ x += 3; \
len -= 3; \ len -= 3; \
DBG("\tNLRI AF=%d sub=%d len=%d\n", af, sub, len);\ DBG("\tNLRI AF=%d sub=%d len=%d\n", af, x[-1], len);\
} \ } \
else \ else \
af = 0; \ af = 0; \
@ -1291,15 +1290,15 @@ bgp_attach_next_hop(rta *a0, byte *x)
static void static void
bgp_do_rx_update(struct bgp_conn *conn, bgp_do_rx_update(struct bgp_conn *conn,
byte *withdrawn, int withdrawn_len, byte *withdrawn UNUSED, int withdrawn_len,
byte *nlri, int nlri_len, byte *nlri UNUSED, int nlri_len,
byte *attrs, int attr_len) byte *attrs, int attr_len)
{ {
struct bgp_proto *p = conn->bgp; struct bgp_proto *p = conn->bgp;
struct rte_src *src = p->p.main_source; struct rte_src *src = p->p.main_source;
byte *start, *x; byte *x;
int len, len0; int len, len0;
unsigned af, sub; unsigned af;
rta *a0, *a = NULL; rta *a0, *a = NULL;
ip_addr prefix; ip_addr prefix;
int pxlen, err = 0; int pxlen, err = 0;
@ -1375,11 +1374,11 @@ bgp_do_rx_update(struct bgp_conn *conn,
#endif #endif
static void static void
bgp_rx_update(struct bgp_conn *conn, byte *pkt, int len) bgp_rx_update(struct bgp_conn *conn, byte *pkt, uint len)
{ {
struct bgp_proto *p = conn->bgp; struct bgp_proto *p = conn->bgp;
byte *withdrawn, *attrs, *nlri; byte *withdrawn, *attrs, *nlri;
int withdrawn_len, attr_len, nlri_len; uint withdrawn_len, attr_len, nlri_len;
BGP_TRACE_RL(&rl_rcv_update, D_PACKETS, "Got UPDATE"); BGP_TRACE_RL(&rl_rcv_update, D_PACKETS, "Got UPDATE");
@ -1525,7 +1524,7 @@ bgp_log_error(struct bgp_proto *p, u8 class, char *msg, unsigned code, unsigned
} }
static void static void
bgp_rx_notification(struct bgp_conn *conn, byte *pkt, int len) bgp_rx_notification(struct bgp_conn *conn, byte *pkt, uint len)
{ {
struct bgp_proto *p = conn->bgp; struct bgp_proto *p = conn->bgp;
if (len < 21) if (len < 21)
@ -1591,7 +1590,7 @@ bgp_rx_keepalive(struct bgp_conn *conn)
} }
static void static void
bgp_rx_route_refresh(struct bgp_conn *conn, byte *pkt, int len) bgp_rx_route_refresh(struct bgp_conn *conn, byte *pkt, uint len)
{ {
struct bgp_proto *p = conn->bgp; struct bgp_proto *p = conn->bgp;
@ -1680,7 +1679,7 @@ bgp_rx_packet(struct bgp_conn *conn, byte *pkt, unsigned len)
* bgp_rx_packet(). * bgp_rx_packet().
*/ */
int int
bgp_rx(sock *sk, int size) bgp_rx(sock *sk, uint size)
{ {
struct bgp_conn *conn = sk->data; struct bgp_conn *conn = sk->data;
struct bgp_proto *p = conn->bgp; struct bgp_proto *p = conn->bgp;

View file

@ -42,6 +42,20 @@ ospf_iface_finish(void)
if ((ip->autype == OSPF_AUTH_NONE) && (ip->passwords != NULL)) if ((ip->autype == OSPF_AUTH_NONE) && (ip->passwords != NULL))
log(L_WARN "Password option without authentication option does not make sense"); log(L_WARN "Password option without authentication option does not make sense");
if (ip->passwords)
{
struct password_item *pass;
WALK_LIST(pass, *ip->passwords)
{
if (pass->alg && (ip->autype != OSPF_AUTH_CRYPT))
cf_error("Password algorithm option requires cryptographic authentication");
/* Set default OSPF crypto algorithms */
if (!pass->alg && (ip->autype == OSPF_AUTH_CRYPT))
pass->alg = ospf_cfg_is_v2() ? ALG_MD5 : ALG_HMAC_SHA256;
}
}
} }
static void static void

View file

@ -105,7 +105,7 @@ ospf_send_hello(struct ospf_iface *ifa, int kind, struct ospf_neighbor *dirn)
} }
i = 0; i = 0;
max = (ospf_pkt_maxsize(p, ifa) - length) / sizeof(u32); max = (ospf_pkt_maxsize(ifa) - length) / sizeof(u32);
/* Fill all neighbors */ /* Fill all neighbors */
if (kind != OHS_SHUTDOWN) if (kind != OHS_SHUTDOWN)
@ -222,9 +222,12 @@ ospf_receive_hello(struct ospf_packet *pkt, struct ospf_iface *ifa,
rcv_priority = ps->priority; rcv_priority = ps->priority;
int pxlen = u32_masklen(ntohl(ps->netmask)); int pxlen = u32_masklen(ntohl(ps->netmask));
if (pxlen < 0)
DROP("prefix garbled", ntohl(ps->netmask));
if ((ifa->type != OSPF_IT_VLINK) && if ((ifa->type != OSPF_IT_VLINK) &&
(ifa->type != OSPF_IT_PTP) && (ifa->type != OSPF_IT_PTP) &&
(pxlen != ifa->addr->prefix.pxlen)) ((uint) pxlen != ifa->addr->prefix.pxlen))
DROP("prefix length mismatch", pxlen); DROP("prefix length mismatch", pxlen);
neighbors = ps->neighbors; neighbors = ps->neighbors;

View file

@ -9,6 +9,7 @@
*/ */
#include "ospf.h" #include "ospf.h"
#include "nest/password.h"
const char *ospf_is_names[] = { const char *ospf_is_names[] = {
@ -51,6 +52,20 @@ ifa_tx_length(struct ospf_iface *ifa)
return ifa->cf->tx_length ?: ifa->iface->mtu; return ifa->cf->tx_length ?: ifa->iface->mtu;
} }
static inline uint
ifa_tx_hdrlen(struct ospf_iface *ifa)
{
struct ospf_proto *p = ifa->oa->po;
uint hlen = ospf_is_v2(p) ? IP4_HEADER_LENGTH : IP6_HEADER_LENGTH;
/* Relevant just for OSPFv2 */
if (ifa->autype == OSPF_AUTH_CRYPT)
hlen += max_mac_length(ifa->passwords);
return hlen;
}
static inline uint static inline uint
ifa_bufsize(struct ospf_iface *ifa) ifa_bufsize(struct ospf_iface *ifa)
{ {
@ -67,13 +82,7 @@ ifa_flood_queue_size(struct ospf_iface *ifa)
int int
ospf_iface_assure_bufsize(struct ospf_iface *ifa, uint plen) ospf_iface_assure_bufsize(struct ospf_iface *ifa, uint plen)
{ {
struct ospf_proto *p = ifa->oa->po; plen += ifa->tx_hdrlen;
plen += ospf_is_v2(p) ? IP4_HEADER_LENGTH : IP6_HEADER_LENGTH;
/* This is relevant just for OSPFv2 */
if (ifa->autype == OSPF_AUTH_CRYPT)
plen += OSPF_AUTH_CRYPT_SIZE;
if (plen <= ifa->sk->tbsize) if (plen <= ifa->sk->tbsize)
return 0; return 0;
@ -569,6 +578,7 @@ ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *i
ifa->stub = ospf_iface_stubby(ip, addr); ifa->stub = ospf_iface_stubby(ip, addr);
ifa->ioprob = OSPF_I_OK; ifa->ioprob = OSPF_I_OK;
ifa->tx_length = ifa_tx_length(ifa); ifa->tx_length = ifa_tx_length(ifa);
ifa->tx_hdrlen = ifa_tx_hdrlen(ifa);
ifa->check_link = ip->check_link; ifa->check_link = ip->check_link;
ifa->ecmp_weight = ip->ecmp_weight; ifa->ecmp_weight = ip->ecmp_weight;
ifa->check_ttl = (ip->ttl_security == 1); ifa->check_ttl = (ip->ttl_security == 1);
@ -680,6 +690,7 @@ ospf_iface_new_vlink(struct ospf_proto *p, struct ospf_iface_patt *ip)
ifa->deadint = ip->deadint; ifa->deadint = ip->deadint;
ifa->inftransdelay = ip->inftransdelay; ifa->inftransdelay = ip->inftransdelay;
ifa->tx_length = ospf_is_v2(p) ? IP4_MIN_MTU : IP6_MIN_MTU; ifa->tx_length = ospf_is_v2(p) ? IP4_MIN_MTU : IP6_MIN_MTU;
ifa->tx_hdrlen = ifa_tx_hdrlen(ifa);
ifa->autype = ip->autype; ifa->autype = ip->autype;
ifa->passwords = ip->passwords; ifa->passwords = ip->passwords;
ifa->instance_id = ip->instance_id; ifa->instance_id = ip->instance_id;
@ -820,6 +831,9 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
/* Update passwords */ /* Update passwords */
ifa->passwords = new->passwords; ifa->passwords = new->passwords;
/* Update header length */
ifa->tx_hdrlen = ifa_tx_hdrlen(ifa);
/* Remaining options are just for proper interfaces */ /* Remaining options are just for proper interfaces */
if (ifa->type == OSPF_IT_VLINK) if (ifa->type == OSPF_IT_VLINK)
return 1; return 1;

View file

@ -461,7 +461,7 @@ lsa_validate_sum3_net(struct ospf_lsa_header *lsa, struct ospf_lsa_sum3_net *bod
} }
static int static int
lsa_validate_sum3_rt(struct ospf_lsa_header *lsa, struct ospf_lsa_sum3_rt *body) lsa_validate_sum3_rt(struct ospf_lsa_header *lsa, struct ospf_lsa_sum3_rt *body UNUSED)
{ {
if (lsa->length != (HDRLEN + sizeof(struct ospf_lsa_sum3_rt))) if (lsa->length != (HDRLEN + sizeof(struct ospf_lsa_sum3_rt)))
return 0; return 0;

View file

@ -105,7 +105,7 @@ invalid:
static inline void static inline void
ospf_lsa_lsrq_down(struct top_hash_entry *req, struct ospf_neighbor *n, struct ospf_neighbor *from) ospf_lsa_lsrq_down(struct top_hash_entry *req, struct ospf_neighbor *n)
{ {
if (req == n->lsrqi) if (req == n->lsrqi)
n->lsrqi = SNODE_NEXT(req); n->lsrqi = SNODE_NEXT(req);
@ -188,7 +188,7 @@ ospf_enqueue_lsa(struct ospf_proto *p, struct top_hash_entry *en, struct ospf_if
{ {
/* If we already have full queue, we send some packets */ /* If we already have full queue, we send some packets */
uint sent = ospf_flood_lsupd(p, ifa->flood_queue, ifa->flood_queue_used, ifa->flood_queue_used / 2, ifa); uint sent = ospf_flood_lsupd(p, ifa->flood_queue, ifa->flood_queue_used, ifa->flood_queue_used / 2, ifa);
int i; uint i;
for (i = 0; i < sent; i++) for (i = 0; i < sent; i++)
ifa->flood_queue[i]->ret_count--; ifa->flood_queue[i]->ret_count--;
@ -275,7 +275,7 @@ ospf_flood_lsa(struct ospf_proto *p, struct top_hash_entry *en, struct ospf_neig
/* If same or newer, remove LSA from the link state request list */ /* If same or newer, remove LSA from the link state request list */
if (cmp > CMP_OLDER) if (cmp > CMP_OLDER)
ospf_lsa_lsrq_down(req, n, from); ospf_lsa_lsrq_down(req, n);
/* If older or same, skip processing of this neighbor */ /* If older or same, skip processing of this neighbor */
if (cmp < CMP_NEWER) if (cmp < CMP_NEWER)
@ -330,7 +330,7 @@ ospf_prepare_lsupd(struct ospf_proto *p, struct ospf_iface *ifa,
pkt = ospf_tx_buffer(ifa); pkt = ospf_tx_buffer(ifa);
hlen = ospf_lsupd_hdrlen(p); hlen = ospf_lsupd_hdrlen(p);
maxsize = ospf_pkt_maxsize(p, ifa); maxsize = ospf_pkt_maxsize(ifa);
ospf_pkt_fill_hdr(ifa, pkt, LSUPD_P); ospf_pkt_fill_hdr(ifa, pkt, LSUPD_P);
pos = hlen; pos = hlen;

View file

@ -171,11 +171,7 @@ struct ospf_iface_patt
#define OSPF_RXBUF_MINSIZE 256 /* Minimal allowed size */ #define OSPF_RXBUF_MINSIZE 256 /* Minimal allowed size */
u8 instance_id; u8 instance_id;
u8 autype; /* Not really used in OSPFv3 */ u8 autype; /* OSPF_AUTH_*, not really used in OSPFv3 */
#define OSPF_AUTH_NONE 0
#define OSPF_AUTH_SIMPLE 1
#define OSPF_AUTH_CRYPT 2
#define OSPF_AUTH_CRYPT_SIZE 16
u8 strictnbma; u8 strictnbma;
u8 check_link; u8 check_link;
u8 ecmp_weight; u8 ecmp_weight;
@ -325,6 +321,7 @@ struct ospf_iface
u8 marked; /* Used in OSPF reconfigure, 2 for force restart */ u8 marked; /* Used in OSPF reconfigure, 2 for force restart */
u16 rxbuf; /* Buffer size */ u16 rxbuf; /* Buffer size */
u16 tx_length; /* Soft TX packet length limit, usually MTU */ u16 tx_length; /* Soft TX packet length limit, usually MTU */
u16 tx_hdrlen; /* Expected packet header length, less than tx_length */
u8 check_link; /* Whether iface link change is used */ u8 check_link; /* Whether iface link change is used */
u8 ecmp_weight; /* Weight used for ECMP */ u8 ecmp_weight; /* Weight used for ECMP */
u8 link_lsa_suppression; /* Suppression of Link-LSA origination */ u8 link_lsa_suppression; /* Suppression of Link-LSA origination */
@ -415,6 +412,11 @@ struct ospf_neighbor
#define ISM_UNLOOP 5 /* Link up */ #define ISM_UNLOOP 5 /* Link up */
#define ISM_DOWN 6 /* Interface down */ #define ISM_DOWN 6 /* Interface down */
/* OSPF authentication types */
#define OSPF_AUTH_NONE 0
#define OSPF_AUTH_SIMPLE 1
#define OSPF_AUTH_CRYPT 2
/* OSPF neighbor states */ /* OSPF neighbor states */
#define NEIGHBOR_DOWN 0 #define NEIGHBOR_DOWN 0
@ -446,7 +448,6 @@ struct ospf_neighbor
#define TRANS_WAIT 2 /* Waiting before the end of translation */ #define TRANS_WAIT 2 /* Waiting before the end of translation */
/* Generic option flags */ /* Generic option flags */
#define OPT_V6 0x01 /* OSPFv3, LSA relevant for IPv6 routing calculation */ #define OPT_V6 0x01 /* OSPFv3, LSA relevant for IPv6 routing calculation */
#define OPT_E 0x02 /* Related to AS-external LSAs */ #define OPT_E 0x02 /* Related to AS-external LSAs */
@ -482,7 +483,7 @@ struct ospf_packet
u8 autype; /* Undefined for OSPFv3 */ u8 autype; /* Undefined for OSPFv3 */
}; };
struct ospf_md5 struct ospf_auth_crypto
{ {
u16 zero; u16 zero;
u8 keyid; u8 keyid;
@ -493,7 +494,7 @@ struct ospf_md5
union ospf_auth union ospf_auth
{ {
u8 password[8]; u8 password[8];
struct ospf_md5 md5; struct ospf_auth_crypto c32;
}; };
/* Packet types */ /* Packet types */
@ -890,8 +891,7 @@ void ospf_sh_neigh_info(struct ospf_neighbor *n);
/* packet.c */ /* packet.c */
void ospf_pkt_fill_hdr(struct ospf_iface *ifa, void *buf, u8 h_type); void ospf_pkt_fill_hdr(struct ospf_iface *ifa, void *buf, u8 h_type);
uint ospf_pkt_maxsize(struct ospf_proto *p, struct ospf_iface *ifa); int ospf_rx_hook(sock * sk, uint size);
int ospf_rx_hook(sock * sk, int size);
// void ospf_tx_hook(sock * sk); // void ospf_tx_hook(sock * sk);
void ospf_err_hook(sock * sk, int err); void ospf_err_hook(sock * sk, int err);
void ospf_verr_hook(sock *sk, int err); void ospf_verr_hook(sock *sk, int err);
@ -899,6 +899,9 @@ void ospf_send_to(struct ospf_iface *ifa, ip_addr ip);
void ospf_send_to_agt(struct ospf_iface *ifa, u8 state); void ospf_send_to_agt(struct ospf_iface *ifa, u8 state);
void ospf_send_to_bdr(struct ospf_iface *ifa); void ospf_send_to_bdr(struct ospf_iface *ifa);
static inline uint ospf_pkt_maxsize(struct ospf_iface *ifa)
{ return ifa->tx_length - ifa->tx_hdrlen; }
static inline void ospf_send_to_all(struct ospf_iface *ifa) static inline void ospf_send_to_all(struct ospf_iface *ifa)
{ ospf_send_to(ifa, ifa->all_routers); } { ospf_send_to(ifa, ifa->all_routers); }

View file

@ -11,6 +11,7 @@
#include "ospf.h" #include "ospf.h"
#include "nest/password.h" #include "nest/password.h"
#include "lib/md5.h" #include "lib/md5.h"
#include "lib/mac.h"
#include "lib/socket.h" #include "lib/socket.h"
void void
@ -23,7 +24,7 @@ ospf_pkt_fill_hdr(struct ospf_iface *ifa, void *buf, u8 h_type)
pkt->version = ospf_get_version(p); pkt->version = ospf_get_version(p);
pkt->type = h_type; pkt->type = h_type;
pkt->length = htons(ospf_pkt_maxsize(p, ifa)); pkt->length = htons(ospf_pkt_maxsize(ifa));
pkt->routerid = htonl(p->router_id); pkt->routerid = htonl(p->router_id);
pkt->areaid = htonl(ifa->oa->areaid); pkt->areaid = htonl(ifa->oa->areaid);
pkt->checksum = 0; pkt->checksum = 0;
@ -31,25 +32,12 @@ ospf_pkt_fill_hdr(struct ospf_iface *ifa, void *buf, u8 h_type)
pkt->autype = ifa->autype; pkt->autype = ifa->autype;
} }
uint
ospf_pkt_maxsize(struct ospf_proto *p, struct ospf_iface *ifa)
{
uint headers = ospf_is_v2(p) ? IP4_HEADER_LENGTH : IP6_HEADER_LENGTH;
/* Relevant just for OSPFv2 */
if (ifa->autype == OSPF_AUTH_CRYPT)
headers += OSPF_AUTH_CRYPT_SIZE;
return ifa->tx_length - headers;
}
/* We assume OSPFv2 in ospf_pkt_finalize() */ /* We assume OSPFv2 in ospf_pkt_finalize() */
static void static void
ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt) ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt, uint *plen)
{ {
struct password_item *passwd = NULL; struct password_item *pass = NULL;
union ospf_auth *auth = (void *) (pkt + 1); union ospf_auth *auth = (void *) (pkt + 1);
uint plen = ntohs(pkt->length);
pkt->checksum = 0; pkt->checksum = 0;
pkt->autype = ifa->autype; pkt->autype = ifa->autype;
@ -61,25 +49,25 @@ ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt)
switch (ifa->autype) switch (ifa->autype)
{ {
case OSPF_AUTH_SIMPLE: case OSPF_AUTH_SIMPLE:
passwd = password_find(ifa->passwords, 1); pass = password_find(ifa->passwords, 1);
if (!passwd) if (!pass)
{ {
log(L_ERR "No suitable password found for authentication"); log(L_ERR "No suitable password found for authentication");
return; return;
} }
strncpy(auth->password, passwd->password, sizeof(auth->password)); strncpy(auth->password, pass->password, sizeof(auth->password));
case OSPF_AUTH_NONE: case OSPF_AUTH_NONE:
{ {
void *body = (void *) (auth + 1); void *body = (void *) (auth + 1);
uint blen = plen - sizeof(struct ospf_packet) - sizeof(union ospf_auth); uint blen = *plen - sizeof(struct ospf_packet) - sizeof(union ospf_auth);
pkt->checksum = ipsum_calculate(pkt, sizeof(struct ospf_packet), body, blen, NULL); pkt->checksum = ipsum_calculate(pkt, sizeof(struct ospf_packet), body, blen, NULL);
} }
break; break;
case OSPF_AUTH_CRYPT: case OSPF_AUTH_CRYPT:
passwd = password_find(ifa->passwords, 0); pass = password_find(ifa->passwords, 0);
if (!passwd) if (!pass)
{ {
log(L_ERR "No suitable password found for authentication"); log(L_ERR "No suitable password found for authentication");
return; return;
@ -100,20 +88,25 @@ ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt)
ifa->csn_use = now; ifa->csn_use = now;
auth->md5.zero = 0; uint auth_len = mac_type_length(pass->alg);
auth->md5.keyid = passwd->id; byte *auth_tail = ((byte *) pkt + *plen);
auth->md5.len = OSPF_AUTH_CRYPT_SIZE; *plen += auth_len;
auth->md5.csn = htonl(ifa->csn);
void *tail = ((void *) pkt) + plen; ASSERT(*plen < ifa->sk->tbsize);
char password[OSPF_AUTH_CRYPT_SIZE];
strncpy(password, passwd->password, sizeof(password));
struct md5_context ctx; auth->c32.zero = 0;
md5_init(&ctx); auth->c32.keyid = pass->id;
md5_update(&ctx, (char *) pkt, plen); auth->c32.len = auth_len;
md5_update(&ctx, password, OSPF_AUTH_CRYPT_SIZE); auth->c32.csn = htonl(ifa->csn);
memcpy((byte *) tail, md5_final(&ctx), MD5_SIZE);
/* Append key for keyed hash, append padding for HMAC (RFC 5709 3.3) */
if (pass->alg < ALG_HMAC)
strncpy(auth_tail, pass->password, auth_len);
else
memset32(auth_tail, HMAC_MAGIC, auth_len / 4);
mac_fill(pass->alg, pass->password, pass->length,
(byte *) pkt, *plen, auth_tail);
break; break;
default: default:
@ -124,7 +117,7 @@ ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt)
/* We assume OSPFv2 in ospf_pkt_checkauth() */ /* We assume OSPFv2 in ospf_pkt_checkauth() */
static int static int
ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_packet *pkt, int len) ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_packet *pkt, uint len)
{ {
struct ospf_proto *p = ifa->oa->po; struct ospf_proto *p = ifa->oa->po;
union ospf_auth *auth = (void *) (pkt + 1); union ospf_auth *auth = (void *) (pkt + 1);
@ -154,13 +147,19 @@ ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_
return 1; return 1;
case OSPF_AUTH_CRYPT: case OSPF_AUTH_CRYPT:
if (auth->md5.len != OSPF_AUTH_CRYPT_SIZE) pass = password_find_by_id(ifa->passwords, auth->c32.keyid);
DROP("invalid MD5 digest length", auth->md5.len); if (!pass)
DROP("no suitable password found", auth->c32.keyid);
if (plen + OSPF_AUTH_CRYPT_SIZE > len) uint auth_len = mac_type_length(pass->alg);
DROP("length mismatch", len);
u32 rcv_csn = ntohl(auth->md5.csn); if (plen + auth->c32.len > len)
DROP("packet length mismatch", len);
if (auth->c32.len != auth_len)
DROP("wrong authentication length", auth->c32.len);
u32 rcv_csn = ntohl(auth->c32.csn);
if (n && (rcv_csn < n->csn)) if (n && (rcv_csn < n->csn))
// DROP("lower sequence number", rcv_csn); // DROP("lower sequence number", rcv_csn);
{ {
@ -171,22 +170,19 @@ ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_
return 0; return 0;
} }
pass = password_find_by_id(ifa->passwords, auth->md5.keyid); byte *auth_tail = ((byte *) pkt) + plen;
if (!pass) byte *auth_data = alloca(auth_len);
DROP("no suitable password found", auth->md5.keyid); memcpy(auth_data, auth_tail, auth_len);
byte *tail = ((byte *) pkt) + plen; /* Append key for keyed hash, append padding for HMAC (RFC 5709 3.3) */
char received[OSPF_AUTH_CRYPT_SIZE]; if (pass->alg < ALG_HMAC)
memcpy(received, tail, OSPF_AUTH_CRYPT_SIZE); strncpy(auth_tail, pass->password, auth_len);
strncpy(tail, pass->password, OSPF_AUTH_CRYPT_SIZE); else
memset32(auth_tail, HMAC_MAGIC, auth_len / 4);
struct md5_context ctx; if (!mac_verify(pass->alg, pass->password, pass->length,
md5_init(&ctx); (byte *) pkt, plen + auth_len, auth_data))
md5_update(&ctx, (byte *) pkt, plen + OSPF_AUTH_CRYPT_SIZE); DROP("wrong authentication code", pass->id);
char *computed = md5_final(&ctx);
if (memcmp(received, computed, OSPF_AUTH_CRYPT_SIZE))
DROP("wrong MD5 digest", pass->id);
if (n) if (n)
n->csn = rcv_csn; n->csn = rcv_csn;
@ -214,7 +210,7 @@ drop:
* non generic functions. * non generic functions.
*/ */
int int
ospf_rx_hook(sock *sk, int len) ospf_rx_hook(sock *sk, uint len)
{ {
/* We want just packets from sk->iface. Unfortunately, on BSD we cannot filter /* We want just packets from sk->iface. Unfortunately, on BSD we cannot filter
out other packets at kernel level and we receive all packets on all sockets */ out other packets at kernel level and we receive all packets on all sockets */
@ -472,15 +468,10 @@ ospf_send_to(struct ospf_iface *ifa, ip_addr dst)
{ {
sock *sk = ifa->sk; sock *sk = ifa->sk;
struct ospf_packet *pkt = (struct ospf_packet *) sk->tbuf; struct ospf_packet *pkt = (struct ospf_packet *) sk->tbuf;
int plen = ntohs(pkt->length); uint plen = ntohs(pkt->length);
if (ospf_is_v2(ifa->oa->po)) if (ospf_is_v2(ifa->oa->po))
{ ospf_pkt_finalize(ifa, pkt, &plen);
if (ifa->autype == OSPF_AUTH_CRYPT)
plen += OSPF_AUTH_CRYPT_SIZE;
ospf_pkt_finalize(ifa, pkt);
}
int done = sk_send_to(sk, plen, dst, 0); int done = sk_send_to(sk, plen, dst, 0);
if (!done) if (!done)

View file

@ -671,7 +671,7 @@ link_back(struct ospf_area *oa, struct top_hash_entry *en, struct top_hash_entry
which may be later used as the next hop. */ which may be later used as the next hop. */
/* In OSPFv2, en->lb is set here. In OSPFv3, en->lb is just cleared here, /* In OSPFv2, en->lb is set here. In OSPFv3, en->lb is just cleared here,
it is set in process_prefixes() to any global addres in the area */ it is set in process_prefixes() to any global address in the area */
en->lb = IPA_NONE; en->lb = IPA_NONE;
en->lb_id = 0; en->lb_id = 0;
@ -923,7 +923,7 @@ ospf_rt_sum_tr(struct ospf_area *oa)
} }
} }
/* Decide about originating or flushing summary LSAs for condended area networks */ /* Decide about originating or flushing summary LSAs for condensed area networks */
static int static int
decide_anet_lsa(struct ospf_area *oa, struct area_net *anet, struct ospf_area *anet_oa) decide_anet_lsa(struct ospf_area *oa, struct area_net *anet, struct ospf_area *anet_oa)
{ {

View file

@ -513,6 +513,7 @@ ospf_update_lsadb(struct ospf_proto *p)
} }
} }
static u32 static u32
ort_to_lsaid(struct ospf_proto *p, ort *nf) ort_to_lsaid(struct ospf_proto *p, ort *nf)
{ {
@ -610,7 +611,7 @@ lsab_offset(struct ospf_proto *p, uint offset)
return ((byte *) p->lsab) + offset; return ((byte *) p->lsab) + offset;
} }
static inline void * static inline void * UNUSED
lsab_end(struct ospf_proto *p) lsab_end(struct ospf_proto *p)
{ {
return ((byte *) p->lsab) + p->lsab_used; return ((byte *) p->lsab) + p->lsab_used;
@ -1558,7 +1559,7 @@ static void
add_link_lsa(struct ospf_proto *p, struct ospf_lsa_link *ll, int offset, int *pxc) add_link_lsa(struct ospf_proto *p, struct ospf_lsa_link *ll, int offset, int *pxc)
{ {
u32 *pxb = ll->rest; u32 *pxb = ll->rest;
int j; uint j;
for (j = 0; j < ll->pxcount; pxb = prefix_advance(pxb), j++) for (j = 0; j < ll->pxcount; pxb = prefix_advance(pxb), j++)
{ {

View file

@ -191,7 +191,7 @@ pipe_reconfigure(struct proto *P, struct proto_config *CF)
} }
static void static void
pipe_copy_config(struct proto_config *dest, struct proto_config *src) pipe_copy_config(struct proto_config *dest UNUSED, struct proto_config *src UNUSED)
{ {
/* Just a shallow copy, not many items here */ /* Just a shallow copy, not many items here */
} }

View file

@ -156,12 +156,12 @@ radv_process_domain(struct radv_dnssl_config *cf)
char *dom = cf->domain; char *dom = cf->domain;
char *dom_end = dom; /* Just to */ char *dom_end = dom; /* Just to */
u8 *dlen_save = &cf->dlen_first; u8 *dlen_save = &cf->dlen_first;
int len; uint len;
while (dom_end) while (dom_end)
{ {
dom_end = strchr(dom, '.'); dom_end = strchr(dom, '.');
len = dom_end ? (dom_end - dom) : strlen(dom); len = dom_end ? (uint)(dom_end - dom) : strlen(dom);
if (len < 1 || len > 63) if (len < 1 || len > 63)
return -1; return -1;
@ -349,7 +349,7 @@ radv_send_ra(struct radv_iface *ifa, int shutdown)
static int static int
radv_rx_hook(sock *sk, int size) radv_rx_hook(sock *sk, uint size)
{ {
struct radv_iface *ifa = sk->data; struct radv_iface *ifa = sk->data;
struct proto_radv *ra = ifa->ra; struct proto_radv *ra = ifa->ra;

View file

@ -240,7 +240,7 @@ radv_if_notify(struct proto *p, unsigned flags, struct iface *iface)
} }
static void static void
radv_ifa_notify(struct proto *p, unsigned flags, struct ifa *a) radv_ifa_notify(struct proto *p, unsigned flags UNUSED, struct ifa *a)
{ {
struct proto_radv *ra = (struct proto_radv *) p; struct proto_radv *ra = (struct proto_radv *) p;

View file

@ -104,15 +104,29 @@ rip_iface_start:
rip_iface_finish: rip_iface_finish:
{ {
/* Default mode is broadcast for RIPv1, multicast for RIPv2 and RIPng */
if (!RIP_IFACE->mode)
RIP_IFACE->mode = (rip_cfg_is_v2() && (RIP_IFACE->version == RIP_V1)) ?
RIP_IM_BROADCAST : RIP_IM_MULTICAST;
RIP_IFACE->passwords = get_passwords(); RIP_IFACE->passwords = get_passwords();
if (!RIP_IFACE->auth_type != !RIP_IFACE->passwords) if (!RIP_IFACE->auth_type != !RIP_IFACE->passwords)
log(L_WARN "Authentication and password options should be used together"); log(L_WARN "Authentication and password options should be used together");
/* Default mode is broadcast for RIPv1, multicast for RIPv2 and RIPng */ if (RIP_IFACE->passwords)
if (!RIP_IFACE->mode) {
RIP_IFACE->mode = (rip_cfg_is_v2() && (RIP_IFACE->version == RIP_V1)) ? struct password_item *pass;
RIP_IM_BROADCAST : RIP_IM_MULTICAST; WALK_LIST(pass, *RIP_IFACE->passwords)
{
if (pass->alg && (RIP_IFACE->auth_type != RIP_AUTH_CRYPTO))
cf_error("Password algorithm option requires cryptographic authentication");
/* Set default crypto algorithm (MD5) */
if (!pass->alg && (RIP_IFACE->auth_type == RIP_AUTH_CRYPTO))
pass->alg = ALG_MD5;
}
}
RIP_CFG->min_timeout_time = MIN_(RIP_CFG->min_timeout_time, RIP_IFACE->timeout_time); RIP_CFG->min_timeout_time = MIN_(RIP_CFG->min_timeout_time, RIP_IFACE->timeout_time);
RIP_CFG->max_garbage_time = MAX_(RIP_CFG->max_garbage_time, RIP_IFACE->garbage_time); RIP_CFG->max_garbage_time = MAX_(RIP_CFG->max_garbage_time, RIP_IFACE->garbage_time);
@ -153,7 +167,7 @@ rip_auth:
NONE { $$ = RIP_AUTH_NONE; } NONE { $$ = RIP_AUTH_NONE; }
| PLAINTEXT { $$ = RIP_AUTH_PLAIN; } | PLAINTEXT { $$ = RIP_AUTH_PLAIN; }
| CRYPTOGRAPHIC { $$ = RIP_AUTH_CRYPTO; } | CRYPTOGRAPHIC { $$ = RIP_AUTH_CRYPTO; }
| MD5 { $$ = RIP_AUTH_CRYPTO; } | MD5 { $$ = RIP_AUTH_CRYPTO; } /* For backward compatibility */
; ;
rip_iface_opts: rip_iface_opts:

View file

@ -12,16 +12,14 @@
#undef LOCAL_DEBUG #undef LOCAL_DEBUG
#include "rip.h" #include "rip.h"
#include "lib/md5.h" #include "lib/mac.h"
#define RIP_CMD_REQUEST 1 /* want info */ #define RIP_CMD_REQUEST 1 /* want info */
#define RIP_CMD_RESPONSE 2 /* responding to request */ #define RIP_CMD_RESPONSE 2 /* responding to request */
#define RIP_BLOCK_LENGTH 20 #define RIP_BLOCK_LENGTH 20
#define RIP_PASSWD_LENGTH 16 #define RIP_PASSWD_LENGTH 16
#define RIP_MD5_LENGTH 16
#define RIP_AF_IPV4 2 #define RIP_AF_IPV4 2
#define RIP_AF_AUTH 0xffff #define RIP_AF_AUTH 0xffff
@ -74,7 +72,7 @@ struct rip_auth_tail
{ {
u16 must_be_ffff; u16 must_be_ffff;
u16 must_be_0001; u16 must_be_0001;
byte auth_data[]; byte auth_data[0];
}; };
/* Internal representation of RTE block data */ /* Internal representation of RTE block data */
@ -132,7 +130,7 @@ rip_put_block(struct rip_proto *p, byte *pos, struct rip_block *rte)
} }
static inline void static inline void
rip_put_next_hop(struct rip_proto *p, byte *pos, struct rip_block *rte) rip_put_next_hop(struct rip_proto *p UNUSED, byte *pos, struct rip_block *rte)
{ {
struct rip_block_ng *block = (void *) pos; struct rip_block_ng *block = (void *) pos;
block->prefix = ip6_hton(ipa_to_ip6(rte->next_hop)); block->prefix = ip6_hton(ipa_to_ip6(rte->next_hop));
@ -221,16 +219,24 @@ rip_fill_authentication(struct rip_proto *p, struct rip_iface *ifa, struct rip_p
auth->auth_type = htons(RIP_AUTH_CRYPTO); auth->auth_type = htons(RIP_AUTH_CRYPTO);
auth->packet_len = htons(*plen); auth->packet_len = htons(*plen);
auth->key_id = pass->id; auth->key_id = pass->id;
auth->auth_len = sizeof(struct rip_auth_tail) + RIP_MD5_LENGTH; auth->auth_len = mac_type_length(pass->alg);
auth->seq_num = ifa->csn_ready ? htonl(ifa->csn) : 0; auth->seq_num = ifa->csn_ready ? htonl(ifa->csn) : 0;
auth->unused1 = 0; auth->unused1 = 0;
auth->unused2 = 0; auth->unused2 = 0;
ifa->csn_ready = 1; ifa->csn_ready = 1;
if (pass->alg < ALG_HMAC)
auth->auth_len += sizeof(struct rip_auth_tail);
/* /*
* Note that RFC 4822 is unclear whether auth_len should cover whole * Note that RFC 4822 is unclear whether auth_len should cover whole
* authentication trailer or just auth_data length. * authentication trailer or just auth_data length.
* *
* FIXME: We should use just auth_data length by default. Currently we put
* the whole auth trailer length in keyed hash case to keep old behavior,
* but we put just auth_data length in the new HMAC case. Note that Quagga
* has config option for this.
*
* Crypto sequence numbers are increased by sender in rip_update_csn(). * Crypto sequence numbers are increased by sender in rip_update_csn().
* First CSN should be zero, this is handled by csn_ready. * First CSN should be zero, this is handled by csn_ready.
*/ */
@ -238,14 +244,18 @@ rip_fill_authentication(struct rip_proto *p, struct rip_iface *ifa, struct rip_p
struct rip_auth_tail *tail = (void *) ((byte *) pkt + *plen); struct rip_auth_tail *tail = (void *) ((byte *) pkt + *plen);
tail->must_be_ffff = htons(0xffff); tail->must_be_ffff = htons(0xffff);
tail->must_be_0001 = htons(0x0001); tail->must_be_0001 = htons(0x0001);
strncpy(tail->auth_data, pass->password, RIP_MD5_LENGTH);
*plen += sizeof(struct rip_auth_tail) + RIP_MD5_LENGTH; uint auth_len = mac_type_length(pass->alg);
*plen += sizeof(struct rip_auth_tail) + auth_len;
struct md5_context ctx; /* Append key for keyed hash, append padding for HMAC (RFC 4822 2.5) */
md5_init(&ctx); if (pass->alg < ALG_HMAC)
md5_update(&ctx, (byte *) pkt, *plen); strncpy(tail->auth_data, pass->password, auth_len);
memcpy(tail->auth_data, md5_final(&ctx), RIP_MD5_LENGTH); else
memset32(tail->auth_data, HMAC_MAGIC, auth_len / 4);
mac_fill(pass->alg, pass->password, pass->length,
(byte *) pkt, *plen, tail->auth_data);
return; return;
default: default:
@ -288,13 +298,25 @@ rip_check_authentication(struct rip_proto *p, struct rip_iface *ifa, struct rip_
DROP("no suitable password found", auth->key_id); DROP("no suitable password found", auth->key_id);
uint data_len = ntohs(auth->packet_len); uint data_len = ntohs(auth->packet_len);
uint auth_len = sizeof(struct rip_auth_tail) + RIP_MD5_LENGTH; uint auth_len = mac_type_length(pass->alg);
uint auth_len2 = sizeof(struct rip_auth_tail) + auth_len;
if (data_len + auth_len != *plen) /*
DROP("packet length mismatch", data_len); * Ideally, first check should be check for internal consistency:
* (data_len + sizeof(struct rip_auth_tail) + auth->auth_len) != *plen
*
* Second one should check expected code length:
* auth->auth_len != auth_len
*
* But as auth->auth_len has two interpretations, we simplify this
*/
if ((auth->auth_len != RIP_MD5_LENGTH) && (auth->auth_len != auth_len)) if (data_len + auth_len2 != *plen)
DROP("authentication data length mismatch", auth->auth_len); DROP("packet length mismatch", *plen);
/* Warning: two interpretations of auth_len field */
if ((auth->auth_len != auth_len) && (auth->auth_len != auth_len2))
DROP("wrong authentication length", auth->auth_len);
struct rip_auth_tail *tail = (void *) ((byte *) pkt + data_len); struct rip_auth_tail *tail = (void *) ((byte *) pkt + data_len);
if ((tail->must_be_ffff != htons(0xffff)) || (tail->must_be_0001 != htons(0x0001))) if ((tail->must_be_ffff != htons(0xffff)) || (tail->must_be_0001 != htons(0x0001)))
@ -312,17 +334,18 @@ rip_check_authentication(struct rip_proto *p, struct rip_iface *ifa, struct rip_
return 0; return 0;
} }
char received[RIP_MD5_LENGTH]; byte *auth_data = alloca(auth_len);
memcpy(received, tail->auth_data, RIP_MD5_LENGTH); memcpy(auth_data, tail->auth_data, auth_len);
strncpy(tail->auth_data, pass->password, RIP_MD5_LENGTH);
struct md5_context ctx; /* Append key for keyed hash, append padding for HMAC (RFC 4822 2.5) */
md5_init(&ctx); if (pass->alg < ALG_HMAC)
md5_update(&ctx, (byte *) pkt, *plen); strncpy(tail->auth_data, pass->password, auth_len);
char *computed = md5_final(&ctx); else
memset32(tail->auth_data, HMAC_MAGIC, auth_len / 4);
if (memcmp(received, computed, RIP_MD5_LENGTH)) if (!mac_verify(pass->alg, pass->password, pass->length,
DROP("wrong MD5 digest", pass->id); (byte *) pkt, *plen, auth_data))
DROP("wrong authentication code", pass->id);
*plen = data_len; *plen = data_len;
n->csn = rcv_csn; n->csn = rcv_csn;
@ -632,7 +655,7 @@ rip_receive_response(struct rip_proto *p, struct rip_iface *ifa, struct rip_pack
} }
static int static int
rip_rx_hook(sock *sk, int len) rip_rx_hook(sock *sk, uint len)
{ {
struct rip_iface *ifa = sk->data; struct rip_iface *ifa = sk->data;
struct rip_proto *p = ifa->rip; struct rip_proto *p = ifa->rip;

View file

@ -575,7 +575,7 @@ rip_iface_update_buffers(struct rip_iface *ifa)
ifa->tx_plen = tbsize - headers; ifa->tx_plen = tbsize - headers;
if (ifa->cf->auth_type == RIP_AUTH_CRYPTO) if (ifa->cf->auth_type == RIP_AUTH_CRYPTO)
ifa->tx_plen -= RIP_AUTH_TAIL_LENGTH; ifa->tx_plen -= RIP_AUTH_TAIL_LENGTH + max_mac_length(ifa->cf->passwords);
} }
static inline void static inline void
@ -687,12 +687,11 @@ rip_reconfigure_iface(struct rip_proto *p, struct rip_iface *ifa, struct rip_ifa
ifa->cf = new; ifa->cf = new;
rip_iface_update_buffers(ifa);
if (ifa->next_regular > (now + new->update_time)) if (ifa->next_regular > (now + new->update_time))
ifa->next_regular = now + (random() % new->update_time) + 1; ifa->next_regular = now + (random() % new->update_time) + 1;
if ((new->tx_length != old->tx_length) || (new->rx_buffer != old->rx_buffer))
rip_iface_update_buffers(ifa);
if (new->check_link != old->check_link) if (new->check_link != old->check_link)
rip_iface_update_state(ifa); rip_iface_update_state(ifa);
@ -1011,7 +1010,7 @@ rip_prepare_attrs(struct linpool *pool, ea_list *next, u8 metric, u16 tag)
} }
static int static int
rip_import_control(struct proto *P, struct rte **rt, struct ea_list **attrs, struct linpool *pool) rip_import_control(struct proto *P UNUSED, struct rte **rt, struct ea_list **attrs, struct linpool *pool)
{ {
/* Prepare attributes with initial values */ /* Prepare attributes with initial values */
if ((*rt)->attrs->source != RTS_RIP) if ((*rt)->attrs->source != RTS_RIP)
@ -1145,7 +1144,7 @@ rip_reconfigure(struct proto *P, struct proto_config *CF)
} }
static void static void
rip_get_route_info(rte *rte, byte *buf, ea_list *attrs) rip_get_route_info(rte *rte, byte *buf, ea_list *attrs UNUSED)
{ {
buf += bsprintf(buf, " (%d/%d)", rte->pref, rte->u.rip.metric); buf += bsprintf(buf, " (%d/%d)", rte->pref, rte->u.rip.metric);

View file

@ -34,7 +34,7 @@
#define RIP_NG_PORT 521 /* RIPng */ #define RIP_NG_PORT 521 /* RIPng */
#define RIP_MAX_PKT_LENGTH 532 /* 512 + IP4_HEADER_LENGTH */ #define RIP_MAX_PKT_LENGTH 532 /* 512 + IP4_HEADER_LENGTH */
#define RIP_AUTH_TAIL_LENGTH 20 /* 4 + MD5 length */ #define RIP_AUTH_TAIL_LENGTH 4 /* Without auth_data */
#define RIP_DEFAULT_ECMP_LIMIT 16 #define RIP_DEFAULT_ECMP_LIMIT 16
#define RIP_DEFAULT_INFINITY 16 #define RIP_DEFAULT_INFINITY 16

View file

@ -244,7 +244,7 @@ static_add(struct proto *p, struct static_config *cf, struct static_route *r)
} }
static void static void
static_rte_cleanup(struct proto *p, struct static_route *r) static_rte_cleanup(struct proto *p UNUSED, struct static_route *r)
{ {
struct static_route *r2; struct static_route *r2;
@ -440,7 +440,7 @@ static_if_notify(struct proto *p, unsigned flags, struct iface *i)
} }
int int
static_rte_mergable(rte *pri, rte *sec) static_rte_mergable(rte *pri UNUSED, rte *sec UNUSED)
{ {
return 1; return 1;
} }

View file

@ -933,7 +933,7 @@ kif_do_scan(struct kif_proto *p)
/* Kernel sockets */ /* Kernel sockets */
static int static int
krt_sock_hook(sock *sk, int size UNUSED) krt_sock_hook(sock *sk, uint size UNUSED)
{ {
struct ks_msg msg; struct ks_msg msg;
int l = read(sk->fd, (char *)&msg, sizeof(msg)); int l = read(sk->fd, (char *)&msg, sizeof(msg));
@ -953,7 +953,7 @@ krt_sock_err_hook(sock *sk, int e UNUSED)
} }
static sock * static sock *
krt_sock_open(pool *pool, void *data, int table_id) krt_sock_open(pool *pool, void *data, int table_id UNUSED)
{ {
sock *sk; sock *sk;
int fd; int fd;
@ -1120,7 +1120,7 @@ kif_sys_shutdown(struct kif_proto *p)
struct ifa * struct ifa *
kif_get_primary_ip(struct iface *i) kif_get_primary_ip(struct iface *i UNUSED)
{ {
#if 0 #if 0
static int fd = -1; static int fd = -1;

View file

@ -48,4 +48,5 @@ static inline void krt_sys_postconfig(struct krt_config *x UNUSED) { }
static inline int krt_sys_get_attr(eattr *a UNUSED, byte *buf UNUSED, int buflen UNUSED) { return GA_UNKNOWN; } static inline int krt_sys_get_attr(eattr *a UNUSED, byte *buf UNUSED, int buflen UNUSED) { return GA_UNKNOWN; }
#endif #endif

View file

@ -28,6 +28,7 @@
#endif #endif
#undef SA_LEN
#define SA_LEN(x) (x).sa.sa_len #define SA_LEN(x) (x).sa.sa_len
@ -133,12 +134,12 @@ sk_process_cmsg4_ttl(sock *s, struct cmsghdr *cm)
s->rcv_ttl = * (byte *) CMSG_DATA(cm); s->rcv_ttl = * (byte *) CMSG_DATA(cm);
} }
#ifdef IP_SENDSRCADDR
static inline void static inline void
sk_prepare_cmsgs4(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen) sk_prepare_cmsgs4(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
{ {
/* Unfortunately, IP_SENDSRCADDR does not work for raw IP sockets on BSD kernels */ /* Unfortunately, IP_SENDSRCADDR does not work for raw IP sockets on BSD kernels */
#ifdef IP_SENDSRCADDR
struct cmsghdr *cm; struct cmsghdr *cm;
struct in_addr *sa; struct in_addr *sa;
int controllen = 0; int controllen = 0;
@ -156,10 +157,13 @@ sk_prepare_cmsgs4(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
*sa = ipa_to_in4(s->saddr); *sa = ipa_to_in4(s->saddr);
msg->msg_controllen = controllen; msg->msg_controllen = controllen;
#endif
} }
#else
static inline void
sk_prepare_cmsgs4(sock *s UNUSED, struct msghdr *msg UNUSED, void *cbuf UNUSED, size_t cbuflen UNUSED) { }
#endif
static void static void UNUSED
sk_prepare_ip_header(sock *s, void *hdr, int dlen) sk_prepare_ip_header(sock *s, void *hdr, int dlen)
{ {
struct ip *ip = hdr; struct ip *ip = hdr;
@ -200,7 +204,7 @@ sk_prepare_ip_header(sock *s, void *hdr, int dlen)
#endif #endif
int int
sk_set_md5_auth(sock *s, ip_addr local, ip_addr remote, struct iface *ifa, char *passwd, int setkey UNUSED) sk_set_md5_auth(sock *s, ip_addr local UNUSED, ip_addr remote UNUSED, struct iface *ifa UNUSED, char *passwd, int setkey UNUSED)
{ {
#ifdef USE_MD5SIG_SETKEY #ifdef USE_MD5SIG_SETKEY
if (setkey) if (setkey)
@ -235,20 +239,20 @@ sk_set_min_ttl4(sock *s, int ttl)
} }
static inline int static inline int
sk_set_min_ttl6(sock *s, int ttl) sk_set_min_ttl6(sock *s, int ttl UNUSED)
{ {
ERR_MSG("Kernel does not support IPv6 TTL security"); ERR_MSG("Kernel does not support IPv6 TTL security");
} }
static inline int static inline int
sk_disable_mtu_disc4(sock *s) sk_disable_mtu_disc4(sock *s UNUSED)
{ {
/* TODO: Set IP_DONTFRAG to 0 ? */ /* TODO: Set IP_DONTFRAG to 0 ? */
return 0; return 0;
} }
static inline int static inline int
sk_disable_mtu_disc6(sock *s) sk_disable_mtu_disc6(sock *s UNUSED)
{ {
/* TODO: Set IPV6_DONTFRAG to 0 ? */ /* TODO: Set IPV6_DONTFRAG to 0 ? */
return 0; return 0;

View file

@ -27,7 +27,7 @@ static inline void kif_sys_postconfig(struct kif_config *c UNUSED) { }
static inline void kif_sys_init_config(struct kif_config *c UNUSED) { } static inline void kif_sys_init_config(struct kif_config *c UNUSED) { }
static inline void kif_sys_copy_config(struct kif_config *d UNUSED, struct kif_config *s UNUSED) { } static inline void kif_sys_copy_config(struct kif_config *d UNUSED, struct kif_config *s UNUSED) { }
static inline struct ifa * kif_get_primary_ip(struct iface *i) { return NULL; } static inline struct ifa * kif_get_primary_ip(struct iface *i UNUSED) { return NULL; }
/* Kernel routes */ /* Kernel routes */

View file

@ -503,7 +503,7 @@ nl_parse_multipath(struct krt_proto *p, struct rtattr *ra)
struct rtattr *a[BIRD_RTA_MAX]; struct rtattr *a[BIRD_RTA_MAX];
struct rtnexthop *nh = RTA_DATA(ra); struct rtnexthop *nh = RTA_DATA(ra);
struct mpnh *rv, *first, **last; struct mpnh *rv, *first, **last;
int len = RTA_PAYLOAD(ra); unsigned len = RTA_PAYLOAD(ra);
first = NULL; first = NULL;
last = &first; last = &first;
@ -1584,7 +1584,7 @@ nl_async_msg(struct nlmsghdr *h)
} }
static int static int
nl_async_hook(sock *sk, int size UNUSED) nl_async_hook(sock *sk, uint size UNUSED)
{ {
struct iovec iov = { nl_async_rx_buffer, NL_RX_SIZE }; struct iovec iov = { nl_async_rx_buffer, NL_RX_SIZE };
struct sockaddr_nl sa; struct sockaddr_nl sa;

View file

@ -1,4 +1,11 @@
#ifndef _BIRD_SYSPRIV_H_
#define _BIRD_SYSPRIV_H_
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <unistd.h>
#include <sys/prctl.h> #include <sys/prctl.h>
#include <linux/capability.h> #include <linux/capability.h>
@ -70,3 +77,5 @@ drop_uid(uid_t uid)
if (setresuid(uid, uid, uid) < 0) if (setresuid(uid, uid, uid) < 0)
die("setresuid: %m"); die("setresuid: %m");
} }
#endif /* _BIRD_SYSPRIV_H_ */

View file

@ -9,7 +9,9 @@
/* Unfortunately, some glibc versions hide parts of RFC 3542 API /* Unfortunately, some glibc versions hide parts of RFC 3542 API
if _GNU_SOURCE is not defined. */ if _GNU_SOURCE is not defined. */
#define _GNU_SOURCE 1 #ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -507,11 +509,11 @@ tm_format_datetime(char *x, struct timeformat *fmt_spec, bird_clock_t t)
* Sockaddr helper functions * Sockaddr helper functions
*/ */
static inline int sockaddr_length(int af) static inline int UNUSED sockaddr_length(int af)
{ return (af == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6); } { return (af == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6); }
static inline void static inline void
sockaddr_fill4(struct sockaddr_in *sa, ip_addr a, struct iface *ifa, uint port) sockaddr_fill4(struct sockaddr_in *sa, ip_addr a, uint port)
{ {
memset(sa, 0, sizeof(struct sockaddr_in)); memset(sa, 0, sizeof(struct sockaddr_in));
#ifdef HAVE_SIN_LEN #ifdef HAVE_SIN_LEN
@ -542,7 +544,7 @@ void
sockaddr_fill(sockaddr *sa, int af, ip_addr a, struct iface *ifa, uint port) sockaddr_fill(sockaddr *sa, int af, ip_addr a, struct iface *ifa, uint port)
{ {
if (af == AF_INET) if (af == AF_INET)
sockaddr_fill4((struct sockaddr_in *) sa, a, ifa, port); sockaddr_fill4((struct sockaddr_in *) sa, a, port);
else if (af == AF_INET6) else if (af == AF_INET6)
sockaddr_fill6((struct sockaddr_in6 *) sa, a, ifa, port); sockaddr_fill6((struct sockaddr_in6 *) sa, a, ifa, port);
else else
@ -550,7 +552,7 @@ sockaddr_fill(sockaddr *sa, int af, ip_addr a, struct iface *ifa, uint port)
} }
static inline void static inline void
sockaddr_read4(struct sockaddr_in *sa, ip_addr *a, struct iface **ifa, uint *port) sockaddr_read4(struct sockaddr_in *sa, ip_addr *a, uint *port)
{ {
*port = ntohs(sa->sin_port); *port = ntohs(sa->sin_port);
*a = ipa_from_in4(sa->sin_addr); *a = ipa_from_in4(sa->sin_addr);
@ -573,7 +575,7 @@ sockaddr_read(sockaddr *sa, int af, ip_addr *a, struct iface **ifa, uint *port)
goto fail; goto fail;
if (af == AF_INET) if (af == AF_INET)
sockaddr_read4((struct sockaddr_in *) sa, a, ifa, port); sockaddr_read4((struct sockaddr_in *) sa, a, port);
else if (af == AF_INET6) else if (af == AF_INET6)
sockaddr_read6((struct sockaddr_in6 *) sa, a, ifa, port); sockaddr_read6((struct sockaddr_in6 *) sa, a, ifa, port);
else else
@ -770,7 +772,7 @@ sk_set_tos6(sock *s, int tos)
} }
static inline int static inline int
sk_set_high_port(sock *s) sk_set_high_port(sock *s UNUSED)
{ {
/* Port range setting is optional, ignore it if not supported */ /* Port range setting is optional, ignore it if not supported */
@ -2085,6 +2087,7 @@ watchdog_stop(void)
volatile int async_config_flag; /* Asynchronous reconfiguration/dump scheduled */ volatile int async_config_flag; /* Asynchronous reconfiguration/dump scheduled */
volatile int async_dump_flag; volatile int async_dump_flag;
volatile int async_shutdown_flag;
void void
io_init(void) io_init(void)

View file

@ -899,7 +899,7 @@ krt_scan_timer_start(struct krt_proto *p)
} }
static void static void
krt_scan_timer_stop(struct krt_proto *p) krt_scan_timer_stop(struct krt_proto *p UNUSED)
{ {
krt_scan_count--; krt_scan_count--;
@ -988,7 +988,7 @@ krt_store_tmp_attrs(rte *rt, struct ea_list *attrs)
} }
static int static int
krt_import_control(struct proto *P, rte **new, ea_list **attrs, struct linpool *pool) krt_import_control(struct proto *P, rte **new, ea_list **attrs UNUSED, struct linpool *pool UNUSED)
{ {
struct krt_proto *p = (struct krt_proto *) P; struct krt_proto *p = (struct krt_proto *) P;
rte *e = *new; rte *e = *new;

View file

@ -288,18 +288,22 @@ log_switch(int debug, list *l, char *new_syslog_name)
current_log_list = l; current_log_list = l;
#ifdef HAVE_SYSLOG #ifdef HAVE_SYSLOG
char *old_syslog_name = current_syslog_name; if (current_syslog_name && new_syslog_name &&
current_syslog_name = new_syslog_name; !strcmp(current_syslog_name, new_syslog_name))
if (old_syslog_name && new_syslog_name &&
!strcmp(old_syslog_name, new_syslog_name))
return; return;
if (old_syslog_name) if (current_syslog_name)
{
closelog(); closelog();
xfree(current_syslog_name);
current_syslog_name = NULL;
}
if (new_syslog_name) if (new_syslog_name)
openlog(new_syslog_name, LOG_CONS | LOG_NDELAY, LOG_DAEMON); {
current_syslog_name = xstrdup(new_syslog_name);
openlog(current_syslog_name, LOG_CONS | LOG_NDELAY, LOG_DAEMON);
}
#endif #endif
} }

View file

@ -8,7 +8,9 @@
#undef LOCAL_DEBUG #undef LOCAL_DEBUG
#define _GNU_SOURCE 1 #ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -73,7 +75,7 @@ async_dump(void)
#else #else
static inline void static inline void
drop_uid(uid_t uid) drop_uid(uid_t uid UNUSED)
{ {
die("Cannot change user on this platform"); die("Cannot change user on this platform");
} }
@ -419,7 +421,7 @@ cli_get_command(cli *c)
} }
static int static int
cli_rx(sock *s, int size UNUSED) cli_rx(sock *s, uint size UNUSED)
{ {
cli_kick(s->data); cli_kick(s->data);
return 0; return 0;
@ -439,7 +441,7 @@ cli_err(sock *s, int err)
} }
static int static int
cli_connect(sock *s, int size UNUSED) cli_connect(sock *s, uint size UNUSED)
{ {
cli *c; cli *c;