static inline int ip6_is_v4mapped(ip6_addr a)
{ return _I0(a) == 0 && _I1(a) == 0 && _I2(a) == 0xffff; }
++static inline int ip4_is_multicast(ip4_addr a)
++{ return (_I(a) & 0xf0000000) == 0xe0000000; }
++
++static inline int ip6_is_multicast(ip6_addr a)
++{ return (_I0(a) & 0xff000000) == 0xff000000; }
++
#define ipa_classify(x) ip6_classify(&(x))
#define ipa_is_link_local(x) ip6_is_link_local(x)
const char * const net_label[] = {
- [NET_IP4] = "ipv4",
- [NET_IP6] = "ipv6",
- [NET_VPN4] = "vpn4",
- [NET_VPN6] = "vpn6",
- [NET_ROA4] = "roa4",
- [NET_ROA6] = "roa6",
- [NET_MREQ4] = "mreq4",
- [NET_MREQ6] = "mreq6",
- [NET_MGRP4] = "mgrp4",
- [NET_MGRP6] = "mgrp6",
+ [NET_IP4] = "ipv4",
+ [NET_IP6] = "ipv6",
+ [NET_VPN4] = "vpn4",
+ [NET_VPN6] = "vpn6",
+ [NET_ROA4] = "roa4",
+ [NET_ROA6] = "roa6",
- [NET_FLOW4] = "flow4",
- [NET_FLOW6] = "flow6",
++ [NET_FLOW4] = "flow4",
++ [NET_FLOW6] = "flow6",
++ [NET_MREQ4] = "mreq4",
++ [NET_MREQ6] = "mreq6",
++ [NET_MGRP4] = "mgrp4",
++ [NET_MGRP6] = "mgrp6",
+ [NET_MPLS] = "mpls",
};
const u16 net_addr_length[] = {
- [NET_IP4] = sizeof(net_addr_ip4),
- [NET_IP6] = sizeof(net_addr_ip6),
- [NET_VPN4] = sizeof(net_addr_vpn4),
- [NET_VPN6] = sizeof(net_addr_vpn6),
- [NET_ROA4] = sizeof(net_addr_roa4),
- [NET_ROA6] = sizeof(net_addr_roa6),
- [NET_MREQ4] = sizeof(net_addr_mreq4),
- [NET_MREQ6] = sizeof(net_addr_mreq6),
- [NET_MGRP4] = sizeof(net_addr_mgrp4),
- [NET_MGRP6] = sizeof(net_addr_mgrp6),
+ [NET_IP4] = sizeof(net_addr_ip4),
+ [NET_IP6] = sizeof(net_addr_ip6),
+ [NET_VPN4] = sizeof(net_addr_vpn4),
+ [NET_VPN6] = sizeof(net_addr_vpn6),
+ [NET_ROA4] = sizeof(net_addr_roa4),
+ [NET_ROA6] = sizeof(net_addr_roa6),
- [NET_FLOW4] = 0,
- [NET_FLOW6] = 0,
++ [NET_FLOW4] = 0,
++ [NET_FLOW6] = 0,
++ [NET_MREQ4] = sizeof(net_addr_mreq4),
++ [NET_MREQ6] = sizeof(net_addr_mreq6),
++ [NET_MGRP4] = sizeof(net_addr_mgrp4),
++ [NET_MGRP6] = sizeof(net_addr_mgrp6),
+ [NET_MPLS] = sizeof(net_addr_mpls),
};
const u8 net_max_prefix_length[] = {
- [NET_IP4] = IP4_MAX_PREFIX_LENGTH,
- [NET_IP6] = IP6_MAX_PREFIX_LENGTH,
- [NET_VPN4] = IP4_MAX_PREFIX_LENGTH,
- [NET_VPN6] = IP6_MAX_PREFIX_LENGTH,
- [NET_ROA4] = IP4_MAX_PREFIX_LENGTH,
- [NET_ROA6] = IP6_MAX_PREFIX_LENGTH,
- [NET_MREQ4] = IP4_MAX_PREFIX_LENGTH,
- [NET_MREQ6] = IP6_MAX_PREFIX_LENGTH,
- [NET_MGRP4] = IP4_MAX_PREFIX_LENGTH,
- [NET_MGRP6] = IP6_MAX_PREFIX_LENGTH,
+ [NET_IP4] = IP4_MAX_PREFIX_LENGTH,
+ [NET_IP6] = IP6_MAX_PREFIX_LENGTH,
+ [NET_VPN4] = IP4_MAX_PREFIX_LENGTH,
+ [NET_VPN6] = IP6_MAX_PREFIX_LENGTH,
+ [NET_ROA4] = IP4_MAX_PREFIX_LENGTH,
+ [NET_ROA6] = IP6_MAX_PREFIX_LENGTH,
- [NET_FLOW4] = IP4_MAX_PREFIX_LENGTH,
- [NET_FLOW6] = IP6_MAX_PREFIX_LENGTH,
++ [NET_FLOW4] = IP4_MAX_PREFIX_LENGTH,
++ [NET_FLOW6] = IP6_MAX_PREFIX_LENGTH,
++ [NET_MREQ4] = IP4_MAX_PREFIX_LENGTH,
++ [NET_MREQ6] = IP6_MAX_PREFIX_LENGTH,
++ [NET_MGRP4] = IP4_MAX_PREFIX_LENGTH,
++ [NET_MGRP6] = IP6_MAX_PREFIX_LENGTH,
+ [NET_MPLS] = 0,
};
const u16 net_max_text_length[] = {
- [NET_IP4] = 18, /* "255.255.255.255/32" */
- [NET_IP6] = 43, /* "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128" */
- [NET_VPN4] = 40, /* "4294967296:4294967296 255.255.255.255/32" */
- [NET_VPN6] = 65, /* "4294967296:4294967296 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128" */
- [NET_ROA4] = 34, /* "255.255.255.255/32-32 AS4294967295" */
- [NET_ROA6] = 60, /* "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128-128 AS4294967295" */
- [NET_MREQ4] = 15, /* "255.255.255.255" */
- [NET_MREQ6] = 39, /* "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" */
- [NET_MGRP4] = 15, /* "255.255.255.255" */
- [NET_MGRP6] = 39, /* "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" */
+ [NET_IP4] = 18, /* "255.255.255.255/32" */
+ [NET_IP6] = 43, /* "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128" */
+ [NET_VPN4] = 40, /* "4294967296:4294967296 255.255.255.255/32" */
+ [NET_VPN6] = 65, /* "4294967296:4294967296 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128" */
+ [NET_ROA4] = 34, /* "255.255.255.255/32-32 AS4294967295" */
+ [NET_ROA6] = 60, /* "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128-128 AS4294967295" */
- [NET_FLOW4] = 0, /* "flow4 { ... }" */
- [NET_FLOW6] = 0, /* "flow6 { ... }" */
++ [NET_FLOW4] = 0, /* "flow4 { ... }" */
++ [NET_FLOW6] = 0, /* "flow6 { ... }" */
++ [NET_MREQ4] = 15, /* "255.255.255.255" */
++ [NET_MREQ6] = 39, /* "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" */
++ [NET_MGRP4] = 15, /* "255.255.255.255" */
++ [NET_MGRP6] = 39, /* "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" */
+ [NET_MPLS] = 7, /* "1048575" */
};
return bsnprintf(buf, buflen, "%I4/%u-%u AS%u", n->roa4.prefix, n->roa4.pxlen, n->roa4.max_pxlen, n->roa4.asn);
case NET_ROA6:
return bsnprintf(buf, buflen, "%I6/%u-%u AS%u", n->roa6.prefix, n->roa6.pxlen, n->roa6.max_pxlen, n->roa6.asn);
- case NET_MGRP4:
- return bsnprintf(buf, buflen, "%I4", n->mgrp4.ga);
+ case NET_FLOW4:
+ return flow4_net_format(buf, buflen, &n->flow4);
+ case NET_FLOW6:
+ return flow6_net_format(buf, buflen, &n->flow6);
+ case NET_MREQ4:
- return bsnprintf(buf, buflen, "%I6", n->mgrp6.ga);
++ return bsnprintf(buf, buflen, "%I4", n->mreq4.grp);
+ case NET_MREQ6:
++ return bsnprintf(buf, buflen, "%I6", n->mreq6.grp);
++ case NET_MGRP4:
++ return bsnprintf(buf, buflen, "%I4", n->mgrp4.grp);
+ case NET_MGRP6:
++ return bsnprintf(buf, buflen, "%I6", n->mgrp6.grp);
+ case NET_MPLS:
+ return bsnprintf(buf, buflen, "%u", n->mpls.label);
}
- return 0;
+ bug("unknown network type");
}
ip_addr
case NET_IP4:
case NET_VPN4:
case NET_ROA4:
+ case NET_FLOW4:
+ case NET_MREQ4:
+ case NET_MGRP4:
return ipa_from_ip4(ip4_mkmask(net4_pxlen(a)));
case NET_IP6:
case NET_VPN6:
case NET_ROA6:
+ case NET_FLOW6:
+ case NET_MREQ6:
+ case NET_MGRP6:
return ipa_from_ip6(ip6_mkmask(net6_pxlen(a)));
+ case NET_MPLS:
default:
return IPA_NONE;
}
return net_compare_roa4((const net_addr_roa4 *) a, (const net_addr_roa4 *) b);
case NET_ROA6:
return net_compare_roa6((const net_addr_roa6 *) a, (const net_addr_roa6 *) b);
- case NET_MREQ6:
+ case NET_FLOW4:
+ return net_compare_flow4((const net_addr_flow4 *) a, (const net_addr_flow4 *) b);
+ case NET_FLOW6:
+ return net_compare_flow6((const net_addr_flow6 *) a, (const net_addr_flow6 *) b);
+ case NET_MREQ4:
++ return net_compare_mreq4((const net_addr_mreq4 *) a, (const net_addr_mreq4 *) b);
++ case NET_MREQ6:
++ return net_compare_mreq6((const net_addr_mreq6 *) a, (const net_addr_mreq6 *) b);
+ case NET_MGRP4:
+ return net_compare_mgrp4((const net_addr_mgrp4 *) a, (const net_addr_mgrp4 *) b);
+ case NET_MGRP6:
+ return net_compare_mgrp6((const net_addr_mgrp6 *) a, (const net_addr_mgrp6 *) b);
+ case NET_MPLS:
+ return net_compare_mpls((const net_addr_mpls *) a, (const net_addr_mpls *) b);
}
return 0;
}
-int
-net_validate(const net_addr *N)
+#define NET_HASH(a,t) net_hash_##t((const net_addr_##t *) a)
+
+u32
+net_hash(const net_addr *n)
{
- switch (N->type)
+ switch (n->type)
{
- case NET_IP4:
- case NET_VPN4:
- case NET_ROA4:
- return net_validate_ip4((net_addr_ip4 *) N);
+ case NET_IP4: return NET_HASH(n, ip4);
+ case NET_IP6: return NET_HASH(n, ip6);
+ case NET_VPN4: return NET_HASH(n, vpn4);
+ case NET_VPN6: return NET_HASH(n, vpn6);
+ case NET_ROA4: return NET_HASH(n, roa4);
+ case NET_ROA6: return NET_HASH(n, roa6);
+ case NET_FLOW4: return NET_HASH(n, flow4);
+ case NET_FLOW6: return NET_HASH(n, flow6);
++ case NET_MREQ4: return NET_HASH(n, mreq4);
++ case NET_MREQ6: return NET_HASH(n, mreq6);
++ case NET_MGRP4: return NET_HASH(n, mgrp4);
++ case NET_MGRP6: return NET_HASH(n, mgrp6);
+ case NET_MPLS: return NET_HASH(n, mpls);
+ default: bug("invalid type");
+ }
+}
- case NET_IP6:
- case NET_VPN6:
- case NET_ROA6:
- return net_validate_ip6((net_addr_ip6 *) N);
- case NET_MREQ4:
- case NET_MGRP4:
- return ip4_classify(((net_addr_mgrp4 *) N)->ga) & IADDR_MULTICAST;
- case NET_MREQ6:
- case NET_MGRP6:
- return ip6_classify(&((net_addr_mgrp6 *) N)->ga) & IADDR_MULTICAST;
+#define NET_VALIDATE(a,t) net_validate_##t((const net_addr_##t *) a)
- default:
- return 0;
+int
+net_validate(const net_addr *n)
+{
+ switch (n->type)
+ {
+ case NET_IP4: return NET_VALIDATE(n, ip4);
+ case NET_IP6: return NET_VALIDATE(n, ip6);
+ case NET_VPN4: return NET_VALIDATE(n, vpn4);
+ case NET_VPN6: return NET_VALIDATE(n, vpn6);
+ case NET_ROA4: return NET_VALIDATE(n, roa4);
+ case NET_ROA6: return NET_VALIDATE(n, roa6);
+ case NET_FLOW4: return NET_VALIDATE(n, flow4);
+ case NET_FLOW6: return NET_VALIDATE(n, flow6);
++ case NET_MREQ4: return NET_VALIDATE(n, mreq4);
++ case NET_MREQ6: return NET_VALIDATE(n, mreq6);
++ case NET_MGRP4: return NET_VALIDATE(n, mgrp4);
++ case NET_MGRP6: return NET_VALIDATE(n, mgrp6);
+ case NET_MPLS: return NET_VALIDATE(n, mpls);
+ default: return 0;
}
}
case NET_IP6:
case NET_VPN6:
case NET_ROA6:
+ case NET_FLOW6:
return net_normalize_ip6(&n->ip6);
+
++ case NET_MREQ4:
++ case NET_MREQ6:
++ case NET_MGRP4:
++ case NET_MGRP6:
+ case NET_MPLS:
+ return;
}
}
case NET_IP4:
case NET_VPN4:
case NET_ROA4:
+ case NET_FLOW4:
++ case NET_MREQ4:
++ case NET_MGRP4:
return ip4_zero(n->ip4.prefix) ? (IADDR_HOST | SCOPE_UNIVERSE) : ip4_classify(n->ip4.prefix);
case NET_IP6:
case NET_VPN6:
case NET_ROA6:
- return ip6_zero(n->ip6.prefix) ? (IADDR_HOST | SCOPE_UNIVERSE) : ip6_classify(&n->ip6.prefix);
-
- case NET_MREQ4:
- case NET_MGRP4:
- return ip4_classify(n->mgrp4.ga);
+ case NET_FLOW6:
+ case NET_MREQ6:
+ case NET_MGRP6:
- return ip6_classify(&n->mgrp6.ga);
+ return ip6_zero(n->ip6.prefix) ? (IADDR_HOST | SCOPE_UNIVERSE) : ip6_classify(&n->ip6.prefix);
+
+ case NET_MPLS:
+ return IADDR_HOST | SCOPE_UNIVERSE;
}
return IADDR_INVALID;
return ip6_zero(ip6_and(ip6_xor(ipa_to_ip6(a), net6_prefix(n)),
ip6_mkmask(net6_pxlen(n))));
- return ip4_equal(ipa_to_ip4(a), ((net_addr_mgrp4 *) n)->ga);
+ case NET_MREQ4:
+ case NET_MGRP4:
+ if (!ipa_is_ip4(a)) return 0;
- return ip6_equal(ipa_to_ip6(a), ((net_addr_mgrp6 *) n)->ga);
++ return ip4_equal(ipa_to_ip4(a), net4_prefix(n));
++
+ case NET_MREQ6:
+ case NET_MGRP6:
+ if (ipa_is_ip4(a)) return 0;
++ return ip6_equal(ipa_to_ip6(a), net6_prefix(n));
+
+ case NET_MPLS:
default:
return 0;
}
return (net_pxlen(n) <= net_pxlen(a)) && ipa_in_netX(net_prefix(a), n);
}
+
+#define CHECK_NET(T,S) \
+ ({ if (sizeof(T) != S) die("sizeof %s is %d/%d", #T, (int) sizeof(T), S); })
+
+void
+net_init(void)
+{
+ CHECK_NET(net_addr, 24);
+ CHECK_NET(net_addr_ip4, 8);
+ CHECK_NET(net_addr_ip6, 20);
+ CHECK_NET(net_addr_vpn4, 16);
+ CHECK_NET(net_addr_vpn6, 32);
+ CHECK_NET(net_addr_roa4, 16);
+ CHECK_NET(net_addr_roa6, 28);
+ CHECK_NET(net_addr_flow4, 8);
+ CHECK_NET(net_addr_flow6, 20);
++ CHECK_NET(net_addr_mreq4, 12);
++ CHECK_NET(net_addr_mreq6, 24);
++ CHECK_NET(net_addr_mgrp4, 8);
++ CHECK_NET(net_addr_mgrp6, 20);
+ CHECK_NET(net_addr_mpls, 8);
+}
#define NET_VPN6 4
#define NET_ROA4 5
#define NET_ROA6 6
-#define NET_MREQ4 7
-#define NET_MREQ6 8
-#define NET_MGRP4 9
-#define NET_MGRP6 10
-#define NET_MAX 11
+#define NET_FLOW4 7
+#define NET_FLOW6 8
- #define NET_MPLS 9
- #define NET_MAX 10
++#define NET_MREQ4 9
++#define NET_MREQ6 10
++#define NET_MGRP4 11
++#define NET_MGRP6 12
++#define NET_MPLS 13
++#define NET_MAX 14
#define NB_IP4 (1 << NET_IP4)
#define NB_IP6 (1 << NET_IP6)
#define NB_VPN6 (1 << NET_VPN6)
#define NB_ROA4 (1 << NET_ROA4)
#define NB_ROA6 (1 << NET_ROA6)
+#define NB_FLOW4 (1 << NET_FLOW4)
+#define NB_FLOW6 (1 << NET_FLOW6)
+ #define NB_MREQ4 (1 << NET_MREQ4)
+ #define NB_MREQ6 (1 << NET_MREQ6)
+ #define NB_MGRP4 (1 << NET_MGRP4)
+ #define NB_MGRP6 (1 << NET_MGRP6)
+#define NB_MPLS (1 << NET_MPLS)
#define NB_IP (NB_IP4 | NB_IP6)
-#define NB_MCAST (NB_MREQ | NB_MGRP)
-#define NB_6 (NB_IP6 | NB_VPN6 | NB_MREQ6 | NB_MGRP6)
+#define NB_VPN (NB_VPN4 | NB_VPN6)
++#define NB_ROA (NB_ROA4 | NB_ROA6)
+#define NB_FLOW (NB_FLOW4 | NB_FLOW6)
+ #define NB_MREQ (NB_MREQ4 | NB_MREQ6)
+ #define NB_MGRP (NB_MGRP4 | NB_MGRP6)
++
++#define NB_HOST (NB_IP | NB_VPN | NB_ROA)
+#define NB_DEST (NB_IP | NB_VPN | NB_MPLS)
#define NB_ANY 0xffffffff
u32 asn;
} net_addr_roa6;
- ip4_addr ga;
- unsigned ifindex;
+typedef struct net_addr_flow4 {
+ u8 type;
+ u8 pxlen;
+ u16 length;
+ ip4_addr prefix;
+ byte data[0];
+} net_addr_flow4;
+
+typedef struct net_addr_flow6 {
+ u8 type;
+ u8 pxlen;
+ u16 length;
+ ip6_addr prefix;
+ byte data[0];
+} net_addr_flow6;
+
+ typedef struct net_addr_mreq4 {
+ u8 type;
+ u8 pxlen;
+ u16 length;
- ip6_addr ga;
- unsigned ifindex;
++ ip4_addr grp;
++ uint ifindex;
+ } net_addr_mreq4;
+
+ typedef struct net_addr_mreq6 {
+ u8 type;
+ u8 pxlen;
+ u16 length;
- ip4_addr ga;
++ ip6_addr grp;
++ uint ifindex;
+ } net_addr_mreq6;
+
+ typedef struct net_addr_mgrp4 {
+ u8 type;
+ u8 pxlen;
+ u16 length;
- ip6_addr ga;
++ ip4_addr grp;
+ } net_addr_mgrp4;
+
+ typedef struct net_addr_mgrp6 {
+ u8 type;
+ u8 pxlen;
+ u16 length;
++ ip6_addr grp;
+ } net_addr_mgrp6;
+
+typedef struct net_addr_mpls {
+ u8 type;
+ u8 pxlen;
+ u16 length;
+ u32 label;
+} net_addr_mpls;
+
typedef union net_addr_union {
net_addr n;
net_addr_ip4 ip4;
net_addr_vpn6 vpn6;
net_addr_roa4 roa4;
net_addr_roa6 roa6;
+ net_addr_flow4 flow4;
+ net_addr_flow6 flow6;
+ net_addr_mreq4 mreq4;
+ net_addr_mreq6 mreq6;
+ net_addr_mgrp4 mgrp4;
+ net_addr_mgrp6 mgrp6;
+ net_addr_mpls mpls;
} net_addr_union;
#define NET_ADDR_ROA6(prefix,pxlen,max_pxlen,asn) \
((net_addr_roa6) { NET_ROA6, pxlen, sizeof(net_addr_roa6), prefix, max_pxlen, asn })
-#define NET_ADDR_MREQ4(ga, ifindex) \
- ((net_addr_mreq4) { NET_MREQ4, IP4_MAX_PREFIX_LENGTH, sizeof(net_addr_mreq4), ga, ifindex })
+#define NET_ADDR_FLOW4(prefix,pxlen,dlen) \
+ ((net_addr_flow4) { NET_FLOW4, pxlen, sizeof(net_addr_ip4) + dlen, prefix })
+
+#define NET_ADDR_FLOW6(prefix,pxlen,dlen) \
+ ((net_addr_flow6) { NET_FLOW6, pxlen, sizeof(net_addr_ip6) + dlen, prefix })
+
++#define NET_ADDR_MREQ4(grp, ifindex) \
++ ((net_addr_mreq4) { NET_MREQ4, IP4_MAX_PREFIX_LENGTH, sizeof(net_addr_mreq4), grp, ifindex })
+
-#define NET_ADDR_MREQ6(ga, ifindex) \
- ((net_addr_mreq6) { NET_MREQ6, IP6_MAX_PREFIX_LENGTH, sizeof(net_addr_mreq6), ga, ifindex })
++#define NET_ADDR_MREQ6(grp, ifindex) \
++ ((net_addr_mreq6) { NET_MREQ6, IP6_MAX_PREFIX_LENGTH, sizeof(net_addr_mreq6), grp, ifindex })
+
-#define NET_ADDR_MGRP4(ga) \
- ((net_addr_mgrp4) { NET_MGRP4, IP4_MAX_PREFIX_LENGTH, sizeof(net_addr_mgrp4), ga })
++#define NET_ADDR_MGRP4(grp) \
++ ((net_addr_mgrp4) { NET_MGRP4, IP4_MAX_PREFIX_LENGTH, sizeof(net_addr_mgrp4), grp })
+
-#define NET_ADDR_MGRP6(ga) \
- ((net_addr_mgrp6) { NET_MGRP6, IP6_MAX_PREFIX_LENGTH, sizeof(net_addr_mgrp6), ga })
++#define NET_ADDR_MGRP6(grp) \
++ ((net_addr_mgrp6) { NET_MGRP6, IP6_MAX_PREFIX_LENGTH, sizeof(net_addr_mgrp6), grp })
++
+#define NET_ADDR_MPLS(label) \
+ ((net_addr_mpls) { NET_MPLS, 20, sizeof(net_addr_mpls), label })
static inline void net_fill_ip4(net_addr *a, ip4_addr prefix, uint pxlen)
static inline void net_fill_roa6(net_addr *a, ip6_addr prefix, uint pxlen, uint max_pxlen, u32 asn)
{ *(net_addr_roa6 *)a = NET_ADDR_ROA6(prefix, pxlen, max_pxlen, asn); }
-static inline void net_fill_mreq4(net_addr *a, ip4_addr ga, unsigned ifindex)
-{ *(net_addr_mreq4 *)a = NET_ADDR_MREQ4(ga, ifindex); }
++static inline void net_fill_mreq4(net_addr *a, ip4_addr grp, uint ifindex)
++{ *(net_addr_mreq4 *)a = NET_ADDR_MREQ4(grp, ifindex); }
++
++static inline void net_fill_mreq6(net_addr *a, ip6_addr grp, uint ifindex)
++{ *(net_addr_mreq6 *)a = NET_ADDR_MREQ6(grp, ifindex); }
+
-static inline void net_fill_mreq6(net_addr *a, ip6_addr ga, unsigned ifindex)
-{ *(net_addr_mreq6 *)a = NET_ADDR_MREQ6(ga, ifindex); }
++static inline void net_fill_mgrp4(net_addr *a, ip4_addr grp)
++{ *(net_addr_mgrp4 *)a = NET_ADDR_MGRP4(grp); }
+
-static inline void net_fill_mgrp4(net_addr *a, ip4_addr ga)
-{ *(net_addr_mgrp4 *)a = NET_ADDR_MGRP4(ga); }
++static inline void net_fill_mgrp6(net_addr *a, ip6_addr grp)
++{ *(net_addr_mgrp6 *)a = NET_ADDR_MGRP6(grp); }
+
-static inline void net_fill_mgrp6(net_addr *a, ip6_addr ga)
-{ *(net_addr_mgrp6 *)a = NET_ADDR_MGRP6(ga); }
+static inline void net_fill_mpls(net_addr *a, u32 label)
+{ *(net_addr_mpls *)a = NET_ADDR_MPLS(label); }
static inline void net_fill_ipa(net_addr *a, ip_addr prefix, uint pxlen)
{
net_fill_ip6(a, ipa_to_ip6(prefix), IP6_MAX_PREFIX_LENGTH);
}
-static inline void net_fill_mreq(net_addr *a, ip_addr ga, unsigned ifindex)
++static inline void net_fill_mreq(net_addr *a, ip_addr grp, unsigned ifindex)
+ {
- if (ipa_is_ip4(ga))
- net_fill_mreq4(a, ipa_to_ip4(ga), ifindex);
++ if (ipa_is_ip4(grp))
++ net_fill_mreq4(a, ipa_to_ip4(grp), ifindex);
+ else
- net_fill_mreq6(a, ipa_to_ip6(ga), ifindex);
++ net_fill_mreq6(a, ipa_to_ip6(grp), ifindex);
+ }
+
-static inline void net_fill_mgrp(net_addr *a, ip_addr ga)
++static inline void net_fill_mgrp(net_addr *a, ip_addr grp)
+ {
- if (ipa_is_ip4(ga))
- net_fill_mgrp4(a, ipa_to_ip4(ga));
++ if (ipa_is_ip4(grp))
++ net_fill_mgrp4(a, ipa_to_ip4(grp));
+ else
- net_fill_mgrp6(a, ipa_to_ip6(ga));
++ net_fill_mgrp6(a, ipa_to_ip6(grp));
++}
++
+static inline void net_fill_flow4(net_addr *a, ip4_addr prefix, uint pxlen, byte *data, uint dlen)
+{
+ net_addr_flow4 *f = (void *) a;
+ *f = NET_ADDR_FLOW4(prefix, pxlen, dlen);
+ memcpy(f->data, data, dlen);
+}
+
+static inline void net_fill_flow6(net_addr *a, ip6_addr prefix, uint pxlen, byte *data, uint dlen)
+{
+ net_addr_flow6 *f = (void *) a;
+ *f = NET_ADDR_FLOW6(prefix, pxlen, dlen);
+ memcpy(f->data, data, dlen);
}
static inline int net_val_match(u8 type, u32 mask)
static inline int net_is_ip(const net_addr *a)
{ return (a->type == NET_IP4) || (a->type == NET_IP6); }
+static inline int net_is_vpn(const net_addr *a)
+{ return (a->type == NET_VPN4) || (a->type == NET_VPN6); }
+
+static inline int net_is_roa(const net_addr *a)
+{ return (a->type == NET_ROA4) || (a->type == NET_ROA6); }
+
+static inline int net_is_flow(const net_addr *a)
+{ return (a->type == NET_FLOW4) || (a->type == NET_FLOW6); }
+
++static inline int net_is_mreq(const net_addr *a)
++{ return (a->type == NET_MREQ4) || (a->type == NET_MREQ6); }
++
++static inline int net_is_mgrp(const net_addr *a)
++{ return (a->type == NET_MGRP4) || (a->type == NET_MGRP6); }
++
static inline ip4_addr net4_prefix(const net_addr *a)
{ return ((net_addr_ip4 *) a)->prefix; }
case NET_IP4:
case NET_VPN4:
case NET_ROA4:
+ case NET_FLOW4:
+ case NET_MREQ4:
+ case NET_MGRP4:
return ipa_from_ip4(net4_prefix(a));
case NET_IP6:
case NET_VPN6:
case NET_ROA6:
+ case NET_FLOW6:
+ case NET_MREQ6:
+ case NET_MGRP6:
return ipa_from_ip6(net6_prefix(a));
+ case NET_MPLS:
default:
return IPA_NONE;
}
{
switch (a->type)
{
- case NET_IP4:
- case NET_VPN4: return net4_pxlen(a) == IP4_MAX_PREFIX_LENGTH;
- case NET_IP6:
- case NET_VPN6: return net6_pxlen(a) == IP6_MAX_PREFIX_LENGTH;
- case NET_MREQ4:
- case NET_MREQ6:
- case NET_MGRP4:
- case NET_MGRP6: return 1;
- default: return 0;
+ case NET_VPN4:
- return ((net_addr_vpn4 *)a)->rd;
++ return ((net_addr_vpn4 *) a)->rd;
+ case NET_VPN6:
- return ((net_addr_vpn6 *)a)->rd;
++ return ((net_addr_vpn6 *) a)->rd;
++ default:
++ return 0;
+ }
+ }
+
-static inline int net_is_v6(net_addr *a)
-{
- return net_type_match(a, NB_6);
-}
-
+ static inline int net_ifindex(net_addr *a)
+ {
+ switch (a->type)
+ {
+ case NET_MREQ4:
- return ((net_addr_mreq4 *) a)->ifindex;
++ return ((net_addr_mreq4 *) a)->ifindex;
+ case NET_MREQ6:
- return ((net_addr_mreq6 *) a)->ifindex;
- default: return 0;
++ return ((net_addr_mreq6 *) a)->ifindex;
++ default:
++ return 0;
}
- return 0;
-
}
+
static inline int net_equal(const net_addr *a, const net_addr *b)
{ return (a->length == b->length) && !memcmp(a, b, a->length); }
static inline int net_zero_roa6(const net_addr_roa6 *a)
{ return !a->pxlen && ip6_zero(a->prefix) && !a->max_pxlen && !a->asn; }
-{ return ip4_zero(a->ga) && !a->ifindex; }
+static inline int net_zero_flow4(const net_addr_flow4 *a)
+{ return !a->pxlen && ip4_zero(a->prefix) && (a->length == sizeof(net_addr_flow4)); }
+
+static inline int net_zero_flow6(const net_addr_flow6 *a)
+{ return !a->pxlen && ip6_zero(a->prefix) && (a->length == sizeof(net_addr_flow6)); }
+
+ static inline int net_zero_mreq4(const net_addr_mreq4 *a)
-{ return ip6_zero(a->ga) && !a->ifindex; }
++{ return ip4_zero(a->grp) && !a->ifindex; }
+
+ static inline int net_zero_mreq6(const net_addr_mreq6 *a)
-{ return ip4_zero(a->ga); }
++{ return ip6_zero(a->grp) && !a->ifindex; }
+
+ static inline int net_zero_mgrp4(const net_addr_mgrp4 *a)
-{ return ip6_zero(a->ga); }
++{ return ip4_zero(a->grp); }
+
+ static inline int net_zero_mgrp6(const net_addr_mgrp6 *a)
++{ return ip6_zero(a->grp); }
++
+static inline int net_zero_mpls(const net_addr_mpls *a)
+{ return !a->label; }
static inline int net_compare_ip4(const net_addr_ip4 *a, const net_addr_ip4 *b)
static inline int net_compare_roa6(const net_addr_roa6 *a, const net_addr_roa6 *b)
{ return ip6_compare(a->prefix, b->prefix) ?: uint_cmp(a->pxlen, b->pxlen) ?: uint_cmp(a->max_pxlen, b->max_pxlen) ?: uint_cmp(a->asn, b->asn); }
-{ return ip4_compare(a->ga, b->ga) ?: uint_cmp(a->ifindex, b->ifindex); }
+static inline int net_compare_flow4(const net_addr_flow4 *a, const net_addr_flow4 *b)
+{ return ip4_compare(a->prefix, b->prefix) ?: uint_cmp(a->pxlen, b->pxlen) ?: uint_cmp(a->length, b->length) ?: memcmp(a->data, b->data, a->length - sizeof(net_addr_flow4)); }
+
+static inline int net_compare_flow6(const net_addr_flow6 *a, const net_addr_flow6 *b)
+{ return ip6_compare(a->prefix, b->prefix) ?: uint_cmp(a->pxlen, b->pxlen) ?: uint_cmp(a->length, b->length) ?: memcmp(a->data, b->data, a->length - sizeof(net_addr_flow6)); }
+
+ static inline int net_compare_mreq4(const net_addr_mreq4 *a, const net_addr_mreq4 *b)
-{ return ip6_compare(a->ga, b->ga) ?: uint_cmp(a->ifindex, b->ifindex); }
++{ return ip4_compare(a->grp, b->grp) ?: uint_cmp(a->ifindex, b->ifindex); }
+
+ static inline int net_compare_mreq6(const net_addr_mreq6 *a, const net_addr_mreq6 *b)
-{ return ip4_compare(a->ga, b->ga); }
++{ return ip6_compare(a->grp, b->grp) ?: uint_cmp(a->ifindex, b->ifindex); }
+
+ static inline int net_compare_mgrp4(const net_addr_mgrp4 *a, const net_addr_mgrp4 *b)
-{ return ip6_compare(a->ga, b->ga); }
++{ return ip4_compare(a->grp, b->grp); }
+
+ static inline int net_compare_mgrp6(const net_addr_mgrp6 *a, const net_addr_mgrp6 *b)
++{ return ip6_compare(a->grp, b->grp); }
++
+static inline int net_compare_mpls(const net_addr_mpls *a, const net_addr_mpls *b)
+{ return uint_cmp(a->label, b->label); }
int net_compare(const net_addr *a, const net_addr *b);
static inline void net_copy_roa6(net_addr_roa6 *dst, const net_addr_roa6 *src)
{ memcpy(dst, src, sizeof(net_addr_roa6)); }
-static inline u32 net_hash_ip4(const net_addr_ip4 *n)
-{ return ip4_hash(n->prefix) ^ ((u32) n->pxlen << 26); }
+static inline void net_copy_flow4(net_addr_flow4 *dst, const net_addr_flow4 *src)
+{ memcpy(dst, src, src->length); }
+
+static inline void net_copy_flow6(net_addr_flow6 *dst, const net_addr_flow6 *src)
+{ memcpy(dst, src, src->length); }
+
+ static inline void net_copy_mreq4(net_addr_mreq4 *dst, const net_addr_mreq4 *src)
+ { memcpy(dst, src, sizeof(net_addr_mreq4)); }
+
+ static inline void net_copy_mreq6(net_addr_mreq6 *dst, const net_addr_mreq6 *src)
+ { memcpy(dst, src, sizeof(net_addr_mreq6)); }
+
+ static inline void net_copy_mgrp4(net_addr_mgrp4 *dst, const net_addr_mgrp4 *src)
+ { memcpy(dst, src, sizeof(net_addr_mgrp4)); }
+
+ static inline void net_copy_mgrp6(net_addr_mgrp6 *dst, const net_addr_mgrp6 *src)
+ { memcpy(dst, src, sizeof(net_addr_mgrp6)); }
+
+static inline void net_copy_mpls(net_addr_mpls *dst, const net_addr_mpls *src)
+{ memcpy(dst, src, sizeof(net_addr_mpls)); }
-static inline u32 net_hash_ip6(const net_addr_ip6 *n)
-{ return ip6_hash(n->prefix) ^ ((u32) n->pxlen << 26); }
/* XXXX */
static inline u32 u64_hash(u64 a)
static inline u32 net_hash_roa6(const net_addr_roa6 *n)
{ return ip6_hash(n->prefix) ^ ((u32) n->pxlen << 26); }
-{ return ip4_hash(n->ga) ^ u64_hash(n->ifindex); }
+static inline u32 net_hash_flow4(const net_addr_flow4 *n)
+{ return ip4_hash(n->prefix) ^ ((u32) n->pxlen << 26); }
+
+static inline u32 net_hash_flow6(const net_addr_flow6 *n)
+{ return ip6_hash(n->prefix) ^ ((u32) n->pxlen << 26); }
+
+ static inline u32 net_hash_mreq4(const net_addr_mreq4 *n)
-{ return ip6_hash(n->ga) ^ u64_hash(n->ifindex); }
++{ return ip4_hash(n->grp) ^ u32_hash(n->ifindex); }
+
+ static inline u32 net_hash_mreq6(const net_addr_mreq6 *n)
-{ return ip4_hash(n->ga); }
++{ return ip6_hash(n->grp) ^ u32_hash(n->ifindex); }
+
+ static inline u32 net_hash_mgrp4(const net_addr_mgrp4 *n)
-{ return ip6_hash(n->ga); }
++{ return ip4_hash(n->grp); }
+
+ static inline u32 net_hash_mgrp6(const net_addr_mgrp6 *n)
-static inline int net_validate_ip4(const net_addr_ip4 *n)
++{ return ip6_hash(n->grp); }
+
+static inline u32 net_hash_mpls(const net_addr_mpls *n)
+{ return n->label; }
+
+u32 net_hash(const net_addr *a);
+
+
+static inline int net_validate_px4(const ip4_addr prefix, uint pxlen)
{
- return (n->pxlen <= IP4_MAX_PREFIX_LENGTH) &&
- ip4_zero(ip4_and(n->prefix, ip4_not(ip4_mkmask(n->pxlen))));
+ return (pxlen <= IP4_MAX_PREFIX_LENGTH) &&
+ ip4_zero(ip4_and(prefix, ip4_not(ip4_mkmask(pxlen))));
}
+static inline int net_validate_px6(const ip6_addr prefix, uint pxlen)
+{
+ return (pxlen <= IP6_MAX_PREFIX_LENGTH) &&
+ ip6_zero(ip6_and(prefix, ip6_not(ip6_mkmask(pxlen))));
+}
+
+static inline int net_validate_ip4(const net_addr_ip4 *n)
+{ return net_validate_px4(n->prefix, n->pxlen); }
+
static inline int net_validate_ip6(const net_addr_ip6 *n)
+{ return net_validate_px6(n->prefix, n->pxlen); }
+
+static inline int net_validate_vpn4(const net_addr_vpn4 *n)
+{ return net_validate_px4(n->prefix, n->pxlen); }
+
+static inline int net_validate_vpn6(const net_addr_vpn6 *n)
+{ return net_validate_px6(n->prefix, n->pxlen); }
+
+static inline int net_validate_roa4(const net_addr_roa4 *n)
+{
+ return net_validate_px4(n->prefix, n->pxlen) &&
+ (n->pxlen <= n->max_pxlen) && (n->max_pxlen <= IP4_MAX_PREFIX_LENGTH);
+}
+
+static inline int net_validate_roa6(const net_addr_roa6 *n)
{
- return (n->pxlen <= IP6_MAX_PREFIX_LENGTH) &&
- ip6_zero(ip6_and(n->prefix, ip6_not(ip6_mkmask(n->pxlen))));
+ return net_validate_px6(n->prefix, n->pxlen) &&
+ (n->pxlen <= n->max_pxlen) && (n->max_pxlen <= IP6_MAX_PREFIX_LENGTH);
}
+// FIXME: Better check, call flow_validate?
+static inline int net_validate_flow4(const net_addr_flow4 *n)
+{ return net_validate_px4(n->prefix, n->pxlen); }
+
+static inline int net_validate_flow6(const net_addr_flow6 *n)
+{ return net_validate_px6(n->prefix, n->pxlen); }
+
++static inline int net_validate_mreq4(const net_addr_mreq4 *n)
++{ return ip4_is_multicast(n->grp); }
++
++static inline int net_validate_mreq6(const net_addr_mreq6 *n)
++{ return ip6_is_multicast(n->grp); }
++
++static inline int net_validate_mgrp4(const net_addr_mgrp4 *n)
++{ return ip4_is_multicast(n->grp); }
++
++static inline int net_validate_mgrp6(const net_addr_mgrp6 *n)
++{ return ip6_is_multicast(n->grp); }
++
+static inline int net_validate_mpls(const net_addr_mpls *n)
+{ return n->label < (1 << 20); }
+
int net_validate(const net_addr *N);
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, IPV6, VPN4, VPN6, ROA4, ROA6, MREQ4, MREQ6, MGRP4, MGRP6)
+CF_KEYWORDS(INTERFACE, IMPORT, EXPORT, FILTER, NONE, VRF, TABLE, STATES, ROUTES, FILTERS)
- CF_KEYWORDS(IPV4, IPV6, VPN4, VPN6, ROA4, ROA6)
++CF_KEYWORDS(IPV4, IPV6, VPN4, VPN6, ROA4, ROA6, FLOW4, FLOW6, MREQ4, MREQ6, MGRP4, MGRP6)
CF_KEYWORDS(RECEIVE, LIMIT, ACTION, WARN, BLOCK, RESTART, DISABLE, KEEP, FILTERED)
CF_KEYWORDS(PASSWORD, FROM, PASSIVE, TO, ID, EVENTS, PACKETS, PROTOCOLS, INTERFACES)
-CF_KEYWORDS(PRIMARY, STATS, COUNT, FOR, COMMANDS, PREEXPORT, NOEXPORT, GENERATE) /* ,ROA */
-CF_KEYWORDS(LISTEN, BGP, V6ONLY, DUAL, ADDRESS, PORT, PASSWORDS, DESCRIPTION, SORTED)
+CF_KEYWORDS(ALGORITHM, KEYED, HMAC, MD5, SHA1, SHA256, SHA384, SHA512)
+CF_KEYWORDS(PRIMARY, STATS, COUNT, BY, FOR, COMMANDS, PREEXPORT, NOEXPORT, GENERATE)
+CF_KEYWORDS(BGP, PASSWORDS, DESCRIPTION, SORTED)
CF_KEYWORDS(RELOAD, IN, OUT, MRTDUMP, MESSAGES, RESTRICT, MEMORY, IGP_METRIC, CLASS, DSCP)
+CF_KEYWORDS(TIMEFORMAT, ISO, SHORT, LONG, ROUTE, PROTOCOL, BASE, LOG, S, MS, US)
CF_KEYWORDS(GRACEFUL, RESTART, WAIT, MAX, FLUSH, AS)
+/* For r_args_channel */
+CF_KEYWORDS(IPV4, IPV4_MC, IPV4_MPLS, IPV6, IPV6_MC, IPV6_MPLS, VPN4, VPN4_MC, VPN4_MPLS, VPN6, VPN6_MC, VPN6_MPLS, ROA4, ROA6, FLOW4, FLOW6, MPLS, PRI, SEC)
+
CF_ENUM(T_ENUM_RTS, RTS_, DUMMY, STATIC, INHERIT, DEVICE, STATIC_DEVICE, REDIRECT,
- RIP, OSPF, OSPF_IA, OSPF_EXT1, OSPF_EXT2, BGP, PIPE)
+ RIP, OSPF, OSPF_IA, OSPF_EXT1, OSPF_EXT2, BGP, PIPE, BABEL)
CF_ENUM(T_ENUM_SCOPE, SCOPE_, HOST, LINK, SITE, ORGANIZATION, UNIVERSE, UNDEFINED)
-CF_ENUM(T_ENUM_RTC, RTC_, UNICAST, BROADCAST, MULTICAST, ANYCAST)
-CF_ENUM(T_ENUM_RTD, RTD_, ROUTER, DEVICE, BLACKHOLE, UNREACHABLE, PROHIBIT, MULTIPATH)
+CF_ENUM(T_ENUM_RTD, RTD_, UNICAST, BLACKHOLE, UNREACHABLE, PROHIBIT)
CF_ENUM(T_ENUM_ROA, ROA_, UNKNOWN, VALID, INVALID)
%type <i32> idval
| VPN6 { $$ = NET_VPN6; }
| ROA4 { $$ = NET_ROA4; }
| ROA6 { $$ = NET_ROA6; }
- | FLOW4{ $$ = NET_FLOW4; }
- | FLOW6{ $$ = NET_FLOW6; }
++ | FLOW4 { $$ = NET_FLOW4; }
++ | FLOW6 { $$ = NET_FLOW6; }
+ | MREQ4 { $$ = NET_MREQ4; }
+ | MREQ6 { $$ = NET_MREQ6; }
+ | MGRP4 { $$ = NET_MGRP4; }
+ | MGRP6 { $$ = NET_MGRP6; }
+ | MPLS { $$ = NET_MPLS; }
;
+CF_ENUM(T_ENUM_NETTYPE, NET_, IP4, IP6, VPN4, VPN6, ROA4, ROA6, FLOW4, FLOW6)
+
/* Creation of routing tables */
u8 best; /* Best route in network, propagated to core */
u32 metric; /* Kernel metric */
} krt;
++ struct {
++ u32 iifs, oifs; /* Bitmaps for iifs and oifs. Use RTE_MGRP_* macros to manipulate. */
++ } mkrt;
} u;
} rte;
#define RIC_REJECT -1 /* Rejected by protocol */
#define RIC_DROP -2 /* Silently dropped by protocol */
-#define RTE_MGRP_SET(iface,m) ((m)|=(1<<if_get_vifi((iface))))
-#define RTE_MGRP_CLR(iface,m) ((m)&=~(1<<if_get_vifi((iface))))
-#define RTE_MGRP_ISSET(iface,m) ((m)&(1<<if_get_vifi((iface))))
-#define RTE_MGRP_CLRALL(m) ((m)=0)
-#define RTE_MGRP_COPY(mfrom,mto) ((mto)=(mfrom))
-#define RTE_MGRP_SAME(m1,m2) ((m1)==(m2))
++#define RTE_MGRP_SET(iface,m) ((m) |= (1 << if_get_vifi((iface))))
++#define RTE_MGRP_CLR(iface,m) ((m) &= ~(1 << if_get_vifi((iface))))
++#define RTE_MGRP_ISSET(iface,m) ((m) & (1 << if_get_vifi((iface))))
++#define RTE_MGRP_ZERO(m) ((m) = 0)
++#define RTE_MGRP_COPY(src,dst) ((dst) = (src))
++#define RTE_MGRP_SAME(m1,m2) ((m1) == (m2))
+
struct config;
void rt_init(void);
#define RTD_BLACKHOLE 2 /* Silently drop packets */
#define RTD_UNREACHABLE 3 /* Reject as unreachable */
#define RTD_PROHIBIT 4 /* Administratively prohibited */
- #define RTD_MAX 5
-#define RTD_MULTIPATH 5 /* Multipath route (nexthops != NULL) */
-#define RTD_MREQUEST 6 /* Multicast pseudoroute */
-#define RTD_MULTICAST 7 /* Multicast pseudoroute */
-#define RTD_NONE 8 /* Invalid RTD */
++#define RTD_MULTICAST 5 /* Multicast route */
++#define RTD_MAX 6
/* Flags for net->n.flags, used by kernel syncer */
#define KRF_INSTALLED 0x80 /* This route should be installed in the kernel */
#include <stddef.h>
+const char * rta_dest_names[RTD_MAX] = {
+ [RTD_NONE] = "",
+ [RTD_UNICAST] = "unicast",
+ [RTD_BLACKHOLE] = "blackhole",
+ [RTD_UNREACHABLE] = "unreachable",
+ [RTD_PROHIBIT] = "prohibited",
++ [RTD_MULTICAST] = "multicast",
+};
+
pool *rta_pool;
-static slab *rta_slab;
-static slab *mpnh_slab;
+static slab *rta_slab_[4];
+static slab *nexthop_slab_[4];
static slab *rte_src_slab;
static struct idm src_ids;
case NET_VPN6: return FIB_HASH(f, a, vpn6);
case NET_ROA4: return FIB_HASH(f, a, roa4);
case NET_ROA6: return FIB_HASH(f, a, roa6);
+ case NET_FLOW4: return FIB_HASH(f, a, flow4);
+ case NET_FLOW6: return FIB_HASH(f, a, flow6);
+ case NET_MREQ4: return FIB_HASH(f, a, mreq4);
+ case NET_MREQ6: return FIB_HASH(f, a, mreq6);
+ case NET_MGRP4: return FIB_HASH(f, a, mgrp4);
+ case NET_MGRP6: return FIB_HASH(f, a, mgrp6);
+ case NET_MPLS: return FIB_HASH(f, a, mpls);
default: bug("invalid type");
}
}
case NET_VPN6: return FIB_FIND(f, a, vpn6);
case NET_ROA4: return FIB_FIND(f, a, roa4);
case NET_ROA6: return FIB_FIND(f, a, roa6);
+ case NET_FLOW4: return FIB_FIND(f, a, flow4);
+ case NET_FLOW6: return FIB_FIND(f, a, flow6);
+ case NET_MREQ4: return FIB_FIND(f, a, mreq4);
+ case NET_MREQ6: return FIB_FIND(f, a, mreq6);
+ case NET_MGRP4: return FIB_FIND(f, a, mgrp4);
+ case NET_MGRP6: return FIB_FIND(f, a, mgrp6);
+ case NET_MPLS: return FIB_FIND(f, a, mpls);
default: bug("invalid type");
}
}
case NET_VPN6: FIB_INSERT(f, a, e, vpn6); return;
case NET_ROA4: FIB_INSERT(f, a, e, roa4); return;
case NET_ROA6: FIB_INSERT(f, a, e, roa6); return;
+ case NET_FLOW4: FIB_INSERT(f, a, e, flow4); return;
+ case NET_FLOW6: FIB_INSERT(f, a, e, flow6); return;
+ case NET_MREQ4: FIB_INSERT(f, a, e, mreq4); return;
+ case NET_MREQ6: FIB_INSERT(f, a, e, mreq6); return;
+ case NET_MGRP4: FIB_INSERT(f, a, e, mgrp4); return;
+ case NET_MGRP6: FIB_INSERT(f, a, e, mgrp6); return;
+ case NET_MPLS: FIB_INSERT(f, a, e, mpls); return;
default: bug("invalid type");
}
}
return 0;
}
- mask = net_val_match(n->n.addr->type, NB_MCAST) ? IADDR_MULTICAST : IADDR_HOST;
-
- c = net_classify(n->n.addr);
- if ((c < 0) || !(c & mask) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK))
+ /* FIXME: better handling different nettypes */
- c = !net_is_flow(n->n.addr) ?
- net_classify(n->n.addr): (IADDR_HOST | SCOPE_UNIVERSE);
- if ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK))
++ /* FIXME: should be check mcast addresses here or in net_validate()? */
++ if (net_type_match(n->n.addr, NB_HOST) &&
++ (c = net_classify(n->n.addr)) &&
++ ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK)))
{
log(L_WARN "Ignoring bogus route %N received via %s",
n->n.addr, e->sender->proto->name);
rte_update_unlock();
return v > 0;
-
}
++#if 0
+ /* Sometimes protocols need to find one route in table without keeping their own copy.
+ * rt_route finds the best route after applying filter.
+ * As the routes may be temporary, successful find is announced by the callback.
+ * Returns 1 if the callback was called.
+ */
+ int
+ rt_route(struct channel *c, net_addr *n, void (*callback)(struct proto *, void *, rte *), void *data)
+ {
+ net *r;
+
+ net_addr *n0 = alloca(n->length);
+ net_copy(n0, n);
+
+ while (1)
+ {
+ r = net_find(c->table, n0);
+ if (r && rte_is_valid(r->routes) && rt_examine2(r, c->proto, c->out_filter, callback, data))
+ return 1;
+ if (n0->pxlen == 0)
+ return 0;
+ n0->pxlen--;
+ net_normalize(n0);
+ }
+ }
++#endif
+
/**
* rt_refresh_begin - start a refresh cycle
return 0;
}
- static u32
-u32
++static u32
rt_get_igp_metric(rte *rt)
{
eattr *ea = ea_find(rt->attrs->eattrs, EA_GEN_IGP_METRIC);
return 0;
}
-
+ static inline int
+ sk_set_router_alert4(sock *s, int ra)
+ {
+ if (setsockopt(s->fd, SOL_IP, IP_ROUTER_ALERT, &ra, sizeof(ra)) < 0)
+ ERR("IP_ROUTER_ALER");
+
+ return 0;
+ }
+
+ static inline int
+ sk_set_router_alert6(sock *s, int ra)
+ {
+ if (setsockopt(s->fd, SOL_IPV6, IPV6_ROUTER_ALERT, &ra, sizeof(ra)) < 0)
+ ERR("IPV6_ROUTER_ALER");
+
+ return 0;
+ }
+
static inline int
sk_disable_mtu_disc4(sock *s)
{