mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-11-17 00:28:42 +00:00
Merge branch 'master' into int-new
This commit is contained in:
commit
8860e991f6
@ -125,7 +125,7 @@ more_end(void)
|
||||
}
|
||||
|
||||
static void
|
||||
sig_handler(int signal)
|
||||
sig_handler(int signal UNUSED)
|
||||
{
|
||||
cleanup();
|
||||
exit(0);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
11
doc/Makefile
11
doc/Makefile
@ -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 $<)
|
||||
|
1179
doc/bird.sgml
1179
doc/bird.sgml
File diff suppressed because it is too large
Load Diff
144
doc/sbase/dist/birddoc/groff/mapping
vendored
144
doc/sbase/dist/birddoc/groff/mapping
vendored
@ -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.
|
||||
|
72
doc/sbase/dist/birddoc/html/mapping
vendored
72
doc/sbase/dist/birddoc/html/mapping
vendored
@ -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>"
|
||||
|
63
doc/sbase/dist/birddoc/latex2e/mapping
vendored
63
doc/sbase/dist/birddoc/latex2e/mapping
vendored
@ -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> "}" +
|
||||
|
4
doc/sbase/dist/fmt_latex2e.pl
vendored
4
doc/sbase/dist/fmt_latex2e.pl
vendored
@ -284,11 +284,11 @@ $latex2e->{postASP} = sub
|
||||
# for nameurl
|
||||
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++;
|
||||
|
@ -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: -->
|
||||
<!-- ================================================= -->
|
||||
|
149
filter/config.Y
149
filter/config.Y
@ -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;
|
||||
|
175
filter/filter.c
175
filter/filter.c
@ -99,6 +99,18 @@ pm_format(struct f_path_mask *p, buffer *buf)
|
||||
static inline int val_is_ip4(const struct f_val v)
|
||||
{ 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);
|
||||
{
|
||||
|
@ -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];
|
||||
};
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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, "]");
|
||||
}
|
||||
|
@ -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;
|
||||
|
1
lib/Doc
1
lib/Doc
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
16
lib/buffer.h
16
lib/buffer.h
@ -1,3 +1,17 @@
|
||||
/*
|
||||
* BIRD Library -- Generic Buffer Structure
|
||||
*
|
||||
* (c) 2013 Ondrej Zajicek <santiago@crfreenet.org>
|
||||
* (c) 2013 CZ.NIC z.s.p.o.
|
||||
*
|
||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||
*/
|
||||
|
||||
#ifndef _BIRD_BUFFER_H_
|
||||
#define _BIRD_BUFFER_H_
|
||||
|
||||
#include "lib/resource.h"
|
||||
#include "sysdep/config.h"
|
||||
|
||||
#define BUFFER(type) struct { type *data; uint used, size; }
|
||||
|
||||
@ -32,4 +46,4 @@
|
||||
|
||||
#define BUFFER_FLUSH(v) ({ (v).used = 0; })
|
||||
|
||||
|
||||
#endif /* _BIRD_BUFFER_H_ */
|
||||
|
27
lib/hash.h
27
lib/hash.h
@ -1,8 +1,18 @@
|
||||
/*
|
||||
* BIRD Library -- Generic Hash Table
|
||||
*
|
||||
* (c) 2013 Ondrej Zajicek <santiago@crfreenet.org>
|
||||
* (c) 2013 CZ.NIC z.s.p.o.
|
||||
*
|
||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||
*/
|
||||
|
||||
#ifndef _BIRD_HASH_H_
|
||||
#define _BIRD_HASH_H_
|
||||
|
||||
#define HASH(type) struct { type **data; uint count, order; }
|
||||
#define HASH_TYPE(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
|
||||
|
@ -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
289
lib/mac.c
Normal file
@ -0,0 +1,289 @@
|
||||
/*
|
||||
* BIRD Library -- Message Authentication Codes
|
||||
*
|
||||
* (c) 2016 Ondrej Zajicek <santiago@crfreenet.org>
|
||||
* (c) 2016 CZ.NIC z.s.p.o.
|
||||
*
|
||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||
*/
|
||||
|
||||
/**
|
||||
* DOC: Message authentication codes
|
||||
*
|
||||
* MAC algorithms are simple cryptographic tools for message authentication.
|
||||
* They use shared a secret key a and message text to generate authentication
|
||||
* code, which is then passed with the message to the other side, where the code
|
||||
* is verified. There are multiple families of MAC algorithms based on different
|
||||
* cryptographic primitives, BIRD implements two MAC families which use hash
|
||||
* functions.
|
||||
*
|
||||
* The first family is simply a cryptographic hash camouflaged as MAC algorithm.
|
||||
* Originally supposed to be (m|k)-hash (message is concatenated with key, and
|
||||
* that is hashed), but later it turned out that a raw hash is more practical.
|
||||
* This is used for cryptographic authentication in OSPFv2, RIP and BFD.
|
||||
*
|
||||
* The second family is the standard HMAC (RFC 2104), using inner and outer hash
|
||||
* to process key and message. HMAC (with SHA) is used in advanced OSPF and RIP
|
||||
* authentication (RFC 5709, RFC 4822).
|
||||
*/
|
||||
|
||||
#include "lib/mac.h"
|
||||
#include "lib/md5.h"
|
||||
#include "lib/sha1.h"
|
||||
#include "lib/sha256.h"
|
||||
#include "lib/sha512.h"
|
||||
|
||||
|
||||
/*
|
||||
* Internal hash calls
|
||||
*/
|
||||
|
||||
static inline void
|
||||
hash_init(struct mac_context *mctx, struct hash_context *hctx)
|
||||
{ mctx->type->hash_init(hctx); }
|
||||
|
||||
static inline void
|
||||
hash_update(struct mac_context *mctx, struct hash_context *hctx, const byte *buf, uint len)
|
||||
{ mctx->type->hash_update(hctx, buf, len); }
|
||||
|
||||
static inline byte *
|
||||
hash_final(struct mac_context *mctx, struct hash_context *hctx)
|
||||
{ return mctx->type->hash_final(hctx); }
|
||||
|
||||
static inline void
|
||||
hash_buffer(struct mac_context *mctx, byte *outbuf, const byte *buffer, uint length)
|
||||
{
|
||||
struct hash_context hctx;
|
||||
|
||||
hash_init(mctx, &hctx);
|
||||
hash_update(mctx, &hctx, buffer, length);
|
||||
memcpy(outbuf, hash_final(mctx, &hctx), mctx->type->hash_size);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (not-really-MAC) Hash
|
||||
*/
|
||||
|
||||
static void
|
||||
nrmh_init(struct mac_context *ctx, const byte *key UNUSED, uint keylen UNUSED)
|
||||
{
|
||||
struct nrmh_context *ct = (void *) ctx;
|
||||
hash_init(ctx, &ct->ictx);
|
||||
}
|
||||
|
||||
static void
|
||||
nrmh_update(struct mac_context *ctx, const byte *data, uint datalen)
|
||||
{
|
||||
struct nrmh_context *ct = (void *) ctx;
|
||||
hash_update(ctx, &ct->ictx, data, datalen);
|
||||
}
|
||||
|
||||
static byte *
|
||||
nrmh_final(struct mac_context *ctx)
|
||||
{
|
||||
struct nrmh_context *ct = (void *) ctx;
|
||||
return hash_final(ctx, &ct->ictx);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* HMAC
|
||||
*/
|
||||
|
||||
static void
|
||||
hmac_init(struct mac_context *ctx, const byte *key, uint keylen)
|
||||
{
|
||||
struct hmac_context *ct = (void *) ctx;
|
||||
uint block_size = ctx->type->block_size;
|
||||
uint hash_size = ctx->type->hash_size;
|
||||
|
||||
byte *keybuf = alloca(block_size);
|
||||
byte *buf = alloca(block_size);
|
||||
uint i;
|
||||
|
||||
/* Hash the key if necessary */
|
||||
if (keylen <= block_size)
|
||||
{
|
||||
memcpy(keybuf, key, keylen);
|
||||
memset(keybuf + keylen, 0, block_size - keylen);
|
||||
}
|
||||
else
|
||||
{
|
||||
hash_buffer(ctx, keybuf, key, keylen);
|
||||
memset(keybuf + hash_size, 0, block_size - hash_size);
|
||||
}
|
||||
|
||||
/* Initialize the inner digest */
|
||||
hash_init(ctx, &ct->ictx);
|
||||
for (i = 0; i < block_size; i++)
|
||||
buf[i] = keybuf[i] ^ 0x36;
|
||||
hash_update(ctx, &ct->ictx, buf, block_size);
|
||||
|
||||
/* Initialize the outer digest */
|
||||
hash_init(ctx, &ct->octx);
|
||||
for (i = 0; i < block_size; i++)
|
||||
buf[i] = keybuf[i] ^ 0x5c;
|
||||
hash_update(ctx, &ct->octx, buf, block_size);
|
||||
}
|
||||
|
||||
static void
|
||||
hmac_update(struct mac_context *ctx, const byte *data, uint datalen)
|
||||
{
|
||||
struct hmac_context *ct = (void *) ctx;
|
||||
|
||||
/* Just update the inner digest */
|
||||
hash_update(ctx, &ct->ictx, data, datalen);
|
||||
}
|
||||
|
||||
static byte *
|
||||
hmac_final(struct mac_context *ctx)
|
||||
{
|
||||
struct hmac_context *ct = (void *) ctx;
|
||||
|
||||
/* Finish the inner digest */
|
||||
byte *isha = hash_final(ctx, &ct->ictx);
|
||||
|
||||
/* Finish the outer digest */
|
||||
hash_update(ctx, &ct->octx, isha, ctx->type->hash_size);
|
||||
return hash_final(ctx, &ct->octx);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Common code
|
||||
*/
|
||||
|
||||
#define HASH_DESC(name, px, PX) \
|
||||
{ name, PX##_SIZE, sizeof(struct nrmh_context), nrmh_init, nrmh_update, nrmh_final, \
|
||||
PX##_SIZE, PX##_BLOCK_SIZE, px##_init, px##_update, px##_final }
|
||||
|
||||
#define HMAC_DESC(name, px, PX) \
|
||||
{ name, PX##_SIZE, sizeof(struct hmac_context), hmac_init, hmac_update, hmac_final, \
|
||||
PX##_SIZE, PX##_BLOCK_SIZE, px##_init, px##_update, px##_final }
|
||||
|
||||
const struct mac_desc mac_table[ALG_MAX] = {
|
||||
[ALG_MD5] = HASH_DESC("Keyed MD5", md5, MD5),
|
||||
[ALG_SHA1] = HASH_DESC("Keyed SHA-1", sha1, SHA1),
|
||||
[ALG_SHA224] = HASH_DESC("Keyed SHA-224", sha224, SHA224),
|
||||
[ALG_SHA256] = HASH_DESC("Keyed SHA-256", sha256, SHA256),
|
||||
[ALG_SHA384] = HASH_DESC("Keyed SHA-384", sha384, SHA384),
|
||||
[ALG_SHA512] = HASH_DESC("Keyed SHA-512", sha512, SHA512),
|
||||
[ALG_HMAC_MD5] = HMAC_DESC("HMAC-MD5", md5, MD5),
|
||||
[ALG_HMAC_SHA1] = HMAC_DESC("HMAC-SHA-1", sha1, SHA1),
|
||||
[ALG_HMAC_SHA224] = HMAC_DESC("HMAC-SHA-224", sha224, SHA224),
|
||||
[ALG_HMAC_SHA256] = HMAC_DESC("HMAC-SHA-256", sha256, SHA256),
|
||||
[ALG_HMAC_SHA384] = HMAC_DESC("HMAC-SHA-384", sha384, SHA384),
|
||||
[ALG_HMAC_SHA512] = HMAC_DESC("HMAC-SHA-512", sha512, SHA512),
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* mac_init - initialize MAC algorithm
|
||||
* @ctx: context to initialize
|
||||
* @id: MAC algorithm ID
|
||||
* @key: MAC key
|
||||
* @keylen: MAC key length
|
||||
*
|
||||
* Initialize MAC context @ctx for algorithm @id (e.g., %ALG_HMAC_SHA1), with
|
||||
* key @key of length @keylen. After that, message data could be added using
|
||||
* mac_update() function.
|
||||
*/
|
||||
void
|
||||
mac_init(struct mac_context *ctx, uint id, const byte *key, uint keylen)
|
||||
{
|
||||
ctx->type = &mac_table[id];
|
||||
ctx->type->init(ctx, key, keylen);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* mac_update - add more data to MAC algorithm
|
||||
* @ctx: MAC context
|
||||
* @data: data to add
|
||||
* @datalen: length of data
|
||||
*
|
||||
* Push another @datalen bytes of data pointed to by @data into the MAC
|
||||
* algorithm currently in @ctx. Can be called multiple times for the same MAC
|
||||
* context. It has the same effect as concatenating all the data together and
|
||||
* passing them at once.
|
||||
*/
|
||||
void mac_update(struct mac_context *ctx, const byte *data, uint datalen)
|
||||
{ DUMMY; }
|
||||
|
||||
/**
|
||||
* mac_final - finalize MAC algorithm
|
||||
* @ctx: MAC context
|
||||
*
|
||||
* Finish MAC computation and return a pointer to the result. No more
|
||||
* @mac_update() calls could be done, but the context may be reinitialized
|
||||
* later.
|
||||
*
|
||||
* Note that the returned pointer points into data in the @ctx context. If it
|
||||
* ceases to exist, the pointer becomes invalid.
|
||||
*/
|
||||
byte *mac_final(struct mac_context *ctx)
|
||||
{ DUMMY; }
|
||||
|
||||
/**
|
||||
* mac_cleanup - cleanup MAC context
|
||||
* @ctx: MAC context
|
||||
*
|
||||
* Cleanup MAC context after computation (by filling with zeros). Not strictly
|
||||
* necessary, just to erase sensitive data from stack. This also invalidates the
|
||||
* pointer returned by @mac_final().
|
||||
*/
|
||||
void mac_cleanup(struct mac_context *ctx)
|
||||
{ DUMMY; }
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* mac_fill - compute and fill MAC
|
||||
* @id: MAC algorithm ID
|
||||
* @key: secret key
|
||||
* @keylen: key length
|
||||
* @data: message data
|
||||
* @datalen: message length
|
||||
* @mac: place to fill MAC
|
||||
*
|
||||
* Compute MAC for specified key @key and message @data using algorithm @id and
|
||||
* copy it to buffer @mac. mac_fill() is a shortcut function doing all usual
|
||||
* steps for transmitted messages.
|
||||
*/
|
||||
void
|
||||
mac_fill(uint id, const byte *key, uint keylen, const byte *data, uint datalen, byte *mac)
|
||||
{
|
||||
struct mac_context ctx;
|
||||
|
||||
mac_init(&ctx, id, key, keylen);
|
||||
mac_update(&ctx, data, datalen);
|
||||
memcpy(mac, mac_final(&ctx), mac_get_length(&ctx));
|
||||
mac_cleanup(&ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* mac_verify - compute and verify MAC
|
||||
* @id: MAC algorithm ID
|
||||
* @key: secret key
|
||||
* @keylen: key length
|
||||
* @data: message data
|
||||
* @datalen: message length
|
||||
* @mac: received MAC
|
||||
*
|
||||
* Compute MAC for specified key @key and message @data using algorithm @id and
|
||||
* compare it with received @mac, return whether they are the same. mac_verify()
|
||||
* is a shortcut function doing all usual steps for received messages.
|
||||
*/
|
||||
int
|
||||
mac_verify(uint id, const byte *key, uint keylen, const byte *data, uint datalen, const byte *mac)
|
||||
{
|
||||
struct mac_context ctx;
|
||||
|
||||
mac_init(&ctx, id, key, keylen);
|
||||
mac_update(&ctx, data, datalen);
|
||||
int res = !memcmp(mac, mac_final(&ctx), mac_get_length(&ctx));
|
||||
mac_cleanup(&ctx);
|
||||
|
||||
return res;
|
||||
}
|
121
lib/mac.h
Normal file
121
lib/mac.h
Normal file
@ -0,0 +1,121 @@
|
||||
/*
|
||||
* BIRD Library -- Message Authentication Codes
|
||||
*
|
||||
* (c) 2016 Ondrej Zajicek <santiago@crfreenet.org>
|
||||
* (c) 2016 CZ.NIC z.s.p.o.
|
||||
*
|
||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||
*/
|
||||
|
||||
#ifndef _BIRD_MAC_H_
|
||||
#define _BIRD_MAC_H_
|
||||
|
||||
#include "nest/bird.h"
|
||||
#include "lib/sha512.h"
|
||||
|
||||
|
||||
#define ALG_UNDEFINED 0
|
||||
#define ALG_MD5 0x01
|
||||
#define ALG_SHA1 0x02
|
||||
#define ALG_SHA224 0x03
|
||||
#define ALG_SHA256 0x04
|
||||
#define ALG_SHA384 0x05
|
||||
#define ALG_SHA512 0x06
|
||||
#define ALG_HMAC 0x10
|
||||
#define ALG_HMAC_MD5 0x11
|
||||
#define ALG_HMAC_SHA1 0x12
|
||||
#define ALG_HMAC_SHA224 0x13
|
||||
#define ALG_HMAC_SHA256 0x14
|
||||
#define ALG_HMAC_SHA384 0x15
|
||||
#define ALG_HMAC_SHA512 0x16
|
||||
#define ALG_MAX 0x17
|
||||
|
||||
/* These are maximums for HASH/MAC lengths and required context space */
|
||||
#define MAX_HASH_SIZE SHA512_SIZE
|
||||
#define HASH_STORAGE sizeof(struct sha512_context)
|
||||
#define MAC_STORAGE sizeof(struct hmac_context)
|
||||
|
||||
/* This value is used by several IETF protocols for padding */
|
||||
#define HMAC_MAGIC htonl(0x878FE1F3)
|
||||
|
||||
/* Generic context used by hash functions */
|
||||
struct hash_context
|
||||
{
|
||||
u8 data[HASH_STORAGE];
|
||||
u64 align[0];
|
||||
};
|
||||
|
||||
/* Context for embedded hash (not-really-MAC hash) */
|
||||
struct nrmh_context {
|
||||
const struct mac_desc *type;
|
||||
struct hash_context ictx;
|
||||
};
|
||||
|
||||
/* Context for hash based HMAC */
|
||||
struct hmac_context {
|
||||
const struct mac_desc *type;
|
||||
struct hash_context ictx;
|
||||
struct hash_context octx;
|
||||
};
|
||||
|
||||
/* Generic context used by MAC functions */
|
||||
struct mac_context
|
||||
{
|
||||
const struct mac_desc *type;
|
||||
u8 data[MAC_STORAGE - sizeof(void *)];
|
||||
u64 align[0];
|
||||
};
|
||||
|
||||
/* Union to satisfy C aliasing rules */
|
||||
union mac_context_union {
|
||||
struct mac_context mac;
|
||||
struct nrmh_context nrmh;
|
||||
struct hmac_context hmac;
|
||||
};
|
||||
|
||||
|
||||
struct mac_desc {
|
||||
const char *name; /* Name of MAC algorithm */
|
||||
uint mac_length; /* Length of authentication code */
|
||||
uint ctx_length; /* Length of algorithm context */
|
||||
void (*init)(struct mac_context *ctx, const byte *key, uint keylen);
|
||||
void (*update)(struct mac_context *ctx, const byte *data, uint datalen);
|
||||
byte *(*final)(struct mac_context *ctx);
|
||||
|
||||
uint hash_size; /* Hash length, for hash-based MACs */
|
||||
uint block_size; /* Hash block size, for hash-based MACs */
|
||||
void (*hash_init)(struct hash_context *ctx);
|
||||
void (*hash_update)(struct hash_context *ctx, const byte *data, uint datalen);
|
||||
byte *(*hash_final)(struct hash_context *ctx);
|
||||
};
|
||||
|
||||
extern const struct mac_desc mac_table[ALG_MAX];
|
||||
|
||||
static inline const char *mac_type_name(uint id)
|
||||
{ return mac_table[id].name; }
|
||||
|
||||
static inline uint mac_type_length(uint id)
|
||||
{ return mac_table[id].mac_length; }
|
||||
|
||||
static inline const char *mac_get_name(struct mac_context *ctx)
|
||||
{ return ctx->type->name; }
|
||||
|
||||
static inline uint mac_get_length(struct mac_context *ctx)
|
||||
{ return ctx->type->mac_length; }
|
||||
|
||||
void mac_init(struct mac_context *ctx, uint id, const byte *key, uint keylen);
|
||||
|
||||
static inline void mac_update(struct mac_context *ctx, const byte *data, uint datalen)
|
||||
{ ctx->type->update(ctx, data, datalen); }
|
||||
|
||||
static inline byte *mac_final(struct mac_context *ctx)
|
||||
{ return ctx->type->final(ctx); }
|
||||
|
||||
static inline void mac_cleanup(struct mac_context *ctx)
|
||||
{ memset(ctx, 0, ctx->type->ctx_length); }
|
||||
|
||||
void mac_fill(uint id, const byte *key, uint keylen, const byte *data, uint datalen, byte *mac);
|
||||
int mac_verify(uint id, const byte *key, uint keylen, const byte *data, uint datalen, const byte *mac);
|
||||
|
||||
|
||||
#endif /* _BIRD_MAC_H_ */
|
81
lib/md5.c
81
lib/md5.c
@ -39,8 +39,10 @@ static void md5_transform(u32 buf[4], u32 const in[16]);
|
||||
* initialization constants.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
21
lib/md5.h
21
lib/md5.h
@ -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_ */
|
||||
|
95
lib/sha1.c
95
lib/sha1.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* BIRD Library -- SHA-1 Hash Function (FIPS 180-1, RFC 3174) and HMAC-SHA-1
|
||||
* BIRD Library -- SHA-1 Hash Function (FIPS 180-1, RFC 3174)
|
||||
*
|
||||
* (c) 2015 CZ.NIC z.s.p.o.
|
||||
*
|
||||
@ -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);
|
||||
}
|
||||
|
30
lib/sha1.h
30
lib/sha1.h
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* BIRD Library -- SHA-1 Hash Function (FIPS 180-1, RFC 3174) and HMAC-SHA-1
|
||||
* BIRD Library -- SHA-1 Hash Function (FIPS 180-1, RFC 3174)
|
||||
*
|
||||
* (c) 2015 CZ.NIC z.s.p.o.
|
||||
*
|
||||
@ -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_ */
|
||||
|
150
lib/sha256.c
150
lib/sha256.c
@ -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);
|
||||
}
|
||||
|
42
lib/sha256.h
42
lib/sha256.h
@ -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_ */
|
||||
|
150
lib/sha512.c
150
lib/sha512.c
@ -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);
|
||||
}
|
||||
|
44
lib/sha512.h
44
lib/sha512.h
@ -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_ */
|
||||
|
@ -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 */
|
||||
|
19
lib/string.h
19
lib/string.h
@ -30,6 +30,25 @@ static inline char *xbasename(const char *str)
|
||||
return s ? s+1 : (char *) str;
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -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;
|
||||
|
||||
|
135
nest/a-set.c
135
nest/a-set.c
@ -116,7 +116,7 @@ int
|
||||
ec_set_format(struct adata *set, int from, byte *buf, uint size)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
32
nest/attrs.h
32
nest/attrs.h
@ -68,6 +68,7 @@ int as_path_match(struct adata *path, struct f_path_mask *mask);
|
||||
/* Transitive bit (for first u32 half of EC) */
|
||||
#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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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]])
|
||||
|
@ -100,7 +100,8 @@ static struct resclass olock_class = {
|
||||
sizeof(struct object_lock),
|
||||
olock_free,
|
||||
olock_dump,
|
||||
NULL
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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++)
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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); }
|
||||
|
@ -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; };
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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)); })
|
||||
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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); }
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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++)
|
||||
{
|
||||
|
@ -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 */
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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_ */
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user