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
sig_handler(int signal)
sig_handler(int signal UNUSED)
{
cleanup();
exit(0);

View file

@ -24,7 +24,7 @@ vlog(const char *msg, va_list args)
int n = vsnprintf(buf, sizeof(buf), msg, args);
if (n < 0)
snprintf(buf, sizeof(buf), "???");
if (n >= sizeof(buf))
else if (n >= (int) sizeof(buf))
snprintf(buf + sizeof(buf) - 100, 100, " ... <too long>");
fputs(buf, 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$@ $<
$(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

View file

@ -577,7 +577,7 @@ cf_lex_init(int is_cli, struct config *c)
cf_lex_init_kh();
ifs_head = ifs = push_ifs(NULL);
if (!is_cli)
if (!is_cli)
{
ifs->file_name = c->file_name;
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.
*/
struct config *
config_alloc(byte *name)
config_alloc(const byte *name)
{
pool *p = rp_new(&root_pool, "Config");
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,
* %CONF_UNQUEUED if a scheduled reconfiguration is removed, %CONF_NOTHING
* 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.
*/
int
@ -450,7 +450,7 @@ config_undo(void)
extern void cmd_reconfig_undo_notify(void);
static void
config_timeout(struct timer *t)
config_timeout(struct timer *t UNUSED)
{
log(L_INFO "Config timeout expired, starting undo");
cmd_reconfig_undo_notify();
@ -530,7 +530,7 @@ cf_error(const char *msg, ...)
* and we want to preserve it for further use.
*/
char *
cfg_strdup(char *c)
cfg_strdup(const char *c)
{
int l = strlen(c) + 1;
char *z = cfg_allocu(l);

View file

@ -20,7 +20,7 @@ struct config {
linpool *mem; /* Linear pool containing configuration data */
list protos; /* Configured protocol instances (struct proto_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) */
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 *new_config; /* Configuration being parsed */
struct config *config_alloc(byte *name);
struct config *config_alloc(const byte *name);
int config_parse(struct config *);
int cli_parse(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_allocu(size) lp_allocu(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);
/* Lexer */

View file

@ -143,7 +143,7 @@ expr_us:
/* Switches */
bool:
expr {$$ = !!$1; }
expr { $$ = !!$1; }
| ON { $$ = 1; }
| YES { $$ = 1; }
| OFF { $$ = 0; }
@ -202,7 +202,7 @@ net_roa4_: net_ip4_ MAX NUM AS NUM
{
$$ = cfg_alloc(sizeof(net_addr_roa4));
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);
};
@ -210,7 +210,7 @@ net_roa6_: net_ip6_ MAX NUM AS NUM
{
$$ = cfg_alloc(sizeof(net_addr_roa6));
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);
};

View file

@ -88,11 +88,13 @@ fi
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_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_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_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_overflow, -fno-strict-overflow)
fi

View file

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

View file

@ -21,7 +21,7 @@
</notes> + "<@@enddoc>" +
% 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>
@ -35,7 +35,7 @@
<title> + "<@@title>"
</title>
<subtitle> + "<H2>"
<subtitle> + "<H2>"
</subtitle> "</H2>" +
<author>
@ -48,26 +48,27 @@
</and>
<thanks> + "Thanks "
</thanks>
</thanks>
<inst> + "<H3>"
</inst> "</H3>" +
<newline> "<BR>"
<label> + "<@@label>[ID]" +
<header>
</header>
</label>
<header>
</header>
<lhead> + "<!-- "
</lhead> " -->" +
</lhead> " -->" +
<rhead> + "<!-- "
</rhead> " -->" +
<comment> + "<H4>Comment</H4>" +
</comment>
</comment>
<abstract> + "<P><HR>\n<EM>"
</abstract> "</EM>\n<HR>" +
@ -99,7 +100,7 @@
<sect3> + "<@@head>"
</sect3>
<sect4> + "<@@head>"
<sect4> + "<@@head>"
</sect4>
<heading>
@ -134,6 +135,9 @@
<ncite> "[<I>[NOTE] ([ID])</I>]"
</ncite>
<file> "<CODE>"
</file> "</CODE>"
<footnote> + "<BLOCKQUOTE>"
</footnote> "</BLOCKQUOTE>" +
@ -198,12 +202,14 @@
"<@@endurl>" +
</url>
<htmlurl> + "<@@url>[URL]\n"
"[NAME]</A>\n"
"<@@endurl>" +
<htmlurl> "<A HREF=\"[URL]\">[NAME]</A>"
</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"
"[NAME]</A>\n"
"<@@endref>" +
@ -228,7 +234,7 @@
</mc> "</MC>"
<biblio> + "<BIBLIO STYLE=\"[STYLE]\" FILES=\"[FILES]\">" +
</biblio>
</biblio>
<code> + "<HR>\n<PRE>" +
</code> + "</PRE>\n<HR>" +
@ -244,28 +250,28 @@
% theorems and such
<def> + "<DEF>"
<def> + "<DEF>"
</def> + "</DEF>" +
<prop> + "<PROP>"
<prop> + "<PROP>"
</prop> + "</PROP>" +
<lemma> + "<LEMMA>"
<lemma> + "<LEMMA>"
</lemma> + "</LEMMA>" +
<coroll> + "<COROLL>"
<coroll> + "<COROLL>"
</coroll> + "</COROLL>" +
<proof> + "<PROOF>"
<proof> + "<PROOF>"
</proof> + "</PROOF>" +
<theorem> + "<THEOREM>"
<theorem> + "<THEOREM>"
</theorem> + "</THEOREM>" +
<thtag> "<THTAG>"
</thtag> "</THTAG>"
% mathematics
% mathematics
<f>
</f>
@ -315,11 +321,11 @@
<ar> "<AR>"
</ar> "</AR>"
<arr> "<ARR>"
</arr>
<arr> "<ARR>"
</arr>
<arc> "<ARC>"
</arc>
</arc>
<sup> "<SUP>"
</sup> "</SUP>"
@ -354,13 +360,13 @@
</figure> + "</FIGURE>" +
<eps> + "<EPS FILE=\"[FILE]\">" +
</eps>
</eps>
<img> + "<IMG SRC=\"[SRC]\">" +
</img>
<ph> + "<PH VSPACE=\"[VSPACE]\">" +
</ph>
</ph>
<caption> + "<CAPTION>"
</caption> "</CAPTION>" +
@ -403,7 +409,7 @@
</opening> "</OPENING>" +
<from> + "<FROM>"
<from> + "<FROM>"
</from> + "</FROM>" +
@ -419,7 +425,7 @@
<email> + "<EMAIL>"
</email> "</EMAIL>" +
<phone> + "<PHONE>"
<phone> + "<PHONE>"
</phone> "</PHONE>" +
@ -430,16 +436,16 @@
</subject> "</SUBJECT>" +
<sref> + "<SREF>"
<sref> + "<SREF>"
</sref> "</SREF>" +
<rref> + "<RREF>"
<rref> + "<RREF>"
</rref> "</RREF>" +
<rdate> + "<RDATE>"
</rdate> "</RDATE>" +
<closing> + "<CLOSING>"
<closing> + "<CLOSING>"
</closing> "</CLOSING>" +
<cc> + "<CC>"

View file

@ -2,7 +2,9 @@
% birddoc to LaTeX replacement file
% 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{qwertz}\n"
"\\usepackage{url}\n"
@ -14,7 +16,7 @@
</book> + "\\end{document}" +
% 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>
@ -26,17 +28,17 @@
</titlepag> + "\n\n\\begin{document}\n"
"\\maketitle\n" +
<title> + "\\title{"
<title> + "\\title{"
</title> "}" +
<subtitle> "\\\\\n"
"{\\large "
</subtitle> "}" +
<author> + "\\author{"
<author> + "\\author{"
</author> "}" +
<name>
<name>
</name>
<and> "\\and " +
@ -51,14 +53,14 @@
<date> + "\\date{"
</date> "}" +
<newline> "\\\\ "
<newline> "\\\\ "
</newline>
<label> "\\label{[ID]}"
</label>
</label>
<header> + "\\markboth"
</header>
</header>
<lhead> "{"
</lhead> "}"
@ -73,7 +75,7 @@
</comment> "}"
% Hacked by mdw to use linuxdoc-sgml \abstract{...}
<abstract> + "\\abstract{"
<abstract> + "\\abstract{"
</abstract> "}" +
<appendix> + "\n \\appendix \n" +
@ -101,15 +103,15 @@
</sect2>
<sect3> + "\n\\paragraph"
</sect3>
</sect3>
<sect4> + "\n\\subparagraph"
</sect4>
<heading> "{"
</heading> "}\n\n"
</heading> "}\n\n"
<p>
<p> "\\phantomsection{}"
</p> "\n\n"
<itemize> + "\\begin{itemize}" +
@ -121,13 +123,13 @@
<list> + "\\begin{list}{}{}\n" +
</list> + "\\end{list}" +
<descrip> + "\\begin{description}" +
<descrip> + "\\begin{description}\[style=unboxed\]" +
</descrip> + "\\end{description}" +
<item> + "\\item "
</item>
<tag> + "\\item\[{\\ttfamily "
<tag> + "\\phantomsection\\item\[{\\ttfamily "
</tag> "}\] \\hfil\\break\n" +
<tagp> + "\\item\[ "
@ -154,7 +156,7 @@
% 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
% a kluge but it works,
<file> "\\url{"
<file> "{\\tt "
</file> "}"
<footnote> "\\footnote{"
@ -223,29 +225,32 @@
<cparam> "\\cparam{"
</cparam> "}"
<ref> "\\ref{[ID]} {([NAME])}"
<ref> "\\hyperref\[[ID]\]{[NAME]} (p.\\,\\getpagerefnumber{[ID]})"
</ref>
<pageref> "\\pageref{[ID]}"
</pageref>
%url added by HG
<url> "\\nameurl{[URL]}{[NAME]}"
<url> "\\href{[URL]}{[NAME]}"
</url>
<htmlurl> "\\onlynameurl{[NAME]}"
<htmlurl> "\\href{[URL]}{[NAME]}"
</htmlurl>
<x>
<rfc> "\\href{http://www.rfc-editor.org/info/rfc[ID]}{RFC [ID]}"
</rfc>
<x>
</x>
<mc>
<mc>
</mc>
<biblio> + "\\bibliographystyle{[STYLE]}\n"
"\\bibliography{[FILES]}\n"
"\\addbibtoc{}" +
</biblio>
</biblio>
% <macro> + "\\macro{[ID]}{\\qw[ID]}"
% </macro>
@ -300,19 +305,19 @@
<thtag> "\["
</thtag> "\]" +
% mathematics
% mathematics
<f> "$"
</f> "$"
<dm> + "\\\["
<dm> + "\\\["
</dm> "\\\]" +
<eq> + "\\begin{equation}" +
</eq> + "\\end{equation}\n" +
<fr> "\\frac"
</fr>
</fr>
<nu> "{"
</nu> "}"
@ -320,7 +325,7 @@
<de> "{"
</de> "}"
<lim>
<lim>
</lim>
<op>
@ -342,7 +347,7 @@
</in>
<sum> "\\sum"
</sum>
</sum>
<root> "\\sqrt\[[n]\]{"
</root> "}"
@ -390,11 +395,11 @@
</figure> + "\\end{figure}\n" +
<eps> + "\\centerline{\\epsfig{file=[FILE],height=[HEIGHT],angle=[ANGLE]}}" +
</eps>
</eps>
<ph> + "\\vspace{[VSPACE]}\n\\par" +
</ph>
</ph>
<caption> + "\\caption{"
</caption> "}" +

View file

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

View file

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

View file

@ -36,6 +36,7 @@ f_valid_set_type(int type)
case T_ENUM:
case T_IP:
case T_EC:
case T_LC:
return 1;
default:
@ -66,6 +67,14 @@ f_merge_items(struct f_tree *a, struct f_tree *b)
static inline struct f_tree *
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();
t->right = t;
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 *
f_new_pair_set(int fa, int ta, int fb, int tb)
{
struct f_tree *lst = NULL;
int i;
check_u16(fa);
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))
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++)
lst = f_merge_items(lst, f_new_pair_item(i, i, fb, tb));
return lst;
}
#define CC_ALL 0xFFFF
#define EC_ALL 0xFFFFFFFF
#define LC_ALL 0xFFFFFFFF
static struct f_tree *
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;
}
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 *
f_generate_empty(struct f_inst *dyn)
{
@ -148,6 +172,9 @@ f_generate_empty(struct f_inst *dyn)
case EAF_TYPE_EC_SET:
e->aux = T_ECLIST;
break;
case EAF_TYPE_LC_SET:
e->aux = T_LCLIST;
break;
default:
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;
}
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_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
ACCEPT, REJECT, ERROR, QUITBIRD,
INT, BOOL, IP, PREFIX, PAIR, QUAD, EC,
SET, STRING, BGPMASK, BGPPATH, CLIST, ECLIST,
INT, BOOL, IP, PREFIX, PAIR, QUAD, EC, LC,
SET, STRING, BGPMASK, BGPPATH, CLIST, ECLIST, LCLIST,
IF, THEN, ELSE, CASE,
TRUE, FALSE, RT, RO, UNKNOWN, GENERIC,
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 <f> filter filter_body where_filter
%type <i> type break_command pair_expr ec_kind
%type <i32> pair_atom ec_expr
%type <e> pair_item ec_item set_item switch_item set_items switch_items switch_body
%type <i> type break_command ec_kind
%type <i32> cnum
%type <e> pair_item ec_item lc_item set_item switch_item set_items switch_items switch_body
%type <trie> fprefix_set
%type <v> set_atom switch_atom fipa
%type <px> fprefix
@ -326,17 +383,20 @@ type:
| PAIR { $$ = T_PAIR; }
| QUAD { $$ = T_QUAD; }
| EC { $$ = T_EC; }
| LC { $$ = T_LC; }
| STRING { $$ = T_STRING; }
| BGPMASK { $$ = T_PATH_MASK; }
| BGPPATH { $$ = T_PATH; }
| CLIST { $$ = T_CLIST; }
| ECLIST { $$ = T_ECLIST; }
| type SET {
| LCLIST { $$ = T_LCLIST; }
| type SET {
switch ($1) {
case T_INT:
case T_PAIR:
case T_QUAD:
case T_EC:
case T_LC:
case T_IP:
$$ = T_SET;
break;
@ -445,7 +505,7 @@ function_def:
} function_params function_body {
$2->def = $5;
$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();
}
;
@ -511,30 +571,23 @@ switch_atom:
| ENUM { $$.type = pair_a($1); $$.val.i = pair_b($1); }
;
pair_expr:
term { $$ = f_eval_int($1); check_u16($$); }
pair_atom:
pair_expr { $$ = pair($1, $1); }
| pair_expr DDOT pair_expr { $$ = pair($1, $3); }
| '*' { $$ = 0xFFFF; }
;
cnum:
term { $$ = f_eval_int($1); }
pair_item:
'(' pair_atom ',' pair_atom ')' {
$$ = f_new_pair_set(pair_a($2), pair_b($2), pair_a($4), pair_b($4));
}
| '(' pair_atom ',' pair_atom ')' DDOT '(' pair_expr ',' pair_expr ')' {
/* Hack: $2 and $4 should be pair_expr, but that would cause shift/reduce conflict */
if ((pair_a($2) != pair_b($2)) || (pair_a($4) != pair_b($4)))
cf_error("syntax error");
$$ = f_new_pair_item(pair_b($2), $8, pair_b($4), $10);
}
'(' cnum ',' cnum ')' { $$ = f_new_pair_item($2, $2, $4, $4); }
| '(' cnum ',' cnum DDOT cnum ')' { $$ = f_new_pair_item($2, $2, $4, $6); }
| '(' cnum ',' '*' ')' { $$ = f_new_pair_item($2, $2, 0, CC_ALL); }
| '(' cnum DDOT cnum ',' cnum ')' { $$ = f_new_pair_set($2, $4, $6, $6); }
| '(' cnum DDOT cnum ',' cnum DDOT cnum ')' { $$ = f_new_pair_set($2, $4, $6, $8); }
| '(' cnum DDOT cnum ',' '*' ')' { $$ = f_new_pair_item($2, $4, 0, CC_ALL); }
| '(' '*' ',' cnum ')' { $$ = f_new_pair_set(0, CC_ALL, $4, $4); }
| '(' '*' ',' 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:
RT { $$ = EC_RT; }
| RO { $$ = EC_RO; }
@ -543,14 +596,27 @@ ec_kind:
;
ec_item:
'(' ec_kind ',' ec_expr ',' ec_expr ')' { $$ = 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 ',' ec_expr ',' '*' ')' { $$ = f_new_ec_item($2, 0, $4, 0, EC_ALL); }
'(' ec_kind ',' cnum ',' cnum ')' { $$ = f_new_ec_item($2, 0, $4, $6, $6); }
| '(' ec_kind ',' cnum ',' cnum DDOT cnum ')' { $$ = f_new_ec_item($2, 0, $4, $6, $8); }
| '(' 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:
pair_item
| ec_item
| lc_item
| set_atom { $$ = f_new_item($1, $1); }
| set_atom DDOT set_atom { $$ = f_new_item($1, $3); }
;
@ -558,6 +624,7 @@ set_item:
switch_item:
pair_item
| ec_item
| lc_item
| switch_atom { $$ = f_new_item($1, $1); }
| 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; } */
bgp_path_expr:
symbol { $$ = $1; }
symbol { $$ = $1; }
| '(' term ')' { $$ = $2; }
;
@ -648,6 +715,7 @@ constant:
constructor:
'(' term ',' term ')' { $$ = f_generate_dpair($2, $4); }
| '(' 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_CLIST; }
| '-' '-' 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; }
| ADD '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('C','a'); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'a'; }
| '-' '-' '-' EMPTY '-' '-' '-' { $$ = f_new_inst(); $$->code = 'E'; $$->aux = T_LCLIST; }
| PREPEND '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('A','p'); $$->a1.p = $3; $$->a2.p = $5; }
| 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'; }
| 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();
$$->code = 's';
$$->a1.p = NULL;
@ -882,7 +951,7 @@ cmd:
$$ = f_new_inst();
$$->code = P('P','S');
$$->a1.p = $3;
}
}
| UNSET '(' rtadot dynamic_attr ')' ';' {
$$ = $4;
$$->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)
{ 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
* @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);
case T_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:
return ipa_compare(v1.val.ip, v2.val.ip);
case T_NET:
@ -201,6 +215,7 @@ val_same(struct f_val v1, struct f_val v2)
case T_PATH:
case T_CLIST:
case T_ECLIST:
case T_LCLIST:
return adata_same(v1.val.ad, v2.val.ad);
case T_SET:
return same_tree(v1.val.t, v2.val.t);
@ -241,6 +256,10 @@ static inline int
eclist_set_type(struct f_tree *set)
{ return set->from.type == T_EC; }
static inline int
lclist_set_type(struct f_tree *set)
{ return set->from.type == T_LC; }
static int
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;
}
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 *
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;
}
int nl = (k - tmp) * 4;
uint nl = (k - tmp) * sizeof(u32);
if (nl == list->length)
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)
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))
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))
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)
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)
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_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_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_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_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_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;
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");
val = v2.val.i;
/* XXXX */
res.type = T_EC;
if (what->aux == EC_GENERIC) {
@ -649,6 +733,24 @@ interpret(struct f_inst *what)
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 */
#define COMPARE(x) \
@ -883,6 +985,13 @@ interpret(struct f_inst *what)
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 */
res.type = T_VOID;
break;
@ -922,6 +1031,10 @@ interpret(struct f_inst *what)
res.type = T_ECLIST;
res.val.ad = e->u.ptr;
break;
case EAF_TYPE_LC_SET:
res.type = T_LCLIST;
res.val.ad = e->u.ptr;
break;
case EAF_TYPE_UNDEF:
res.type = T_VOID;
break;
@ -1010,6 +1123,11 @@ interpret(struct f_inst *what)
runtime( "Setting eclist attribute to non-eclist value" );
l->attrs[0].u.ptr = v1.val.ad;
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:
if (v1.type != T_VOID)
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_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_LCLIST: res.val.i = lc_set_get_size(v1.val.ad); break;
default: runtime( "Prefix, path, clist or eclist expected" );
}
break;
@ -1240,7 +1359,7 @@ interpret(struct f_inst *what)
else if (v2.type == T_ECLIST)
arg_set = 2;
else if (v2.type != T_EC)
runtime("Can't add/delete non-pair");
runtime("Can't add/delete non-ec");
res.type = T_ECLIST;
switch (what->aux)
@ -1271,8 +1390,50 @@ interpret(struct f_inst *what)
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
runtime("Can't add/delete to non-(e)clist");
runtime("Can't add/delete to non-[e|l]clist");
break;
@ -1370,6 +1531,12 @@ i_same(struct f_inst *f1, struct f_inst *f2)
case '~': TWOARGS; 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':
ARG(v2, a2.p);
{

View file

@ -38,6 +38,17 @@ struct f_inst_roa_check {
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 {
net_addr net;
u8 lo, hi;
@ -48,6 +59,7 @@ struct f_val {
union {
uint i;
u64 ec;
lcomm lc;
ip_addr ip;
const net_addr *net;
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 0x24 /* BGP path */
#define T_CLIST 0x25 /* Community list */
#define T_ECLIST 0x26 /* Extended community list */
#define T_EC 0x27 /* Extended community value, u64 */
#define T_EC 0x26 /* 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_SET 0x80
@ -160,10 +174,10 @@ void val_format(struct f_val v, buffer *buf);
#define SA_PROTO 4
#define SA_SOURCE 5
#define SA_SCOPE 6
#define SA_CAST 7
#define SA_DEST 8
#define SA_IFNAME 9
#define SA_IFINDEX 10
#define SA_CAST 7
#define SA_DEST 8
#define SA_IFNAME 9
#define SA_IFINDEX 10
struct f_tree {
@ -175,7 +189,7 @@ struct f_tree {
struct f_trie_node
{
ip_addr addr, mask, accept;
int plen;
uint plen;
struct f_trie_node *c[2];
};

View file

@ -31,6 +31,11 @@ function 'mkpair-a'(int a)
return (1, a);
}
function mktrip(int a)
{
return (a, 2*a, 3*a);
}
function mkpath(int a; int b)
{
return [= a b 3 2 1 =];
@ -95,6 +100,8 @@ clist l;
clist l2;
eclist el;
eclist el2;
lclist ll;
lclist ll2;
{
print "Entering path test...";
pm1 = / 4 3 2 1 /;
@ -160,7 +167,7 @@ eclist el2;
print "Community list (1,2) (3,1) (3,5) ", l, " len: ", l.len;
l = add( l, (3,2) );
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 false: ", l ~ [(*,3)], " ", l ~ [(*,(one+6))], " ", l ~ [(*, (one+one+one))];
l = delete( l, [(*,(one+onef(3)))] );
@ -175,7 +182,7 @@ eclist el2;
print "clist B (3..6): ", l2;
print "clist A union B: ", add( l2, l );
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 = add(el, (rt, 10, 20));
@ -207,7 +214,34 @@ eclist el2;
print "eclist B (30,40,50): ", el2;
print "eclist A union B: ", add( el2, el );
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();
}

View file

@ -63,7 +63,7 @@ tree_compare(const void *p1, const void *p2)
* build_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 *
build_tree(struct f_tree *from)
@ -162,12 +162,15 @@ void
tree_format(struct f_tree *t, buffer *buf)
{
buffer_puts(buf, "[");
tree_node_format(t, buf);
if (buf->pos == buf->end)
return;
/* Undo last separator */
if (buf->pos[-1] != '[')
buf->pos -= 2;
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
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 paddr = ipa_and(px, pmask);
@ -266,7 +266,8 @@ trie_match_prefix(struct f_trie *t, ip_addr px, int plen)
int
trie_match_net(struct f_trie *t, const net_addr *n)
{
int add = 0;
uint add = 0;
switch (n->type) {
case NET_IP4:
case NET_VPN4:
@ -333,9 +334,12 @@ trie_format(struct f_trie *t, buffer *buf)
buffer_puts(buf, "[");
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);
if (buf->pos == buf->end)
return;
/* Undo last separator */
if (buf->pos[-1] != '[')
buf->pos -= 2;

View file

@ -2,6 +2,7 @@ H Library functions
S ip.c
S lists.c
S checksum.c bitops.c patmatch.c printf.c xmalloc.c tbf.c
S mac.c
D resource.sgml
S resource.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)
$(all-daemon)

View file

@ -63,7 +63,6 @@ static inline int u64_cmp(u64 i1, u64 i2)
#define UNUSED __attribute__((unused))
#define PACKED __attribute__((packed))
/* Microsecond time */
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; }
@ -32,4 +46,4 @@
#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(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_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) \
({ \
int _o = (v).order; \
while (((v).count < ((1 << _o) REHASH_LO_MARK(args))) && \
uint _o = (v).order; \
while (((v).count < ((1U << _o) REHASH_LO_MARK(args))) && \
(_o > (REHASH_LO_BOUND(args)))) \
_o -= (REHASH_LO_STEP(args)); \
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)
static inline void
mem_hash_init(u64 *h)
{
@ -185,14 +196,15 @@ mem_hash_init(u64 *h)
}
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 char *pp = p;
uint i;
for (i=0; i<s/4; i++)
*h = *h * multiplier + ((const u32 *)pp)[i];
for (i=s & ~0x3; i<s; i++)
*h = *h * multiplier + pp[i];
}
@ -204,7 +216,7 @@ mem_hash_value(u64 *h)
}
static inline uint
mem_hash(void *p, int s)
mem_hash(void *p, uint s)
{
static u64 h;
mem_hash_init(&h);
@ -212,3 +224,4 @@ mem_hash(void *p, int s)
return mem_hash_value(&h);
}
#endif

View file

@ -53,7 +53,7 @@ idm_alloc(struct idm *m)
ASSERT(0);
found:
found:
ASSERT(i < 0x8000000);
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.
*/
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[1] = 0xefcdab89;
ctx->buf[2] = 0x98badcfe;
@ -55,8 +57,9 @@ md5_init(struct md5_context *ctx)
* of bytes.
*/
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;
/* 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)
*/
byte *
md5_final(struct md5_context *ctx)
md5_final(struct hash_context *CTX)
{
struct md5_context *ctx = (void *) CTX;
uint count;
byte *p;
@ -149,13 +153,6 @@ md5_final(struct md5_context *ctx)
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 */
/* #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[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
struct hash_context;
struct md5_context {
u32 buf[4];
u32 bits[2];
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);
/*
* HMAC-MD5
*/
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);
void md5_init(struct hash_context *ctx);
void md5_update(struct hash_context *ctx, const byte *buf, uint len);
byte *md5_final(struct hash_context *ctx);
#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.
*
@ -17,8 +17,10 @@
void
sha1_init(struct sha1_context *ctx)
sha1_init(struct hash_context *CTX)
{
struct sha1_context *ctx = (void *) CTX;
ctx->h0 = 0x67452301;
ctx->h1 = 0xefcdab89;
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.
*/
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)
{
/* 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.
*/
byte *
sha1_final(struct sha1_context *ctx)
sha1_final(struct hash_context *CTX)
{
struct sha1_context *ctx = (void *) CTX;
u32 t, msb, lsb;
sha1_update(ctx, NULL, 0); /* flush */
sha1_update(CTX, NULL, 0); /* flush */
t = ctx->nblocks;
/* 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 */
while (ctx->count < 64)
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 */
}
@ -268,81 +273,3 @@ sha1_final(struct sha1_context *ctx)
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.
*
@ -27,6 +27,8 @@
* Internal SHA1 state.
* You should use it just as an opaque handle only.
*/
struct hash_context;
struct sha1_context {
u32 h0, h1, h2, h3, h4;
byte buf[SHA1_BLOCK_SIZE];
@ -34,15 +36,14 @@ struct sha1_context {
uint count;
};
void sha1_init(struct sha1_context *ctx); /* Initialize new algorithm run in the @ctx context. **/
void sha1_init(struct hash_context *ctx); /* Initialize new algorithm run in the @ctx context. **/
/*
* 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
* 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.
*/
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
* 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
* 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
@ -63,24 +64,5 @@ byte *sha1_final(struct sha1_context *ctx);
*/
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_ */

View file

@ -1,6 +1,5 @@
/*
* BIRD Library -- SHA-256 and SHA-224 Hash Functions,
* HMAC-SHA-256 and HMAC-SHA-224 Functions
* BIRD Library -- SHA-256 and SHA-224 Hash Functions
*
* (c) 2015 CZ.NIC z.s.p.o.
*
@ -17,8 +16,10 @@
// #define SHA256_UNROLLED
void
sha256_init(struct sha256_context *ctx)
sha256_init(struct hash_context *CTX)
{
struct sha256_context *ctx = (void *) CTX;
ctx->h0 = 0x6a09e667;
ctx->h1 = 0xbb67ae85;
ctx->h2 = 0x3c6ef372;
@ -33,8 +34,10 @@ sha256_init(struct sha256_context *ctx)
}
void
sha224_init(struct sha224_context *ctx)
sha224_init(struct hash_context *CTX)
{
struct sha224_context *ctx = (void *) CTX;
ctx->h0 = 0xc1059ed8;
ctx->h1 = 0x367cd507;
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
helpful to mitigate timing attacks. */
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)
{
/* 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.
*/
byte *
sha256_final(struct sha256_context *ctx)
sha256_final(struct hash_context *CTX)
{
struct sha256_context *ctx = (void *) CTX;
u32 t, th, msb, lsb;
sha256_update(ctx, NULL, 0); /* flush */
sha256_update(CTX, NULL, 0); /* flush */
t = ctx->nblocks;
th = 0;
@ -296,7 +302,7 @@ sha256_final(struct sha256_context *ctx)
ctx->buf[ctx->count++] = 0x80; /* pad character */
while (ctx->count < 64)
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 */
}
@ -319,131 +325,3 @@ sha256_final(struct sha256_context *ctx)
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,
* HMAC-SHA-256 and HMAC-SHA-224 Functions
* BIRD Library -- SHA-256 and SHA-224 Hash Functions
*
* (c) 2015 CZ.NIC z.s.p.o.
*
@ -25,6 +24,8 @@
#define SHA256_BLOCK_SIZE 64
struct hash_context;
struct sha256_context {
u32 h0, h1, h2, h3, h4, h5, h6, h7;
byte buf[SHA256_BLOCK_SIZE];
@ -35,39 +36,14 @@ struct sha256_context {
#define sha224_context sha256_context
void sha256_init(struct sha256_context *ctx);
void sha224_init(struct sha224_context *ctx);
void sha256_init(struct hash_context *ctx);
void sha224_init(struct hash_context *ctx);
void sha256_update(struct sha256_context *ctx, const byte *buf, size_t len);
static inline void sha224_update(struct sha224_context *ctx, const byte *buf, size_t len)
{ sha256_update(ctx, buf, len); }
void sha256_update(struct hash_context *ctx, const byte *buf, uint len);
#define sha224_update sha256_update
byte *sha256_final(struct sha256_context *ctx);
static inline byte *sha224_final(struct sha224_context *ctx)
{ 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);
byte *sha256_final(struct hash_context *ctx);
#define sha224_final sha256_final
#endif /* _BIRD_SHA256_H_ */

View file

@ -1,6 +1,5 @@
/*
* BIRD Library -- SHA-512 and SHA-384 Hash Functions,
* HMAC-SHA-512 and HMAC-SHA-384 Functions
* BIRD Library -- SHA-512 and SHA-384 Hash Functions
*
* (c) 2015 CZ.NIC z.s.p.o.
*
@ -17,8 +16,10 @@
// #define SHA512_UNROLLED
void
sha512_init(struct sha512_context *ctx)
sha512_init(struct hash_context *CTX)
{
struct sha512_context *ctx = (void *) CTX;
ctx->h0 = U64(0x6a09e667f3bcc908);
ctx->h1 = U64(0xbb67ae8584caa73b);
ctx->h2 = U64(0x3c6ef372fe94f82b);
@ -33,8 +34,10 @@ sha512_init(struct sha512_context *ctx)
}
void
sha384_init(struct sha384_context *ctx)
sha384_init(struct hash_context *CTX)
{
struct sha384_context *ctx = (void *) CTX;
ctx->h0 = U64(0xcbbb9d5dc1059ed8);
ctx->h1 = U64(0x629a292a367cd507);
ctx->h2 = U64(0x9159015a3070dd17);
@ -389,8 +392,10 @@ sha512_transform(struct sha512_context *ctx, const byte *data)
}
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)
{
/* 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.
*/
byte *
sha512_final(struct sha512_context *ctx)
sha512_final(struct hash_context *CTX)
{
struct sha512_context *ctx = (void *) CTX;
u64 t, th, msb, lsb;
sha512_update(ctx, NULL, 0); /* flush */
sha512_update(CTX, NULL, 0); /* flush */
t = ctx->nblocks;
th = 0;
@ -467,7 +473,7 @@ sha512_final(struct sha512_context *ctx)
ctx->buf[ctx->count++] = 0x80; /* pad character */
while(ctx->count < 128)
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 */
}
@ -490,131 +496,3 @@ sha512_final(struct sha512_context *ctx)
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,
* HMAC-SHA-512 and HMAC-SHA-384 Functions
* BIRD Library -- SHA-512 and SHA-384 Hash Functions
*
* (c) 2015 CZ.NIC z.s.p.o.
*
@ -25,8 +24,10 @@
#define SHA512_BLOCK_SIZE 128
struct hash_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];
uint nblocks;
uint count;
@ -35,39 +36,14 @@ struct sha512_context {
#define sha384_context sha512_context
void sha512_init(struct sha512_context *ctx);
void sha384_init(struct sha384_context *ctx);
void sha512_init(struct hash_context *ctx);
void sha384_init(struct hash_context *ctx);
void sha512_update(struct sha512_context *ctx, const byte *buf, size_t len);
static inline void sha384_update(struct sha384_context *ctx, const byte *buf, size_t len)
{ sha512_update(ctx, buf, len); }
void sha512_update(struct hash_context *ctx, const byte *buf, uint len);
#define sha384_update sha512_update
byte *sha512_final(struct sha512_context *ctx);
static inline byte *sha384_final(struct sha384_context *ctx)
{ 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);
byte *sha512_final(struct hash_context *ctx);
#define sha384_final sha512_final
#endif /* _BIRD_SHA512_H_ */

View file

@ -30,7 +30,7 @@ typedef struct birdsock {
byte *rbuf, *rpos; /* NULL=allocate automatically */
uint fast_rx; /* RX has higher priority in event loop */
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 *ttx; /* Internal */

View file

@ -30,6 +30,25 @@ static inline char *xbasename(const 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
#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)
return path;

View file

@ -116,7 +116,7 @@ int
ec_set_format(struct adata *set, int from, byte *buf, uint size)
{
u32 *z = int_set_get_data(set);
byte *end = buf + size - 24;
byte *end = buf + size - 64;
int from2 = MAX(from, 0);
int to = int_set_get_size(set);
int i;
@ -141,6 +141,43 @@ ec_set_format(struct adata *set, int from, byte *buf, uint size)
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_set_contains(struct adata *list, u32 val)
{
@ -177,6 +214,24 @@ ec_set_contains(struct adata *list, u64 val)
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 *
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;
res = lp_alloc(pool, sizeof(struct adata) + len + 4);
res->length = len + 4;
* (u32 *) res->data = val;
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;
}
@ -208,13 +267,30 @@ ec_set_add(struct linpool *pool, struct adata *list, u64 val)
if (list)
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[1] = ec_lo(val);
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 *
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;
}
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 *
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);
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) */
#define EC_TBIT 0x40000000
#define ECOMM_LENGTH 8
static inline int int_set_get_size(struct adata *list)
{ 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)
{ 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)
{ 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)
{ 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 ec_format(byte *buf, u64 ec);
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 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 *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 *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 *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

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);
static inline void cf_check_bfd(int use) { }
static inline void cf_check_bfd(int use UNUSED) { }
#else

View file

@ -13,6 +13,7 @@ CF_HDR
#include "nest/password.h"
#include "nest/cmds.h"
#include "lib/lists.h"
#include "lib/mac.h"
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(RECEIVE, LIMIT, ACTION, WARN, BLOCK, RESTART, DISABLE, KEEP, FILTERED)
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(RELOAD, IN, OUT, MRTDUMP, MESSAGES, RESTRICT, MEMORY, IGP_METRIC, CLASS, DSCP)
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 <ra> r_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 <cc> channel_start proto_channel
%type <cl> limit_spec
@ -419,7 +421,7 @@ password_list:
| password_item
;
password_items:
password_items:
/* empty */
| password_item ';' password_items
;
@ -438,11 +440,13 @@ password_item_begin:
}
this_p_item = cfg_alloc(sizeof (struct password_item));
this_p_item->password = $2;
this_p_item->length = strlen($2);
this_p_item->genfrom = 0;
this_p_item->gento = TIME_INFINITY;
this_p_item->accfrom = 0;
this_p_item->accto = TIME_INFINITY;
this_p_item->id = password_id++;
this_p_item->alg = ALG_UNDEFINED;
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; }
| ACCEPT FROM datetime ';' password_item_params { this_p_item->accfrom = $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."); }
| 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 */
CF_CLI_HELP(SHOW, ..., [[Show status information]])
@ -605,7 +623,7 @@ CF_CLI(EVAL, term, <expr>, [[Evaluate an expression]])
{ cmd_eval($2); } ;
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_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); } ;
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); } ;
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); } ;
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),
olock_free,
olock_dump,
NULL
NULL,
NULL,
};
/**

View file

@ -10,6 +10,7 @@
#include "nest/bird.h"
#include "nest/password.h"
#include "lib/string.h"
#include "lib/mac.h"
struct password_item *last_password_item = NULL;
@ -37,7 +38,7 @@ password_find(list *l, int first_fit)
}
struct password_item *
password_find_by_id(list *l, int id)
password_find_by_id(list *l, uint id)
{
struct password_item *pi;
@ -66,3 +67,17 @@ password_find_by_value(list *l, char *pass, uint size)
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
#define PASSWORD_H
#include "sysdep/unix/timer.h"
struct password_item {
node n;
char *password;
int id;
char *password; /* Key data, null terminated */
uint length; /* Key length, without null */
uint id; /* Key ID */
uint alg; /* MAC algorithm */
bird_clock_t accfrom, accto, genfrom, gento;
};
extern struct password_item *last_password_item;
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);
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);
}
uint max_mac_length(list *l);
#endif

