mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-22 09:41:54 +00:00
Merge branch 'master' into int-new
This commit is contained in:
commit
8860e991f6
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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 */
|
||||||
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
11
doc/Makefile
11
doc/Makefile
@ -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 $<)
|
||||||
|
1175
doc/bird.sgml
1175
doc/bird.sgml
File diff suppressed because it is too large
Load Diff
12
doc/sbase/dist/birddoc/html/mapping
vendored
12
doc/sbase/dist/birddoc/html/mapping
vendored
@ -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"
|
||||||
|
21
doc/sbase/dist/birddoc/latex2e/mapping
vendored
21
doc/sbase/dist/birddoc/latex2e/mapping
vendored
@ -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>
|
||||||
|
|
||||||
|
4
doc/sbase/dist/fmt_latex2e.pl
vendored
4
doc/sbase/dist/fmt_latex2e.pl
vendored
@ -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++;
|
||||||
|
@ -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)>
|
||||||
|
135
filter/config.Y
135
filter/config.Y
@ -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'; }
|
||||||
|
175
filter/filter.c
175
filter/filter.c
@ -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);
|
||||||
{
|
{
|
||||||
|
@ -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];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
1
lib/Doc
1
lib/Doc
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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;
|
||||||
|
16
lib/buffer.h
16
lib/buffer.h
@ -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_ */
|
||||||
|
25
lib/hash.h
25
lib/hash.h
@ -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
|
||||||
|
@ -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
289
lib/mac.c
Normal 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
121
lib/mac.h
Normal 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_ */
|
81
lib/md5.c
81
lib/md5.c
@ -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);
|
|
||||||
}
|
|
||||||
|
21
lib/md5.h
21
lib/md5.h
@ -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_ */
|
||||||
|
95
lib/sha1.c
95
lib/sha1.c
@ -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);
|
|
||||||
}
|
|
||||||
|
30
lib/sha1.h
30
lib/sha1.h
@ -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_ */
|
||||||
|
150
lib/sha256.c
150
lib/sha256.c
@ -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);
|
|
||||||
}
|
|
||||||
|
42
lib/sha256.h
42
lib/sha256.h
@ -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_ */
|
||||||
|
150
lib/sha512.c
150
lib/sha512.c
@ -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);
|
|
||||||
}
|
|
||||||
|
42
lib/sha512.h
42
lib/sha512.h
@ -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_ */
|
||||||
|
@ -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 */
|
||||||
|
19
lib/string.h
19
lib/string.h
@ -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
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
135
nest/a-set.c
135
nest/a-set.c
@ -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;
|
||||||
|
}
|
||||||
|
32
nest/attrs.h
32
nest/attrs.h
@ -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
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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]])
|
||||||
|
@ -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,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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 */
|
||||||
|
@ -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);
|
||||||
|
@ -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++)
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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); }
|
||||||
|
@ -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; };
|
||||||
|
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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 */
|
||||||
|
|
||||||
|
@ -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)); })
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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); }
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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++)
|
||||||
{
|
{
|
||||||
|
@ -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 */
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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:
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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 */
|
||||||
|
@ -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;
|
||||||
|
@ -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_ */
|
||||||
|
@ -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)
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user