mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2025-03-11 17:08:46 +00:00
Temporary integrated commit.
This commit is contained in:
parent
ed6c144066
commit
3f03288514
11
lib/printf.c
11
lib/printf.c
@ -141,6 +141,7 @@ int bvsnprintf(char *buf, int size, const char *fmt, va_list args)
|
||||
const char *s;
|
||||
char ipbuf[MAX_ADDRESS_P_LENGTH];
|
||||
struct iface *iface;
|
||||
ip_addr ip;
|
||||
|
||||
int flags; /* flags to number() */
|
||||
|
||||
@ -272,11 +273,15 @@ int bvsnprintf(char *buf, int size, const char *fmt, va_list args)
|
||||
|
||||
/* IP address */
|
||||
case 'I':
|
||||
ip = va_arg(args, ip_addr);
|
||||
if (flags & SPECIAL)
|
||||
ip6_ntox(va_arg(args, ip_addr), ipbuf);
|
||||
ip6_ntox(ip, ipbuf);
|
||||
else {
|
||||
// XXXX update IPv4 / IPv6 distinction
|
||||
ip6_ntop(va_arg(args, ip_addr), ipbuf);
|
||||
// XXXX better IPv4 / IPv6 distinction
|
||||
if (ipa_is_ip4(ip))
|
||||
ip4_ntop(ipa_to_ip4(ip), ipbuf);
|
||||
else
|
||||
ip6_ntop(ipa_to_ip6(ip), ipbuf);
|
||||
if (field_width > 0)
|
||||
field_width = STD_ADDRESS_P_LENGTH;
|
||||
}
|
||||
|
@ -44,6 +44,7 @@ CF_DECLS
|
||||
|
||||
CF_KEYWORDS(ROUTER, ID, PROTOCOL, TEMPLATE, PREFERENCE, DISABLED, DEBUG, ALL, OFF, DIRECT)
|
||||
CF_KEYWORDS(INTERFACE, IMPORT, EXPORT, FILTER, NONE, TABLE, STATES, ROUTES, FILTERS)
|
||||
CF_KEYWORDS(IPV4, IPVX, VPN4, VPN6, MPLS)
|
||||
CF_KEYWORDS(LIMIT, ACTION, WARN, BLOCK, RESTART, DISABLE)
|
||||
CF_KEYWORDS(PASSWORD, FROM, PASSIVE, TO, ID, EVENTS, PACKETS, PROTOCOLS, INTERFACES)
|
||||
CF_KEYWORDS(PRIMARY, STATS, COUNT, FOR, COMMANDS, PREEXPORT, GENERATE, ROA, AS, MAX, FLUSH)
|
||||
@ -65,7 +66,7 @@ CF_ENUM(T_ENUM_ROA, ROA_, UNKNOWN, VALID, INVALID)
|
||||
%type <ro> roa_args
|
||||
%type <rot> roa_table_arg
|
||||
%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_or_preexport roa_mode limit_action
|
||||
%type <i> proto_start echo_mask echo_size debug_mask debug_list debug_flag mrtdump_mask mrtdump_list mrtdump_flag export_or_preexport roa_mode limit_action table_type
|
||||
%type <ps> proto_patt proto_patt2
|
||||
%type <g> limit_spec
|
||||
|
||||
@ -107,11 +108,19 @@ listen_opt:
|
||||
|
||||
CF_ADDTO(conf, newtab)
|
||||
|
||||
newtab: TABLE SYM {
|
||||
rt_new_table($2, RT_IP);
|
||||
}
|
||||
table_type:
|
||||
/* empty */ { $$ = RT_IP; }
|
||||
| IPV4 { $$ = RT_IPV4; }
|
||||
| IPVX { $$ = RT_IPV6; } /* XXXX */
|
||||
| VPN4 { $$ = RT_VPN4; }
|
||||
| VPN6 { $$ = RT_VPN6; }
|
||||
| MPLS { $$ = RT_MPLS; }
|
||||
;
|
||||
|
||||
newtab: table_type TABLE SYM {
|
||||
rt_new_table($3, $1);
|
||||
};
|
||||
|
||||
CF_ADDTO(conf, roa_table)
|
||||
|
||||
roa_table_start: ROA TABLE SYM {
|
||||
@ -173,7 +182,11 @@ proto_item:
|
||||
| EXPORT imexport { this_proto->out_filter = $2; }
|
||||
| IMPORT LIMIT limit_spec { this_proto->in_limit = $3; }
|
||||
| EXPORT LIMIT limit_spec { this_proto->out_limit = $3; }
|
||||
| TABLE rtable { this_proto->table = $2; }
|
||||
| TABLE rtable {
|
||||
if (!rt_match($2->addr_type, this_proto->protocol->tables))
|
||||
cf_error("Incompatible table class");
|
||||
this_proto->table = $2;
|
||||
}
|
||||
| ROUTER ID idval { this_proto->router_id = $3; }
|
||||
| DESCRIPTION TEXT { this_proto->dsc = $2; }
|
||||
;
|
||||
|
@ -40,7 +40,8 @@ struct protocol {
|
||||
int name_counter; /* Counter for automatic name generation */
|
||||
int attr_class; /* Attribute class known to this protocol */
|
||||
int multitable; /* Protocol handles all announce hooks itself */
|
||||
unsigned preference; /* Default protocol preference */
|
||||
u32 tables; /* Can be attached to these classes of tables (RTB_* flags) */
|
||||
u32 preference; /* Default protocol preference */
|
||||
|
||||
void (*preconfig)(struct protocol *, struct config *); /* Just before configuring */
|
||||
void (*postconfig)(struct proto_config *); /* After configuring each instance */
|
||||
|
@ -257,8 +257,10 @@ typedef struct rte {
|
||||
#define RTB_VPN6 (1 << RT_VPN6)
|
||||
#define RTB_MPLS (1 << RT_MPLS)
|
||||
|
||||
#define RTB_IP (RTB_IPV4 | RTB_IPV6)
|
||||
|
||||
// XXXX these should probably go away, check their users
|
||||
#define RT_IP RT_IPV6
|
||||
#define RTB_IP RTB_IPV6
|
||||
|
||||
|
||||
/* Types of route announcement, also used as flags */
|
||||
@ -291,6 +293,7 @@ void rt_feed_baby_abort(struct proto *p);
|
||||
void rt_schedule_prune_all(void);
|
||||
int rt_prune_loop(void);
|
||||
struct rtable_config *rt_new_table(struct symbol *s, int addr_type);
|
||||
static inline int rt_match(int rt, u32 rtlist) { return !rtlist || ((1 << rt) & rtlist); }
|
||||
int rt_addrsize(int addr_type); // XXXX needed?
|
||||
|
||||
|
||||
|
@ -37,6 +37,9 @@ dev_ifa_notify(struct proto *p, unsigned c, struct ifa *ad)
|
||||
if (ad->scope <= SCOPE_LINK)
|
||||
return;
|
||||
|
||||
if (ipa_is_ip4(ad->prefix) != (p->table->addr_type == RT_IPV4))
|
||||
return;
|
||||
|
||||
if (c & IF_CHANGE_DOWN)
|
||||
{
|
||||
net *n;
|
||||
@ -107,10 +110,11 @@ dev_copy_config(struct proto_config *dest, struct proto_config *src)
|
||||
}
|
||||
|
||||
struct protocol proto_device = {
|
||||
name: "Direct",
|
||||
template: "direct%d",
|
||||
preference: DEF_PREF_DIRECT,
|
||||
init: dev_init,
|
||||
reconfigure: dev_reconfigure,
|
||||
copy_config: dev_copy_config
|
||||
.name = "Direct",
|
||||
.template = "direct%d",
|
||||
.tables = RTB_IP,
|
||||
.preference = DEF_PREF_DIRECT,
|
||||
.init = dev_init,
|
||||
.reconfigure = dev_reconfigure,
|
||||
.copy_config = dev_copy_config
|
||||
};
|
||||
|
@ -954,7 +954,8 @@ rt_addrsize(int addr_type)
|
||||
return sizeof(vpn6_addr);
|
||||
#endif
|
||||
case RT_IPV4:
|
||||
return sizeof(ip4_addr);
|
||||
// XXXX
|
||||
return sizeof(ip6_addr);
|
||||
case RT_IPV6:
|
||||
return sizeof(ip6_addr);
|
||||
}
|
||||
|
@ -237,6 +237,8 @@ nl_parse_attrs(struct rtattr *a, struct rtattr **k, int ksize)
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define IPSIZE(ipv4) ((ipv4) ? sizeof(ip4_addr) : sizeof(ip6_addr))
|
||||
|
||||
static inline ip4_addr rta4_get_ip4(struct rtattr *a)
|
||||
{ return ip4_get(RTA_DATA(a)); }
|
||||
|
||||
@ -249,10 +251,15 @@ static inline ip_addr rta4_get_ipa(struct rtattr *a)
|
||||
static inline ip_addr rta6_get_ipa(struct rtattr *a)
|
||||
{ return ipa_from_ip6(ip6_get(RTA_DATA(a))); }
|
||||
|
||||
static inline ip_addr rtax_get_ipa(struct rtattr *a, const int ipv4)
|
||||
{ return ipv4 ? rta4_get_ipa(a) : rta6_get_ipa(a); }
|
||||
|
||||
void
|
||||
nl_add_attr(struct nlmsghdr *h, unsigned bufsize, unsigned code,
|
||||
void *data, unsigned dlen)
|
||||
static inline void ipax_put(void *buf, ip_addr a, const int ipv4)
|
||||
{ if (ipv4) ip4_put(buf, ipa_to_ip4(a)); else ip6_put(buf, ipa_to_ip6(a)); }
|
||||
|
||||
|
||||
void *
|
||||
nl_add_attr(struct nlmsghdr *h, unsigned bufsize, unsigned code, unsigned dlen)
|
||||
{
|
||||
unsigned len = RTA_LENGTH(dlen);
|
||||
unsigned pos = NLMSG_ALIGN(h->nlmsg_len);
|
||||
@ -264,42 +271,42 @@ nl_add_attr(struct nlmsghdr *h, unsigned bufsize, unsigned code,
|
||||
a->rta_type = code;
|
||||
a->rta_len = len;
|
||||
h->nlmsg_len = pos + len;
|
||||
memcpy(RTA_DATA(a), data, dlen);
|
||||
return RTA_DATA(a);
|
||||
}
|
||||
|
||||
static inline void
|
||||
nl_add_attr_u32(struct nlmsghdr *h, unsigned bufsize, int code, u32 data)
|
||||
{
|
||||
nl_add_attr(h, bufsize, code, &data, 4);
|
||||
void *buf = nl_add_attr(h, bufsize, code, 4);
|
||||
memcpy(buf, &data, 4);
|
||||
}
|
||||
|
||||
static inline void
|
||||
nl_add_attr_ipa(struct nlmsghdr *h, unsigned bufsize, int code, ip_addr ipa)
|
||||
nl_add_attr_ipa(struct nlmsghdr *h, unsigned bufsize, int code, ip_addr ipa, const int ipv4)
|
||||
{
|
||||
ipa_hton(ipa);
|
||||
nl_add_attr(h, bufsize, code, &ipa, sizeof(ipa));
|
||||
void *buf = nl_add_attr(h, bufsize, code, IPSIZE(ipv4));
|
||||
ipax_put(buf, ipa, ipv4);
|
||||
}
|
||||
|
||||
#define RTNH_SIZE (sizeof(struct rtnexthop) + sizeof(struct rtattr) + sizeof(ip_addr))
|
||||
#define RTNH_SIZE(ipv4) (sizeof(struct rtnexthop) + sizeof(struct rtattr) + IPSIZE(ipv4))
|
||||
|
||||
static inline void
|
||||
add_mpnexthop(char *buf, ip_addr ipa, unsigned iface, unsigned char weight)
|
||||
add_mpnexthop(char *buf, ip_addr ipa, const int ipv4, unsigned iface, unsigned char weight)
|
||||
{
|
||||
struct rtnexthop *nh = (void *) buf;
|
||||
struct rtattr *rt = (void *) (buf + sizeof(*nh));
|
||||
nh->rtnh_len = RTNH_SIZE;
|
||||
nh->rtnh_len = RTNH_SIZE(ipv4);
|
||||
nh->rtnh_flags = 0;
|
||||
nh->rtnh_hops = weight;
|
||||
nh->rtnh_ifindex = iface;
|
||||
rt->rta_len = sizeof(*rt) + sizeof(ipa);
|
||||
rt->rta_len = sizeof(*rt) + IPSIZE(ipv4);
|
||||
rt->rta_type = RTA_GATEWAY;
|
||||
ipa_hton(ipa);
|
||||
memcpy(buf + sizeof(*nh) + sizeof(*rt), &ipa, sizeof(ipa));
|
||||
ipax_put(buf + sizeof(*nh) + sizeof(*rt), ipa, ipv4);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
nl_add_multipath(struct nlmsghdr *h, unsigned bufsize, struct mpnh *nh)
|
||||
nl_add_multipath(struct nlmsghdr *h, unsigned bufsize, struct mpnh *nh, const int ipv4)
|
||||
{
|
||||
unsigned len = sizeof(struct rtattr);
|
||||
unsigned pos = NLMSG_ALIGN(h->nlmsg_len);
|
||||
@ -309,12 +316,12 @@ nl_add_multipath(struct nlmsghdr *h, unsigned bufsize, struct mpnh *nh)
|
||||
|
||||
for (; nh; nh = nh->next)
|
||||
{
|
||||
len += RTNH_SIZE;
|
||||
len += RTNH_SIZE(ipv4);
|
||||
if (pos + len > bufsize)
|
||||
bug("nl_add_multipath: packet buffer overflow");
|
||||
|
||||
add_mpnexthop(buf, nh->gw, nh->iface->index, nh->weight);
|
||||
buf += RTNH_SIZE;
|
||||
add_mpnexthop(buf, nh->gw, ipv4, nh->iface->index, nh->weight);
|
||||
buf += RTNH_SIZE(ipv4);
|
||||
}
|
||||
|
||||
rt->rta_type = RTA_MULTIPATH;
|
||||
@ -324,7 +331,7 @@ nl_add_multipath(struct nlmsghdr *h, unsigned bufsize, struct mpnh *nh)
|
||||
|
||||
|
||||
static struct mpnh *
|
||||
nl_parse_multipath(struct krt_proto *p, struct rtattr *ra)
|
||||
nl_parse_multipath(struct krt_proto *p, struct rtattr *ra, const int ipv4)
|
||||
{
|
||||
/* Temporary buffer for multicast nexthops */
|
||||
static struct mpnh *nh_buffer;
|
||||
@ -365,12 +372,10 @@ nl_parse_multipath(struct krt_proto *p, struct rtattr *ra)
|
||||
nl_parse_attrs(RTNH_DATA(nh), a, sizeof(a));
|
||||
if (a[RTA_GATEWAY])
|
||||
{
|
||||
if (RTA_PAYLOAD(a[RTA_GATEWAY]) != sizeof(ip_addr))
|
||||
if (RTA_PAYLOAD(a[RTA_GATEWAY]) != IPSIZE(ipv4))
|
||||
return NULL;
|
||||
|
||||
memcpy(&rv->gw, RTA_DATA(a[RTA_GATEWAY]), sizeof(ip_addr));
|
||||
ipa_ntoh(rv->gw);
|
||||
|
||||
rv->gw = rtax_get_ipa(a[RTA_GATEWAY], ipv4);
|
||||
neighbor *ng = neigh_find2(&p->p, &rv->gw, rv->iface,
|
||||
(nh->rtnh_flags & RTNH_F_ONLINK) ? NEF_ONLINK : 0);
|
||||
if (!ng || (ng->scope == SCOPE_HOST))
|
||||
@ -499,7 +504,7 @@ nl_parse_addr(struct nlmsghdr *h)
|
||||
if (i->ifa_flags & IFA_F_SECONDARY)
|
||||
ifa.flags |= IA_SECONDARY;
|
||||
|
||||
ifa.pxlen = i->ifa_prefixlen + (ipv4 ? 96 : 0); // XXXXX: Hack
|
||||
ifa.pxlen = i->ifa_prefixlen + (ipv4 ? 96 : 0); // XXXX: Hack
|
||||
if (ifa.pxlen > BITS_PER_IP_ADDRESS)
|
||||
{
|
||||
log(L_ERR "KIF: Received invalid pxlen %d on %s", i->ifa_prefixlen, ifa.iface->name);
|
||||
@ -592,7 +597,9 @@ kif_do_scan(struct kif_proto *p UNUSED)
|
||||
* Routes
|
||||
*/
|
||||
|
||||
static struct krt_proto *nl_table_map[NL_NUM_TABLES];
|
||||
static struct krt_proto *nl_table4_map[NL_NUM_TABLES];
|
||||
static struct krt_proto *nl_table6_map[NL_NUM_TABLES];
|
||||
#define nl_tablex_map(x) (x ? nl_table4_map : nl_table6_map)
|
||||
|
||||
int
|
||||
krt_capable(rte *e)
|
||||
@ -620,24 +627,25 @@ krt_capable(rte *e)
|
||||
}
|
||||
|
||||
static inline int
|
||||
nh_bufsize(struct mpnh *nh)
|
||||
nh_bufsize(struct mpnh *nh, const int ipv4)
|
||||
{
|
||||
int rv = 0;
|
||||
for (; nh != NULL; nh = nh->next)
|
||||
rv += RTNH_SIZE;
|
||||
rv += RTNH_SIZE(ipv4);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int
|
||||
nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int new)
|
||||
{
|
||||
int ipv4 = (p->addr_type == RT_IPV4);
|
||||
eattr *ea;
|
||||
net *net = e->net;
|
||||
rta *a = e->attrs;
|
||||
struct {
|
||||
struct nlmsghdr h;
|
||||
struct rtmsg r;
|
||||
char buf[128 + nh_bufsize(a->nexthops)];
|
||||
char buf[128 + nh_bufsize(a->nexthops, ipv4)];
|
||||
} r;
|
||||
|
||||
DBG("nl_send_route(%F,new=%d)\n", &net->n, new);
|
||||
@ -648,13 +656,13 @@ nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int new)
|
||||
r.h.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
|
||||
r.h.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | (new ? NLM_F_CREATE|NLM_F_EXCL : 0);
|
||||
|
||||
r.r.rtm_family = BIRD_AF;
|
||||
r.r.rtm_dst_len = net->n.pxlen;
|
||||
r.r.rtm_family = ipv4 ? AF_INET : AF_INET6;
|
||||
r.r.rtm_dst_len = net->n.pxlen - (ipv4 ? 96 : 0); // XXXX: Hack;
|
||||
r.r.rtm_tos = 0;
|
||||
r.r.rtm_table = KRT_CF->sys.table_id;
|
||||
r.r.rtm_protocol = RTPROT_BIRD;
|
||||
r.r.rtm_scope = RT_SCOPE_UNIVERSE;
|
||||
nl_add_attr_ipa(&r.h, sizeof(r), RTA_DST, *FPREFIX_IP(&net->n));
|
||||
nl_add_attr_ipa(&r.h, sizeof(r), RTA_DST, *FPREFIX_IP(&net->n), ipv4);
|
||||
|
||||
u32 metric = 0;
|
||||
if (new && e->attrs->source == RTS_INHERIT)
|
||||
@ -665,7 +673,7 @@ nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int new)
|
||||
nl_add_attr_u32(&r.h, sizeof(r), RTA_PRIORITY, metric);
|
||||
|
||||
if (ea = ea_find(eattrs, EA_KRT_PREFSRC))
|
||||
nl_add_attr_ipa(&r.h, sizeof(r), RTA_PREFSRC, *(ip_addr *)ea->u.ptr->data);
|
||||
nl_add_attr_ipa(&r.h, sizeof(r), RTA_PREFSRC, *(ip_addr *)ea->u.ptr->data, ipv4);
|
||||
|
||||
if (ea = ea_find(eattrs, EA_KRT_REALM))
|
||||
nl_add_attr_u32(&r.h, sizeof(r), RTA_FLOW, ea->u.data);
|
||||
@ -677,7 +685,7 @@ nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int new)
|
||||
case RTD_ROUTER:
|
||||
r.r.rtm_type = RTN_UNICAST;
|
||||
nl_add_attr_u32(&r.h, sizeof(r), RTA_OIF, a->iface->index);
|
||||
nl_add_attr_ipa(&r.h, sizeof(r), RTA_GATEWAY, a->gw);
|
||||
nl_add_attr_ipa(&r.h, sizeof(r), RTA_GATEWAY, a->gw, ipv4);
|
||||
break;
|
||||
case RTD_DEVICE:
|
||||
r.r.rtm_type = RTN_UNICAST;
|
||||
@ -694,7 +702,7 @@ nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int new)
|
||||
break;
|
||||
case RTD_MULTIPATH:
|
||||
r.r.rtm_type = RTN_UNICAST;
|
||||
nl_add_multipath(&r.h, sizeof(r), a->nexthops);
|
||||
nl_add_multipath(&r.h, sizeof(r), a->nexthops, ipv4);
|
||||
break;
|
||||
default:
|
||||
bug("krt_capable inconsistent with nl_send_route");
|
||||
@ -716,10 +724,16 @@ krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old, struct ea_list
|
||||
*/
|
||||
|
||||
if (old)
|
||||
{
|
||||
// log(L_WARN "KRT: %p OLD %I/%d GW %I", p, n->n.prefix, n->n.pxlen, old->attrs->gw);
|
||||
nl_send_route(p, old, NULL, 0);
|
||||
}
|
||||
|
||||
if (new)
|
||||
{
|
||||
// log(L_WARN "KRT: %p NEW %I/%d %I/%d GW %I", p, n->n.prefix, n->n.pxlen, new->attrs->gw);
|
||||
err = nl_send_route(p, new, eattrs, 1);
|
||||
}
|
||||
|
||||
if (err < 0)
|
||||
n->n.flags |= KRF_SYNC_ERROR;
|
||||
@ -737,51 +751,52 @@ nl_parse_route(struct nlmsghdr *h, int scan)
|
||||
struct rtmsg *i;
|
||||
struct rtattr *a[RTA_CACHEINFO+1];
|
||||
int new = h->nlmsg_type == RTM_NEWROUTE;
|
||||
|
||||
ip_addr dst = IPA_NONE;
|
||||
u32 oif = ~0;
|
||||
int src;
|
||||
int src, ipv4, ipsize;
|
||||
|
||||
if (!(i = nl_checkin(h, sizeof(*i))) || !nl_parse_attrs(RTM_RTA(i), a, sizeof(a)))
|
||||
return;
|
||||
if (i->rtm_family != BIRD_AF)
|
||||
return;
|
||||
if ((a[RTA_DST] && RTA_PAYLOAD(a[RTA_DST]) != sizeof(ip_addr)) ||
|
||||
#ifdef IPV6
|
||||
|
||||
if (i->rtm_family == AF_INET)
|
||||
ipv4 = 1;
|
||||
else if (i->rtm_family == AF_INET6)
|
||||
ipv4 = 0;
|
||||
else
|
||||
return; /* Ignore unknown address families */
|
||||
|
||||
ipsize = IPSIZE(ipv4);
|
||||
if ((a[RTA_DST] && RTA_PAYLOAD(a[RTA_DST]) != ipsize) ||
|
||||
(a[RTA_IIF] && RTA_PAYLOAD(a[RTA_IIF]) != 4) ||
|
||||
#endif
|
||||
(a[RTA_OIF] && RTA_PAYLOAD(a[RTA_OIF]) != 4) ||
|
||||
(a[RTA_GATEWAY] && RTA_PAYLOAD(a[RTA_GATEWAY]) != sizeof(ip_addr)) ||
|
||||
(a[RTA_GATEWAY] && RTA_PAYLOAD(a[RTA_GATEWAY]) != ipsize) ||
|
||||
(a[RTA_PRIORITY] && RTA_PAYLOAD(a[RTA_PRIORITY]) != 4) ||
|
||||
(a[RTA_PREFSRC] && RTA_PAYLOAD(a[RTA_PREFSRC]) != sizeof(ip_addr)) ||
|
||||
(a[RTA_FLOW] && RTA_PAYLOAD(a[RTA_OIF]) != 4))
|
||||
(a[RTA_PREFSRC] && RTA_PAYLOAD(a[RTA_PREFSRC]) != ipsize) ||
|
||||
(a[RTA_FLOW] && RTA_PAYLOAD(a[RTA_FLOW]) != 4))
|
||||
{
|
||||
log(L_ERR "KRT: Malformed message received");
|
||||
return;
|
||||
}
|
||||
|
||||
if (a[RTA_DST])
|
||||
{
|
||||
memcpy(&dst, RTA_DATA(a[RTA_DST]), sizeof(dst));
|
||||
ipa_ntoh(dst);
|
||||
}
|
||||
dst = rtax_get_ipa(a[RTA_DST], ipv4);
|
||||
else if (ipv4) // XXXX hack
|
||||
dst = ipa_build4(0,0,0,0);
|
||||
|
||||
if (a[RTA_OIF])
|
||||
memcpy(&oif, RTA_DATA(a[RTA_OIF]), sizeof(oif));
|
||||
|
||||
p = nl_table_map[i->rtm_table]; /* Do we know this table? */
|
||||
DBG("KRT: Got %I/%d, type=%d, oif=%d, table=%d, prid=%d, proto=%s\n", dst, i->rtm_dst_len, i->rtm_type, oif, i->rtm_table, i->rtm_protocol, p ? p->p.name : "(none)");
|
||||
if (!p)
|
||||
DBG("KRT: Got %I/%d, type=%d, oif=%d, table=%d, prid=%d\n", dst, i->rtm_dst_len, i->rtm_type, oif, i->rtm_table, i->rtm_protocol);
|
||||
|
||||
p = nl_tablex_map(ipv4)[i->rtm_table];
|
||||
if (!p) /* We don't know this table */
|
||||
SKIP("unknown table %d\n", i->rtm_table);
|
||||
|
||||
|
||||
#ifdef IPV6
|
||||
if (a[RTA_IIF])
|
||||
if (a[RTA_IIF]) /* We don't support IIF */
|
||||
SKIP("IIF set\n");
|
||||
#else
|
||||
|
||||
if (i->rtm_tos != 0) /* We don't support TOS */
|
||||
SKIP("TOS %02x\n", i->rtm_tos);
|
||||
#endif
|
||||
|
||||
if (scan && !new)
|
||||
SKIP("RTM_DELROUTE in scan\n");
|
||||
@ -818,7 +833,8 @@ nl_parse_route(struct nlmsghdr *h, int scan)
|
||||
src = KRT_SRC_ALIEN;
|
||||
}
|
||||
|
||||
net *net = net_get(p->p.table, dst, i->rtm_dst_len);
|
||||
int pxlen = i->rtm_dst_len + (ipv4 ? 96 : 0); // XXXX: Hack
|
||||
net *net = net_get(p->p.table, dst, pxlen);
|
||||
|
||||
rta ra = {
|
||||
.proto = &p->p,
|
||||
@ -834,7 +850,7 @@ nl_parse_route(struct nlmsghdr *h, int scan)
|
||||
if (a[RTA_MULTIPATH])
|
||||
{
|
||||
ra.dest = RTD_MULTIPATH;
|
||||
ra.nexthops = nl_parse_multipath(p, a[RTA_MULTIPATH]);
|
||||
ra.nexthops = nl_parse_multipath(p, a[RTA_MULTIPATH], ipv4);
|
||||
if (!ra.nexthops)
|
||||
{
|
||||
log(L_ERR "KRT: Received strange multipath route %F", &net->n);
|
||||
@ -847,8 +863,7 @@ nl_parse_route(struct nlmsghdr *h, int scan)
|
||||
ra.iface = if_find_by_index(oif);
|
||||
if (!ra.iface)
|
||||
{
|
||||
log(L_ERR "KRT: Received route %F with unknown ifindex %u",
|
||||
&net->n, oif);
|
||||
log(L_ERR "KRT: Received route %F with unknown ifindex %u", &net->n, oif);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -856,8 +871,7 @@ nl_parse_route(struct nlmsghdr *h, int scan)
|
||||
{
|
||||
neighbor *ng;
|
||||
ra.dest = RTD_ROUTER;
|
||||
memcpy(&ra.gw, RTA_DATA(a[RTA_GATEWAY]), sizeof(ra.gw));
|
||||
ipa_ntoh(ra.gw);
|
||||
ra.gw = rtax_get_ipa(a[RTA_GATEWAY], ipv4);
|
||||
|
||||
/* Silently skip strange 6to4 routes */
|
||||
if (ipa_in_net(ra.gw, IPA_NONE, 96))
|
||||
@ -873,22 +887,7 @@ nl_parse_route(struct nlmsghdr *h, int scan)
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ra.dest = RTD_DEVICE;
|
||||
|
||||
/*
|
||||
* In Linux IPv6, 'native' device routes have proto
|
||||
* RTPROT_BOOT and not RTPROT_KERNEL (which they have in
|
||||
* IPv4 and which is expected). We cannot distinguish
|
||||
* 'native' and user defined device routes, so we ignore all
|
||||
* such device routes and for consistency, we have the same
|
||||
* behavior in IPv4. Anyway, users should use RTPROT_STATIC
|
||||
* for their 'alien' routes.
|
||||
*/
|
||||
|
||||
if (i->rtm_protocol == RTPROT_BOOT)
|
||||
src = KRT_SRC_KERNEL;
|
||||
}
|
||||
ra.dest = RTD_DEVICE;
|
||||
|
||||
break;
|
||||
case RTN_BLACKHOLE:
|
||||
@ -919,9 +918,7 @@ nl_parse_route(struct nlmsghdr *h, int scan)
|
||||
|
||||
if (a[RTA_PREFSRC])
|
||||
{
|
||||
ip_addr ps;
|
||||
memcpy(&ps, RTA_DATA(a[RTA_PREFSRC]), sizeof(ps));
|
||||
ipa_ntoh(ps);
|
||||
ip_addr ps = rtax_get_ipa(a[RTA_PREFSRC], ipv4);
|
||||
|
||||
ea_list *ea = alloca(sizeof(ea_list) + sizeof(eattr));
|
||||
ea->next = ra.eattrs;
|
||||
@ -960,7 +957,14 @@ krt_do_scan(struct krt_proto *p UNUSED) /* CONFIG_ALL_TABLES_AT_ONCE => p is NUL
|
||||
{
|
||||
struct nlmsghdr *h;
|
||||
|
||||
nl_request_dump(BIRD_PF, RTM_GETROUTE);
|
||||
nl_request_dump(PF_INET, RTM_GETROUTE);
|
||||
while (h = nl_get_scan())
|
||||
if (h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE)
|
||||
nl_parse_route(h, 1);
|
||||
else
|
||||
log(L_DEBUG "nl_scan_fire: Unknown packet received (type=%d)", h->nlmsg_type);
|
||||
|
||||
nl_request_dump(PF_INET6, RTM_GETROUTE);
|
||||
while (h = nl_get_scan())
|
||||
if (h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE)
|
||||
nl_parse_route(h, 1);
|
||||
@ -1095,12 +1099,10 @@ nl_open_async(void)
|
||||
* Interface to the UNIX krt module
|
||||
*/
|
||||
|
||||
static u8 nl_cf_table[(NL_NUM_TABLES+7) / 8];
|
||||
|
||||
void
|
||||
krt_sys_start(struct krt_proto *p, int first)
|
||||
{
|
||||
nl_table_map[KRT_CF->sys.table_id] = p;
|
||||
nl_tablex_map(p->addr_type == RT_IPV4)[KRT_CF->sys.table_id] = p;
|
||||
if (first)
|
||||
{
|
||||
nl_open();
|
||||
@ -1119,21 +1121,25 @@ krt_sys_reconfigure(struct krt_proto *p UNUSED, struct krt_config *n, struct krt
|
||||
return n->sys.table_id == o->sys.table_id;
|
||||
}
|
||||
|
||||
static u32 nl_table4_cf[(NL_NUM_TABLES+31) / 32];
|
||||
static u32 nl_table6_cf[(NL_NUM_TABLES+31) / 32];
|
||||
|
||||
void
|
||||
krt_sys_preconfig(struct config *c UNUSED)
|
||||
{
|
||||
bzero(&nl_cf_table, sizeof(nl_cf_table));
|
||||
bzero(&nl_table4_cf, sizeof(nl_table4_cf));
|
||||
bzero(&nl_table6_cf, sizeof(nl_table6_cf));
|
||||
}
|
||||
|
||||
void
|
||||
krt_sys_postconfig(struct krt_config *x)
|
||||
{
|
||||
int id = x->sys.table_id;
|
||||
u32 *tbl = (x->c.table->addr_type == RT_IPV4) ? nl_table4_cf : nl_table6_cf;
|
||||
u32 id = x->sys.table_id;
|
||||
|
||||
if (nl_cf_table[id/8] & (1 << (id%8)))
|
||||
if (tbl[id/32] & (1 << (id%32)))
|
||||
cf_error("Multiple kernel syncers defined for table #%d", id);
|
||||
nl_cf_table[id/8] |= (1 << (id%8));
|
||||
tbl[id/32] |= (1 << (id%32));
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -595,6 +595,7 @@ krt_same_dest(rte *k, rte *e)
|
||||
switch (ka->dest)
|
||||
{
|
||||
case RTD_ROUTER:
|
||||
// XXXX check iface
|
||||
return ipa_equal(ka->gw, ea->gw);
|
||||
case RTD_DEVICE:
|
||||
return !strcmp(ka->iface->name, ea->iface->name);
|
||||
@ -966,6 +967,8 @@ krt_start(struct proto *P)
|
||||
p->krt_pool = P->pool;
|
||||
#endif
|
||||
|
||||
p->addr_type = p->p.table->addr_type;
|
||||
|
||||
#ifdef KRT_ALLOW_LEARN
|
||||
krt_learn_init(p);
|
||||
#endif
|
||||
@ -1106,20 +1109,21 @@ krt_get_attr(eattr * a, byte * buf, int buflen UNUSED)
|
||||
|
||||
|
||||
struct protocol proto_unix_kernel = {
|
||||
name: "Kernel",
|
||||
template: "kernel%d",
|
||||
attr_class: EAP_KRT,
|
||||
preference: DEF_PREF_INHERITED,
|
||||
preconfig: krt_preconfig,
|
||||
postconfig: krt_postconfig,
|
||||
init: krt_init,
|
||||
start: krt_start,
|
||||
shutdown: krt_shutdown,
|
||||
reconfigure: krt_reconfigure,
|
||||
copy_config: krt_copy_config,
|
||||
get_attr: krt_get_attr,
|
||||
.name = "Kernel",
|
||||
.template = "kernel%d",
|
||||
.attr_class = EAP_KRT,
|
||||
.tables = RTB_IP,
|
||||
.preference = DEF_PREF_INHERITED,
|
||||
.preconfig = krt_preconfig,
|
||||
.postconfig = krt_postconfig,
|
||||
.init = krt_init,
|
||||
.start = krt_start,
|
||||
.shutdown = krt_shutdown,
|
||||
.reconfigure = krt_reconfigure,
|
||||
.copy_config = krt_copy_config,
|
||||
.get_attr = krt_get_attr,
|
||||
#ifdef KRT_ALLOW_LEARN
|
||||
dump: krt_dump,
|
||||
dump_attrs: krt_dump_attrs,
|
||||
.dump = krt_dump,
|
||||
.dump_attrs = krt_dump_attrs,
|
||||
#endif
|
||||
};
|
||||
|
@ -61,6 +61,7 @@ struct krt_proto {
|
||||
#ifdef CONFIG_ALL_TABLES_AT_ONCE
|
||||
node instance_node; /* Node in krt instance list */
|
||||
#endif
|
||||
int addr_type; /* Kernel table address type */
|
||||
int initialized; /* First scan has already been finished */
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user