View file

@ -285,7 +285,6 @@ rte *rte_find(net *net, struct rte_src *src);
rte *rte_get_temp(struct rta *);
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 */
void rte_discard(rtable *tab, rte *old);
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);
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_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_OPAQUE 0x02 /* Opaque byte string (not filterable) */
#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_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_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_VAR_LENGTH 0x02 /* Attribute length is variable (part of type spec) */
#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)
{
byte *bound = buf + size - 10;
int i;
uint 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
* @c: destination CLI
@ -840,6 +852,9 @@ ea_show(struct cli *c, eattr *e)
case EAF_TYPE_EC_SET:
ea_show_ec_set(c, ad, pos, buf, end);
return;
case EAF_TYPE_LC_SET:
ea_show_lc_set(c, ad, pos, buf, end);
return;
case EAF_TYPE_UNDEF:
default:
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);
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 *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 *
@ -1403,8 +1403,8 @@ rte_announce_i(rtable *tab, unsigned type, net *net, rte *new, rte *old,
rte_update_unlock();
}
void
rte_discard(rtable *t, rte *old) /* Non-filtered route deletion, used during garbage collection */
static inline void
rte_discard(rte *old) /* Non-filtered route deletion, used during garbage collection */
{
rte_update_lock();
rte_recalculate(old->sender, old->net, NULL, old->attrs->src);
@ -1695,7 +1695,7 @@ again:
return;
}
rte_discard(tab, e);
rte_discard(e);
limit--;
goto rescan;
@ -1780,7 +1780,7 @@ rta_apply_hostentry(rta *a, struct hostentry *he)
}
static inline rte *
rt_next_hop_update_rte(rtable *tab, rte *old)
rt_next_hop_update_rte(rtable *tab UNUSED, rte *old)
{
rta a;
memcpy(&a, old->attrs, sizeof(rta));
@ -2166,11 +2166,11 @@ hc_remove(struct hostcache *hc, struct hostentry *he)
static void
hc_alloc_table(struct hostcache *hc, unsigned order)
{
unsigned hsize = 1 << order;
uint hsize = 1 << order;
hc->hash_order = order;
hc->hash_shift = 32 - order;
hc->hash_max = (order >= HC_HI_ORDER) ? ~0 : (hsize HC_HI_MARK);
hc->hash_min = (order <= HC_LO_ORDER) ? 0 : (hsize HC_LO_MARK);
hc->hash_max = (order >= HC_HI_ORDER) ? ~0U : (hsize HC_HI_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 *));
}
@ -2178,10 +2178,10 @@ hc_alloc_table(struct hostcache *hc, unsigned order)
static void
hc_resize(struct hostcache *hc, unsigned new_order)
{
unsigned old_size = 1 << hc->hash_order;
struct hostentry **old_table = hc->hash_table;
struct hostentry *he, *hen;
int i;
uint old_size = 1 << hc->hash_order;
uint i;
hc_alloc_table(hc, new_order);
for (i = 0; i < old_size; i++)

View file

@ -1723,7 +1723,7 @@ babel_dump(struct proto *P)
}
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);
}
@ -1965,7 +1965,7 @@ babel_store_tmp_attrs(struct rte *rt, struct ea_list *attrs)
*/
static void
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_entry *e;

