Merge remote-tracking branch 'origin/mq-static-analysis'
This commit is contained in:
commit
048eb2ddf1
35 changed files with 253 additions and 251 deletions
|
@ -184,6 +184,15 @@ check: tests tests_run
|
||||||
tests: $(tests_targets)
|
tests: $(tests_targets)
|
||||||
tests_run: $(tests_targets_ok)
|
tests_run: $(tests_targets_ok)
|
||||||
|
|
||||||
|
STATIC_CHECKERS_ENABLE := nullability.NullableDereferenced nullability.NullablePassedToNonnull nullability.NullableReturnedFromNonnull optin.portability.UnixAPI valist.CopyToSelf valist.Uninitialized valist.Unterminated
|
||||||
|
STATIC_CHECKERS_DISABLE := deadcode.DeadStores
|
||||||
|
STATIC_SCAN_FLAGS := -o $(objdir)/static-scan/ $(addprefix -enable-checker ,$(STATIC_CHECKERS_ENABLE)) $(addprefix -disable-checker ,$(STATIC_CHECKERS_DISABLE))
|
||||||
|
|
||||||
|
static-scan:
|
||||||
|
$(E)echo Running static code analysis
|
||||||
|
$(Q)$(MAKE) clean
|
||||||
|
$(Q)scan-build $(STATIC_SCAN_FLAGS) $(MAKE) -$(MAKEFLAGS)
|
||||||
|
|
||||||
tags:
|
tags:
|
||||||
cd $(srcdir) ; etags -lc `find $(dirs) -name *.[chY]`
|
cd $(srcdir) ; etags -lc `find $(dirs) -name *.[chY]`
|
||||||
|
|
||||||
|
|
|
@ -169,7 +169,7 @@ WHITE [ \t]
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
l = bstrtoul10(yytext, &e);
|
l = bstrtoul10(yytext, &e);
|
||||||
if (e && (*e != ':') || (errno == ERANGE) || (l >> 32))
|
if (!e || (*e != ':') || (errno == ERANGE) || (l >> 32))
|
||||||
cf_error("ASN out of range");
|
cf_error("ASN out of range");
|
||||||
|
|
||||||
if (l >> 16)
|
if (l >> 16)
|
||||||
|
@ -187,7 +187,7 @@ WHITE [ \t]
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
l = bstrtoul10(e+1, &e);
|
l = bstrtoul10(e+1, &e);
|
||||||
if (e && *e || (errno == ERANGE) || (l >> len2))
|
if (!e || *e || (errno == ERANGE) || (l >> len2))
|
||||||
cf_error("Number out of range");
|
cf_error("Number out of range");
|
||||||
cf_lval.i64 |= l;
|
cf_lval.i64 |= l;
|
||||||
|
|
||||||
|
@ -214,13 +214,13 @@ WHITE [ \t]
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
l = bstrtoul10(yytext+2, &e);
|
l = bstrtoul10(yytext+2, &e);
|
||||||
if (e && (*e != ':') || (errno == ERANGE) || (l >> len1))
|
if (!e || (*e != ':') || (errno == ERANGE) || (l >> len1))
|
||||||
cf_error("ASN out of range");
|
cf_error("ASN out of range");
|
||||||
cf_lval.i64 |= ((u64) l) << len2;
|
cf_lval.i64 |= ((u64) l) << len2;
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
l = bstrtoul10(e+1, &e);
|
l = bstrtoul10(e+1, &e);
|
||||||
if (e && *e || (errno == ERANGE) || (l >> len2))
|
if (!e || *e || (errno == ERANGE) || (l >> len2))
|
||||||
cf_error("Number out of range");
|
cf_error("Number out of range");
|
||||||
cf_lval.i64 |= l;
|
cf_lval.i64 |= l;
|
||||||
|
|
||||||
|
@ -242,7 +242,7 @@ WHITE [ \t]
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
l = bstrtoul10(e, &e);
|
l = bstrtoul10(e, &e);
|
||||||
if (e && *e || (errno == ERANGE) || (l >> 16))
|
if (!e || *e || (errno == ERANGE) || (l >> 16))
|
||||||
cf_error("Number out of range");
|
cf_error("Number out of range");
|
||||||
cf_lval.i64 |= l;
|
cf_lval.i64 |= l;
|
||||||
|
|
||||||
|
@ -266,7 +266,7 @@ WHITE [ \t]
|
||||||
unsigned long int l;
|
unsigned long int l;
|
||||||
errno = 0;
|
errno = 0;
|
||||||
l = bstrtoul16(yytext+2, &e);
|
l = bstrtoul16(yytext+2, &e);
|
||||||
if (e && *e || errno == ERANGE || (unsigned long int)(unsigned int) l != l)
|
if (!e || *e || errno == ERANGE || (unsigned long int)(unsigned int) l != l)
|
||||||
cf_error("Number out of range");
|
cf_error("Number out of range");
|
||||||
cf_lval.i = l;
|
cf_lval.i = l;
|
||||||
return NUM;
|
return NUM;
|
||||||
|
@ -277,7 +277,7 @@ WHITE [ \t]
|
||||||
unsigned long int l;
|
unsigned long int l;
|
||||||
errno = 0;
|
errno = 0;
|
||||||
l = bstrtoul10(yytext, &e);
|
l = bstrtoul10(yytext, &e);
|
||||||
if (e && *e || errno == ERANGE || (unsigned long int)(unsigned int) l != l)
|
if (!e || *e || errno == ERANGE || (unsigned long int)(unsigned int) l != l)
|
||||||
cf_error("Number out of range");
|
cf_error("Number out of range");
|
||||||
cf_lval.i = l;
|
cf_lval.i = l;
|
||||||
return NUM;
|
return NUM;
|
||||||
|
|
13
configure.ac
13
configure.ac
|
@ -24,6 +24,12 @@ AC_ARG_ENABLE([debug-generated],
|
||||||
[enable_debug_generated=no]
|
[enable_debug_generated=no]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
AC_ARG_ENABLE([debug-expensive],
|
||||||
|
[AS_HELP_STRING([--enable-debug-expensive], [enable expensive consistency checks (implies --enable-debug) @<:@no@:>@])],
|
||||||
|
[],
|
||||||
|
[enable_debug_expensive=no]
|
||||||
|
)
|
||||||
|
|
||||||
AC_ARG_ENABLE([memcheck],
|
AC_ARG_ENABLE([memcheck],
|
||||||
[AS_HELP_STRING([--enable-memcheck], [check memory allocations when debugging @<:@yes@:>@])],
|
[AS_HELP_STRING([--enable-memcheck], [check memory allocations when debugging @<:@yes@:>@])],
|
||||||
[],
|
[],
|
||||||
|
@ -72,6 +78,9 @@ AC_ARG_VAR([FLEX], [location of the Flex program])
|
||||||
AC_ARG_VAR([BISON], [location of the Bison program])
|
AC_ARG_VAR([BISON], [location of the Bison program])
|
||||||
AC_ARG_VAR([M4], [location of the M4 program])
|
AC_ARG_VAR([M4], [location of the M4 program])
|
||||||
|
|
||||||
|
if test "$enable_debug_expensive" = yes; then
|
||||||
|
enable_debug=yes
|
||||||
|
fi
|
||||||
|
|
||||||
if test "$srcdir" = . ; then
|
if test "$srcdir" = . ; then
|
||||||
# Building in current directory => create obj directory holding all objects
|
# Building in current directory => create obj directory holding all objects
|
||||||
|
@ -388,6 +397,10 @@ if test "$enable_debug" = yes ; then
|
||||||
AC_CHECK_LIB([efence], [malloc])
|
AC_CHECK_LIB([efence], [malloc])
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if test "enable_debug_expensive" = yes ; then
|
||||||
|
AC_DEFINE([ENABLE_EXPENSIVE_CHECKS], [1], [Define to 1 if you want to run expensive consistency checks.])
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
CLIENT=birdcl
|
CLIENT=birdcl
|
||||||
|
|
153
filter/config.Y
153
filter/config.Y
|
@ -185,159 +185,6 @@ f_generate_empty(struct f_dynamic_attr dyn)
|
||||||
return f_new_inst(FI_EA_SET, f_new_inst(FI_CONSTANT, empty), dyn);
|
return f_new_inst(FI_EA_SET, f_new_inst(FI_CONSTANT, empty), dyn);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
|
|
||||||
static inline struct f_inst *
|
|
||||||
f_generate_dpair(struct f_inst *t1, struct f_inst *t2)
|
|
||||||
{
|
|
||||||
struct f_inst *rv;
|
|
||||||
|
|
||||||
if ((t1->fi_code == FI_CONSTANT) && (t2->fi_code == FI_CONSTANT)) {
|
|
||||||
if ((t1->val.type != T_INT) || (t2->val.type != T_INT))
|
|
||||||
cf_error( "Can't operate with value of non-integer type in pair constructor");
|
|
||||||
|
|
||||||
check_u16(t1->a[1].i);
|
|
||||||
check_u16(t2->a[1].i);
|
|
||||||
|
|
||||||
rv = f_new_inst(FI_CONSTANT);
|
|
||||||
rv->val = (struct f_val) {
|
|
||||||
.type = T_PAIR,
|
|
||||||
.val.i = pair(t1->a[1].i, t2->a[1].i),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
rv = f_new_inst(FI_PAIR_CONSTRUCT);
|
|
||||||
rv->a[0].p = t1;
|
|
||||||
rv->a[1].p = t2;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline struct f_inst *
|
|
||||||
f_generate_ec(u16 kind, struct f_inst *tk, struct f_inst *tv)
|
|
||||||
{
|
|
||||||
struct f_inst *rv;
|
|
||||||
int c1 = 0, c2 = 0, ipv4_used = 0;
|
|
||||||
u32 key = 0, val2 = 0;
|
|
||||||
|
|
||||||
if (tk->fi_code == FI_CONSTANT) {
|
|
||||||
c1 = 1;
|
|
||||||
struct f_val *val = &(tk->val);
|
|
||||||
|
|
||||||
if (val->type == T_INT) {
|
|
||||||
ipv4_used = 0; key = val->val.i;
|
|
||||||
}
|
|
||||||
else if (tk->val.type == T_QUAD) {
|
|
||||||
ipv4_used = 1; key = val->val.i;
|
|
||||||
}
|
|
||||||
else if ((val->type == T_IP) && ipa_is_ip4(val->val.ip)) {
|
|
||||||
ipv4_used = 1; key = ipa_to_u32(val->val.ip);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
cf_error("Can't operate with key of non-integer/IPv4 type in EC constructor");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tv->fi_code == FI_CONSTANT) {
|
|
||||||
if (tv->val.type != T_INT)
|
|
||||||
cf_error("Can't operate with value of non-integer type in EC constructor");
|
|
||||||
c2 = 1;
|
|
||||||
val2 = tv->val.val.i;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c1 && c2) {
|
|
||||||
u64 ec;
|
|
||||||
|
|
||||||
if (kind == EC_GENERIC) {
|
|
||||||
ec = ec_generic(key, val2);
|
|
||||||
}
|
|
||||||
else if (ipv4_used) {
|
|
||||||
check_u16(val2);
|
|
||||||
ec = ec_ip4(kind, key, val2);
|
|
||||||
}
|
|
||||||
else if (key < 0x10000) {
|
|
||||||
ec = ec_as2(kind, key, val2);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
check_u16(val2);
|
|
||||||
ec = ec_as4(kind, key, val2);
|
|
||||||
}
|
|
||||||
|
|
||||||
rv = f_new_inst(FI_CONSTANT);
|
|
||||||
rv->val = (struct f_val) {
|
|
||||||
.type = T_EC,
|
|
||||||
.val.ec = ec,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
rv = f_new_inst(FI_EC_CONSTRUCT);
|
|
||||||
rv->aux = kind;
|
|
||||||
rv->a[0].p = tk;
|
|
||||||
rv->a[1].p = 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->fi_code == FI_CONSTANT) && (t2->fi_code == FI_CONSTANT) && (t3->fi_code == FI_CONSTANT)) {
|
|
||||||
if ((t1->val.type != T_INT) || (t2->val.type != T_INT) || (t3->val.type != T_INT))
|
|
||||||
cf_error( "LC - Can't operate with value of non-integer type in tuple constructor");
|
|
||||||
|
|
||||||
rv = f_new_inst(FI_CONSTANT);
|
|
||||||
rv->val = (struct f_val) {
|
|
||||||
.type = T_LC,
|
|
||||||
.val.lc = (lcomm) { t1->a[1].i, t2->a[1].i, t3->a[1].i },
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rv = f_new_inst(FI_LC_CONSTRUCT);
|
|
||||||
rv->a[0].p = t1;
|
|
||||||
rv->a[1].p = t2;
|
|
||||||
rv->a[2].p = t3;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline struct f_inst *
|
|
||||||
f_generate_path_mask(struct f_inst *t)
|
|
||||||
{
|
|
||||||
uint len = 0;
|
|
||||||
uint dyn = 0;
|
|
||||||
for (const struct f_inst *tt = t; tt; tt = tt->next) {
|
|
||||||
if (tt->fi_code != FI_CONSTANT)
|
|
||||||
dyn++;
|
|
||||||
len++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dyn) {
|
|
||||||
struct f_inst *pmc = f_new_inst(FI_PATHMASK_CONSTRUCT);
|
|
||||||
pmc->a[0].p = t;
|
|
||||||
pmc->a[1].i = len;
|
|
||||||
return pmc;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct f_path_mask *pm = cfg_allocz(sizeof(struct f_path_mask) + len * sizeof(struct f_path_mask_item));
|
|
||||||
|
|
||||||
uint i = 0;
|
|
||||||
for (const struct f_inst *tt = t; tt; tt = tt->next)
|
|
||||||
pm->item[i++] = tt->val.val.pmi;
|
|
||||||
|
|
||||||
pm->len = i;
|
|
||||||
struct f_inst *pmc = f_new_inst(FI_CONSTANT);
|
|
||||||
pmc->val = (struct f_val) { .type = T_PATH_MASK, .val.path_mask = pm, };
|
|
||||||
|
|
||||||
return pmc;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Remove all new lines and doubled whitespaces
|
* Remove all new lines and doubled whitespaces
|
||||||
* and convert all tabulators to spaces
|
* and convert all tabulators to spaces
|
||||||
|
|
|
@ -138,7 +138,7 @@ FID_IFCONST([[
|
||||||
}
|
}
|
||||||
FID_IFCONST([[
|
FID_IFCONST([[
|
||||||
const struct f_inst **items = NULL;
|
const struct f_inst **items = NULL;
|
||||||
if (constargs) {
|
if (constargs && whati->varcount) {
|
||||||
items = alloca(whati->varcount * sizeof(struct f_inst *));
|
items = alloca(whati->varcount * sizeof(struct f_inst *));
|
||||||
const struct f_inst *child = fvar;
|
const struct f_inst *child = fvar;
|
||||||
for (uint i=0; child; i++)
|
for (uint i=0; child; i++)
|
||||||
|
|
|
@ -261,7 +261,7 @@
|
||||||
|
|
||||||
FID_MEMBER(enum ec_subtype, ecs, f1->ecs != f2->ecs, "ec subtype %s", ec_subtype_str(item->ecs));
|
FID_MEMBER(enum ec_subtype, ecs, f1->ecs != f2->ecs, "ec subtype %s", ec_subtype_str(item->ecs));
|
||||||
|
|
||||||
int check, ipv4_used;
|
int ipv4_used;
|
||||||
u32 key, val;
|
u32 key, val;
|
||||||
|
|
||||||
if (v1.type == T_INT) {
|
if (v1.type == T_INT) {
|
||||||
|
@ -279,21 +279,20 @@
|
||||||
|
|
||||||
val = v2.val.i;
|
val = v2.val.i;
|
||||||
|
|
||||||
if (ecs == EC_GENERIC) {
|
if (ecs == EC_GENERIC)
|
||||||
check = 0; RESULT(T_EC, ec, ec_generic(key, val));
|
RESULT(T_EC, ec, ec_generic(key, val));
|
||||||
}
|
else if (ipv4_used)
|
||||||
else if (ipv4_used) {
|
if (val <= 0xFFFF)
|
||||||
check = 1; RESULT(T_EC, ec, ec_ip4(ecs, key, val));
|
RESULT(T_EC, ec, ec_ip4(ecs, key, val));
|
||||||
}
|
else
|
||||||
else if (key < 0x10000) {
|
runtime("4-byte value %u can't be used with IP-address key in extended community", val);
|
||||||
check = 0; RESULT(T_EC, ec, ec_as2(ecs, key, val));
|
else if (key < 0x10000)
|
||||||
}
|
RESULT(T_EC, ec, ec_as2(ecs, key, val));
|
||||||
else {
|
else
|
||||||
check = 1; RESULT(T_EC, ec, ec_as4(ecs, key, val));
|
if (val <= 0xFFFF)
|
||||||
}
|
RESULT(T_EC, ec, ec_as4(ecs, key, val));
|
||||||
|
else
|
||||||
if (check && (val > 0xFFFF))
|
runtime("4-byte value %u can't be used with 4-byte ASN in extended community", val);
|
||||||
runtime("Value %u > %u out of bounds in EC constructor", val, 0xFFFF);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
INST(FI_LC_CONSTRUCT, 3, 1) {
|
INST(FI_LC_CONSTRUCT, 3, 1) {
|
||||||
|
|
|
@ -72,6 +72,7 @@ static inline int u64_cmp(u64 i1, u64 i2)
|
||||||
#define NORET __attribute__((noreturn))
|
#define NORET __attribute__((noreturn))
|
||||||
#define UNUSED __attribute__((unused))
|
#define UNUSED __attribute__((unused))
|
||||||
#define PACKED __attribute__((packed))
|
#define PACKED __attribute__((packed))
|
||||||
|
#define NONNULL(...) __attribute__((nonnull((__VA_ARGS__))))
|
||||||
|
|
||||||
#ifndef HAVE_THREAD_LOCAL
|
#ifndef HAVE_THREAD_LOCAL
|
||||||
#define _Thread_local
|
#define _Thread_local
|
||||||
|
@ -162,12 +163,23 @@ void debug(const char *msg, ...); /* Printf to debug output */
|
||||||
#define DBG(x, y...) do { } while(0)
|
#define DBG(x, y...) do { } while(0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define ASSERT_DIE(x) do { if (!(x)) bug("Assertion '%s' failed at %s:%d", #x, __FILE__, __LINE__); } while(0)
|
||||||
|
|
||||||
|
#define EXPENSIVE_CHECK(x) /* intentionally left blank */
|
||||||
|
|
||||||
#ifdef DEBUGGING
|
#ifdef DEBUGGING
|
||||||
#define ASSERT(x) do { if (!(x)) bug("Assertion '%s' failed at %s:%d", #x, __FILE__, __LINE__); } while(0)
|
#define ASSERT(x) ASSERT_DIE(x)
|
||||||
|
#define ASSUME(x) ASSERT_DIE(x)
|
||||||
|
#ifdef ENABLE_EXPENSIVE_CHECKS
|
||||||
|
#undef EXPENSIVE_CHECK
|
||||||
|
#define EXPENSIVE_CHECK(x) ASSERT_DIE(x)
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
#define ASSERT(x) do { if (!(x)) log(L_BUG "Assertion '%s' failed at %s:%d", #x, __FILE__, __LINE__); } while(0)
|
#define ASSERT(x) do { if (!(x)) log(L_BUG "Assertion '%s' failed at %s:%d", #x, __FILE__, __LINE__); } while(0)
|
||||||
|
#define ASSUME(x) /* intentionally left blank */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef DEBUGGING
|
#ifdef DEBUGGING
|
||||||
asm(
|
asm(
|
||||||
".pushsection \".debug_gdb_scripts\", \"MS\",@progbits,1\n"
|
".pushsection \".debug_gdb_scripts\", \"MS\",@progbits,1\n"
|
||||||
|
|
5
lib/ip.c
5
lib/ip.c
|
@ -264,6 +264,9 @@ ip6_pton(const char *a, ip6_addr *o)
|
||||||
int i, j, k, l, hfil;
|
int i, j, k, l, hfil;
|
||||||
const char *start;
|
const char *start;
|
||||||
|
|
||||||
|
if (!a[0]) /* Empty string check */
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (a[0] == ':') /* Leading :: */
|
if (a[0] == ':') /* Leading :: */
|
||||||
{
|
{
|
||||||
if (a[1] != ':')
|
if (a[1] != ':')
|
||||||
|
@ -333,6 +336,8 @@ ip6_pton(const char *a, ip6_addr *o)
|
||||||
for (; i>=hfil; i--)
|
for (; i>=hfil; i--)
|
||||||
words[i] = 0;
|
words[i] = 0;
|
||||||
}
|
}
|
||||||
|
else if (i != 8) /* Incomplete address */
|
||||||
|
return 0;
|
||||||
|
|
||||||
/* Convert the address to ip6_addr format */
|
/* Convert the address to ip6_addr format */
|
||||||
for (i=0; i<4; i++)
|
for (i=0; i<4; i++)
|
||||||
|
|
|
@ -13,25 +13,38 @@
|
||||||
#define IP4_MAX_LEN 16
|
#define IP4_MAX_LEN 16
|
||||||
|
|
||||||
static int
|
static int
|
||||||
test_ipa_pton(void *out_, const void *in_, const void *expected_out_)
|
test_ip4_pton(void *out_, const void *in_, const void *expected_out_)
|
||||||
|
{
|
||||||
|
ip_addr *out = out_;
|
||||||
|
const char *in = in_;
|
||||||
|
const ip_addr *expected_out = expected_out_;
|
||||||
|
ip4_addr ip4;
|
||||||
|
|
||||||
|
if (expected_out)
|
||||||
|
{
|
||||||
|
bt_assert(ip4_pton(in, &ip4));
|
||||||
|
*out = ipa_from_ip4(ip4);
|
||||||
|
return ipa_equal(*out, *expected_out);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return !ip4_pton(in, &ip4);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
test_ip6_pton(void *out_, const void *in_, const void *expected_out_)
|
||||||
{
|
{
|
||||||
ip_addr *out = out_;
|
ip_addr *out = out_;
|
||||||
const char *in = in_;
|
const char *in = in_;
|
||||||
const ip_addr *expected_out = expected_out_;
|
const ip_addr *expected_out = expected_out_;
|
||||||
|
|
||||||
if (ipa_is_ip4(*expected_out))
|
if (expected_out)
|
||||||
{
|
|
||||||
ip4_addr ip4;
|
|
||||||
bt_assert(ip4_pton(in, &ip4));
|
|
||||||
*out = ipa_from_ip4(ip4);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
bt_assert(ip6_pton(in, out));
|
bt_assert(ip6_pton(in, out));
|
||||||
/* ip_addr == ip6_addr */
|
|
||||||
}
|
|
||||||
|
|
||||||
return ipa_equal(*out, *expected_out);
|
return ipa_equal(*out, *expected_out);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return !ip6_pton(in, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -52,7 +65,7 @@ t_ip4_pton(void)
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
return bt_assert_batch(test_vectors, test_ipa_pton, bt_fmt_str, bt_fmt_ipa);
|
return bt_assert_batch(test_vectors, test_ip4_pton, bt_fmt_str, bt_fmt_ipa);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -87,9 +100,17 @@ t_ip6_pton(void)
|
||||||
.in = "2605:2700:0:3::4713:93e3",
|
.in = "2605:2700:0:3::4713:93e3",
|
||||||
.out = & ipa_build6(0x26052700, 0x00000003, 0x00000000, 0x471393E3),
|
.out = & ipa_build6(0x26052700, 0x00000003, 0x00000000, 0x471393E3),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.in = "2605:2700:0:3:4713:93e3",
|
||||||
|
.out = NULL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.in = "2",
|
||||||
|
.out = NULL,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
return bt_assert_batch(test_vectors, test_ipa_pton, bt_fmt_str, bt_fmt_ipa);
|
return bt_assert_batch(test_vectors, test_ip6_pton, bt_fmt_str, bt_fmt_ipa);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|
79
lib/lists.c
79
lib/lists.c
|
@ -29,6 +29,42 @@
|
||||||
#include "nest/bird.h"
|
#include "nest/bird.h"
|
||||||
#include "lib/lists.h"
|
#include "lib/lists.h"
|
||||||
|
|
||||||
|
LIST_INLINE int
|
||||||
|
check_list(list *l, node *n)
|
||||||
|
{
|
||||||
|
if (!l)
|
||||||
|
{
|
||||||
|
ASSERT_DIE(n);
|
||||||
|
ASSERT_DIE(n->prev);
|
||||||
|
|
||||||
|
do { n = n->prev; } while (n->prev);
|
||||||
|
|
||||||
|
l = SKIP_BACK(list, head_node, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
int seen = 0;
|
||||||
|
|
||||||
|
ASSERT_DIE(l->null == NULL);
|
||||||
|
ASSERT_DIE(l->head != NULL);
|
||||||
|
ASSERT_DIE(l->tail != NULL);
|
||||||
|
|
||||||
|
node *prev = &l->head_node, *cur = l->head, *next = l->head->next;
|
||||||
|
while (next)
|
||||||
|
{
|
||||||
|
if (cur == n)
|
||||||
|
seen++;
|
||||||
|
ASSERT_DIE(cur->prev == prev);
|
||||||
|
prev = cur;
|
||||||
|
cur = next;
|
||||||
|
next = next->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT_DIE(cur == &(l->tail_node));
|
||||||
|
ASSERT_DIE(!n || (seen == 1));
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* add_tail - append a node to a list
|
* add_tail - append a node to a list
|
||||||
* @l: linked list
|
* @l: linked list
|
||||||
|
@ -39,6 +75,10 @@
|
||||||
LIST_INLINE void
|
LIST_INLINE void
|
||||||
add_tail(list *l, node *n)
|
add_tail(list *l, node *n)
|
||||||
{
|
{
|
||||||
|
EXPENSIVE_CHECK(check_list(l, NULL));
|
||||||
|
ASSUME(n->prev == NULL);
|
||||||
|
ASSUME(n->next == NULL);
|
||||||
|
|
||||||
node *z = l->tail;
|
node *z = l->tail;
|
||||||
|
|
||||||
n->next = &l->tail_node;
|
n->next = &l->tail_node;
|
||||||
|
@ -57,6 +97,10 @@ add_tail(list *l, node *n)
|
||||||
LIST_INLINE void
|
LIST_INLINE void
|
||||||
add_head(list *l, node *n)
|
add_head(list *l, node *n)
|
||||||
{
|
{
|
||||||
|
EXPENSIVE_CHECK(check_list(l, NULL));
|
||||||
|
ASSUME(n->prev == NULL);
|
||||||
|
ASSUME(n->next == NULL);
|
||||||
|
|
||||||
node *z = l->head;
|
node *z = l->head;
|
||||||
|
|
||||||
n->next = z;
|
n->next = z;
|
||||||
|
@ -76,6 +120,10 @@ add_head(list *l, node *n)
|
||||||
LIST_INLINE void
|
LIST_INLINE void
|
||||||
insert_node(node *n, node *after)
|
insert_node(node *n, node *after)
|
||||||
{
|
{
|
||||||
|
EXPENSIVE_CHECK(check_list(l, after));
|
||||||
|
ASSUME(n->prev == NULL);
|
||||||
|
ASSUME(n->next == NULL);
|
||||||
|
|
||||||
node *z = after->next;
|
node *z = after->next;
|
||||||
|
|
||||||
n->next = z;
|
n->next = z;
|
||||||
|
@ -93,6 +141,8 @@ insert_node(node *n, node *after)
|
||||||
LIST_INLINE void
|
LIST_INLINE void
|
||||||
rem_node(node *n)
|
rem_node(node *n)
|
||||||
{
|
{
|
||||||
|
EXPENSIVE_CHECK(check_list(NULL, n));
|
||||||
|
|
||||||
node *z = n->prev;
|
node *z = n->prev;
|
||||||
node *x = n->next;
|
node *x = n->next;
|
||||||
|
|
||||||
|
@ -103,24 +153,20 @@ rem_node(node *n)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* replace_node - replace a node in a list with another one
|
* update_node - update node after calling realloc on it
|
||||||
* @old: node to be removed
|
* @n: node to be updated
|
||||||
* @new: node to be inserted
|
|
||||||
*
|
*
|
||||||
* Replaces node @old in the list it's linked in with node @new. Node
|
* Fixes neighbor pointers.
|
||||||
* @old may be a copy of the original node, which is not accessed
|
|
||||||
* through the list. The function could be called with @old == @new,
|
|
||||||
* which just fixes neighbors' pointers in the case that the node
|
|
||||||
* was reallocated.
|
|
||||||
*/
|
*/
|
||||||
LIST_INLINE void
|
LIST_INLINE void
|
||||||
replace_node(node *old, node *new)
|
update_node(node *n)
|
||||||
{
|
{
|
||||||
old->next->prev = new;
|
ASSUME(n->next->prev == n->prev->next);
|
||||||
old->prev->next = new;
|
|
||||||
|
|
||||||
new->prev = old->prev;
|
n->next->prev = n;
|
||||||
new->next = old->next;
|
n->prev->next = n;
|
||||||
|
|
||||||
|
EXPENSIVE_CHECK(check_list(NULL, n));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -149,6 +195,9 @@ init_list(list *l)
|
||||||
LIST_INLINE void
|
LIST_INLINE void
|
||||||
add_tail_list(list *to, list *l)
|
add_tail_list(list *to, list *l)
|
||||||
{
|
{
|
||||||
|
EXPENSIVE_CHECK(check_list(to, NULL));
|
||||||
|
EXPENSIVE_CHECK(check_list(l, NULL));
|
||||||
|
|
||||||
node *p = to->tail;
|
node *p = to->tail;
|
||||||
node *q = l->head;
|
node *q = l->head;
|
||||||
|
|
||||||
|
@ -157,6 +206,8 @@ add_tail_list(list *to, list *l)
|
||||||
q = l->tail;
|
q = l->tail;
|
||||||
q->next = &to->tail_node;
|
q->next = &to->tail_node;
|
||||||
to->tail = q;
|
to->tail = q;
|
||||||
|
|
||||||
|
EXPENSIVE_CHECK(check_list(to, NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
LIST_INLINE uint
|
LIST_INLINE uint
|
||||||
|
@ -165,6 +216,8 @@ list_length(list *l)
|
||||||
uint len = 0;
|
uint len = 0;
|
||||||
node *n;
|
node *n;
|
||||||
|
|
||||||
|
EXPENSIVE_CHECK(check_list(l, NULL));
|
||||||
|
|
||||||
WALK_LIST(n, *l)
|
WALK_LIST(n, *l)
|
||||||
len++;
|
len++;
|
||||||
|
|
||||||
|
|
|
@ -222,26 +222,29 @@ t_remove_node(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
t_replace_node(void)
|
t_update_node(void)
|
||||||
{
|
{
|
||||||
node head, inside, tail;
|
node head, inside, tail;
|
||||||
|
|
||||||
init_list_();
|
init_list_();
|
||||||
fill_list();
|
fill_list();
|
||||||
|
|
||||||
replace_node(&nodes[0], &head);
|
head = nodes[0];
|
||||||
|
update_node(&head);
|
||||||
bt_assert(l.head == &head);
|
bt_assert(l.head == &head);
|
||||||
bt_assert(head.prev == NODE &l.head);
|
bt_assert(head.prev == NODE &l.head);
|
||||||
bt_assert(head.next == &nodes[1]);
|
bt_assert(head.next == &nodes[1]);
|
||||||
bt_assert(nodes[1].prev == &head);
|
bt_assert(nodes[1].prev == &head);
|
||||||
|
|
||||||
replace_node(&nodes[MAX_NUM/2], &inside);
|
inside = nodes[MAX_NUM/2];
|
||||||
|
update_node(&inside);
|
||||||
bt_assert(nodes[MAX_NUM/2-1].next == &inside);
|
bt_assert(nodes[MAX_NUM/2-1].next == &inside);
|
||||||
bt_assert(nodes[MAX_NUM/2+1].prev == &inside);
|
bt_assert(nodes[MAX_NUM/2+1].prev == &inside);
|
||||||
bt_assert(inside.prev == &nodes[MAX_NUM/2-1]);
|
bt_assert(inside.prev == &nodes[MAX_NUM/2-1]);
|
||||||
bt_assert(inside.next == &nodes[MAX_NUM/2+1]);
|
bt_assert(inside.next == &nodes[MAX_NUM/2+1]);
|
||||||
|
|
||||||
replace_node(&nodes[MAX_NUM-1], &tail);
|
tail = nodes[MAX_NUM-1];
|
||||||
|
update_node(&tail);
|
||||||
bt_assert(l.tail == &tail);
|
bt_assert(l.tail == &tail);
|
||||||
bt_assert(tail.prev == &nodes[MAX_NUM-2]);
|
bt_assert(tail.prev == &nodes[MAX_NUM-2]);
|
||||||
bt_assert(tail.next == NODE &l.null);
|
bt_assert(tail.next == NODE &l.null);
|
||||||
|
@ -280,7 +283,7 @@ main(int argc, char *argv[])
|
||||||
bt_test_suite(t_add_head, "Adding nodes to head of list");
|
bt_test_suite(t_add_head, "Adding nodes to head of list");
|
||||||
bt_test_suite(t_insert_node, "Inserting nodes to list");
|
bt_test_suite(t_insert_node, "Inserting nodes to list");
|
||||||
bt_test_suite(t_remove_node, "Removing nodes from list");
|
bt_test_suite(t_remove_node, "Removing nodes from list");
|
||||||
bt_test_suite(t_replace_node, "Replacing nodes in list");
|
bt_test_suite(t_update_node, "Updating nodes in list");
|
||||||
bt_test_suite(t_add_tail_list, "At the tail of a list adding the another list");
|
bt_test_suite(t_add_tail_list, "At the tail of a list adding the another list");
|
||||||
|
|
||||||
return bt_exit_value();
|
return bt_exit_value();
|
||||||
|
|
|
@ -340,6 +340,7 @@ mb_alloc(pool *p, unsigned size)
|
||||||
struct mblock *b = xmalloc(sizeof(struct mblock) + size);
|
struct mblock *b = xmalloc(sizeof(struct mblock) + size);
|
||||||
|
|
||||||
b->r.class = &mb_class;
|
b->r.class = &mb_class;
|
||||||
|
b->r.n = (node) {};
|
||||||
add_tail(&p->inside, &b->r.n);
|
add_tail(&p->inside, &b->r.n);
|
||||||
b->size = size;
|
b->size = size;
|
||||||
return b->data;
|
return b->data;
|
||||||
|
@ -387,7 +388,7 @@ mb_realloc(void *m, unsigned size)
|
||||||
struct mblock *b = SKIP_BACK(struct mblock, data, m);
|
struct mblock *b = SKIP_BACK(struct mblock, data, m);
|
||||||
|
|
||||||
b = xrealloc(b, sizeof(struct mblock) + size);
|
b = xrealloc(b, sizeof(struct mblock) + size);
|
||||||
replace_node(&b->r.n, &b->r.n);
|
update_node(&b->r.n);
|
||||||
b->size = size;
|
b->size = size;
|
||||||
return b->data;
|
return b->data;
|
||||||
}
|
}
|
||||||
|
|
|
@ -216,8 +216,11 @@ sl_new_head(slab *s)
|
||||||
struct sl_obj *no;
|
struct sl_obj *no;
|
||||||
uint n = s->objs_per_slab;
|
uint n = s->objs_per_slab;
|
||||||
|
|
||||||
h->first_free = o;
|
*h = (struct sl_head) {
|
||||||
h->num_full = 0;
|
.first_free = o,
|
||||||
|
.num_full = 0,
|
||||||
|
};
|
||||||
|
|
||||||
while (n--)
|
while (n--)
|
||||||
{
|
{
|
||||||
o->slab = h;
|
o->slab = h;
|
||||||
|
|
|
@ -72,6 +72,15 @@ bstrcmp(const char *s1, const char *s2)
|
||||||
return !s2 - !s1;
|
return !s2 - !s1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void *
|
||||||
|
bmemcpy(void *dest, const void *src, size_t n)
|
||||||
|
{
|
||||||
|
if (n)
|
||||||
|
return memcpy(dest, src, n);
|
||||||
|
else
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
#define ROUTER_ID_64_LENGTH 23
|
#define ROUTER_ID_64_LENGTH 23
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -255,7 +255,7 @@ timer_init(void)
|
||||||
btime
|
btime
|
||||||
tm_parse_time(const char *x)
|
tm_parse_time(const char *x)
|
||||||
{
|
{
|
||||||
struct tm tm;
|
struct tm tm = {};
|
||||||
int usec, n1, n2, n3, r;
|
int usec, n1, n2, n3, r;
|
||||||
|
|
||||||
r = sscanf(x, "%d-%d-%d%n %d:%d:%d%n.%d%n",
|
r = sscanf(x, "%d-%d-%d%n %d:%d:%d%n.%d%n",
|
||||||
|
|
|
@ -80,7 +80,7 @@ struct protocol {
|
||||||
void (*cleanup)(struct proto *); /* Called after shutdown when protocol became hungry/down */
|
void (*cleanup)(struct proto *); /* Called after shutdown when protocol became hungry/down */
|
||||||
void (*get_status)(struct proto *, byte *buf); /* Get instance status (for `show protocols' command) */
|
void (*get_status)(struct proto *, byte *buf); /* Get instance status (for `show protocols' command) */
|
||||||
void (*get_route_info)(struct rte *, byte *buf); /* Get route information (for `show route' command) */
|
void (*get_route_info)(struct rte *, byte *buf); /* Get route information (for `show route' command) */
|
||||||
int (*get_attr)(struct eattr *, byte *buf, int buflen); /* ASCIIfy dynamic attribute (returns GA_*) */
|
int (*get_attr)(const struct eattr *, byte *buf, int buflen); /* ASCIIfy dynamic attribute (returns GA_*) */
|
||||||
void (*show_proto_info)(struct proto *); /* Show protocol info (for `show protocols all' command) */
|
void (*show_proto_info)(struct proto *); /* Show protocol info (for `show protocols all' command) */
|
||||||
void (*copy_config)(struct proto_config *, struct proto_config *); /* Copy config from given protocol instance */
|
void (*copy_config)(struct proto_config *, struct proto_config *); /* Copy config from given protocol instance */
|
||||||
};
|
};
|
||||||
|
|
|
@ -577,7 +577,7 @@ void ea_merge(ea_list *from, ea_list *to); /* Merge sub-lists to allocated buffe
|
||||||
int ea_same(ea_list *x, ea_list *y); /* Test whether two ea_lists are identical */
|
int ea_same(ea_list *x, ea_list *y); /* Test whether two ea_lists are identical */
|
||||||
uint ea_hash(ea_list *e); /* Calculate 16-bit hash value */
|
uint ea_hash(ea_list *e); /* Calculate 16-bit hash value */
|
||||||
ea_list *ea_append(ea_list *to, ea_list *what);
|
ea_list *ea_append(ea_list *to, ea_list *what);
|
||||||
void ea_format_bitfield(struct eattr *a, byte *buf, int bufsize, const char **names, int min, int max);
|
void ea_format_bitfield(const struct eattr *a, byte *buf, int bufsize, const char **names, int min, int max);
|
||||||
|
|
||||||
#define ea_normalize(ea) do { \
|
#define ea_normalize(ea) do { \
|
||||||
if (ea->next) { \
|
if (ea->next) { \
|
||||||
|
|
|
@ -278,18 +278,22 @@ nexthop_merge(struct nexthop *x, struct nexthop *y, int rx, int ry, int max, lin
|
||||||
while ((x || y) && max--)
|
while ((x || y) && max--)
|
||||||
{
|
{
|
||||||
int cmp = nexthop_compare_node(x, y);
|
int cmp = nexthop_compare_node(x, y);
|
||||||
|
|
||||||
if (cmp < 0)
|
if (cmp < 0)
|
||||||
{
|
{
|
||||||
|
ASSUME(x);
|
||||||
*n = rx ? x : nexthop_copy_node(x, lp);
|
*n = rx ? x : nexthop_copy_node(x, lp);
|
||||||
x = x->next;
|
x = x->next;
|
||||||
}
|
}
|
||||||
else if (cmp > 0)
|
else if (cmp > 0)
|
||||||
{
|
{
|
||||||
|
ASSUME(y);
|
||||||
*n = ry ? y : nexthop_copy_node(y, lp);
|
*n = ry ? y : nexthop_copy_node(y, lp);
|
||||||
y = y->next;
|
y = y->next;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
ASSUME(x && y);
|
||||||
*n = rx ? x : (ry ? y : nexthop_copy_node(x, lp));
|
*n = rx ? x : (ry ? y : nexthop_copy_node(x, lp));
|
||||||
x = x->next;
|
x = x->next;
|
||||||
y = y->next;
|
y = y->next;
|
||||||
|
@ -786,7 +790,7 @@ ea_free(ea_list *o)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
get_generic_attr(eattr *a, byte **buf, int buflen UNUSED)
|
get_generic_attr(const eattr *a, byte **buf, int buflen UNUSED)
|
||||||
{
|
{
|
||||||
if (a->id == EA_GEN_IGP_METRIC)
|
if (a->id == EA_GEN_IGP_METRIC)
|
||||||
{
|
{
|
||||||
|
@ -798,7 +802,7 @@ get_generic_attr(eattr *a, byte **buf, int buflen UNUSED)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ea_format_bitfield(struct eattr *a, byte *buf, int bufsize, const char **names, int min, int max)
|
ea_format_bitfield(const struct eattr *a, byte *buf, int bufsize, const char **names, int min, int max)
|
||||||
{
|
{
|
||||||
byte *bound = buf + bufsize - 32;
|
byte *bound = buf + bufsize - 32;
|
||||||
u32 data = a->u.data;
|
u32 data = a->u.data;
|
||||||
|
@ -894,7 +898,7 @@ ea_show_lc_set(struct cli *c, const struct adata *ad, byte *pos, byte *buf, byte
|
||||||
* get_attr() hook, it's consulted first.
|
* get_attr() hook, it's consulted first.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
ea_show(struct cli *c, eattr *e)
|
ea_show(struct cli *c, const eattr *e)
|
||||||
{
|
{
|
||||||
struct protocol *p;
|
struct protocol *p;
|
||||||
int status = GA_UNKNOWN;
|
int status = GA_UNKNOWN;
|
||||||
|
|
|
@ -104,6 +104,12 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
|
||||||
rte *e, *ee;
|
rte *e, *ee;
|
||||||
byte ia[NET_MAX_TEXT_LENGTH+1];
|
byte ia[NET_MAX_TEXT_LENGTH+1];
|
||||||
struct channel *ec = d->tab->export_channel;
|
struct channel *ec = d->tab->export_channel;
|
||||||
|
|
||||||
|
/* The Clang static analyzer complains that ec may be NULL.
|
||||||
|
* It should be ensured to be not NULL by rt_show_prepare_tables() */
|
||||||
|
if (d->export_mode)
|
||||||
|
ASSUME(ec);
|
||||||
|
|
||||||
int first = 1;
|
int first = 1;
|
||||||
int pass = 0;
|
int pass = 0;
|
||||||
|
|
||||||
|
|
|
@ -2304,7 +2304,7 @@ rt_commit(struct config *new, struct config *old)
|
||||||
WALK_LIST(r, new->tables)
|
WALK_LIST(r, new->tables)
|
||||||
if (!r->table)
|
if (!r->table)
|
||||||
{
|
{
|
||||||
rtable *t = mb_alloc(rt_table_pool, sizeof(struct rtable));
|
rtable *t = mb_allocz(rt_table_pool, sizeof(struct rtable));
|
||||||
DBG("\t%s: created\n", r->name);
|
DBG("\t%s: created\n", r->name);
|
||||||
rt_setup(rt_table_pool, t, r);
|
rt_setup(rt_table_pool, t, r);
|
||||||
add_tail(&routing_tables, &t->n);
|
add_tail(&routing_tables, &t->n);
|
||||||
|
|
|
@ -1852,7 +1852,7 @@ babel_get_route_info(rte *rte, byte *buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
babel_get_attr(eattr *a, byte *buf, int buflen UNUSED)
|
babel_get_attr(const eattr *a, byte *buf, int buflen UNUSED)
|
||||||
{
|
{
|
||||||
switch (a->id)
|
switch (a->id)
|
||||||
{
|
{
|
||||||
|
|
|
@ -72,7 +72,7 @@ struct bgp_attr_desc {
|
||||||
void (*export)(struct bgp_export_state *s, eattr *a);
|
void (*export)(struct bgp_export_state *s, eattr *a);
|
||||||
int (*encode)(struct bgp_write_state *s, eattr *a, byte *buf, uint size);
|
int (*encode)(struct bgp_write_state *s, eattr *a, byte *buf, uint size);
|
||||||
void (*decode)(struct bgp_parse_state *s, uint code, uint flags, byte *data, uint len, ea_list **to);
|
void (*decode)(struct bgp_parse_state *s, uint code, uint flags, byte *data, uint len, ea_list **to);
|
||||||
void (*format)(eattr *ea, byte *buf, uint size);
|
void (*format)(const eattr *ea, byte *buf, uint size);
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct bgp_attr_desc bgp_attr_table[];
|
static const struct bgp_attr_desc bgp_attr_table[];
|
||||||
|
@ -396,7 +396,7 @@ bgp_decode_origin(struct bgp_parse_state *s, uint code UNUSED, uint flags, byte
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bgp_format_origin(eattr *a, byte *buf, uint size UNUSED)
|
bgp_format_origin(const eattr *a, byte *buf, uint size UNUSED)
|
||||||
{
|
{
|
||||||
static const char *bgp_origin_names[] = { "IGP", "EGP", "Incomplete" };
|
static const char *bgp_origin_names[] = { "IGP", "EGP", "Incomplete" };
|
||||||
|
|
||||||
|
@ -510,7 +510,7 @@ bgp_decode_next_hop(struct bgp_parse_state *s, uint code UNUSED, uint flags UNUS
|
||||||
|
|
||||||
/* TODO: This function should use AF-specific hook */
|
/* TODO: This function should use AF-specific hook */
|
||||||
static void
|
static void
|
||||||
bgp_format_next_hop(eattr *a, byte *buf, uint size UNUSED)
|
bgp_format_next_hop(const eattr *a, byte *buf, uint size UNUSED)
|
||||||
{
|
{
|
||||||
ip_addr *nh = (void *) a->u.ptr->data;
|
ip_addr *nh = (void *) a->u.ptr->data;
|
||||||
uint len = a->u.ptr->length;
|
uint len = a->u.ptr->length;
|
||||||
|
@ -601,7 +601,7 @@ bgp_decode_aggregator(struct bgp_parse_state *s, uint code UNUSED, uint flags, b
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bgp_format_aggregator(eattr *a, byte *buf, uint size UNUSED)
|
bgp_format_aggregator(const eattr *a, byte *buf, uint size UNUSED)
|
||||||
{
|
{
|
||||||
const byte *data = a->u.ptr->data;
|
const byte *data = a->u.ptr->data;
|
||||||
|
|
||||||
|
@ -676,7 +676,7 @@ bgp_decode_cluster_list(struct bgp_parse_state *s, uint code UNUSED, uint flags,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bgp_format_cluster_list(eattr *a, byte *buf, uint size)
|
bgp_format_cluster_list(const eattr *a, byte *buf, uint size)
|
||||||
{
|
{
|
||||||
/* Truncates cluster lists larger than buflen, probably not a problem */
|
/* Truncates cluster lists larger than buflen, probably not a problem */
|
||||||
int_set_format(a->u.ptr, 0, -1, buf, size);
|
int_set_format(a->u.ptr, 0, -1, buf, size);
|
||||||
|
@ -831,7 +831,7 @@ bgp_decode_aigp(struct bgp_parse_state *s, uint code UNUSED, uint flags, byte *d
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bgp_format_aigp(eattr *a, byte *buf, uint size UNUSED)
|
bgp_format_aigp(const eattr *a, byte *buf, uint size UNUSED)
|
||||||
{
|
{
|
||||||
const byte *b = bgp_aigp_get_tlv(a->u.ptr, BGP_AIGP_METRIC);
|
const byte *b = bgp_aigp_get_tlv(a->u.ptr, BGP_AIGP_METRIC);
|
||||||
|
|
||||||
|
@ -909,7 +909,7 @@ bgp_decode_mpls_label_stack(struct bgp_parse_state *s, uint code UNUSED, uint fl
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bgp_format_mpls_label_stack(eattr *a, byte *buf, uint size)
|
bgp_format_mpls_label_stack(const eattr *a, byte *buf, uint size)
|
||||||
{
|
{
|
||||||
u32 *labels = (u32 *) a->u.ptr->data;
|
u32 *labels = (u32 *) a->u.ptr->data;
|
||||||
uint lnum = a->u.ptr->length / 4;
|
uint lnum = a->u.ptr->length / 4;
|
||||||
|
@ -2293,7 +2293,7 @@ bgp_process_as4_attrs(ea_list **attrs, struct linpool *pool)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
bgp_get_attr(eattr *a, byte *buf, int buflen)
|
bgp_get_attr(const eattr *a, byte *buf, int buflen)
|
||||||
{
|
{
|
||||||
uint i = EA_ID(a->id);
|
uint i = EA_ID(a->id);
|
||||||
const struct bgp_attr_desc *d;
|
const struct bgp_attr_desc *d;
|
||||||
|
|
|
@ -552,7 +552,7 @@ static inline void
|
||||||
bgp_set_attr_data(ea_list **to, struct linpool *pool, uint code, uint flags, void *data, uint len)
|
bgp_set_attr_data(ea_list **to, struct linpool *pool, uint code, uint flags, void *data, uint len)
|
||||||
{
|
{
|
||||||
struct adata *a = lp_alloc_adata(pool, len);
|
struct adata *a = lp_alloc_adata(pool, len);
|
||||||
memcpy(a->data, data, len);
|
bmemcpy(a->data, data, len);
|
||||||
bgp_set_attr(to, pool, code, flags, (uintptr_t) a);
|
bgp_set_attr(to, pool, code, flags, (uintptr_t) a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -581,7 +581,7 @@ int bgp_rte_recalculate(rtable *table, net *net, rte *new, rte *old, rte *old_be
|
||||||
struct rte *bgp_rte_modify_stale(struct rte *r, struct linpool *pool);
|
struct rte *bgp_rte_modify_stale(struct rte *r, struct linpool *pool);
|
||||||
void bgp_rt_notify(struct proto *P, struct channel *C, net *n, rte *new, rte *old);
|
void bgp_rt_notify(struct proto *P, struct channel *C, net *n, rte *new, rte *old);
|
||||||
int bgp_preexport(struct proto *, struct rte **, struct linpool *);
|
int bgp_preexport(struct proto *, struct rte **, struct linpool *);
|
||||||
int bgp_get_attr(struct eattr *e, byte *buf, int buflen);
|
int bgp_get_attr(const struct eattr *e, byte *buf, int buflen);
|
||||||
void bgp_get_route_info(struct rte *, byte *buf);
|
void bgp_get_route_info(struct rte *, byte *buf);
|
||||||
int bgp_total_aigp_metric_(rte *e, u64 *metric, const struct adata **ad);
|
int bgp_total_aigp_metric_(rte *e, u64 *metric, const struct adata **ad);
|
||||||
|
|
||||||
|
|
|
@ -650,19 +650,20 @@ void
|
||||||
ospf_dr_election(struct ospf_iface *ifa)
|
ospf_dr_election(struct ospf_iface *ifa)
|
||||||
{
|
{
|
||||||
struct ospf_proto *p = ifa->oa->po;
|
struct ospf_proto *p = ifa->oa->po;
|
||||||
struct ospf_neighbor *neigh, *ndr, *nbdr, me;
|
struct ospf_neighbor *neigh, *ndr, *nbdr;
|
||||||
u32 myid = p->router_id;
|
u32 myid = p->router_id;
|
||||||
|
|
||||||
DBG("(B)DR election.\n");
|
DBG("(B)DR election.\n");
|
||||||
|
|
||||||
me.state = NEIGHBOR_2WAY;
|
struct ospf_neighbor me = {
|
||||||
me.rid = myid;
|
.state = NEIGHBOR_2WAY,
|
||||||
me.priority = ifa->priority;
|
.rid = myid,
|
||||||
me.ip = ifa->addr->ip;
|
.priority = ifa->priority,
|
||||||
|
.ip = ifa->addr->ip,
|
||||||
me.dr = ospf_is_v2(p) ? ipa_to_u32(ifa->drip) : ifa->drid;
|
.dr = ospf_is_v2(p) ? ipa_to_u32(ifa->drip) : ifa->drid,
|
||||||
me.bdr = ospf_is_v2(p) ? ipa_to_u32(ifa->bdrip) : ifa->bdrid;
|
.bdr = ospf_is_v2(p) ? ipa_to_u32(ifa->bdrip) : ifa->bdrid,
|
||||||
me.iface_id = ifa->iface_id;
|
.iface_id = ifa->iface_id,
|
||||||
|
};
|
||||||
|
|
||||||
add_tail(&ifa->neigh_list, NODE & me);
|
add_tail(&ifa->neigh_list, NODE & me);
|
||||||
|
|
||||||
|
|
|
@ -620,7 +620,7 @@ ospf_get_route_info(rte * rte, byte * buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ospf_get_attr(eattr * a, byte * buf, int buflen UNUSED)
|
ospf_get_attr(const eattr * a, byte * buf, int buflen UNUSED)
|
||||||
{
|
{
|
||||||
switch (a->id)
|
switch (a->id)
|
||||||
{
|
{
|
||||||
|
@ -1244,7 +1244,7 @@ ospf_sh_state(struct proto *P, int verbose, int reachable)
|
||||||
|
|
||||||
uint num = p->gr->hash_entries;
|
uint num = p->gr->hash_entries;
|
||||||
struct top_hash_entry *hea[num];
|
struct top_hash_entry *hea[num];
|
||||||
struct top_hash_entry *hex[verbose ? num : 0];
|
struct top_hash_entry **hex = verbose ? alloca(num * sizeof(struct top_hash_entry *)) : NULL;
|
||||||
struct top_hash_entry *he;
|
struct top_hash_entry *he;
|
||||||
struct top_hash_entry *cnode = NULL;
|
struct top_hash_entry *cnode = NULL;
|
||||||
|
|
||||||
|
@ -1289,6 +1289,8 @@ ospf_sh_state(struct proto *P, int verbose, int reachable)
|
||||||
|
|
||||||
lsa_compare_ospf3 = !ospf2;
|
lsa_compare_ospf3 = !ospf2;
|
||||||
qsort(hea, j1, sizeof(struct top_hash_entry *), lsa_compare_for_state);
|
qsort(hea, j1, sizeof(struct top_hash_entry *), lsa_compare_for_state);
|
||||||
|
|
||||||
|
if (verbose)
|
||||||
qsort(hex, jx, sizeof(struct top_hash_entry *), ext_compare_for_state);
|
qsort(hex, jx, sizeof(struct top_hash_entry *), ext_compare_for_state);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -329,6 +329,14 @@ ospf_originate_lsa(struct ospf_proto *p, struct ospf_new_lsa *lsa)
|
||||||
en->next_lsa_opts = 0;
|
en->next_lsa_opts = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The static analyzer complains here that en->lsa_body may be NULL.
|
||||||
|
* Yes, it may if ospf_hash_get() creates a new struct top_hash_entry.
|
||||||
|
* In this case, also en->lsa.length must be 0 and lsa_length is never
|
||||||
|
* equal to 0 while sizeof(struct ospf_lsa_header) is non-zero.
|
||||||
|
* Therefore memcmp() is never executed with NULL here.
|
||||||
|
* */
|
||||||
|
ASSUME((en->lsa.length == 0) == (en->lsa_body == NULL));
|
||||||
|
|
||||||
/* Ignore the the new LSA if is the same as the current one */
|
/* Ignore the the new LSA if is the same as the current one */
|
||||||
if ((en->lsa.age < LSA_MAXAGE) &&
|
if ((en->lsa.age < LSA_MAXAGE) &&
|
||||||
(lsa_length == en->lsa.length) &&
|
(lsa_length == en->lsa.length) &&
|
||||||
|
|
|
@ -740,7 +740,7 @@ radv_pref_str(u32 pref)
|
||||||
|
|
||||||
/* The buffer has some minimal size */
|
/* The buffer has some minimal size */
|
||||||
static int
|
static int
|
||||||
radv_get_attr(eattr *a, byte *buf, int buflen UNUSED)
|
radv_get_attr(const eattr *a, byte *buf, int buflen UNUSED)
|
||||||
{
|
{
|
||||||
switch (a->id)
|
switch (a->id)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1190,7 +1190,7 @@ rip_get_route_info(rte *rte, byte *buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
rip_get_attr(eattr *a, byte *buf, int buflen UNUSED)
|
rip_get_attr(const eattr *a, byte *buf, int buflen UNUSED)
|
||||||
{
|
{
|
||||||
switch (a->id)
|
switch (a->id)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1011,6 +1011,7 @@ rpki_send_error_pdu(struct rpki_cache *cache, const enum pdu_error_type error_co
|
||||||
{
|
{
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
msg_len = bvsnprintf(msg, sizeof(msg), fmt, args) + 1;
|
msg_len = bvsnprintf(msg, sizeof(msg), fmt, args) + 1;
|
||||||
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 pdu_size = 16 + err_pdu_len + msg_len;
|
u32 pdu_size = 16 + err_pdu_len + msg_len;
|
||||||
|
|
|
@ -46,7 +46,7 @@ static inline void krt_sys_io_init(void) { }
|
||||||
static inline void krt_sys_init(struct krt_proto *p UNUSED) { }
|
static inline void krt_sys_init(struct krt_proto *p UNUSED) { }
|
||||||
static inline void krt_sys_postconfig(struct krt_config *x UNUSED) { }
|
static inline void krt_sys_postconfig(struct krt_config *x UNUSED) { }
|
||||||
|
|
||||||
static inline int krt_sys_get_attr(eattr *a UNUSED, byte *buf UNUSED, int buflen UNUSED) { return GA_UNKNOWN; }
|
static inline int krt_sys_get_attr(const eattr *a UNUSED, byte *buf UNUSED, int buflen UNUSED) { return GA_UNKNOWN; }
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -2065,7 +2065,7 @@ static const char *krt_features_names[KRT_FEATURES_MAX] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
int
|
int
|
||||||
krt_sys_get_attr(eattr *a, byte *buf, int buflen UNUSED)
|
krt_sys_get_attr(const eattr *a, byte *buf, int buflen UNUSED)
|
||||||
{
|
{
|
||||||
switch (a->id)
|
switch (a->id)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1495,7 +1495,9 @@ sk_open_unix(sock *s, char *name)
|
||||||
if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
|
if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* Path length checked in test_old_bird() */
|
/* Path length checked in test_old_bird() but we may need unix sockets for other reasons in future */
|
||||||
|
ASSERT_DIE(strlen(name) < sizeof(sa.sun_path));
|
||||||
|
|
||||||
sa.sun_family = AF_UNIX;
|
sa.sun_family = AF_UNIX;
|
||||||
strcpy(sa.sun_path, name);
|
strcpy(sa.sun_path, name);
|
||||||
|
|
||||||
|
|
|
@ -1156,7 +1156,7 @@ krt_copy_config(struct proto_config *dest, struct proto_config *src)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
krt_get_attr(eattr *a, byte *buf, int buflen)
|
krt_get_attr(const eattr *a, byte *buf, int buflen)
|
||||||
{
|
{
|
||||||
switch (a->id)
|
switch (a->id)
|
||||||
{
|
{
|
||||||
|
|
|
@ -141,7 +141,7 @@ void krt_sys_copy_config(struct krt_config *, struct krt_config *);
|
||||||
int krt_capable(rte *e);
|
int krt_capable(rte *e);
|
||||||
void krt_do_scan(struct krt_proto *);
|
void krt_do_scan(struct krt_proto *);
|
||||||
void krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old);
|
void krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old);
|
||||||
int krt_sys_get_attr(eattr *a, byte *buf, int buflen);
|
int krt_sys_get_attr(const eattr *a, byte *buf, int buflen);
|
||||||
|
|
||||||
|
|
||||||
/* kif sysdep */
|
/* kif sysdep */
|
||||||
|
|
|
@ -495,7 +495,10 @@ void
|
||||||
bt_fmt_ipa(char *buf, size_t size, const void *data)
|
bt_fmt_ipa(char *buf, size_t size, const void *data)
|
||||||
{
|
{
|
||||||
const ip_addr *ip = data;
|
const ip_addr *ip = data;
|
||||||
|
if (data)
|
||||||
bsnprintf(buf, size, "%I", *ip);
|
bsnprintf(buf, size, "%I", *ip);
|
||||||
|
else
|
||||||
|
bsnprintf(buf, size, "(null)");
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
Loading…
Reference in a new issue