Merge branch 'master' into int-new

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

View file

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

View file

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

View file

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

View file

@ -577,7 +577,7 @@ cf_lex_init(int is_cli, struct config *c)
cf_lex_init_kh(); cf_lex_init_kh();
ifs_head = ifs = push_ifs(NULL); ifs_head = ifs = push_ifs(NULL);
if (!is_cli) if (!is_cli)
{ {
ifs->file_name = c->file_name; ifs->file_name = c->file_name;
ifs->fd = c->file_fd; ifs->fd = c->file_fd;

View file

@ -85,7 +85,7 @@ int undo_available; /* Undo was not requested from last reconfiguration */
* further use. Returns a pointer to the structure. * further use. Returns a pointer to the structure.
*/ */
struct config * struct config *
config_alloc(byte *name) config_alloc(const byte *name)
{ {
pool *p = rp_new(&root_pool, "Config"); pool *p = rp_new(&root_pool, "Config");
linpool *l = lp_new(p, 4080); linpool *l = lp_new(p, 4080);
@ -405,7 +405,7 @@ config_confirm(void)
* if it's been queued due to another reconfiguration being in progress now, * if it's been queued due to another reconfiguration being in progress now,
* %CONF_UNQUEUED if a scheduled reconfiguration is removed, %CONF_NOTHING * %CONF_UNQUEUED if a scheduled reconfiguration is removed, %CONF_NOTHING
* if there is no relevant configuration to undo (the previous config request * if there is no relevant configuration to undo (the previous config request
* was config_undo() too) or %CONF_SHUTDOWN if BIRD is in shutdown mode and * was config_undo() too) or %CONF_SHUTDOWN if BIRD is in shutdown mode and
* no new configuration changes are accepted. * no new configuration changes are accepted.
*/ */
int int
@ -450,7 +450,7 @@ config_undo(void)
extern void cmd_reconfig_undo_notify(void); extern void cmd_reconfig_undo_notify(void);
static void static void
config_timeout(struct timer *t) config_timeout(struct timer *t UNUSED)
{ {
log(L_INFO "Config timeout expired, starting undo"); log(L_INFO "Config timeout expired, starting undo");
cmd_reconfig_undo_notify(); cmd_reconfig_undo_notify();
@ -530,7 +530,7 @@ cf_error(const char *msg, ...)
* and we want to preserve it for further use. * and we want to preserve it for further use.
*/ */
char * char *
cfg_strdup(char *c) cfg_strdup(const char *c)
{ {
int l = strlen(c) + 1; int l = strlen(c) + 1;
char *z = cfg_allocu(l); char *z = cfg_allocu(l);

View file

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

View file

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

View file

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

View file

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

File diff suppressed because it is too large Load diff

View file

@ -6,7 +6,7 @@
% Based on qwertz replacement file by Tom Gordon % Based on qwertz replacement file by Tom Gordon
% linuxdoc mods by mdw % linuxdoc mods by mdw
% Groff dependencies are few. To port to another roff: % Groff dependencies are few. To port to another roff:
% 1. Check and modify, if necessary, font changes. (e.g. In psroff the % 1. Check and modify, if necessary, font changes. (e.g. In psroff the
% same fonts have other names.) % same fonts have other names.)
% 2. Check the code for including Encapsulated PostScript, generated % 2. Check the code for including Encapsulated PostScript, generated
@ -19,13 +19,13 @@
% Hacked by mdw % Hacked by mdw
".nr PI 3n\n" ".nr PI 3n\n"
".ds CF \\\\n\%\n" ".ds CF \\\\n\%\n"
".ds CH \\&\n" ".ds CH \\&\n"
".ds dR $\n" % dollar, to avoid EQN conflicts ".ds dR $\n" % dollar, to avoid EQN conflicts
% Start with no TOC % Start with no TOC
".ds printtoc\n" ".ds printtoc\n"
% Footnote style % Footnote style
".nr FF 1\n" ".nr FF 1\n"
@ -51,16 +51,16 @@
".nr HM 0i\n" ".nr HM 0i\n"
".nr FM 0i\n" ".nr FM 0i\n"
% Turn off right-margin filling % Turn off right-margin filling
".na\n" ".na\n"
% h is 1 if first paragraph after heading % h is 1 if first paragraph after heading
".nr h 0\n" ".nr h 0\n"
% initialize heading level % initialize heading level
".nr il 1\n" ".nr il 1\n"
% Number registers for list % Number registers for list
@ -68,20 +68,20 @@
".nr ll 0\n" % list level, stores current level ".nr ll 0\n" % list level, stores current level
".nr el 0\n" % current enumeration level ".nr el 0\n" % current enumeration level
% Not all list levels are enumerations, as % Not all list levels are enumerations, as
% itemizations can be embedded within enumerations % itemizations can be embedded within enumerations
% and vice versa % and vice versa
% type of list level is in \n(t\n(ll, where % type of list level is in \n(t\n(ll, where
% 0 : itemize, 1 : enumerate, 2: description % 0 : itemize, 1 : enumerate, 2: description
% enumerator for an enumeration level is in % enumerator for an enumeration level is in
% \n(e\n(el -- i.e. \n(e1=2 means current item of % \n(e\n(el -- i.e. \n(e1=2 means current item of
% enumeration level 1 is 2 % enumeration level 1 is 2
% context-sensitive paragraph macro % context-sensitive paragraph macro
% Bug: There's some problem using this to re-start paragraphs after the % Bug: There's some problem using this to re-start paragraphs after the
% </verb> and </code>, so after verb and code I insert .LP. That's fine % </verb> and </code>, so after verb and code I insert .LP. That's fine
% except that is loses indentation when using verb or code inside of a list. % except that is loses indentation when using verb or code inside of a list.
@ -95,21 +95,21 @@
% for this enumeration level % for this enumeration level
".if \\\\n(t\\\\n(ll=1 \\{.IP \\\\n+(e\\\\n(el.\\}\n" ".if \\\\n(t\\\\n(ll=1 \\{.IP \\\\n+(e\\\\n(el.\\}\n"
% if first par element of descrip, do nothing % if first par element of descrip, do nothing
".\\}\n" ".\\}\n"
".el .sp \n" % subsequent par element of item ".el .sp \n" % subsequent par element of item
".\\}\n" ".\\}\n"
".el \\{\\\n" % not within list ".el \\{\\\n" % not within list
".ie \\\\nh=1 \\{\\\n" % first par after heading ".ie \\\\nh=1 \\{\\\n" % first par after heading
".LP\n" ".LP\n"
".nr h 0\n" % reset h flag ".nr h 0\n" % reset h flag
".\\}\n" ".\\}\n"
".el .LP \n" % Changed from .PP, mdw ".el .LP \n" % Changed from .PP, mdw
".\\}\n" ".\\}\n"
".nh\n" ".nh\n"
"..\n" "..\n"
% for each level, a number register is created % for each level, a number register is created
% to store its type and current item number, where % to store its type and current item number, where
% -1=bullet of an itemized list. % -1=bullet of an itemized list.
@ -141,7 +141,7 @@
% set initial level of headings, in register il % set initial level of headings, in register il
<article> + ".nr il 0" + <article> + ".nr il 0" +
</article> + ".if '\\*[printtoc]'true' .PX\n" </article> + ".if '\\*[printtoc]'true' .PX\n"
<report> + ".nr il 1" + <report> + ".nr il 1" +
</report> + ".bp\n" </report> + ".bp\n"
@ -153,23 +153,23 @@
".bp\n" ".bp\n"
".TC" + ".TC" +
<notes> <notes>
</notes> </notes>
<manpage> + ".nr il -1" + <manpage> + ".nr il -1" +
</manpage> </manpage>
<progdoc> <progdoc>
</progdoc> </progdoc>
% Hacked up titlepag stuff to look more reasonable. Titles and author % Hacked up titlepag stuff to look more reasonable. Titles and author
% names are now stored in strings, printed by the end of </titlepag>. % names are now stored in strings, printed by the end of </titlepag>.
% Wake up! This uses groff-like long string names. You must use groff % Wake up! This uses groff-like long string names. You must use groff
% to format this. % to format this.
<titlepag> + ".ds mdwtitle\n" <titlepag> + ".ds mdwtitle\n"
".ds mdwsubtitle\n" ".ds mdwsubtitle\n"
".ds mdwdate\n" ".ds mdwdate\n"
".de printabstract\n" ".de printabstract\n"
"..\n" + "..\n" +
</titlepag> + "\\*[mdwtitle]\n" </titlepag> + "\\*[mdwtitle]\n"
@ -181,10 +181,10 @@
"\\*[mdwdate]\n" "\\*[mdwdate]\n"
".br\n" ".br\n"
".printabstract\n" ".printabstract\n"
".br\n" ".br\n"
%<title> + ".TL" + %<title> + ".TL" +
%</title> %</title>
<title> + ".ds mdwtitle " <title> + ".ds mdwtitle "
</title> + </title> +
@ -194,13 +194,13 @@
% ".SM" + % ".SM" +
%</subtitle> + ".LG" + %</subtitle> + ".LG" +
<subtitle> + ".ds mdwsubtitle " <subtitle> + ".ds mdwsubtitle "
</subtitle> + </subtitle> +
<date> + ".ds mdwdate " <date> + ".ds mdwdate "
</date> + </date> +
<abstract> + ".de printabstract\n" <abstract> + ".de printabstract\n"
".LP\n" ".LP\n"
</abstract> + ".." + </abstract> + ".." +
@ -215,10 +215,10 @@
<name> + ".br" + <name> + ".br" +
</name> </name>
<and> <and>
</and> </and>
<thanks> "\\**\n" <thanks> "\\**\n"
".FS" + ".FS" +
</thanks> + ".FE" + </thanks> + ".FE" +
@ -229,11 +229,11 @@
<newline> + ".br" <newline> + ".br"
</newline> </newline>
<label> <label>
</label> </label>
<header> <header>
</header> </header>
<lhead> + ".EH '" <lhead> + ".EH '"
</lhead> "'''" + </lhead> "'''" +
@ -263,13 +263,13 @@
<toc> <toc>
</toc> </toc>
<lof> <lof>
</lof> </lof>
<lot> <lot>
</lot> </lot>
<chapt> + ".bp\n" <chapt> + ".bp\n"
".NH \\n(il " + ".NH \\n(il " +
</chapt> </chapt>
@ -283,7 +283,7 @@
</sect2> </sect2>
<sect3> + ".NH 4+\\n(il" + <sect3> + ".NH 4+\\n(il" +
</sect3> </sect3>
<sect4> + ".NH 5+\\n(il" + <sect4> + ".NH 5+\\n(il" +
</sect4> </sect4>
@ -292,10 +292,10 @@
</heading> + "\\*h\n" </heading> + "\\*h\n"
".XS \\n%\n" ".XS \\n%\n"
"\\*(SN \\*h\n" "\\*(SN \\*h\n"
".XE\n" ".XE\n"
".nr h 1\n" % set heading flag to true ".nr h 1\n" % set heading flag to true
<p> + ".Pp" + <p> + ".Pp" +
</p> </p>
<itemize> + ".nr ll +1\n" % increment list level <itemize> + ".nr ll +1\n" % increment list level
@ -309,9 +309,9 @@
".af e\\n(el \\*(f\\n(el\n" % style of enumerator ".af e\\n(el \\*(f\\n(el\n" % style of enumerator
".if \\n(ll>1 .RS" + ".if \\n(ll>1 .RS" +
</enum> + ".if \\n(ll>1 .RE\n" </enum> + ".if \\n(ll>1 .RE\n"
".br\n" ".br\n"
".nr el -1\n" % decrement enumeration level ".nr el -1\n" % decrement enumeration level
".nr ll -1\n" % decrement list level ".nr ll -1\n" % decrement list level
<descrip> + ".RS\n" <descrip> + ".RS\n"
".nr ll +1\n" % increment list level ".nr ll +1\n" % increment list level
@ -324,7 +324,7 @@
% If bi=1 then the paragraph is the first one of the item. % If bi=1 then the paragraph is the first one of the item.
<item> + ".nr bi 1\n.Pp" + <item> + ".nr bi 1\n.Pp" +
</item> </item>
<tag> + ".IP \"\\fB" <tag> + ".IP \"\\fB"
</tag> "\\fR\"\n" </tag> "\\fR\"\n"
@ -337,12 +337,12 @@
</cf> "" </cf> ""
<cite> + ".\[\n[ID]\n.\]" + <cite> + ".\[\n[ID]\n.\]" +
</cite> </cite>
<ncite> + ".\[\n[ID]\n.\]\n([NOTE])" <ncite> + ".\[\n[ID]\n.\]\n([NOTE])"
</ncite> </ncite>
<footnote> " (-- " <footnote> " (-- "
</footnote> "--)" + </footnote> "--)" +
<sq> "\\*Q" <sq> "\\*Q"
@ -353,20 +353,20 @@
</lq> + ".nr LL \\n(LL+\\n(PI\n" </lq> + ".nr LL \\n(LL+\\n(PI\n"
".RE" + ".RE" +
<em> "\\fI" <em> "\\fI"
</em> "\\fP" </em> "\\fP"
<bf> "\\fB" <bf> "\\fB"
</bf> "\\fR" </bf> "\\fR"
<it> "\\fI" <it> "\\fI"
</it> "\\fR" </it> "\\fR"
<sf> "\\fR" <sf> "\\fR"
</sf> "\\fR" </sf> "\\fR"
<sl> "\\fI" <sl> "\\fI"
</sl> "\\fR" </sl> "\\fR"
% Changed by mdw % Changed by mdw
<tt> "\\fC" <tt> "\\fC"
@ -394,10 +394,10 @@
<pageref> "??" <pageref> "??"
</pageref> </pageref>
<x> <x>
</x> </x>
<mc> <mc>
</mc> </mc>
<biblio> + ".\[\n" <biblio> + ".\[\n"
@ -423,7 +423,7 @@
% ".Pp" + % continue previous paragraph (changed mdw) % ".Pp" + % continue previous paragraph (changed mdw)
".LP" ".LP"
% tscreen added by mdw % tscreen added by mdw
<tscreen> + ".br\n" <tscreen> + ".br\n"
".po 0.75i\n" ".po 0.75i\n"
".ll 6.0i\n" ".ll 6.0i\n"
@ -487,8 +487,8 @@
% mathematics -- this nroff version needs work. % mathematics -- this nroff version needs work.
<f> <f>
</f> </f>
<dm> + ".DS L" + <dm> + ".DS L" +
</dm> + ".DE" + </dm> + ".DE" +
@ -496,8 +496,8 @@
<eq> + ".DS L" + <eq> + ".DS L" +
</eq> + ".DE" + </eq> + ".DE" +
<fr> <fr>
</fr> </fr>
<nu> "{" <nu> "{"
</nu> "} over " </nu> "} over "
@ -505,7 +505,7 @@
<de> "{" <de> "{"
</de> "}" </de> "}"
<lim> <lim>
</lim> </lim>
<op> <op>
@ -527,7 +527,7 @@
</in> </in>
<sum> " sum " <sum> " sum "
</sum> </sum>
% limitation: eqn only does square roots! % limitation: eqn only does square roots!
@ -539,7 +539,7 @@
"[ca]." + "[ca]." +
</ar> + ".TE" + </ar> + ".TE" +
<arr> "\n" <arr> "\n"
</arr> </arr>
<arc> "|" <arc> "|"
@ -567,8 +567,8 @@
% limitation: no calligraphic characters, using helvetica italics instead. Is there a better font? % limitation: no calligraphic characters, using helvetica italics instead. Is there a better font?
<fi> "\\fI" <fi> "\\fI"
</fi> "\\fP" </fi> "\\fP"
<phr> " roman }" <phr> " roman }"
</phr> "}" </phr> "}"
@ -584,12 +584,12 @@
<eps> + ".if t .PSPIC [file].ps\n" <eps> + ".if t .PSPIC [file].ps\n"
".if n .sp 4" + ".if n .sp 4" +
</eps> </eps>
% Are TeX units properly handled by this translation of ph? % Are TeX units properly handled by this translation of ph?
<ph> + ".sp [VSPACE]" + <ph> + ".sp [VSPACE]" +
</ph> </ph>
<caption> + ".sp\n.ce" + <caption> + ".sp\n.ce" +
</caption> </caption>
@ -619,7 +619,7 @@
<slides> + ".nr PS 18" + <slides> + ".nr PS 18" +
</slides> </slides>
<slide> <slide>
</slide> + ".bp\n\\&" + </slide> + ".bp\n\\&" +
% letters -- replacement for email, using mh format. % letters -- replacement for email, using mh format.

View file

@ -21,7 +21,7 @@
</notes> + "<@@enddoc>" + </notes> + "<@@enddoc>" +
% Manual Pages are expected to be formatted using nroff (or groff), unless % Manual Pages are expected to be formatted using nroff (or groff), unless
% they are included as sections of other qwertz documents. % they are included as sections of other qwertz documents.
<manpage> <manpage>
</manpage> </manpage>
@ -35,7 +35,7 @@
<title> + "<@@title>" <title> + "<@@title>"
</title> </title>
<subtitle> + "<H2>" <subtitle> + "<H2>"
</subtitle> "</H2>" + </subtitle> "</H2>" +
<author> <author>
@ -48,26 +48,27 @@
</and> </and>
<thanks> + "Thanks " <thanks> + "Thanks "
</thanks> </thanks>
<inst> + "<H3>" <inst> + "<H3>"
</inst> "</H3>" + </inst> "</H3>" +
<newline> "<BR>" <newline> "<BR>"
<label> + "<@@label>[ID]" + <label> + "<@@label>[ID]" +
</label>
<header>
</header> <header>
</header>
<lhead> + "<!-- " <lhead> + "<!-- "
</lhead> " -->" + </lhead> " -->" +
<rhead> + "<!-- " <rhead> + "<!-- "
</rhead> " -->" + </rhead> " -->" +
<comment> + "<H4>Comment</H4>" + <comment> + "<H4>Comment</H4>" +
</comment> </comment>
<abstract> + "<P><HR>\n<EM>" <abstract> + "<P><HR>\n<EM>"
</abstract> "</EM>\n<HR>" + </abstract> "</EM>\n<HR>" +
@ -99,7 +100,7 @@
<sect3> + "<@@head>" <sect3> + "<@@head>"
</sect3> </sect3>
<sect4> + "<@@head>" <sect4> + "<@@head>"
</sect4> </sect4>
<heading> <heading>
@ -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,12 +202,14 @@
"<@@endurl>" + "<@@endurl>" +
</url> </url>
<htmlurl> + "<@@url>[URL]\n" <htmlurl> "<A HREF=\"[URL]\">[NAME]</A>"
"[NAME]</A>\n"
"<@@endurl>" +
</htmlurl> </htmlurl>
% ref modified to have an optional name field <rfc> "<A HREF=\"http://www.rfc-editor.org/info/rfc[ID]\">RFC [ID]</A>"
</rfc>
% ref modified to have an optional name field
<ref> + "<@@ref>[ID]\n" <ref> + "<@@ref>[ID]\n"
"[NAME]</A>\n" "[NAME]</A>\n"
"<@@endref>" + "<@@endref>" +
@ -228,7 +234,7 @@
</mc> "</MC>" </mc> "</MC>"
<biblio> + "<BIBLIO STYLE=\"[STYLE]\" FILES=\"[FILES]\">" + <biblio> + "<BIBLIO STYLE=\"[STYLE]\" FILES=\"[FILES]\">" +
</biblio> </biblio>
<code> + "<HR>\n<PRE>" + <code> + "<HR>\n<PRE>" +
</code> + "</PRE>\n<HR>" + </code> + "</PRE>\n<HR>" +
@ -244,28 +250,28 @@
% theorems and such % theorems and such
<def> + "<DEF>" <def> + "<DEF>"
</def> + "</DEF>" + </def> + "</DEF>" +
<prop> + "<PROP>" <prop> + "<PROP>"
</prop> + "</PROP>" + </prop> + "</PROP>" +
<lemma> + "<LEMMA>" <lemma> + "<LEMMA>"
</lemma> + "</LEMMA>" + </lemma> + "</LEMMA>" +
<coroll> + "<COROLL>" <coroll> + "<COROLL>"
</coroll> + "</COROLL>" + </coroll> + "</COROLL>" +
<proof> + "<PROOF>" <proof> + "<PROOF>"
</proof> + "</PROOF>" + </proof> + "</PROOF>" +
<theorem> + "<THEOREM>" <theorem> + "<THEOREM>"
</theorem> + "</THEOREM>" + </theorem> + "</THEOREM>" +
<thtag> "<THTAG>" <thtag> "<THTAG>"
</thtag> "</THTAG>" </thtag> "</THTAG>"
% mathematics % mathematics
<f> <f>
</f> </f>
@ -315,11 +321,11 @@
<ar> "<AR>" <ar> "<AR>"
</ar> "</AR>" </ar> "</AR>"
<arr> "<ARR>" <arr> "<ARR>"
</arr> </arr>
<arc> "<ARC>" <arc> "<ARC>"
</arc> </arc>
<sup> "<SUP>" <sup> "<SUP>"
</sup> "</SUP>" </sup> "</SUP>"
@ -354,13 +360,13 @@
</figure> + "</FIGURE>" + </figure> + "</FIGURE>" +
<eps> + "<EPS FILE=\"[FILE]\">" + <eps> + "<EPS FILE=\"[FILE]\">" +
</eps> </eps>
<img> + "<IMG SRC=\"[SRC]\">" + <img> + "<IMG SRC=\"[SRC]\">" +
</img> </img>
<ph> + "<PH VSPACE=\"[VSPACE]\">" + <ph> + "<PH VSPACE=\"[VSPACE]\">" +
</ph> </ph>
<caption> + "<CAPTION>" <caption> + "<CAPTION>"
</caption> "</CAPTION>" + </caption> "</CAPTION>" +
@ -403,7 +409,7 @@
</opening> "</OPENING>" + </opening> "</OPENING>" +
<from> + "<FROM>" <from> + "<FROM>"
</from> + "</FROM>" + </from> + "</FROM>" +
@ -419,7 +425,7 @@
<email> + "<EMAIL>" <email> + "<EMAIL>"
</email> "</EMAIL>" + </email> "</EMAIL>" +
<phone> + "<PHONE>" <phone> + "<PHONE>"
</phone> "</PHONE>" + </phone> "</PHONE>" +
@ -430,16 +436,16 @@
</subject> "</SUBJECT>" + </subject> "</SUBJECT>" +
<sref> + "<SREF>" <sref> + "<SREF>"
</sref> "</SREF>" + </sref> "</SREF>" +
<rref> + "<RREF>" <rref> + "<RREF>"
</rref> "</RREF>" + </rref> "</RREF>" +
<rdate> + "<RDATE>" <rdate> + "<RDATE>"
</rdate> "</RDATE>" + </rdate> "</RDATE>" +
<closing> + "<CLOSING>" <closing> + "<CLOSING>"
</closing> "</CLOSING>" + </closing> "</CLOSING>" +
<cc> + "<CC>" <cc> + "<CC>"

View file

@ -2,7 +2,9 @@
% birddoc to LaTeX replacement file % birddoc to LaTeX replacement file
% The \relax is there to avoid sgml2latex rewriting the class % The \relax is there to avoid sgml2latex rewriting the class
<book> + "\\relax\\documentclass\[a4paper,10pt,openany\]{book}\n" <book> + "\\relax\\documentclass\[a4paper,10pt,openany,oneside\]{book}\n"
"\\usepackage\[colorlinks=true,linkcolor=blue,pdftitle={BIRD User's Guide}\]{hyperref}\n"
"\\usepackage{enumitem}\n"
"\\usepackage{birddoc}\n" "\\usepackage{birddoc}\n"
"\\usepackage{qwertz}\n" "\\usepackage{qwertz}\n"
"\\usepackage{url}\n" "\\usepackage{url}\n"
@ -14,7 +16,7 @@
</book> + "\\end{document}" + </book> + "\\end{document}" +
% Manual Pages are expected to be formatted using nroff (or groff), unless % Manual Pages are expected to be formatted using nroff (or groff), unless
% they are included as sections of other qwertz documents. % they are included as sections of other qwertz documents.
<manpage> <manpage>
</manpage> </manpage>
@ -26,17 +28,17 @@
</titlepag> + "\n\n\\begin{document}\n" </titlepag> + "\n\n\\begin{document}\n"
"\\maketitle\n" + "\\maketitle\n" +
<title> + "\\title{" <title> + "\\title{"
</title> "}" + </title> "}" +
<subtitle> "\\\\\n" <subtitle> "\\\\\n"
"{\\large " "{\\large "
</subtitle> "}" + </subtitle> "}" +
<author> + "\\author{" <author> + "\\author{"
</author> "}" + </author> "}" +
<name> <name>
</name> </name>
<and> "\\and " + <and> "\\and " +
@ -51,14 +53,14 @@
<date> + "\\date{" <date> + "\\date{"
</date> "}" + </date> "}" +
<newline> "\\\\ " <newline> "\\\\ "
</newline> </newline>
<label> "\\label{[ID]}" <label> "\\label{[ID]}"
</label> </label>
<header> + "\\markboth" <header> + "\\markboth"
</header> </header>
<lhead> "{" <lhead> "{"
</lhead> "}" </lhead> "}"
@ -73,7 +75,7 @@
</comment> "}" </comment> "}"
% Hacked by mdw to use linuxdoc-sgml \abstract{...} % Hacked by mdw to use linuxdoc-sgml \abstract{...}
<abstract> + "\\abstract{" <abstract> + "\\abstract{"
</abstract> "}" + </abstract> "}" +
<appendix> + "\n \\appendix \n" + <appendix> + "\n \\appendix \n" +
@ -101,15 +103,15 @@
</sect2> </sect2>
<sect3> + "\n\\paragraph" <sect3> + "\n\\paragraph"
</sect3> </sect3>
<sect4> + "\n\\subparagraph" <sect4> + "\n\\subparagraph"
</sect4> </sect4>
<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,29 +225,32 @@
<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>
<x> <rfc> "\\href{http://www.rfc-editor.org/info/rfc[ID]}{RFC [ID]}"
</rfc>
<x>
</x> </x>
<mc> <mc>
</mc> </mc>
<biblio> + "\\bibliographystyle{[STYLE]}\n" <biblio> + "\\bibliographystyle{[STYLE]}\n"
"\\bibliography{[FILES]}\n" "\\bibliography{[FILES]}\n"
"\\addbibtoc{}" + "\\addbibtoc{}" +
</biblio> </biblio>
% <macro> + "\\macro{[ID]}{\\qw[ID]}" % <macro> + "\\macro{[ID]}{\\qw[ID]}"
% </macro> % </macro>
@ -300,19 +305,19 @@
<thtag> "\[" <thtag> "\["
</thtag> "\]" + </thtag> "\]" +
% mathematics % mathematics
<f> "$" <f> "$"
</f> "$" </f> "$"
<dm> + "\\\[" <dm> + "\\\["
</dm> "\\\]" + </dm> "\\\]" +
<eq> + "\\begin{equation}" + <eq> + "\\begin{equation}" +
</eq> + "\\end{equation}\n" + </eq> + "\\end{equation}\n" +
<fr> "\\frac" <fr> "\\frac"
</fr> </fr>
<nu> "{" <nu> "{"
</nu> "}" </nu> "}"
@ -320,7 +325,7 @@
<de> "{" <de> "{"
</de> "}" </de> "}"
<lim> <lim>
</lim> </lim>
<op> <op>
@ -342,7 +347,7 @@
</in> </in>
<sum> "\\sum" <sum> "\\sum"
</sum> </sum>
<root> "\\sqrt\[[n]\]{" <root> "\\sqrt\[[n]\]{"
</root> "}" </root> "}"
@ -390,11 +395,11 @@
</figure> + "\\end{figure}\n" + </figure> + "\\end{figure}\n" +
<eps> + "\\centerline{\\epsfig{file=[FILE],height=[HEIGHT],angle=[ANGLE]}}" + <eps> + "\\centerline{\\epsfig{file=[FILE],height=[HEIGHT],angle=[ANGLE]}}" +
</eps> </eps>
<ph> + "\\vspace{[VSPACE]}\n\\par" + <ph> + "\\vspace{[VSPACE]}\n\\par" +
</ph> </ph>
<caption> + "\\caption{" <caption> + "\\caption{"
</caption> "}" + </caption> "}" +

View file

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

View file

@ -1,6 +1,6 @@
<!-- This is a DTD, but will be read as -*- sgml -*- --> <!-- This is a DTD, but will be read as -*- sgml -*- -->
<!-- ================================================= --> <!-- ================================================= -->
<!-- $Id$ <!-- $Id$
This was heavilly modified for use with bird! Don't you dare to use it This was heavilly modified for use with bird! Don't you dare to use it
anywhere else. <pavel@ucw.cz> anywhere else. <pavel@ucw.cz>
@ -79,7 +79,7 @@ anywhere else. <pavel@ucw.cz>
weren't in the original linuxdoc 1.3 DTD, and are weren't in the original linuxdoc 1.3 DTD, and are
superseded by the new if/unless facility. --> superseded by the new if/unless facility. -->
<!-- BK/97/05/09: this is the original Linuxdoc DTD, <!-- BK/97/05/09: this is the original Linuxdoc DTD,
as of SGML Tools 0.99.0. It is not longer as of SGML Tools 0.99.0. It is not longer
supported. Use only if in dire need, for backwards supported. Use only if in dire need, for backwards
compabitlity. Backend support for undocumented compabitlity. Backend support for undocumented
QWERTZ leftovers not in the strict Linuxdoc DTD's QWERTZ leftovers not in the strict Linuxdoc DTD's
@ -92,36 +92,36 @@ anywhere else. <pavel@ucw.cz>
any changes to this, just replacing. --> any changes to this, just replacing. -->
<!-- ================================================= --> <!-- ================================================= -->
<!entity % emph <!entity % emph
" em|it|bf|sf|sl|tt|cf|m|cparam|const|func|struct|param|type|funcdef " > " em|it|bf|sf|sl|tt|cf|m|cparam|const|func|struct|param|type|funcdef " >
<!entity % index "idx|cdx|nidx|ncdx" > <!entity % index "idx|cdx|nidx|ncdx" >
<!-- 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 )* " >
<!entity % list <!entity % list
" list | itemize | enum | descrip " > " list | itemize | enum | descrip " >
<!entity % par <!entity % par
" %list; | comment | lq | quote | tscreen | hrule " > " %list; | comment | lq | quote | tscreen | hrule " >
<!entity % mathpar " dm | eq " > <!entity % mathpar " dm | eq " >
<!entity % thrm <!entity % thrm
" def | prop | lemma | coroll | proof | theorem " > " def | prop | lemma | coroll | proof | theorem " >
<!entity % litprog " code | verb " > <!entity % litprog " code | verb " >
<!entity % sectpar <!entity % sectpar
" %par; | figure | tabular | table | %mathpar; | " %par; | figure | tabular | table | %mathpar; |
%thrm; | %litprog; | function "> %thrm; | %litprog; | function ">
<!element birddoc o o <!element birddoc o o
(sect | chapt | article | report | (sect | chapt | article | report |
book | letter | telefax | slides | notes | manpage ) > book | letter | telefax | slides | notes | manpage ) >
<!-- `general' entity replaced with ISO entities - kwm --> <!-- `general' entity replaced with ISO entities - kwm -->
@ -150,7 +150,7 @@ anywhere else. <pavel@ucw.cz>
<!element hrule - - EMPTY> <!element hrule - - EMPTY>
<!shortref pmap <!shortref pmap
"&#RS;B" null "&#RS;B" null
"&#RS;B&#RE;" psplit "&#RS;B&#RE;" psplit
"&#RS;&#RE;" psplit "&#RS;&#RE;" psplit
-- '"' qtag -- -- '"' qtag --
@ -189,7 +189,7 @@ anywhere else. <pavel@ucw.cz>
<!entity ftag '<f>' -- formula begin -- > <!entity ftag '<f>' -- formula begin -- >
<!entity qendtag '</sq>'> <!entity qendtag '</sq>'>
<!shortref sqmap <!shortref sqmap
"&#RS;B" null "&#RS;B" null
-- '"' qendtag -- -- '"' qendtag --
"[" lsqb "[" lsqb
@ -249,7 +249,7 @@ anywhere else. <pavel@ucw.cz>
<!shortref bodymap <!shortref bodymap
"&#RS;B&#RE;" ptag "&#RS;B&#RE;" ptag
"&#RS;&#RE;" ptag "&#RS;&#RE;" ptag
'"' qtag '"' qtag
"[" lsqb "[" lsqb
"~" nbsp "~" nbsp
"_" lowbar "_" lowbar
@ -285,7 +285,7 @@ anywhere else. <pavel@ucw.cz>
<!shortref oneline <!shortref oneline
"B&#RE;" space "B&#RE;" space
"&#RS;&#RE;" null "&#RS;&#RE;" null
"&#RS;B&#RE;" null "&#RS;B&#RE;" null
-- '"' qtag -- -- '"' qtag --
"[" ftag "[" ftag
@ -302,7 +302,7 @@ anywhere else. <pavel@ucw.cz>
<!usemap oneline caption> <!usemap oneline caption>
<!entity % tabrow "(%inline, (colsep, %inline)*)" > <!entity % tabrow "(%inline, (colsep, %inline)*)" >
<!element tabular - - <!element tabular - -
(hline?, %tabrow, (rowsep, hline?, %tabrow)*, caption?) > (hline?, %tabrow, (rowsep, hline?, %tabrow)*, caption?) >
<!attlist tabular <!attlist tabular
@ -323,7 +323,7 @@ anywhere else. <pavel@ucw.cz>
"B&#RE;" null "B&#RE;" null
"BB" space "BB" space
"@" rowsep "@" rowsep
"|" colsep "|" colsep
"[" ftag "[" ftag
-- '"' qtag -- -- '"' qtag --
"_" thinsp "_" thinsp
@ -344,7 +344,7 @@ anywhere else. <pavel@ucw.cz>
<!shortref ttmap -- also on one-line -- <!shortref ttmap -- also on one-line --
"B&#RE;" space "B&#RE;" space
"&#RS;&#RE;" null "&#RS;&#RE;" null
"&#RS;B&#RE;" null "&#RS;B&#RE;" null
"&#RS;B" null "&#RS;B" null
'#' num '#' num
@ -365,14 +365,14 @@ anywhere else. <pavel@ucw.cz>
<!entity % limits "pr|in|sum" > <!entity % limits "pr|in|sum" >
<!entity % fbu "fr|lim|ar|root" > <!entity % fbu "fr|lim|ar|root" >
<!entity % fph "unl|ovl|sup|inf" > <!entity % fph "unl|ovl|sup|inf" >
<!entity % fbutxt "(%fbu;) | (%limits;) | <!entity % fbutxt "(%fbu;) | (%limits;) |
(%fcstxt;)|(%fscs;)|(%fph;)" > (%fcstxt;)|(%fscs;)|(%fph;)" >
<!entity % fphtxt "p|#pcdata" > <!entity % fphtxt "p|#pcdata" >
<!element f - - ((%fbutxt;)*) > <!element f - - ((%fbutxt;)*) >
<!entity fendtag '</f>' -- formula end -- > <!entity fendtag '</f>' -- formula end -- >
<!shortref fmap <!shortref fmap
"&#RS;B" null "&#RS;B" null
"&#RS;B&#RE;" null "&#RS;B&#RE;" null
"&#RS;&#RE;" null "&#RS;&#RE;" null
@ -432,7 +432,7 @@ anywhere else. <pavel@ucw.cz>
<!shortref arrmap <!shortref arrmap
"&#RE;" space "&#RE;" space
"@" arr "@" arr
"|" arc "|" arc
"_" thinsp "_" thinsp
"~" nbsp "~" nbsp
"#" num "#" num
@ -448,7 +448,7 @@ anywhere else. <pavel@ucw.cz>
<!element ovl - - ((%fbutxt;)*) > <!element ovl - - ((%fbutxt;)*) >
<!element rf - o (#pcdata) > <!element rf - o (#pcdata) >
<!element phr - o ((%fphtxt;)*) > <!element phr - o ((%fphtxt;)*) >
<!element v - o ((%fcstxt;)*) <!element v - o ((%fcstxt;)*)
-(tu|%limits;|%fbu;|%fph;) > -(tu|%limits;|%fbu;|%fph;) >
<!element fi - o (#pcdata) > <!element fi - o (#pcdata) >
<!element tu - o empty > <!element tu - o empty >
@ -468,7 +468,7 @@ anywhere else. <pavel@ucw.cz>
<!shortref global <!shortref global
"&#RS;B" null -- delete leading blanks -- "&#RS;B" null -- delete leading blanks --
-- '"' qtag -- -- '"' qtag --
"[" ftag "[" ftag
"~" nbsp "~" nbsp
"_" lowbar "_" lowbar
@ -485,22 +485,26 @@ anywhere else. <pavel@ucw.cz>
<!-- ref modified to have an optional name field HG --> <!-- ref modified to have an optional name field HG -->
<!element ref - o empty> <!element ref - o empty>
<!attlist ref <!attlist ref
id cdata #required id cdata #required
name cdata "&refnam"> name cdata "&refnam">
<!-- url entity added to have direct url references HG --> <!-- url entity added to have direct url references HG -->
<!element url - o empty> <!element url - o empty>
<!attlist url <!attlist url
url cdata #required url cdata #required
name cdata "&urlnam" > name cdata "&urlnam" >
<!-- htmlurl entity added to have quieter url references esr --> <!-- htmlurl entity added to have quieter url references esr -->
<!element htmlurl - o empty> <!element htmlurl - o empty>
<!attlist htmlurl <!attlist htmlurl
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>
@ -510,22 +514,22 @@ anywhere else. <pavel@ucw.cz>
<!-- Hacked by mdw to exclude abstract; abstract now part of titlepag --> <!-- Hacked by mdw to exclude abstract; abstract now part of titlepag -->
<!element article - - <!element article - -
(titlepag, header?, (titlepag, header?,
toc?, lof?, lot?, p*, sect*, toc?, lof?, lot?, p*, sect*,
(appendix, sect+)?, biblio?) +(footnote)> (appendix, sect+)?, biblio?) +(footnote)>
<!attlist article <!attlist article
opts cdata "null"> opts cdata "null">
<!-- Hacked by mdw to exclude abstract; abstract now part of titlepag --> <!-- Hacked by mdw to exclude abstract; abstract now part of titlepag -->
<!element report - - <!element report - -
(titlepag, header?, toc?, lof?, lot?, p*, (titlepag, header?, toc?, lof?, lot?, p*,
chapt*, (appendix, chapt+)?, biblio?) +(footnote)> chapt*, (appendix, chapt+)?, biblio?) +(footnote)>
<!attlist report <!attlist report
opts cdata "null"> opts cdata "null">
<!element book - - <!element book - -
(titlepag, header?, toc?, lof?, lot?, p*, chapt*, (titlepag, header?, toc?, lof?, lot?, p*, chapt*,
(appendix, chapt+)?, biblio?) +(footnote) > (appendix, chapt+)?, biblio?) +(footnote) >
<!attlist book <!attlist book
@ -536,7 +540,7 @@ anywhere else. <pavel@ucw.cz>
<!element title - o (%inline, subtitle?) +(newline)> <!element title - o (%inline, subtitle?) +(newline)>
<!element subtitle - o (%inline)> <!element subtitle - o (%inline)>
<!usemap oneline titlepag> <!usemap oneline titlepag>
<!element author - o (name, thanks?, inst?, <!element author - o (name, thanks?, inst?,
(and, name, thanks?, inst?)*)> (and, name, thanks?, inst?)*)>
<!element name o o (%inline) +(newline)> <!element name o o (%inline) +(newline)>
<!element and - o empty> <!element and - o empty>
@ -545,9 +549,9 @@ anywhere else. <pavel@ucw.cz>
<!element date - o (#pcdata) > <!element date - o (#pcdata) >
<!usemap global thanks> <!usemap global thanks>
<!element newline - o empty > <!element newline - o empty >
<!entity nl "<newline>"> <!entity nl "<newline>">
<!element progdoc - o empty> <!element progdoc - o empty>
@ -564,9 +568,9 @@ anywhere else. <pavel@ucw.cz>
<!element rhead - o (%inline)> <!element rhead - o (%inline)>
<!entity % sect "heading, header?, p* " > <!entity % sect "heading, header?, p* " >
<!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)>
@ -575,11 +579,11 @@ anywhere else. <pavel@ucw.cz>
<!element footnote - - (%inline)> <!element footnote - - (%inline)>
<!usemap global footnote> <!usemap global footnote>
<!element cite - o empty> <!element cite - o empty>
<!attlist cite <!attlist cite
id cdata #required> id cdata #required>
<!element ncite - o empty> <!element ncite - o empty>
<!attlist ncite <!attlist ncite
id cdata #required id cdata #required
note cdata #required> note cdata #required>
@ -599,41 +603,41 @@ anywhere else. <pavel@ucw.cz>
<!attlist slides <!attlist slides
opts cdata "null"> opts cdata "null">
<!element slide - o (title?, p+) > <!element slide - o (title?, p+) >
<!entity % addr "(address?, email?, phone?, fax?)" > <!entity % addr "(address?, email?, phone?, fax?)" >
<!element letter - - <!element letter - -
(from, %addr, to, %addr, cc?, subject?, sref?, rref?, (from, %addr, to, %addr, cc?, subject?, sref?, rref?,
rdate?, opening, p+, closing, encl?, ps?)> rdate?, opening, p+, closing, encl?, ps?)>
<!attlist letter <!attlist letter
opts cdata "null"> opts cdata "null">
<!element from - o (#pcdata) > <!element from - o (#pcdata) >
<!element to - o (#pcdata) > <!element to - o (#pcdata) >
<!usemap oneline (from,to)> <!usemap oneline (from,to)>
<!element address - o (#pcdata) +(newline) > <!element address - o (#pcdata) +(newline) >
<!element email - o (#pcdata) > <!element email - o (#pcdata) >
<!element phone - o (#pcdata) > <!element phone - o (#pcdata) >
<!element fax - o (#pcdata) > <!element fax - o (#pcdata) >
<!element subject - o (%inline;) > <!element subject - o (%inline;) >
<!element sref - o (#pcdata) > <!element sref - o (#pcdata) >
<!element rref - o (#pcdata) > <!element rref - o (#pcdata) >
<!element rdate - o (#pcdata) > <!element rdate - o (#pcdata) >
<!element opening - o (%inline;) > <!element opening - o (%inline;) >
<!usemap oneline opening> <!usemap oneline opening>
<!element closing - o (%inline;) > <!element closing - o (%inline;) >
<!element cc - o (%inline;) +(newline) > <!element cc - o (%inline;) +(newline) >
<!element encl - o (%inline;) +(newline) > <!element encl - o (%inline;) +(newline) >
<!element ps - o (p+) > <!element ps - o (p+) >
<!element telefax - - <!element telefax - -
(from, %addr, to, address, email?, (from, %addr, to, address, email?,
phone?, fax, cc?, subject?, phone?, fax, cc?, subject?,
opening, p+, closing, ps?)> opening, p+, closing, ps?)>
@ -644,8 +648,8 @@ anywhere else. <pavel@ucw.cz>
<!element notes - - (title?, p+) > <!element notes - - (title?, p+) >
<!attlist notes <!attlist notes
opts cdata "null" > opts cdata "null" >
<!element manpage - - (sect1*) <!element manpage - - (sect1*)
-(sect2 | f | %mathpar | figure | tabular | -(sect2 | f | %mathpar | figure | tabular |
table | %xref | %thrm )> table | %xref | %thrm )>
@ -673,5 +677,5 @@ anywhere else. <pavel@ucw.cz>
<!-- <!--
Local Variables: Local Variables:
mode: sgml mode: sgml
End: --> End: -->
<!-- ================================================= --> <!-- ================================================= -->

View file

@ -36,6 +36,7 @@ f_valid_set_type(int type)
case T_ENUM: case T_ENUM:
case T_IP: case T_IP:
case T_EC: case T_EC:
case T_LC:
return 1; return 1;
default: default:
@ -66,6 +67,14 @@ f_merge_items(struct f_tree *a, struct f_tree *b)
static inline struct f_tree * static inline struct f_tree *
f_new_pair_item(int fa, int ta, int fb, int tb) f_new_pair_item(int fa, int ta, int fb, int tb)
{ {
check_u16(fa);
check_u16(ta);
check_u16(fb);
check_u16(tb);
if ((ta < fa) || (tb < fb))
cf_error( "From value cannot be higher that To value in pair sets");
struct f_tree *t = f_new_tree(); struct f_tree *t = f_new_tree();
t->right = t; t->right = t;
t->from.type = t->to.type = T_PAIR; t->from.type = t->to.type = T_PAIR;
@ -77,22 +86,26 @@ f_new_pair_item(int fa, int ta, int fb, int tb)
static inline struct f_tree * static inline struct f_tree *
f_new_pair_set(int fa, int ta, int fb, int tb) f_new_pair_set(int fa, int ta, int fb, int tb)
{ {
struct f_tree *lst = NULL; check_u16(fa);
int i; check_u16(ta);
check_u16(fb);
check_u16(tb);
if ((fa == ta) || ((fb == 0) && (tb == 0xFFFF)))
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; }
| type SET { | LCLIST { $$ = T_LCLIST; }
| 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;
@ -445,7 +505,7 @@ function_def:
} function_params function_body { } function_params function_body {
$2->def = $5; $2->def = $5;
$2->aux2 = $4; $2->aux2 = $4;
DBG("Hmm, we've got one function here - %s\n", $2->name); DBG("Hmm, we've got one function here - %s\n", $2->name);
cf_pop_scope(); cf_pop_scope();
} }
; ;
@ -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); }
; ;
@ -608,7 +675,7 @@ switch_body: /* EMPTY */ { $$ = NULL; }
/* CONST '(' expr ')' { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_INT; $$->a2.i = $3; } */ /* CONST '(' expr ')' { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_INT; $$->a2.i = $3; } */
bgp_path_expr: bgp_path_expr:
symbol { $$ = $1; } symbol { $$ = $1; }
| '(' term ')' { $$ = $2; } | '(' term ')' { $$ = $2; }
; ;
@ -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,8 +826,9 @@ 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; }
| PREPEND '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('A','p'); $$->a1.p = $3; $$->a2.p = $5; } | '-' '-' '-' EMPTY '-' '-' '-' { $$ = f_new_inst(); $$->code = 'E'; $$->aux = T_LCLIST; }
| ADD '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('C','a'); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'a'; } | 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'; }
| 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'; }
| FILTER '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('C','a'); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'f'; } | FILTER '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('C','a'); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'f'; }
@ -814,7 +883,7 @@ print_list: /* EMPTY */ { $$ = NULL; }
} }
; ;
var_listn: term { var_listn: term {
$$ = f_new_inst(); $$ = f_new_inst();
$$->code = 's'; $$->code = 's';
$$->a1.p = NULL; $$->a1.p = NULL;
@ -882,7 +951,7 @@ cmd:
$$ = f_new_inst(); $$ = f_new_inst();
$$->code = P('P','S'); $$->code = P('P','S');
$$->a1.p = $3; $$->a1.p = $3;
} }
| UNSET '(' rtadot dynamic_attr ')' ';' { | UNSET '(' rtadot dynamic_attr ')' ';' {
$$ = $4; $$ = $4;
$$->aux = EAF_TYPE_UNDEF | EAF_TEMP; $$->aux = EAF_TYPE_UNDEF | EAF_TEMP;

View file

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

View file

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

View file

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

View file

@ -63,7 +63,7 @@ tree_compare(const void *p1, const void *p2)
* build_tree * build_tree
* @from: degenerated tree (linked by @tree->left) to be transformed into form suitable for find_tree() * @from: degenerated tree (linked by @tree->left) to be transformed into form suitable for find_tree()
* *
* Transforms denerated tree into balanced tree. * Transforms degenerated tree into balanced tree.
*/ */
struct f_tree * struct f_tree *
build_tree(struct f_tree *from) build_tree(struct f_tree *from)
@ -162,12 +162,15 @@ void
tree_format(struct f_tree *t, buffer *buf) tree_format(struct f_tree *t, buffer *buf)
{ {
buffer_puts(buf, "["); buffer_puts(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;
buffer_puts(buf, "]"); buffer_puts(buf, "]");
} }

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

289
lib/mac.c Normal file
View file

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

121
lib/mac.h Normal file
View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,6 +1,5 @@
/* /*
* BIRD Library -- SHA-512 and SHA-384 Hash Functions, * BIRD Library -- SHA-512 and SHA-384 Hash Functions
* HMAC-SHA-512 and HMAC-SHA-384 Functions
* *
* (c) 2015 CZ.NIC z.s.p.o. * (c) 2015 CZ.NIC z.s.p.o.
* *
@ -25,8 +24,10 @@
#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];
uint nblocks; uint nblocks;
uint count; uint count;
@ -35,39 +36,14 @@ struct sha512_context {
#define sha384_context sha512_context #define sha384_context sha512_context
void sha512_init(struct sha512_context *ctx); void sha512_init(struct hash_context *ctx);
void sha384_init(struct sha384_context *ctx); void sha384_init(struct hash_context *ctx);
void sha512_update(struct sha512_context *ctx, const byte *buf, size_t len); void sha512_update(struct hash_context *ctx, const byte *buf, uint len);
static inline void sha384_update(struct sha384_context *ctx, const byte *buf, size_t len) #define sha384_update sha512_update
{ sha512_update(ctx, buf, len); }
byte *sha512_final(struct sha512_context *ctx); byte *sha512_final(struct hash_context *ctx);
static inline byte *sha384_final(struct sha384_context *ctx) #define sha384_final sha512_final
{ return sha512_final(ctx); }
/*
* HMAC-SHA512, HMAC-SHA384
*/
struct sha512_hmac_context
{
struct sha512_context ictx;
struct sha512_context octx;
};
#define sha384_hmac_context sha512_hmac_context
void sha512_hmac_init(struct sha512_hmac_context *ctx, const byte *key, size_t keylen);
void sha384_hmac_init(struct sha384_hmac_context *ctx, const byte *key, size_t keylen);
void sha512_hmac_update(struct sha512_hmac_context *ctx, const byte *buf, size_t buflen);
void sha384_hmac_update(struct sha384_hmac_context *ctx, const byte *buf, size_t buflen);
byte *sha512_hmac_final(struct sha512_hmac_context *ctx);
byte *sha384_hmac_final(struct sha384_hmac_context *ctx);
#endif /* _BIRD_SHA512_H_ */ #endif /* _BIRD_SHA512_H_ */

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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