View file

@ -111,7 +111,7 @@ struct babel_iface_config {
u16 rxcost;
u8 type;
u8 check_link;
int port;
uint port;
u16 hello_interval;
u16 ihu_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_HDR0(tlv,t) TLV_HDR(tlv, t, tlv_data[t].min_length)
#define BYTES(n) ((((uint) n) + 7) / 8)
static inline u16
get_time16(const void *p)
@ -161,18 +162,18 @@ put_time16(void *p, u16 v)
}
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;
memcpy(&addr, p, (plen + 7) / 8);
memcpy(&addr, p, BYTES(plen));
return ip6_ntoh(addr);
}
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);
memcpy(p, &addr, (plen + 7) / 8);
memcpy(p, &addr, BYTES(plen));
}
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_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 int babel_write_hello(struct babel_tlv *hdr, union babel_msg *msg, struct babel_write_state *state, int max_len);
static int babel_write_ihu(struct babel_tlv *hdr, union babel_msg *msg, struct babel_write_state *state, int max_len);
static int babel_write_update(struct babel_tlv *hdr, union babel_msg *msg, struct babel_write_state *state, int 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 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_ack(struct babel_tlv *hdr, union babel_msg *msg, struct babel_write_state *state, uint max_len);
static uint babel_write_hello(struct babel_tlv *hdr, union babel_msg *msg, struct babel_write_state *state, uint max_len);
static uint babel_write_ihu(struct babel_tlv *hdr, union babel_msg *msg, struct babel_write_state *state, uint max_len);
static uint babel_write_update(struct babel_tlv *hdr, union babel_msg *msg, struct babel_write_state *state, uint 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 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 {
u8 min_length;
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);
};
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] = {
sizeof(struct babel_tlv_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;
}
static int
static uint
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_msg_ack *msg = &m->ack;
@ -319,9 +320,9 @@ babel_read_hello(struct babel_tlv *hdr, union babel_msg *m,
return PARSE_SUCCESS;
}
static int
static uint
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_msg_hello *msg = &m->hello;
@ -363,9 +364,9 @@ babel_read_ihu(struct babel_tlv *hdr, union babel_msg *m,
return PARSE_SUCCESS;
}
static int
static uint
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_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() */
static int
static uint
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;
@ -467,10 +468,10 @@ babel_read_update(struct babel_tlv *hdr, union babel_msg *m,
msg->metric = get_u16(&tlv->metric);
/* 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] = {};
if ((len < 0) || (len > TLV_OPT_LENGTH(tlv)))
if ((len < 0) || ((uint) len > TLV_OPT_LENGTH(tlv)))
return PARSE_ERROR;
switch (tlv->ae)
@ -536,13 +537,13 @@ babel_read_update(struct babel_tlv *hdr, union babel_msg *m,
return PARSE_SUCCESS;
}
static int
static uint
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_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
@ -558,7 +559,7 @@ babel_write_update(struct babel_tlv *hdr, union babel_msg *m,
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)
return 0;
@ -587,7 +588,7 @@ babel_write_update(struct babel_tlv *hdr, union babel_msg *m,
static int
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_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)
return PARSE_ERROR;
if (TLV_OPT_LENGTH(tlv) < (tlv->plen + 7)/8)
if (TLV_OPT_LENGTH(tlv) < BYTES(tlv->plen))
return PARSE_ERROR;
msg->plen = tlv->plen;
@ -629,14 +630,14 @@ babel_read_route_request(struct babel_tlv *hdr, union babel_msg *m,
return PARSE_IGNORE;
}
static int
static uint
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_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)
return 0;
@ -687,7 +688,7 @@ babel_read_seqno_request(struct babel_tlv *hdr, union babel_msg *m,
if (tlv->plen > MAX_PREFIX_LENGTH)
return PARSE_ERROR;
if (TLV_OPT_LENGTH(tlv) < (tlv->plen + 7)/8)
if (TLV_OPT_LENGTH(tlv) < BYTES(tlv->plen))
return PARSE_ERROR;
msg->plen = tlv->plen;
@ -704,14 +705,14 @@ babel_read_seqno_request(struct babel_tlv *hdr, union babel_msg *m,
return PARSE_IGNORE;
}
static int
static uint
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_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)
return 0;
@ -744,11 +745,11 @@ babel_read_tlv(struct babel_tlv *hdr,
return tlv_data[hdr->type].read_tlv(hdr, msg, state);
}
static int
static uint
babel_write_tlv(struct babel_tlv *hdr,
union babel_msg *msg,
struct babel_write_state *state,
int max_len)
uint max_len)
{
if ((msg->type <= BABEL_TLV_PADN) ||
(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.
*/
static int
static uint
babel_write_queue(struct babel_iface *ifa, list *queue)
{
struct babel_proto *p = ifa->proto;
@ -813,6 +814,9 @@ babel_write_queue(struct babel_iface *ifa, list *queue)
struct babel_msg_node *msg;
WALK_LIST_FIRST(msg, *queue)
{
if (pos >= end)
break;
int len = babel_write_tlv((struct babel_tlv *) pos, &msg->msg, &state, end - pos);
if (!len)
@ -823,7 +827,7 @@ babel_write_queue(struct babel_iface *ifa, list *queue)
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));
return plen;
@ -1027,7 +1031,7 @@ babel_tx_hook(sock *sk)
static int
babel_rx_hook(sock *sk, int len)
babel_rx_hook(sock *sk, uint len)
{
struct babel_iface *ifa = sk->data;
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_demand_mode = 0;
s->rem_detect_mult = 0;
s->rx_csn_known = 0;
s->poll_active = 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->detect_mult = ifa->cf->multiplier;
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->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
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)
n->neigh->data = NULL;
@ -853,7 +855,7 @@ void pipe_drain(int fd);
void pipe_kick(int fd);
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_session *s;
@ -1062,7 +1064,7 @@ bfd_preconfig(struct protocol *P UNUSED, struct config *c UNUSED)
}
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 *s = (struct bfd_config *) src;

View file

@ -14,6 +14,7 @@
#include "nest/iface.h"
#include "nest/protocol.h"
#include "nest/route.h"
#include "nest/password.h"
#include "conf/conf.h"
#include "lib/hash.h"
#include "lib/resource.h"
@ -52,6 +53,8 @@ struct bfd_iface_config
u32 idle_tx_int;
u8 multiplier;
u8 passive;
u8 auth_type; /* Authentication type (BFD_AUTH_*) */
list *passwords; /* Passwords for authentication */
};
struct bfd_neighbor
@ -116,7 +119,7 @@ struct bfd_session
u8 passive;
u8 poll_active;
u8 poll_scheduled;
u8 loc_state;
u8 rem_state;
u8 loc_diag;
@ -143,6 +146,11 @@ struct bfd_session
list request_list; /* List of client requests (struct bfd_request) */
bird_clock_t last_state_change; /* Time of last state change */
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_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_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_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 <a> bfd_neigh_local
%type <i> bfd_neigh_multihop
%type <i> bfd_neigh_multihop bfd_auth_type
CF_GRAMMAR
@ -62,12 +63,35 @@ bfd_proto:
bfd_iface_start:
{
this_ipatt = cfg_allocz(sizeof(struct bfd_iface_config));
add_tail(&BFD_CFG->patt_list, NODE this_ipatt);
init_list(&this_ipatt->ipn_list);
BFD_IFACE->min_rx_int = BFD_DEFAULT_MIN_RX_INT;
BFD_IFACE->min_tx_int = BFD_DEFAULT_MIN_TX_INT;
BFD_IFACE->idle_tx_int = BFD_DEFAULT_IDLE_TX_INT;
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:
@ -77,6 +101,17 @@ bfd_iface_item:
| IDLE TX INTERVAL expr_us { BFD_IFACE->idle_tx_int = $4; }
| MULTIPLIER expr { BFD_IFACE->multiplier = $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:
@ -89,10 +124,11 @@ bfd_iface_opt_list:
| '{' bfd_iface_opts '}'
;
bfd_iface: bfd_iface_start iface_patt_list_nopx bfd_iface_opt_list
{ add_tail(&BFD_CFG->patt_list, NODE this_ipatt); };
bfd_iface:
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; };

View file

@ -5,24 +5,60 @@
*/
#include "bfd.h"
#include "lib/mac.h"
struct bfd_ctl_packet
{
u8 vdiag; /* version and diagnostic */
u8 flags; /* state and flags */
u8 vdiag; /* Version and diagnostic */
u8 flags; /* State and flags */
u8 detect_mult;
u8 length;
u32 snd_id; /* sender ID, aka 'my discriminator' */
u32 rcv_id; /* receiver ID, aka 'your discriminator' */
u8 length; /* Whole packet length */
u32 snd_id; /* Sender ID, aka 'my discriminator' */
u32 rcv_id; /* Receiver ID, aka 'your discriminator' */
u32 des_min_tx_int;
u32 req_min_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_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)
{ 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)
{ 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; }
@ -59,6 +95,189 @@ bfd_format_flags(u8 flags, char *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
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)
pkt->flags |= BFD_FLAG_POLL;
if (s->ifa->cf->auth_type)
bfd_fill_authentication(p, s, pkt);
if (sk->tbuf != sk->tpos)
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);
}
#define DROP(DSC,VAL) do { err_dsc = DSC; err_val = VAL; goto drop; } while(0)
static int
bfd_rx_hook(sock *sk, int len)
bfd_rx_hook(sock *sk, uint len)
{
struct bfd_proto *p = sk->data;
struct bfd_ctl_packet *pkt = (struct bfd_ctl_packet *) sk->rbuf;
@ -151,10 +371,9 @@ bfd_rx_hook(sock *sk, int len)
return 1;
}
/* FIXME: better authentication handling and message */
if (pkt->flags & BFD_FLAG_AP)
DROP("authentication not supported", 0);
/* bfd_check_authentication() has its own error logging */
if (!bfd_check_authentication(p, s, pkt))
return 1;
u32 old_tx_int = s->des_min_tx_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);
return 1;
drop:
log(L_REMOTE "%s: Bad packet from %I - %s (%u)", p->p.name, sk->faddr, err_dsc, err_val);
drop:
LOG_PKT("Bad packet from %I - %s (%u)", sk->faddr, err_dsc, err_val);
return 1;
}

