Revision 62e64905
conf/cf-lex.l | ||
---|---|---|
124 | 124 |
} |
125 | 125 |
|
126 | 126 |
[02]:{DIGIT}+:{DIGIT}+ { |
127 |
unsigned long int l, len1, len2; |
|
127 | 128 |
char *e; |
128 |
unsigned long int l; |
|
129 | 129 |
|
130 | 130 |
if (yytext[0] == '0') |
131 |
{ |
|
131 | 132 |
cf_lval.i64 = 0; |
133 |
len1 = 16; |
|
134 |
len2 = 32; |
|
135 |
} |
|
132 | 136 |
else |
133 |
cf_lval.i64 = 0x2000000000000ULL; |
|
137 |
{ |
|
138 |
cf_lval.i64 = 2ULL << 48; |
|
139 |
len1 = 32; |
|
140 |
len2 = 16; |
|
141 |
} |
|
134 | 142 |
|
135 | 143 |
errno = 0; |
136 | 144 |
l = strtoul(yytext+2, &e, 10); |
137 |
if (e && (*e != ':') || errno == ERANGE || (yytext[0] == '0') && (l >= (1<<16)))
|
|
145 |
if (e && (*e != ':') || (errno == ERANGE) || (l >> len1))
|
|
138 | 146 |
cf_error("ASN out of range"); |
139 |
cf_lval.i64 |= (((u64) l) << 32); |
|
147 |
cf_lval.i64 |= ((u64) l) << len2; |
|
148 |
|
|
140 | 149 |
errno = 0; |
141 | 150 |
l = strtoul(e+1, &e, 10); |
142 |
if (e && *e || errno == ERANGE || (yytext[0] == '2') && (l >= (1<<16)))
|
|
143 |
cf_error("Assigned number out of range");
|
|
151 |
if (e && *e || (errno == ERANGE) || (l >> len2))
|
|
152 |
cf_error("Number out of range");
|
|
144 | 153 |
cf_lval.i64 |= l; |
154 |
|
|
145 | 155 |
return VPN_RD; |
146 | 156 |
} |
147 | 157 |
|
148 | 158 |
1:{DIGIT}+\.{DIGIT}+\.{DIGIT}+\.{DIGIT}+:{DIGIT}+ { |
149 | 159 |
unsigned long int l; |
150 |
char *e = strchr(yytext+2, ':'); |
|
151 |
*e++ = '\0'; |
|
152 | 160 |
ip4_addr ip4; |
161 |
char *e; |
|
162 |
|
|
163 |
cf_lval.i64 = 1ULL << 48; |
|
164 |
|
|
165 |
e = strchr(yytext+2, ':'); |
|
166 |
*e++ = '\0'; |
|
153 | 167 |
if (!ip4_pton(yytext+2, &ip4)) |
154 | 168 |
cf_error("Invalid IPv4 address %s in Route Distinguisher", yytext+2); |
169 |
cf_lval.i64 |= ((u64) ip4_to_u32(ip4)) << 16; |
|
170 |
|
|
155 | 171 |
errno = 0; |
156 | 172 |
l = strtoul(e, &e, 10); |
157 |
if (e && *e || errno == ERANGE || (l >= (1<<16))) |
|
158 |
cf_error("Assigned number out of range"); |
|
159 |
cf_lval.i64 = (1ULL<<48) | (((u64)ip4_to_u32(ip4)) << 16) | ((u64)l); |
|
173 |
if (e && *e || (errno == ERANGE) || (l >> 16)) |
|
174 |
cf_error("Number out of range"); |
|
175 |
cf_lval.i64 |= l; |
|
176 |
|
|
160 | 177 |
return VPN_RD; |
161 | 178 |
} |
162 | 179 |
|
conf/confbase.Y | ||
---|---|---|
203 | 203 |
net_vpn4_: VPN_RD net_ip4_ |
204 | 204 |
{ |
205 | 205 |
$$ = cfg_alloc(sizeof(net_addr_vpn4)); |
206 |
net_fill_vpn4($$, ((net_addr_ip4 *)&$2)->prefix, $2.pxlen, $1);
|
|
206 |
net_fill_vpn4($$, net4_prefix(&$2), net4_pxlen(&$2), $1);
|
|
207 | 207 |
} |
208 | 208 |
|
209 | 209 |
net_vpn6_: VPN_RD net_ip6_ |
210 | 210 |
{ |
211 | 211 |
$$ = cfg_alloc(sizeof(net_addr_vpn6)); |
212 |
net_fill_vpn6($$, ((net_addr_ip6 *)&$2)->prefix, $2.pxlen, $1);
|
|
212 |
net_fill_vpn6($$, net6_prefix(&$2), net6_pxlen(&$2), $1);
|
|
213 | 213 |
} |
214 | 214 |
|
215 | 215 |
net_roa4_: net_ip4_ MAX NUM AS NUM |
... | ... | |
229 | 229 |
}; |
230 | 230 |
|
231 | 231 |
net_ip_: net_ip4_ | net_ip6_ ; |
232 |
net_roa_: net_roa4_ | net_roa6_ ; |
|
233 | 232 |
net_vpn_: net_vpn4_ | net_vpn6_ ; |
233 |
net_roa_: net_roa4_ | net_roa6_ ; |
|
234 | 234 |
|
235 | 235 |
net_: |
236 | 236 |
net_ip_ { $$ = cfg_alloc($1.length); net_copy($$, &($1)); } |
... | ... | |
297 | 297 |
label_stack_start |
298 | 298 |
| label_stack '/' NUM { |
299 | 299 |
if ($1[0] >= MPLS_MAX_LABEL_STACK) |
300 |
cf_error("Too many labels in stack."); |
|
301 |
$1[++$1[0]] = $3; |
|
300 |
cf_error("Too many labels in stack"); |
|
301 |
$1[0]++; |
|
302 |
$1[*$1] = $3; |
|
302 | 303 |
$$ = $1; |
303 | 304 |
} |
304 | 305 |
; |
doc/bird.sgml | ||
---|---|---|
4140 | 4140 |
specific destination for them and you don't want to send them out through the |
4141 | 4141 |
default route to prevent routing loops). |
4142 | 4142 |
|
4143 |
<p>There are five types of static routes: `classical' routes telling to forward
|
|
4143 |
<p>There are four types of static routes: `classical' routes telling to forward
|
|
4144 | 4144 |
packets to a neighboring router (single path or multipath, possibly weighted), |
4145 |
device routes specifying forwarding to hosts on a |
|
4146 |
directly connected network, recursive routes computing their nexthops by doing
|
|
4147 |
route table lookups for a given IP, and special routes (sink, blackhole etc.)
|
|
4148 |
which specify a special action to be done instead of forwarding the packet.
|
|
4145 |
device routes specifying forwarding to hosts on a directly connected network,
|
|
4146 |
recursive routes computing their nexthops by doing route table lookups for a
|
|
4147 |
given IP, and special routes (sink, blackhole etc.) which specify a special
|
|
4148 |
action to be done instead of forwarding the packet. |
|
4149 | 4149 |
|
4150 | 4150 |
<p>When the particular destination is not available (the interface is down or |
4151 | 4151 |
the next hop of the route is not a neighbor at the moment), Static just |
filter/filter.h | ||
---|---|---|
174 | 174 |
#define SA_PROTO 4 |
175 | 175 |
#define SA_SOURCE 5 |
176 | 176 |
#define SA_SCOPE 6 |
177 |
#define SA_DEST 8
|
|
178 |
#define SA_IFNAME 9
|
|
179 |
#define SA_IFINDEX 10
|
|
177 |
#define SA_DEST 7
|
|
178 |
#define SA_IFNAME 8
|
|
179 |
#define SA_IFINDEX 9
|
|
180 | 180 |
|
181 | 181 |
|
182 | 182 |
struct f_tree { |
lib/alloca.h | ||
---|---|---|
15 | 15 |
#include <stdlib.h> |
16 | 16 |
#endif |
17 | 17 |
|
18 |
#define allocz(len) ({ void *_x = alloca(len); memset(_x, 0, len); _x; }) |
|
19 |
|
|
18 | 20 |
#endif |
lib/net.c | ||
---|---|---|
69 | 69 |
case NET_VPN4: |
70 | 70 |
switch (n->vpn4.rd >> 48) |
71 | 71 |
{ |
72 |
case 0: return bsnprintf(buf, buflen, "0:%u:%u %I4/%d", (u32) (n->vpn4.rd >> 32), (u32) n->vpn4.rd, n->vpn4.prefix, n->vpn4.pxlen); |
|
73 |
case 1: return bsnprintf(buf, buflen, "1:%I4:%u %I4/%d", ip4_from_u32(n->vpn4.rd >> 16), (u32) (n->vpn4.rd & 0xffff), n->vpn4.prefix, n->vpn4.pxlen); |
|
74 |
case 2: return bsnprintf(buf, buflen, "2:%u:%u %I4/%d", (u32) (n->vpn4.rd >> 16), (u32) (n->vpn4.rd & 0xffff), n->vpn4.prefix, n->vpn4.pxlen); |
|
72 |
case 0: return bsnprintf(buf, buflen, "0:%u:%u %I4/%d", (u32) (n->vpn4.rd >> 32), (u32) n->vpn4.rd, n->vpn4.prefix, n->vpn4.pxlen); |
|
73 |
case 1: return bsnprintf(buf, buflen, "1:%I4:%u %I4/%d", ip4_from_u32(n->vpn4.rd >> 16), (u32) (n->vpn4.rd & 0xffff), n->vpn4.prefix, n->vpn4.pxlen); |
|
74 |
case 2: return bsnprintf(buf, buflen, "2:%u:%u %I4/%d", (u32) (n->vpn4.rd >> 16), (u32) (n->vpn4.rd & 0xffff), n->vpn4.prefix, n->vpn4.pxlen); |
|
75 |
default: return bsnprintf(buf, buflen, "X:%08x:%08x %I4/%d", (u32) (n->vpn4.rd >> 32), (u32) n->vpn4.rd, n->vpn4.prefix, n->vpn4.pxlen); |
|
75 | 76 |
} |
76 |
return bsnprintf(buf, buflen, "X: %016x %I4/%d", (n->vpn4.rd), n->vpn4.prefix, n->vpn4.pxlen); |
|
77 |
|
|
78 |
/* XXX: RD format is specified for VPN4; not found any for VPN6, reusing the same as for VPN4. */ |
|
79 | 77 |
case NET_VPN6: |
78 |
/* XXX: RD format is specified for VPN4; not found any for VPN6, reusing the same as for VPN4 */ |
|
80 | 79 |
switch (n->vpn6.rd >> 48) |
81 | 80 |
{ |
82 |
case 0: return bsnprintf(buf, buflen, "0:%u:%u %I6/%d", (u32) (n->vpn6.rd >> 32), (u32) n->vpn6.rd, n->vpn6.prefix, n->vpn6.pxlen); |
|
83 |
case 1: return bsnprintf(buf, buflen, "1:%I4:%u %I6/%d", ip4_from_u32(n->vpn6.rd >> 16), (u32) (n->vpn6.rd & 0xffff), n->vpn6.prefix, n->vpn6.pxlen); |
|
84 |
case 2: return bsnprintf(buf, buflen, "2:%u:%u %I6/%d", (u32) (n->vpn6.rd >> 16), (u32) (n->vpn6.rd & 0xffff), n->vpn6.prefix, n->vpn6.pxlen); |
|
81 |
case 0: return bsnprintf(buf, buflen, "0:%u:%u %I6/%d", (u32) (n->vpn6.rd >> 32), (u32) n->vpn6.rd, n->vpn6.prefix, n->vpn6.pxlen); |
|
82 |
case 1: return bsnprintf(buf, buflen, "1:%I4:%u %I6/%d", ip4_from_u32(n->vpn6.rd >> 16), (u32) (n->vpn6.rd & 0xffff), n->vpn6.prefix, n->vpn6.pxlen); |
|
83 |
case 2: return bsnprintf(buf, buflen, "2:%u:%u %I6/%d", (u32) (n->vpn6.rd >> 16), (u32) (n->vpn6.rd & 0xffff), n->vpn6.prefix, n->vpn6.pxlen); |
|
84 |
default: return bsnprintf(buf, buflen, "X:%08x:%08x %I6/%d", (u32) (n->vpn6.rd >> 32), (u32) n->vpn6.rd, n->vpn6.prefix, n->vpn6.pxlen); |
|
85 | 85 |
} |
86 |
return bsnprintf(buf, buflen, "X: %016x %I6/%d", (n->vpn6.rd), n->vpn6.prefix, n->vpn6.pxlen); |
|
87 | 86 |
case NET_ROA4: |
88 | 87 |
return bsnprintf(buf, buflen, "%I4/%u-%u AS%u", n->roa4.prefix, n->roa4.pxlen, n->roa4.max_pxlen, n->roa4.asn); |
89 | 88 |
case NET_ROA6: |
lib/net.h | ||
---|---|---|
306 | 306 |
static inline int net_equal_flow6(const net_addr_flow6 *a, const net_addr_flow6 *b) |
307 | 307 |
{ return net_equal((const net_addr *) a, (const net_addr *) b); } |
308 | 308 |
|
309 |
static inline int net_equal_mpls(const net_addr_mpls *a, const net_addr_mpls *b) |
|
310 |
{ return !memcmp(a, b, sizeof(net_addr_mpls)); } |
|
311 |
|
|
309 | 312 |
|
310 | 313 |
static inline int net_equal_prefix_roa4(const net_addr_roa4 *a, const net_addr_roa4 *b) |
311 | 314 |
{ return ip4_equal(a->prefix, b->prefix) && (a->pxlen == b->pxlen); } |
... | ... | |
313 | 316 |
static inline int net_equal_prefix_roa6(const net_addr_roa6 *a, const net_addr_roa6 *b) |
314 | 317 |
{ return ip6_equal(a->prefix, b->prefix) && (a->pxlen == b->pxlen); } |
315 | 318 |
|
316 |
static inline int net_equal_mpls(const net_addr_mpls *a, const net_addr_mpls *b) |
|
317 |
{ return !memcmp(a, b, sizeof(net_addr_mpls)); } |
|
318 | 319 |
|
319 | 320 |
static inline int net_zero_ip4(const net_addr_ip4 *a) |
320 | 321 |
{ return !a->pxlen && ip4_zero(a->prefix); } |
... | ... | |
404 | 405 |
static inline void net_copy_mpls(net_addr_mpls *dst, const net_addr_mpls *src) |
405 | 406 |
{ memcpy(dst, src, sizeof(net_addr_mpls)); } |
406 | 407 |
|
408 |
|
|
409 |
/* XXXX */ |
|
410 |
static inline u32 u64_hash(u64 a) |
|
411 |
{ return u32_hash(a); } |
|
412 |
|
|
407 | 413 |
static inline u32 net_hash_ip4(const net_addr_ip4 *n) |
408 | 414 |
{ return ip4_hash(n->prefix) ^ ((u32) n->pxlen << 26); } |
409 | 415 |
|
410 | 416 |
static inline u32 net_hash_ip6(const net_addr_ip6 *n) |
411 | 417 |
{ return ip6_hash(n->prefix) ^ ((u32) n->pxlen << 26); } |
412 | 418 |
|
413 |
/* XXXX */ |
|
414 |
static inline u32 u64_hash(u64 a) |
|
415 |
{ return u32_hash(a); } |
|
416 |
|
|
417 | 419 |
static inline u32 net_hash_vpn4(const net_addr_vpn4 *n) |
418 | 420 |
{ return ip4_hash(n->prefix) ^ ((u32) n->pxlen << 26) ^ u64_hash(n->rd); } |
419 | 421 |
|
... | ... | |
452 | 454 |
|
453 | 455 |
static inline int net_validate_mpls(const net_addr_mpls *n) |
454 | 456 |
{ |
455 |
return n->label < (1<<20);
|
|
457 |
return n->label < (1 << 20);
|
|
456 | 458 |
} |
457 | 459 |
|
458 | 460 |
int net_validate(const net_addr *N); |
nest/route.h | ||
---|---|---|
390 | 390 |
#define RTC_MULTICAST 2 |
391 | 391 |
#define RTC_ANYCAST 3 /* IPv6 Anycast */ |
392 | 392 |
|
393 |
#define RTD_UNICAST 0 /* Next hop is neighbor router */ |
|
393 |
#define RTD_NONE 0 /* Undefined next hop */ |
|
394 |
#define RTD_UNICAST 1 /* Next hop is neighbor router */ |
|
394 | 395 |
#define RTD_BLACKHOLE 2 /* Silently drop packets */ |
395 | 396 |
#define RTD_UNREACHABLE 3 /* Reject as unreachable */ |
396 | 397 |
#define RTD_PROHIBIT 4 /* Administratively prohibited */ |
397 |
#define RTD_NONE 6 /* Invalid RTD */ |
|
398 | 398 |
|
399 | 399 |
/* Flags for net->n.flags, used by kernel syncer */ |
400 | 400 |
#define KRF_INSTALLED 0x80 /* This route should be installed in the kernel */ |
... | ... | |
408 | 408 |
|
409 | 409 |
/* Route has regular, reachable nexthop (i.e. not RTD_UNREACHABLE and like) */ |
410 | 410 |
static inline int rte_is_reachable(rte *r) |
411 |
{ uint d = r->attrs->dest; return (d == RTD_UNICAST); }
|
|
411 |
{ return r->attrs->dest == RTD_UNICAST; }
|
|
412 | 412 |
|
413 | 413 |
|
414 | 414 |
/* |
... | ... | |
523 | 523 |
struct nexthop *nexthop_merge(struct nexthop *x, struct nexthop *y, int rx, int ry, int max, linpool *lp); |
524 | 524 |
static inline void nexthop_link(struct rta *a, struct nexthop *from) |
525 | 525 |
{ memcpy(&a->nh, from, nexthop_size(from)); } |
526 |
void nexthop_insert(struct nexthop *n, struct nexthop *y); |
|
526 |
void nexthop_insert(struct nexthop **n, struct nexthop *y);
|
|
527 | 527 |
int nexthop_is_sorted(struct nexthop *x); |
528 | 528 |
|
529 | 529 |
void rta_init(void); |
nest/rt-attr.c | ||
---|---|---|
150 | 150 |
for (; x; x = x->next) |
151 | 151 |
{ |
152 | 152 |
h ^= ipa_hash(x->gw) ^ (h << 5) ^ (h >> 9); |
153 |
for (int i=0; i<x->labels; i++) |
|
153 |
|
|
154 |
for (int i = 0; i < x->labels; i++) |
|
154 | 155 |
h ^= x->label[i] ^ (h << 6) ^ (h >> 7); |
155 | 156 |
} |
156 | 157 |
|
... | ... | |
164 | 165 |
{ |
165 | 166 |
if (!ipa_equal(x->gw, y->gw) || (x->iface != y->iface) || (x->weight != y->weight) || (x->labels != y->labels)) |
166 | 167 |
return 0; |
167 |
for (int i=0; i<x->labels; i++) |
|
168 |
|
|
169 |
for (int i = 0; i < x->labels; i++) |
|
168 | 170 |
if (x->label[i] != y->label[i]) |
169 | 171 |
return 0; |
170 | 172 |
} |
171 | 173 |
|
172 |
return 1;
|
|
174 |
return x == y;
|
|
173 | 175 |
} |
174 | 176 |
|
175 | 177 |
static int |
... | ... | |
195 | 197 |
if (r) |
196 | 198 |
return r; |
197 | 199 |
|
198 |
for (int i=0; i<y->labels; i++)
|
|
200 |
for (int i = 0; i < y->labels; i++)
|
|
199 | 201 |
{ |
200 | 202 |
r = ((int) y->label[i]) - ((int) x->label[i]); |
201 | 203 |
if (r) |
... | ... | |
271 | 273 |
} |
272 | 274 |
|
273 | 275 |
void |
274 |
nexthop_insert(struct nexthop *n, struct nexthop *x) |
|
276 |
nexthop_insert(struct nexthop **n, struct nexthop *x)
|
|
275 | 277 |
{ |
276 |
struct nexthop tmp; |
|
277 |
memcpy(&tmp, n, sizeof(struct nexthop)); |
|
278 |
if (nexthop_compare_node(n, x) > 0) /* Insert to the included nexthop */ |
|
279 |
{ |
|
280 |
memcpy(n, x, sizeof(struct nexthop)); |
|
281 |
memcpy(x, &tmp, sizeof(struct nexthop)); |
|
282 |
n->next = x; |
|
283 |
return; |
|
284 |
} |
|
285 |
|
|
286 |
for (struct nexthop **nn = &(n->next); *nn; nn = &((*nn)->next)) |
|
278 |
for (; *n; n = &((*n)->next)) |
|
287 | 279 |
{ |
288 |
int cmp = nexthop_compare_node(*nn, x);
|
|
280 |
int cmp = nexthop_compare_node(*n, x); |
|
289 | 281 |
|
290 | 282 |
if (cmp < 0) |
291 | 283 |
continue; |
292 |
|
|
293 |
if (cmp > 0) |
|
294 |
{ |
|
295 |
x->next = *nn; |
|
296 |
*nn = x; |
|
297 |
} |
|
298 |
|
|
299 |
return; |
|
284 |
else if (cmp > 0) |
|
285 |
break; |
|
286 |
else |
|
287 |
return; |
|
300 | 288 |
} |
301 | 289 |
|
290 |
x->next = *n; |
|
291 |
*n = x; |
|
302 | 292 |
} |
303 | 293 |
|
304 | 294 |
int |
... | ... | |
314 | 304 |
static inline slab * |
315 | 305 |
nexthop_slab(struct nexthop *nh) |
316 | 306 |
{ |
317 |
return nexthop_slab_[nh->labels > 2 ? 3 : nh->labels];
|
|
307 |
return nexthop_slab_[MIN(nh->labels, 3)];
|
|
318 | 308 |
} |
319 | 309 |
|
320 | 310 |
static struct nexthop * |
nest/rt-dev.c | ||
---|---|---|
79 | 79 |
.source = RTS_DEVICE, |
80 | 80 |
.scope = SCOPE_UNIVERSE, |
81 | 81 |
.dest = RTD_UNICAST, |
82 |
.nh = { |
|
83 |
.iface = ad->iface |
|
84 |
} |
|
82 |
.nh.iface = ad->iface, |
|
85 | 83 |
}; |
86 | 84 |
|
87 | 85 |
a = rta_lookup(&a0); |
nest/rt-table.c | ||
---|---|---|
1768 | 1768 |
rta_apply_hostentry(rta *a, struct hostentry *he) |
1769 | 1769 |
{ |
1770 | 1770 |
a->hostentry = he; |
1771 |
|
|
1772 | 1771 |
a->dest = he->dest; |
1773 | 1772 |
a->igp_metric = he->igp_metric; |
1774 | 1773 |
|
... | ... | |
1810 | 1809 |
static inline rte * |
1811 | 1810 |
rt_next_hop_update_rte(rtable *tab UNUSED, rte *old) |
1812 | 1811 |
{ |
1813 |
rta *ap = alloca(RTA_MAX_SIZE);
|
|
1814 |
memcpy(ap, old->attrs, rta_size(old->attrs));
|
|
1815 |
rta_apply_hostentry(ap, old->attrs->hostentry);
|
|
1816 |
ap->aflags = 0;
|
|
1812 |
rta *a = alloca(RTA_MAX_SIZE); |
|
1813 |
memcpy(a, old->attrs, rta_size(old->attrs)); |
|
1814 |
rta_apply_hostentry(a, old->attrs->hostentry); |
|
1815 |
a->aflags = 0; |
|
1817 | 1816 |
|
1818 | 1817 |
rte *e = sl_alloc(rte_slab); |
1819 | 1818 |
memcpy(e, old, sizeof(rte)); |
1820 |
e->attrs = rta_lookup(ap);
|
|
1819 |
e->attrs = rta_lookup(a); |
|
1821 | 1820 |
|
1822 | 1821 |
return e; |
1823 | 1822 |
} |
... | ... | |
2373 | 2372 |
} |
2374 | 2373 |
|
2375 | 2374 |
if ((a->dest == RTD_UNICAST) && ipa_zero(a->nh.gw) && !a->next) |
2376 |
{ /* We have singlepath device route */ |
|
2375 |
{ |
|
2376 |
/* We have singlepath device route */ |
|
2377 | 2377 |
if (if_local_addr(he->addr, a->nh.iface)) |
2378 | 2378 |
{ |
2379 | 2379 |
/* The host address is a local address, this is not valid */ |
... | ... | |
2389 | 2389 |
else |
2390 | 2390 |
{ |
2391 | 2391 |
/* The host is reachable through some route entry */ |
2392 |
he->nh = (&a->nh);
|
|
2392 |
he->nh = &(a->nh);
|
|
2393 | 2393 |
he->dest = a->dest; |
2394 | 2394 |
} |
2395 | 2395 |
|
proto/bgp/attrs.c | ||
---|---|---|
1461 | 1461 |
static inline int |
1462 | 1462 |
rte_resolvable(rte *rt) |
1463 | 1463 |
{ |
1464 |
int rd = rt->attrs->dest; |
|
1465 |
return (rd == RTD_UNICAST); |
|
1464 |
return rt->attrs->dest == RTD_UNICAST; |
|
1466 | 1465 |
} |
1467 | 1466 |
|
1468 | 1467 |
int |
proto/bgp/packets.c | ||
---|---|---|
700 | 700 |
WITHDRAW(BAD_NEXT_HOP); |
701 | 701 |
|
702 | 702 |
a->dest = RTD_UNICAST; |
703 |
a->nh.gw = nbr->addr; |
|
704 |
a->nh.iface = nbr->iface; |
|
705 |
a->nh.next = NULL; |
|
703 |
a->nh = (struct nexthop){ .gw = nbr->addr, .iface = nbr->iface }; |
|
706 | 704 |
a->hostentry = NULL; |
707 | 705 |
a->igp_metric = 0; |
708 | 706 |
} |
... | ... | |
749 | 747 |
if (s->channel->cf->next_hop_self) |
750 | 748 |
return 0; |
751 | 749 |
|
752 |
/* We need valid global gateway */ |
|
753 |
if ((ra->dest != RTD_UNICAST) || (ra->nh.next) || ipa_zero(ra->nh.gw) || ipa_is_link_local(ra->nh.gw))
|
|
750 |
/* We need one valid global gateway */
|
|
751 |
if ((ra->dest != RTD_UNICAST) || ra->nh.next || ipa_zero(ra->nh.gw) || ipa_is_link_local(ra->nh.gw))
|
|
754 | 752 |
return 0; |
755 | 753 |
|
756 | 754 |
/* Use it when exported to internal peers */ |
... | ... | |
1434 | 1432 |
|
1435 | 1433 |
if (ea) |
1436 | 1434 |
{ |
1437 |
a = alloca(sizeof(struct rta)); |
|
1438 |
memset(a, 0, sizeof(struct rta)); |
|
1435 |
a = allocz(sizeof(struct rta)); |
|
1439 | 1436 |
|
1440 | 1437 |
a->source = RTS_BGP; |
1441 | 1438 |
a->scope = SCOPE_UNIVERSE; |
1442 |
a->dest = RTD_UNREACHABLE; |
|
1443 | 1439 |
a->from = s->proto->cf->remote_ip; |
1444 | 1440 |
a->eattrs = ea; |
1445 | 1441 |
|
proto/ospf/rt.c | ||
---|---|---|
36 | 36 |
static inline struct nexthop * |
37 | 37 |
new_nexthop(struct ospf_proto *p, ip_addr gw, struct iface *iface, byte weight) |
38 | 38 |
{ |
39 |
struct nexthop *nh = lp_alloc(p->nhpool, sizeof(struct nexthop)); |
|
40 |
nh->labels = 0; |
|
39 |
struct nexthop *nh = lp_allocz(p->nhpool, sizeof(struct nexthop)); |
|
41 | 40 |
nh->gw = gw; |
42 | 41 |
nh->iface = iface; |
43 |
nh->next = NULL; |
|
44 | 42 |
nh->weight = weight; |
45 | 43 |
return nh; |
46 | 44 |
} |
... | ... | |
1907 | 1905 |
(nf->n.metric1 != nf->old_metric1) || (nf->n.metric2 != nf->old_metric2) || |
1908 | 1906 |
(nf->n.tag != nf->old_tag) || (nf->n.rid != nf->old_rid) || |
1909 | 1907 |
(nr->source != or->source) || (nr->dest != or->dest) || |
1910 |
(nr->nh.iface != or->nh.iface) || !ipa_equal(nr->nh.gw, or->nh.gw) || |
|
1911 | 1908 |
!nexthop_same(&(nr->nh), &(or->nh)); |
1912 | 1909 |
} |
1913 | 1910 |
|
... | ... | |
1952 | 1949 |
.src = p->p.main_source, |
1953 | 1950 |
.source = nf->n.type, |
1954 | 1951 |
.scope = SCOPE_UNIVERSE, |
1952 |
.dest = RTD_UNICAST, |
|
1953 |
.nh = *(nf->n.nhs), |
|
1955 | 1954 |
}; |
1956 | 1955 |
|
1957 |
nexthop_link(&a0, nf->n.nhs); |
|
1958 |
a0.dest = RTD_UNICAST; |
|
1959 |
|
|
1960 | 1956 |
if (reload || ort_changed(nf, &a0)) |
1961 | 1957 |
{ |
1962 | 1958 |
rta *a = rta_lookup(&a0); |
proto/pipe/pipe.c | ||
---|---|---|
43 | 43 |
|
44 | 44 |
#include "pipe.h" |
45 | 45 |
|
46 |
#include <alloca.h> |
|
47 |
|
|
48 | 46 |
static void |
49 | 47 |
pipe_rt_notify(struct proto *P, struct channel *src_ch, net *n, rte *new, rte *old, ea_list *attrs) |
50 | 48 |
{ |
proto/rip/rip.c | ||
---|---|---|
147 | 147 |
.src = p->p.main_source, |
148 | 148 |
.source = RTS_RIP, |
149 | 149 |
.scope = SCOPE_UNIVERSE, |
150 |
.dest = RTD_UNICAST, |
|
150 | 151 |
}; |
151 | 152 |
|
152 | 153 |
u8 rt_metric = rt->metric; |
153 | 154 |
u16 rt_tag = rt->tag; |
154 |
struct rip_rte *rt2 = rt->next; |
|
155 | 155 |
|
156 |
/* Find second valid rte */ |
|
157 |
while (rt2 && !rip_valid_rte(rt2)) |
|
158 |
rt2 = rt2->next; |
|
159 |
|
|
160 |
a0.dest = RTD_UNICAST; |
|
161 |
if (p->ecmp && rt2) |
|
156 |
if (p->ecmp) |
|
162 | 157 |
{ |
163 | 158 |
/* ECMP route */ |
159 |
struct nexthop *nhs = NULL; |
|
164 | 160 |
int num = 0; |
165 | 161 |
|
166 | 162 |
for (rt = en->routes; rt && (num < p->ecmp); rt = rt->next) |
... | ... | |
168 | 164 |
if (!rip_valid_rte(rt)) |
169 | 165 |
continue; |
170 | 166 |
|
171 |
struct nexthop *nh = (a0.nh.next ? &(a0.nh) : alloca(sizeof(struct nexthop)));
|
|
167 |
struct nexthop *nh = allocz(sizeof(struct nexthop));
|
|
172 | 168 |
|
173 | 169 |
nh->gw = rt->next_hop; |
174 | 170 |
nh->iface = rt->from->nbr->iface; |
175 | 171 |
nh->weight = rt->from->ifa->cf->ecmp_weight; |
176 | 172 |
|
177 |
if (a0.nh.next) |
|
178 |
nexthop_insert(&(a0.nh), nh); |
|
179 |
|
|
173 |
nexthop_insert(&nhs, nh); |
|
180 | 174 |
num++; |
181 | 175 |
|
182 | 176 |
if (rt->tag != rt_tag) |
183 | 177 |
rt_tag = 0; |
184 | 178 |
} |
179 |
|
|
180 |
a0.nh = *nhs; |
|
185 | 181 |
} |
186 | 182 |
else |
187 | 183 |
{ |
188 | 184 |
/* Unipath route */ |
189 |
a0.nh.next = NULL;
|
|
185 |
a0.from = rt->from->nbr->addr;
|
|
190 | 186 |
a0.nh.gw = rt->next_hop; |
191 | 187 |
a0.nh.iface = rt->from->nbr->iface; |
192 |
a0.from = rt->from->nbr->addr; |
|
193 | 188 |
} |
194 | 189 |
|
195 | 190 |
rta *a = rta_lookup(&a0); |
proto/rpki/rpki.c | ||
---|---|---|
124 | 124 |
.src = p->p.main_source, |
125 | 125 |
.source = RTS_RPKI, |
126 | 126 |
.scope = SCOPE_UNIVERSE, |
127 |
.dest = RTD_BLACKHOLE,
|
|
127 |
.dest = RTD_NONE,
|
|
128 | 128 |
}; |
129 | 129 |
|
130 | 130 |
rta *a = rta_lookup(&a0); |
proto/static/config.Y | ||
---|---|---|
13 | 13 |
CF_DEFINES |
14 | 14 |
|
15 | 15 |
#define STATIC_CFG ((struct static_config *) this_proto) |
16 |
static struct static_route *this_srt, *last_srt;
|
|
16 |
static struct static_route *this_srt, *this_snh;
|
|
17 | 17 |
static struct f_inst **this_srt_last_cmd; |
18 | 18 |
|
19 |
static struct static_route * |
|
20 |
static_nexthop_new(void) |
|
21 |
{ |
|
22 |
struct static_route *nh; |
|
23 |
|
|
24 |
if (!this_snh) |
|
25 |
{ |
|
26 |
/* First next hop */ |
|
27 |
nh = this_srt; |
|
28 |
rem_node(&this_srt->n); |
|
29 |
} |
|
30 |
else |
|
31 |
{ |
|
32 |
/* Additional next hop */ |
|
33 |
nh = cfg_allocz(sizeof(struct static_route)); |
|
34 |
nh->net = this_srt->net; |
|
35 |
this_snh->mp_next = nh; |
|
36 |
} |
|
37 |
|
|
38 |
nh->dest = RTD_UNICAST; |
|
39 |
nh->mp_head = this_srt; |
|
40 |
return nh; |
|
41 |
}; |
|
42 |
|
|
19 | 43 |
static void |
20 | 44 |
static_route_finish(void) |
21 | 45 |
{ } |
... | ... | |
45 | 69 |
| static_proto stat_route stat_route_opt_list ';' { static_route_finish(); } |
46 | 70 |
; |
47 | 71 |
|
48 |
stat_nexthop_via: VIA |
|
49 |
{ |
|
50 |
if (last_srt) |
|
51 |
{ |
|
52 |
last_srt = (last_srt->mp_next = cfg_allocz(sizeof(struct static_route))); |
|
53 |
last_srt->net = this_srt->net; |
|
54 |
} |
|
55 |
else |
|
56 |
{ |
|
57 |
last_srt = this_srt; |
|
58 |
rem_node(&this_srt->n); |
|
59 |
} |
|
60 |
|
|
61 |
last_srt->mp_head = this_srt; |
|
62 |
last_srt->dest = RTD_UNICAST; |
|
63 |
}; |
|
64 |
|
|
65 |
stat_nexthop_ident: |
|
66 |
stat_nexthop_via ipa ipa_scope { |
|
67 |
last_srt->via = $2; |
|
68 |
last_srt->iface = $3; |
|
69 |
add_tail(&STATIC_CFG->neigh_routes, &last_srt->n); |
|
72 |
stat_nexthop: |
|
73 |
VIA ipa ipa_scope { |
|
74 |
this_snh = static_nexthop_new(); |
|
75 |
this_snh->via = $2; |
|
76 |
this_snh->iface = $3; |
|
77 |
add_tail(&STATIC_CFG->neigh_routes, &this_snh->n); |
|
70 | 78 |
} |
71 |
| stat_nexthop_via TEXT { |
|
72 |
last_srt->via = IPA_NONE; |
|
73 |
last_srt->if_name = $2; |
|
74 |
add_tail(&STATIC_CFG->iface_routes, &last_srt->n); |
|
79 |
| VIA TEXT { |
|
80 |
this_snh = static_nexthop_new(); |
|
81 |
this_snh->via = IPA_NONE; |
|
82 |
this_snh->if_name = $2; |
|
83 |
add_tail(&STATIC_CFG->iface_routes, &this_snh->n); |
|
75 | 84 |
} |
76 |
| stat_nexthop_ident MPLS label_stack {
|
|
77 |
last_srt->label_count = $3[0];
|
|
78 |
last_srt->label_stack = &($3[1]);
|
|
85 |
| stat_nexthop MPLS label_stack { |
|
86 |
this_snh->label_count = $3[0];
|
|
87 |
this_snh->label_stack = &($3[1]);
|
|
79 | 88 |
} |
80 |
| stat_nexthop_ident WEIGHT expr {
|
|
81 |
last_srt->weight = $3 - 1;
|
|
89 |
| stat_nexthop WEIGHT expr { |
|
90 |
this_snh->weight = $3 - 1;
|
|
82 | 91 |
if (($3<1) || ($3>256)) cf_error("Weight must be in range 1-256"); |
83 | 92 |
} |
84 |
| stat_nexthop_ident BFD bool { last_srt->use_bfd = $3; cf_check_bfd($3); } |
|
93 |
| stat_nexthop BFD bool { |
|
94 |
this_snh->use_bfd = $3; cf_check_bfd($3); |
|
95 |
} |
|
85 | 96 |
; |
86 | 97 |
|
87 |
stat_nexthop: |
|
88 |
stat_nexthop_ident
|
|
89 |
| stat_nexthop stat_nexthop_ident
|
|
98 |
stat_nexthops:
|
|
99 |
stat_nexthop |
|
100 |
| stat_nexthops stat_nexthop
|
|
90 | 101 |
; |
91 | 102 |
|
92 | 103 |
stat_route0: ROUTE net_any { |
... | ... | |
95 | 106 |
this_srt->net = $2; |
96 | 107 |
this_srt_last_cmd = &(this_srt->cmds); |
97 | 108 |
this_srt->mp_next = NULL; |
98 |
last_srt = NULL;
|
|
109 |
this_snh = NULL;
|
|
99 | 110 |
} |
100 | 111 |
; |
101 | 112 |
|
102 | 113 |
stat_route: |
103 |
stat_route0 stat_nexthop |
|
114 |
stat_route0 stat_nexthops
|
|
104 | 115 |
| stat_route0 RECURSIVE ipa { |
105 | 116 |
this_srt->dest = RTDX_RECURSIVE; |
106 | 117 |
this_srt->via = $3; |
proto/static/static.c | ||
---|---|---|
60 | 60 |
static void |
61 | 61 |
static_install(struct proto *p, struct static_route *r) |
62 | 62 |
{ |
63 |
rta *ap = alloca(RTA_MAX_SIZE);
|
|
63 |
rta *ap = allocz(RTA_MAX_SIZE);
|
|
64 | 64 |
rte *e; |
65 | 65 |
|
66 | 66 |
if (!(r->state & STS_WANT) && (r->state & (STS_INSTALLED | STS_FORCE)) && r->dest != RTD_UNICAST) |
67 | 67 |
goto drop; |
68 | 68 |
|
69 | 69 |
DBG("Installing static route %N, rtd=%d\n", r->net, r->dest); |
70 |
bzero(ap, RTA_MAX_SIZE); |
|
71 | 70 |
ap->src = p->main_source; |
72 |
ap->source = ((r->dest == RTD_UNICAST) && ipa_zero(r->via)) ? RTS_STATIC_DEVICE : RTS_STATIC;
|
|
71 |
ap->source = RTS_STATIC; |
|
73 | 72 |
ap->scope = SCOPE_UNIVERSE; |
74 | 73 |
ap->dest = r->dest; |
75 | 74 |
|
76 | 75 |
if (r->dest == RTD_UNICAST) |
77 | 76 |
{ |
77 |
struct nexthop *nhs = NULL; |
|
78 | 78 |
struct static_route *r2; |
79 |
int num = 0, update = 0;
|
|
79 |
int update = 0; |
|
80 | 80 |
|
81 |
r = r->mp_head; |
|
81 | 82 |
for (r2 = r; r2; r2 = r2->mp_next) |
82 | 83 |
{ |
83 |
|
|
84 | 84 |
if ((r2->state & STS_FORCE) || |
85 | 85 |
(!!(r2->state & STS_INSTALLED) != !!(r2->state & STS_WANT))) |
86 | 86 |
update++; |
87 | 87 |
|
88 | 88 |
if (r2->state & STS_WANT) |
89 |
{ |
|
90 |
struct nexthop *nh = (ap->nh.next) ? alloca(NEXTHOP_MAX_SIZE) : &(ap->nh); |
|
91 |
if (ipa_zero(r2->via)) // Device nexthop |
|
92 |
{ |
|
93 |
nh->gw = IPA_NONE; |
|
94 |
nh->iface = r2->iface; |
|
95 |
} |
|
96 |
else // Router nexthop |
|
97 |
{ |
|
98 |
nh->gw = r2->via; |
|
99 |
nh->iface = r2->neigh->iface; |
|
100 |
} |
|
101 |
nh->weight = r2->weight; |
|
102 |
nh->labels = r2->label_count; |
|
103 |
for (int i=0; i<nh->labels; i++) |
|
104 |
nh->label[i] = r2->label_stack[i]; |
|
105 |
|
|
106 |
if (ap->nh.next) |
|
107 |
nexthop_insert(&(ap->nh), nh); |
|
108 |
r2->state |= STS_INSTALLED; |
|
109 |
num++; |
|
110 |
} |
|
89 |
{ |
|
90 |
struct nexthop *nh = allocz(NEXTHOP_MAX_SIZE); |
|
91 |
|
|
92 |
nh->gw = r2->via; |
|
93 |
nh->iface = r2->neigh ? r2->neigh->iface : r2->iface; |
|
94 |
nh->weight = r2->weight; |
|
95 |
nh->labels = r2->label_count; |
|
96 |
memcpy(nh->label, r2->label_stack, r2->label_count * sizeof(u32)); |
|
97 |
|
|
98 |
r2->state |= STS_INSTALLED; |
|
99 |
nexthop_insert(&nhs, nh); |
|
100 |
} |
|
111 | 101 |
else |
112 | 102 |
r2->state = 0; |
113 | 103 |
} |
... | ... | |
115 | 105 |
if (!update) // Nothing changed |
116 | 106 |
return; |
117 | 107 |
|
118 |
r = r->mp_head; |
|
119 |
|
|
120 |
if (!num) // No nexthop to install |
|
108 |
if (!nhs) // No nexthop to install |
|
121 | 109 |
{ |
122 | 110 |
drop: |
123 | 111 |
rte_update(p, r->net, NULL); |
124 | 112 |
return; |
125 | 113 |
} |
114 |
|
|
115 |
ap->dest = RTD_UNICAST; |
|
116 |
nexthop_link(ap, nhs); |
|
126 | 117 |
} |
127 | 118 |
else |
128 | 119 |
r->state |= STS_INSTALLED; |
129 |
|
|
120 |
|
|
130 | 121 |
if (r->dest == RTDX_RECURSIVE) |
131 | 122 |
{ |
132 | 123 |
ap->nh.labels_append = ap->nh.labels = r->label_count; |
sysdep/bsd/krt-sock.c | ||
---|---|---|
193 | 193 |
struct ks_msg msg; |
194 | 194 |
char *body = (char *)msg.buf; |
195 | 195 |
sockaddr gate, mask, dst; |
196 |
ip_addr gw; |
|
197 | 196 |
|
198 | 197 |
DBG("krt-sock: send %I/%d via %I\n", net->n.prefix, net->n.pxlen, a->gw); |
199 | 198 |
|
... | ... | |
223 | 222 |
msg.rtm.rtm_flags |= RTF_BLACKHOLE; |
224 | 223 |
#endif |
225 | 224 |
|
226 |
/* This is really very nasty, but I'm not able
|
|
227 |
* to add "(reject|blackhole)" route without
|
|
228 |
* gateway set
|
|
225 |
/* |
|
226 |
* This is really very nasty, but I'm not able to add reject/blackhole route
|
|
227 |
* without gateway address.
|
|
229 | 228 |
*/ |
230 |
if(!i) |
|
229 |
if (!i)
|
|
231 | 230 |
{ |
232 |
i = HEAD(iface_list); |
|
233 |
|
|
234 | 231 |
WALK_LIST(j, iface_list) |
235 | 232 |
{ |
236 | 233 |
if (j->flags & IF_LOOPBACK) |
... | ... | |
239 | 236 |
break; |
240 | 237 |
} |
241 | 238 |
} |
242 |
} |
|
243 | 239 |
|
244 |
gw = a->nh.gw; |
|
245 |
|
|
246 |
/* Embed interface ID to link-local address */ |
|
247 |
if (ipa_is_link_local(gw)) |
|
248 |
_I0(gw) = 0xfe800000 | (i->index & 0x0000ffff); |
|
240 |
if (!i) |
|
241 |
{ |
|
242 |
log(L_ERR "KRT: Cannot find loopback iface"); |
|
243 |
return -1; |
|
244 |
} |
|
245 |
} |
|
249 | 246 |
|
250 | 247 |
int af = AF_UNSPEC; |
251 | 248 |
|
... | ... | |
261 | 258 |
return -1; |
262 | 259 |
} |
263 | 260 |
|
264 |
|
|
265 | 261 |
sockaddr_fill(&dst, af, net_prefix(net->n.addr), NULL, 0); |
266 | 262 |
sockaddr_fill(&mask, af, net_pxmask(net->n.addr), NULL, 0); |
267 |
sockaddr_fill(&gate, af, gw, NULL, 0); |
|
268 | 263 |
|
269 | 264 |
switch (a->dest) |
270 | 265 |
{ |
271 |
case RTD_UNICAST: |
|
272 |
if (ipa_zero(gw)) |
|
273 |
{ |
|
274 |
if(i) |
|
275 |
{ |
|
276 |
#ifdef RTF_CLONING |
|
277 |
if (cmd == RTM_ADD && (i->flags & IF_MULTIACCESS) != IF_MULTIACCESS) /* PTP */ |
|
278 |
msg.rtm.rtm_flags |= RTF_CLONING; |
|
279 |
#endif |
|
266 |
case RTD_UNICAST: |
|
267 |
if (ipa_nonzero(a->nh.gw)) |
|
268 |
{ |
|
269 |
ip_addr gw = a->nh.gw; |
|
280 | 270 |
|
281 |
if(!i->addr) { |
|
282 |
log(L_ERR "KRT: interface %s has no IP addess", i->name); |
|
283 |
return -1; |
|
284 |
} |
|
285 |
|
|
286 |
sockaddr_fill(&gate, ipa_is_ip4(i->addr->ip) ? AF_INET : AF_INET6, i->addr->ip, NULL, 0); |
|
287 |
msg.rtm.rtm_addrs |= RTA_GATEWAY; |
|
288 |
} |
|
289 |
} else { |
|
290 |
msg.rtm.rtm_flags |= RTF_GATEWAY; |
|
291 |
msg.rtm.rtm_addrs |= RTA_GATEWAY; |
|
292 |
} |
|
271 |
/* Embed interface ID to link-local address */ |
|
272 |
if (ipa_is_link_local(gw)) |
|
273 |
_I0(gw) = 0xfe800000 | (i->index & 0x0000ffff); |
|
274 |
|
|
275 |
sockaddr_fill(&gate, af, gw, NULL, 0); |
|
276 |
msg.rtm.rtm_flags |= RTF_GATEWAY; |
|
277 |
msg.rtm.rtm_addrs |= RTA_GATEWAY; |
|
293 | 278 |
break; |
279 |
} |
|
294 | 280 |
|
295 | 281 |
#ifdef RTF_REJECT |
296 |
case RTD_UNREACHABLE:
|
|
282 |
case RTD_UNREACHABLE: |
|
297 | 283 |
#endif |
298 | 284 |
#ifdef RTF_BLACKHOLE |
299 |
case RTD_BLACKHOLE:
|
|
285 |
case RTD_BLACKHOLE: |
|
300 | 286 |
#endif |
301 |
default: |
|
302 |
bug("krt-sock: unknown flags, but not filtered"); |
|
287 |
{ |
|
288 |
/* Fallback for all other valid cases */ |
|
289 |
if (!i->addr) |
|
290 |
{ |
|
291 |
log(L_ERR "KRT: interface %s has no IP addess", i->name); |
|
292 |
return -1; |
|
293 |
} |
|
294 |
|
|
295 |
#ifdef RTF_CLONING |
|
296 |
if (cmd == RTM_ADD && (i->flags & IF_MULTIACCESS) != IF_MULTIACCESS) /* PTP */ |
|
297 |
msg.rtm.rtm_flags |= RTF_CLONING; |
|
298 |
#endif |
|
299 |
|
|
300 |
sockaddr_fill(&gate, ipa_is_ip4(i->addr->ip) ? AF_INET : AF_INET6, i->addr->ip, NULL, 0); |
|
301 |
msg.rtm.rtm_addrs |= RTA_GATEWAY; |
|
302 |
} |
|
303 |
|
|
304 |
default: |
|
305 |
bug("krt-sock: unknown flags, but not filtered"); |
|
303 | 306 |
} |
304 | 307 |
|
305 | 308 |
msg.rtm.rtm_index = i->index; |
... | ... | |
497 | 500 |
} |
498 | 501 |
|
499 | 502 |
a.dest = RTD_UNICAST; |
500 |
a.nh.next = NULL; |
|
501 | 503 |
if (flags & RTF_GATEWAY) |
502 | 504 |
{ |
503 | 505 |
neighbor *ng; |
... | ... | |
520 | 522 |
return; |
521 | 523 |
} |
522 | 524 |
} |
523 |
else |
|
524 |
a.nh.gw = IPA_NONE; |
|
525 | 525 |
|
526 | 526 |
done: |
527 | 527 |
e = rte_get_temp(&a); |
sysdep/linux/netlink.c | ||
---|---|---|
320 | 320 |
[IFA_ADDRESS] = { 1, 1, sizeof(ip4_addr) }, |
321 | 321 |
[IFA_LOCAL] = { 1, 1, sizeof(ip4_addr) }, |
322 | 322 |
[IFA_BROADCAST] = { 1, 1, sizeof(ip4_addr) }, |
323 |
[IFA_FLAGS] = { 1, 1, sizeof(u32) }, |
|
323 | 324 |
}; |
324 | 325 |
|
325 | 326 |
static struct nl_want_attrs ifa_attr_want6[BIRD_IFA_MAX] = { |
... | ... | |
543 | 544 |
|
544 | 545 |
h->nlmsg_len += sizeof(*via); |
545 | 546 |
|
546 |
if (ipa_is_ip4(ipa)) { |
|
547 |
ip4_addr ip4 = ipa_to_ip4(ipa); |
|
548 |
ip4 = ip4_hton(ip4); |
|
547 |
if (ipa_is_ip4(ipa)) |
|
548 |
{ |
|
549 | 549 |
via->rtvia_family = AF_INET; |
550 |
memcpy(via->rtvia_addr, &ip4, sizeof(ip4));
|
|
551 |
h->nlmsg_len += sizeof(ip4); |
|
552 |
} else {
|
|
553 |
ip6_addr ip6 = ipa_to_ip6(ipa);
|
|
554 |
ip6 = ip6_hton(ip6);
|
|
550 |
put_ip4(via->rtvia_addr, ipa_to_ip4(ipa));
|
|
551 |
h->nlmsg_len += sizeof(ip4_addr);
|
|
552 |
} |
|
553 |
else
|
|
554 |
{
|
|
555 | 555 |
via->rtvia_family = AF_INET6; |
556 |
memcpy(via->rtvia_addr, &ip6, sizeof(ip6));
|
|
557 |
h->nlmsg_len += sizeof(ip6); |
|
556 |
put_ip6(via->rtvia_addr, ipa_to_ip6(ipa));
|
|
557 |
h->nlmsg_len += sizeof(ip6_addr);
|
|
558 | 558 |
} |
559 | 559 |
|
560 | 560 |
nl_close_attr(h, nest); |
... | ... | |
669 | 669 |
} |
670 | 670 |
else |
671 | 671 |
rv->gw = IPA_NONE; |
672 |
|
|
672 | 673 |
if (a[RTA_ENCAP_TYPE]) |
673 | 674 |
{ |
674 | 675 |
if (rta_get_u16(a[RTA_ENCAP_TYPE]) != LWTUNNEL_ENCAP_MPLS) { |
... | ... | |
1092 | 1093 |
rta *a = e->attrs; |
1093 | 1094 |
|
1094 | 1095 |
switch (a->dest) |
1095 |
{
|
|
1096 |
{ |
|
1096 | 1097 |
case RTD_UNICAST: |
1097 |
for (struct nexthop *nh = &(a->nh); nh; nh = nh->next) |
|
1098 |
if (nh->iface) |
|
1099 |
return 1; |
|
1100 |
return 0; |
|
1101 | 1098 |
case RTD_BLACKHOLE: |
1102 | 1099 |
case RTD_UNREACHABLE: |
1103 | 1100 |
case RTD_PROHIBIT: |
1104 |
break; |
|
1101 |
return 1; |
|
1102 |
|
|
1105 | 1103 |
default: |
1106 | 1104 |
return 0; |
1107 |
} |
|
1108 |
return 1; |
|
1105 |
} |
|
1109 | 1106 |
} |
1110 | 1107 |
|
1111 | 1108 |
static inline int |
... | ... | |
1210 | 1207 |
|
1211 | 1208 |
|
1212 | 1209 |
dest: |
1213 |
/* a->iface != NULL checked in krt_capable() for router and device routes */ |
|
1214 | 1210 |
switch (dest) |
1215 | 1211 |
{ |
1216 | 1212 |
case RTD_UNICAST: |
... | ... | |
1502 | 1498 |
switch (i->rtm_type) |
1503 | 1499 |
{ |
1504 | 1500 |
case RTN_UNICAST: |
1501 |
ra->dest = RTD_UNICAST; |
|
1505 | 1502 |
|
1506 | 1503 |
if (a[RTA_MULTIPATH] && (i->rtm_family == AF_INET)) |
1507 | 1504 |
{ |
... | ... | |
1512 | 1509 |
return; |
1513 | 1510 |
} |
1514 | 1511 |
|
1515 |
nexthop_link(ra, nh);
|
|
1512 |
ra->nh = *nh;
|
|
1516 | 1513 |
break; |
1517 | 1514 |
} |
1518 | 1515 |
|
... | ... | |
1698 | 1695 |
else |
1699 | 1696 |
{ |
1700 | 1697 |
/* Merge next hops with the stored route */ |
1701 |
rta *a = s->attrs; |
|
1698 |
rta *oa = s->attrs;
|
|
1702 | 1699 |
|
1703 |
nexthop_insert(&a->nh, &ra->nh); |
|
1700 |
struct nexthop *nhs = &oa->nh; |
|
1701 |
nexthop_insert(&nhs, &ra->nh); |
|
1702 |
|
|
1703 |
/* Perhaps new nexthop is inserted at the first position */ |
|
1704 |
if (nhs == &ra->nh) |
|
1705 |
{ |
|
1706 |
/* Swap rtas */ |
|
1707 |
s->attrs = ra; |
|
1708 |
|
|
1709 |
/* Keep old eattrs */ |
|
1710 |
ra->eattrs = oa->eattrs; |
|
1711 |
} |
|
1704 | 1712 |
} |
1705 | 1713 |
} |
1706 | 1714 |
|
sysdep/unix/krt.c | ||
---|---|---|
984 | 984 |
static int |
985 | 985 |
krt_import_control(struct proto *P, rte **new, ea_list **attrs UNUSED, struct linpool *pool UNUSED) |
986 | 986 |
{ |
987 |
struct krt_proto *p = (struct krt_proto *) P; |
|
987 |
// struct krt_proto *p = (struct krt_proto *) P;
|
|
988 | 988 |
rte *e = *new; |
989 | 989 |
|
990 | 990 |
if (e->attrs->src->proto == P) |
... | ... | |
1005 | 1005 |
return -1; |
1006 | 1006 |
} |
1007 | 1007 |
|
1008 |
if (!KRT_CF->devroutes && (e->attrs->source != RTS_STATIC_DEVICE)) |
|
1009 |
{ |
|
1010 |
struct nexthop *nh = &(e->attrs->nh); |
|
1011 |
for (; nh; nh = nh->next) |
|
1012 |
if (ipa_nonzero(nh->gw)) |
|
1013 |
break; |
|
1014 |
|
|
1015 |
if (!nh) /* Gone through all the nexthops and no explicit GW found */ |
|
1016 |
return -1; |
|
1017 |
} |
|
1018 |
|
|
1019 | 1008 |
if (!krt_capable(e)) |
1020 | 1009 |
return -1; |
1021 | 1010 |
|
Also available in: Unified diff