View file

@ -191,7 +191,7 @@ validate_as4_path(struct bgp_proto *p, struct adata *path)
}
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
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;
}
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[] = {
{ 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 */
NULL, NULL },
{ "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.
@ -575,7 +584,7 @@ bgp_encode_attrs(struct bgp_proto *p, byte *w, ea_list *attrs, int remains)
len = bgp_get_attr_len(a);
/* 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;
if (remains < len + 4)
@ -601,6 +610,7 @@ bgp_encode_attrs(struct bgp_proto *p, byte *w, ea_list *attrs, int remains)
break;
}
case EAF_TYPE_INT_SET:
case EAF_TYPE_LC_SET:
case EAF_TYPE_EC_SET:
{
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);
}
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
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;
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: ;
}
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);
break;
case EAF_TYPE_INT_SET:
case EAF_TYPE_LC_SET:
case EAF_TYPE_EC_SET:
{
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.
*/
static int
bgp_incoming_connection(sock *sk, int dummy UNUSED)
bgp_incoming_connection(sock *sk, uint dummy UNUSED)
{
struct bgp_proto *p;
int acc, hops;

View file

@ -191,7 +191,7 @@ struct bgp_bucket {
#define BGP_RX_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; }
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_kick_tx(void *vconn);
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);
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_AS4_PATH 0x11 /* [RFC4893] */
#define BA_AS4_AGGREGATOR 0x12
#define BA_LARGE_COMMUNITY 0x20 /* [draft-ietf-idr-large-community] */
/* 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,
TABLE, GATEWAY, DIRECT, RECURSIVE, MED, TTL, SECURITY, DETERMINISTIC,
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
@ -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)); })
CF_ADDTO(dynamic_attr, BGP_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 *
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++ = 2; /* Capability data length */
@ -931,7 +931,7 @@ bgp_parse_options(struct bgp_conn *conn, byte *opt, int len)
}
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_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; }
/* 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; }
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 */
@ -1256,16 +1256,15 @@ bgp_do_rx_update(struct bgp_conn *conn,
#else /* IPv6 version */
#define DO_NLRI(name) \
start = x = p->name##_start; \
x = p->name##_start; \
len = len0 = p->name##_len; \
if (len) \
{ \
if (len < 3) { err=9; goto done; } \
af = get_u16(x); \
sub = x[2]; \
x += 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 \
af = 0; \
@ -1291,15 +1290,15 @@ bgp_attach_next_hop(rta *a0, byte *x)
static void
bgp_do_rx_update(struct bgp_conn *conn,
byte *withdrawn, int withdrawn_len,
byte *nlri, int nlri_len,
byte *withdrawn UNUSED, int withdrawn_len,
byte *nlri UNUSED, int nlri_len,
byte *attrs, int attr_len)
{
struct bgp_proto *p = conn->bgp;
struct rte_src *src = p->p.main_source;
byte *start, *x;
byte *x;
int len, len0;
unsigned af, sub;
unsigned af;
rta *a0, *a = NULL;
ip_addr prefix;
int pxlen, err = 0;
@ -1375,11 +1374,11 @@ bgp_do_rx_update(struct bgp_conn *conn,
#endif
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;
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");
@ -1525,7 +1524,7 @@ bgp_log_error(struct bgp_proto *p, u8 class, char *msg, unsigned code, unsigned
}
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;
if (len < 21)
@ -1591,7 +1590,7 @@ bgp_rx_keepalive(struct bgp_conn *conn)
}
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;
@ -1680,7 +1679,7 @@ bgp_rx_packet(struct bgp_conn *conn, byte *pkt, unsigned len)
* bgp_rx_packet().
*/
int
bgp_rx(sock *sk, int size)
bgp_rx(sock *sk, uint size)
{
struct bgp_conn *conn = sk->data;
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))
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

View file

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

View file

@ -9,6 +9,7 @@
*/
#include "ospf.h"
#include "nest/password.h"
const char *ospf_is_names[] = {
@ -51,6 +52,20 @@ ifa_tx_length(struct ospf_iface *ifa)
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
ifa_bufsize(struct ospf_iface *ifa)
{
@ -67,13 +82,7 @@ ifa_flood_queue_size(struct ospf_iface *ifa)
int
ospf_iface_assure_bufsize(struct ospf_iface *ifa, uint plen)
{
struct ospf_proto *p = ifa->oa->po;
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;
plen += ifa->tx_hdrlen;
if (plen <= ifa->sk->tbsize)
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->ioprob = OSPF_I_OK;
ifa->tx_length = ifa_tx_length(ifa);
ifa->tx_hdrlen = ifa_tx_hdrlen(ifa);
ifa->check_link = ip->check_link;
ifa->ecmp_weight = ip->ecmp_weight;
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->inftransdelay = ip->inftransdelay;
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->passwords = ip->passwords;
ifa->instance_id = ip->instance_id;
@ -820,6 +831,9 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
/* Update passwords */
ifa->passwords = new->passwords;
/* Update header length */
ifa->tx_hdrlen = ifa_tx_hdrlen(ifa);
/* Remaining options are just for proper interfaces */
if (ifa->type == OSPF_IT_VLINK)
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
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)))
return 0;

View file

@ -105,7 +105,7 @@ invalid:
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)
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 */
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++)
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 (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 (cmp < CMP_NEWER)
@ -330,7 +330,7 @@ ospf_prepare_lsupd(struct ospf_proto *p, struct ospf_iface *ifa,
pkt = ospf_tx_buffer(ifa);
hlen = ospf_lsupd_hdrlen(p);
maxsize = ospf_pkt_maxsize(p, ifa);
maxsize = ospf_pkt_maxsize(ifa);
ospf_pkt_fill_hdr(ifa, pkt, LSUPD_P);
pos = hlen;

View file

@ -171,11 +171,7 @@ struct ospf_iface_patt
#define OSPF_RXBUF_MINSIZE 256 /* Minimal allowed size */
u8 instance_id;
u8 autype; /* 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 autype; /* OSPF_AUTH_*, not really used in OSPFv3 */
u8 strictnbma;
u8 check_link;
u8 ecmp_weight;
@ -325,6 +321,7 @@ struct ospf_iface
u8 marked; /* Used in OSPF reconfigure, 2 for force restart */
u16 rxbuf; /* Buffer size */
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 ecmp_weight; /* Weight used for ECMP */
u8 link_lsa_suppression; /* Suppression of Link-LSA origination */
@ -415,6 +412,11 @@ struct ospf_neighbor
#define ISM_UNLOOP 5 /* Link up */
#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 */
#define NEIGHBOR_DOWN 0
@ -446,7 +448,6 @@ struct ospf_neighbor
#define TRANS_WAIT 2 /* Waiting before the end of translation */
/* Generic option flags */
#define OPT_V6 0x01 /* OSPFv3, LSA relevant for IPv6 routing calculation */
#define OPT_E 0x02 /* Related to AS-external LSAs */
@ -482,7 +483,7 @@ struct ospf_packet
u8 autype; /* Undefined for OSPFv3 */
};
struct ospf_md5
struct ospf_auth_crypto
{
u16 zero;
u8 keyid;
@ -493,7 +494,7 @@ struct ospf_md5
union ospf_auth
{
u8 password[8];
struct ospf_md5 md5;
struct ospf_auth_crypto c32;
};
/* Packet types */
@ -890,8 +891,7 @@ void ospf_sh_neigh_info(struct ospf_neighbor *n);
/* packet.c */
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, int size);
int ospf_rx_hook(sock * sk, uint size);
// void ospf_tx_hook(sock * sk);
void ospf_err_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_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)
{ ospf_send_to(ifa, ifa->all_routers); }

View file

@ -11,6 +11,7 @@
#include "ospf.h"
#include "nest/password.h"
#include "lib/md5.h"
#include "lib/mac.h"
#include "lib/socket.h"
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->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->areaid = htonl(ifa->oa->areaid);
pkt->checksum = 0;
@ -31,25 +32,12 @@ ospf_pkt_fill_hdr(struct ospf_iface *ifa, void *buf, u8 h_type)
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() */
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);
uint plen = ntohs(pkt->length);
pkt->checksum = 0;
pkt->autype = ifa->autype;
@ -61,25 +49,25 @@ ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt)
switch (ifa->autype)
{
case OSPF_AUTH_SIMPLE:
passwd = password_find(ifa->passwords, 1);
if (!passwd)
pass = password_find(ifa->passwords, 1);
if (!pass)
{
log(L_ERR "No suitable password found for authentication");
return;
}
strncpy(auth->password, passwd->password, sizeof(auth->password));
strncpy(auth->password, pass->password, sizeof(auth->password));
case OSPF_AUTH_NONE:
{
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);
}
break;
case OSPF_AUTH_CRYPT:
passwd = password_find(ifa->passwords, 0);
if (!passwd)
pass = password_find(ifa->passwords, 0);
if (!pass)
{
log(L_ERR "No suitable password found for authentication");
return;
@ -100,20 +88,25 @@ ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt)
ifa->csn_use = now;
auth->md5.zero = 0;
auth->md5.keyid = passwd->id;
auth->md5.len = OSPF_AUTH_CRYPT_SIZE;
auth->md5.csn = htonl(ifa->csn);
uint auth_len = mac_type_length(pass->alg);
byte *auth_tail = ((byte *) pkt + *plen);
*plen += auth_len;
void *tail = ((void *) pkt) + plen;
char password[OSPF_AUTH_CRYPT_SIZE];
strncpy(password, passwd->password, sizeof(password));
ASSERT(*plen < ifa->sk->tbsize);
struct md5_context ctx;
md5_init(&ctx);
md5_update(&ctx, (char *) pkt, plen);
md5_update(&ctx, password, OSPF_AUTH_CRYPT_SIZE);
memcpy((byte *) tail, md5_final(&ctx), MD5_SIZE);
auth->c32.zero = 0;
auth->c32.keyid = pass->id;
auth->c32.len = auth_len;
auth->c32.csn = htonl(ifa->csn);
/* 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;
default:
@ -124,7 +117,7 @@ ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt)
/* We assume OSPFv2 in ospf_pkt_checkauth() */
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;
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;
case OSPF_AUTH_CRYPT:
if (auth->md5.len != OSPF_AUTH_CRYPT_SIZE)
DROP("invalid MD5 digest length", auth->md5.len);
pass = password_find_by_id(ifa->passwords, auth->c32.keyid);
if (!pass)
DROP("no suitable password found", auth->c32.keyid);
if (plen + OSPF_AUTH_CRYPT_SIZE > len)
DROP("length mismatch", len);
uint auth_len = mac_type_length(pass->alg);
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))
// 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;
}
pass = password_find_by_id(ifa->passwords, auth->md5.keyid);
if (!pass)
DROP("no suitable password found", auth->md5.keyid);
byte *auth_tail = ((byte *) pkt) + plen;
byte *auth_data = alloca(auth_len);
memcpy(auth_data, auth_tail, auth_len);
byte *tail = ((byte *) pkt) + plen;
char received[OSPF_AUTH_CRYPT_SIZE];
memcpy(received, tail, OSPF_AUTH_CRYPT_SIZE);
strncpy(tail, pass->password, OSPF_AUTH_CRYPT_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);
struct md5_context ctx;
md5_init(&ctx);
md5_update(&ctx, (byte *) pkt, plen + OSPF_AUTH_CRYPT_SIZE);
char *computed = md5_final(&ctx);
if (memcmp(received, computed, OSPF_AUTH_CRYPT_SIZE))
DROP("wrong MD5 digest", pass->id);
if (!mac_verify(pass->alg, pass->password, pass->length,
(byte *) pkt, plen + auth_len, auth_data))
DROP("wrong authentication code", pass->id);
if (n)
n->csn = rcv_csn;
@ -214,7 +210,7 @@ drop:
* non generic functions.
*/
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
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;
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 (ifa->autype == OSPF_AUTH_CRYPT)
plen += OSPF_AUTH_CRYPT_SIZE;
ospf_pkt_finalize(ifa, pkt);
}
ospf_pkt_finalize(ifa, pkt, &plen);
int done = sk_send_to(sk, plen, dst, 0);
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. */
/* 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_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
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
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;
}
static inline void *
static inline void * UNUSED
lsab_end(struct ospf_proto *p)
{
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)
{
u32 *pxb = ll->rest;
int j;
uint 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
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 */
}

View file

@ -156,12 +156,12 @@ radv_process_domain(struct radv_dnssl_config *cf)
char *dom = cf->domain;
char *dom_end = dom; /* Just to */
u8 *dlen_save = &cf->dlen_first;
int len;
uint len;
while (dom_end)
{
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)
return -1;
@ -349,7 +349,7 @@ radv_send_ra(struct radv_iface *ifa, int shutdown)
static int
radv_rx_hook(sock *sk, int size)
radv_rx_hook(sock *sk, uint size)
{
struct radv_iface *ifa = sk->data;
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
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;

View file

@ -104,15 +104,29 @@ rip_iface_start:
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();
if (!RIP_IFACE->auth_type != !RIP_IFACE->passwords)
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->mode)
RIP_IFACE->mode = (rip_cfg_is_v2() && (RIP_IFACE->version == RIP_V1)) ?
RIP_IM_BROADCAST : RIP_IM_MULTICAST;
if (RIP_IFACE->passwords)
{
struct password_item *pass;
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->max_garbage_time = MAX_(RIP_CFG->max_garbage_time, RIP_IFACE->garbage_time);
@ -153,7 +167,7 @@ rip_auth:
NONE { $$ = RIP_AUTH_NONE; }
| PLAINTEXT { $$ = RIP_AUTH_PLAIN; }
| CRYPTOGRAPHIC { $$ = RIP_AUTH_CRYPTO; }
| MD5 { $$ = RIP_AUTH_CRYPTO; }
| MD5 { $$ = RIP_AUTH_CRYPTO; } /* For backward compatibility */
;
rip_iface_opts:

View file

@ -12,16 +12,14 @@
#undef LOCAL_DEBUG
#include "rip.h"
#include "lib/md5.h"
#include "lib/mac.h"
#define RIP_CMD_REQUEST 1 /* want info */
#define RIP_CMD_RESPONSE 2 /* responding to request */
#define RIP_BLOCK_LENGTH 20
#define RIP_PASSWD_LENGTH 16
#define RIP_MD5_LENGTH 16
#define RIP_AF_IPV4 2
#define RIP_AF_AUTH 0xffff
@ -74,7 +72,7 @@ struct rip_auth_tail
{
u16 must_be_ffff;
u16 must_be_0001;
byte auth_data[];
byte auth_data[0];
};
/* 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
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;
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->packet_len = htons(*plen);
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->unused1 = 0;
auth->unused2 = 0;
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
* 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().
* 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);
tail->must_be_ffff = htons(0xffff);
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;
md5_init(&ctx);
md5_update(&ctx, (byte *) pkt, *plen);
memcpy(tail->auth_data, md5_final(&ctx), RIP_MD5_LENGTH);
/* Append key for keyed hash, append padding for HMAC (RFC 4822 2.5) */
if (pass->alg < ALG_HMAC)
strncpy(tail->auth_data, pass->password, auth_len);
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;
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);
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))
DROP("authentication data length mismatch", auth->auth_len);
if (data_len + auth_len2 != *plen)
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);
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;
}
char received[RIP_MD5_LENGTH];
memcpy(received, tail->auth_data, RIP_MD5_LENGTH);
strncpy(tail->auth_data, pass->password, RIP_MD5_LENGTH);
byte *auth_data = alloca(auth_len);
memcpy(auth_data, tail->auth_data, auth_len);
struct md5_context ctx;
md5_init(&ctx);
md5_update(&ctx, (byte *) pkt, *plen);
char *computed = md5_final(&ctx);
/* Append key for keyed hash, append padding for HMAC (RFC 4822 2.5) */
if (pass->alg < ALG_HMAC)
strncpy(tail->auth_data, pass->password, auth_len);
else
memset32(tail->auth_data, HMAC_MAGIC, auth_len / 4);
if (memcmp(received, computed, RIP_MD5_LENGTH))
DROP("wrong MD5 digest", pass->id);
if (!mac_verify(pass->alg, pass->password, pass->length,
(byte *) pkt, *plen, auth_data))
DROP("wrong authentication code", pass->id);
*plen = data_len;
n->csn = rcv_csn;
@ -632,7 +655,7 @@ rip_receive_response(struct rip_proto *p, struct rip_iface *ifa, struct rip_pack
}
static int
rip_rx_hook(sock *sk, int len)
rip_rx_hook(sock *sk, uint len)
{
struct rip_iface *ifa = sk->data;
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;
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
@ -687,12 +687,11 @@ rip_reconfigure_iface(struct rip_proto *p, struct rip_iface *ifa, struct rip_ifa
ifa->cf = new;
rip_iface_update_buffers(ifa);
if (ifa->next_regular > (now + new->update_time))
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)
rip_iface_update_state(ifa);
@ -1011,7 +1010,7 @@ rip_prepare_attrs(struct linpool *pool, ea_list *next, u8 metric, u16 tag)
}
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 */
if ((*rt)->attrs->source != RTS_RIP)
@ -1145,7 +1144,7 @@ rip_reconfigure(struct proto *P, struct proto_config *CF)
}
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);

View file

@ -34,7 +34,7 @@
#define RIP_NG_PORT 521 /* RIPng */
#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_INFINITY 16

View file

@ -244,7 +244,7 @@ static_add(struct proto *p, struct static_config *cf, struct static_route *r)
}
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;
@ -440,7 +440,7 @@ static_if_notify(struct proto *p, unsigned flags, struct iface *i)
}
int
static_rte_mergable(rte *pri, rte *sec)
static_rte_mergable(rte *pri UNUSED, rte *sec UNUSED)
{
return 1;
}

View file

@ -933,7 +933,7 @@ kif_do_scan(struct kif_proto *p)
/* Kernel sockets */
static int
krt_sock_hook(sock *sk, int size UNUSED)
krt_sock_hook(sock *sk, uint size UNUSED)
{
struct ks_msg 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 *
krt_sock_open(pool *pool, void *data, int table_id)
krt_sock_open(pool *pool, void *data, int table_id UNUSED)
{
sock *sk;
int fd;
@ -1120,7 +1120,7 @@ kif_sys_shutdown(struct kif_proto *p)
struct ifa *
kif_get_primary_ip(struct iface *i)
kif_get_primary_ip(struct iface *i UNUSED)
{
#if 0
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; }
#endif

View file

@ -28,6 +28,7 @@
#endif
#undef 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);
}
#ifdef IP_SENDSRCADDR
static inline void
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 */
#ifdef IP_SENDSRCADDR
struct cmsghdr *cm;
struct in_addr *sa;
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);
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)
{
struct ip *ip = hdr;
@ -200,7 +204,7 @@ sk_prepare_ip_header(sock *s, void *hdr, int dlen)
#endif
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
if (setkey)
@ -235,20 +239,20 @@ sk_set_min_ttl4(sock *s, int ttl)
}
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");
}
static inline int
sk_disable_mtu_disc4(sock *s)
sk_disable_mtu_disc4(sock *s UNUSED)
{
/* TODO: Set IP_DONTFRAG to 0 ? */
return 0;
}
static inline int
sk_disable_mtu_disc6(sock *s)
sk_disable_mtu_disc6(sock *s UNUSED)
{
/* TODO: Set IPV6_DONTFRAG to 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_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 */

View file

@ -503,7 +503,7 @@ nl_parse_multipath(struct krt_proto *p, struct rtattr *ra)
struct rtattr *a[BIRD_RTA_MAX];
struct rtnexthop *nh = RTA_DATA(ra);
struct mpnh *rv, *first, **last;
int len = RTA_PAYLOAD(ra);
unsigned len = RTA_PAYLOAD(ra);
first = NULL;
last = &first;
@ -1584,7 +1584,7 @@ nl_async_msg(struct nlmsghdr *h)
}
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 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 <linux/capability.h>
@ -70,3 +77,5 @@ drop_uid(uid_t uid)
if (setresuid(uid, uid, uid) < 0)
die("setresuid: %m");
}
#endif /* _BIRD_SYSPRIV_H_ */

View file

@ -9,7 +9,9 @@
/* Unfortunately, some glibc versions hide parts of RFC 3542 API
if _GNU_SOURCE is not defined. */
#define _GNU_SOURCE 1
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <stdio.h>
#include <stdlib.h>
@ -507,11 +509,11 @@ tm_format_datetime(char *x, struct timeformat *fmt_spec, bird_clock_t t)
* 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); }
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));
#ifdef HAVE_SIN_LEN
@ -542,7 +544,7 @@ void
sockaddr_fill(sockaddr *sa, int af, ip_addr a, struct iface *ifa, uint port)
{
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)
sockaddr_fill6((struct sockaddr_in6 *) sa, a, ifa, port);
else
@ -550,7 +552,7 @@ sockaddr_fill(sockaddr *sa, int af, ip_addr a, struct iface *ifa, uint port)
}
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);
*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;
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)
sockaddr_read6((struct sockaddr_in6 *) sa, a, ifa, port);
else
@ -770,7 +772,7 @@ sk_set_tos6(sock *s, int tos)
}
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 */
@ -2085,6 +2087,7 @@ watchdog_stop(void)
volatile int async_config_flag; /* Asynchronous reconfiguration/dump scheduled */
volatile int async_dump_flag;
volatile int async_shutdown_flag;
void
io_init(void)

View file

@ -899,7 +899,7 @@ krt_scan_timer_start(struct krt_proto *p)
}
static void
krt_scan_timer_stop(struct krt_proto *p)
krt_scan_timer_stop(struct krt_proto *p UNUSED)
{
krt_scan_count--;
@ -988,7 +988,7 @@ krt_store_tmp_attrs(rte *rt, struct ea_list *attrs)
}
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;
rte *e = *new;

View file

@ -288,18 +288,22 @@ log_switch(int debug, list *l, char *new_syslog_name)
current_log_list = l;
#ifdef HAVE_SYSLOG
char *old_syslog_name = current_syslog_name;
current_syslog_name = new_syslog_name;
if (old_syslog_name && new_syslog_name &&
!strcmp(old_syslog_name, new_syslog_name))
if (current_syslog_name && new_syslog_name &&
!strcmp(current_syslog_name, new_syslog_name))
return;
if (old_syslog_name)
if (current_syslog_name)
{
closelog();
xfree(current_syslog_name);
current_syslog_name = NULL;
}
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
}

View file

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