diff options
-rw-r--r-- | conf/confbase.Y | 27 | ||||
-rw-r--r-- | filter/config.Y | 4 | ||||
-rw-r--r-- | filter/filter.c | 2 | ||||
-rw-r--r-- | lib/ip.h | 4 | ||||
-rw-r--r-- | lib/net.c | 10 | ||||
-rw-r--r-- | lib/net.h | 3 | ||||
-rw-r--r-- | nest/config.Y | 110 | ||||
-rw-r--r-- | nest/neighbor.c | 2 | ||||
-rw-r--r-- | nest/route.h | 3 | ||||
-rw-r--r-- | nest/rt-table.c | 8 | ||||
-rw-r--r-- | proto/bfd/packets.c | 8 | ||||
-rw-r--r-- | proto/ospf/iface.c | 2 | ||||
-rw-r--r-- | proto/ospf/lsalib.c | 2 | ||||
-rw-r--r-- | proto/ospf/ospf.h | 9 | ||||
-rw-r--r-- | proto/ospf/rt.c | 31 | ||||
-rw-r--r-- | proto/radv/packets.c | 1 | ||||
-rw-r--r-- | proto/rip/packets.c | 1 | ||||
-rw-r--r-- | sysdep/bsd/krt-sock.c | 47 | ||||
-rw-r--r-- | sysdep/linux/netlink.c | 38 | ||||
-rw-r--r-- | sysdep/unix/io.c | 16 | ||||
-rw-r--r-- | sysdep/unix/unix.h | 18 |
21 files changed, 146 insertions, 200 deletions
diff --git a/conf/confbase.Y b/conf/confbase.Y index 3ad0c5f0..4bf9599b 100644 --- a/conf/confbase.Y +++ b/conf/confbase.Y @@ -76,11 +76,10 @@ CF_DECLS %token <t> TEXT %type <iface> ipa_scope -%type <i> expr bool pxlen +%type <i> expr bool pxlen4 pxlen6 %type <i32> expr_us %type <time> datetime %type <a> ipa ipa_raw -%type <px> prefix %type <net> net_ip4 net_ip6 net_ip net_or_ipa %type <net_ptr> net_any @@ -175,9 +174,9 @@ ipa_scope: /* XXXX - symbols and tests */ -net_ip4: IP4 pxlen { $$.ip4 = NET_ADDR_IP4($1, $2); } +net_ip4: IP4 pxlen4 { $$.ip4 = NET_ADDR_IP4($1, $2); } -net_ip6: IP6 pxlen { $$.ip6 = NET_ADDR_IP6($1, $2); } +net_ip6: IP6 pxlen6 { $$.ip6 = NET_ADDR_IP6($1, $2); } net_ip: net_ip4 | net_ip6 ; @@ -191,22 +190,22 @@ net_or_ipa: ; -prefix: - ipa pxlen { - if (!ip_is_prefix($1, $2)) cf_error("Invalid prefix"); - $$.addr = $1; $$.len = $2; +pxlen4: + '/' expr { + if ($2 < 0 || $2 > IP4_MAX_PREFIX_LENGTH) cf_error("Invalid prefix length %d", $2); + $$ = $2; + } + | ':' IP4 { + $$ = ip4_masklen($2); + if ($$ < 0) cf_error("Invalid netmask %I", $2); } ; -pxlen: +pxlen6: '/' expr { - if ($2 < 0 || $2 > BITS_PER_IP_ADDRESS) cf_error("Invalid prefix length %d", $2); + if ($2 < 0 || $2 > IP6_MAX_PREFIX_LENGTH) cf_error("Invalid prefix length %d", $2); $$ = $2; } - | ':' ipa { - $$ = ipa_masklen($2); - if ($$ < 0) cf_error("Invalid netmask %I", $2); - } ; datetime: diff --git a/filter/config.Y b/filter/config.Y index 312506c4..d6844751 100644 --- a/filter/config.Y +++ b/filter/config.Y @@ -574,7 +574,7 @@ switch_items: fprefix_s: ipa_raw '/' NUM %prec '/' { - if (($3 < 0) || ($3 > MAX_PREFIX_LENGTH) || !ip_is_prefix($1, $3)) cf_error("Invalid network prefix: %I/%d.", $1, $3); + if (($3 < 0) || ($3 > (ipa_is_ip4($1) ? IP4_MAX_PREFIX_LENGTH : IP6_MAX_PREFIX_LENGTH)) || !ip_is_prefix($1, $3)) cf_error("Invalid network prefix: %I/%d.", $1, $3); $$.type = T_PREFIX; $$.val.px.ip = $1; $$.val.px.len = $3; } ; @@ -584,7 +584,7 @@ fprefix: | fprefix_s '+' { $$ = $1; $$.val.px.len |= LEN_PLUS; } | fprefix_s '-' { $$ = $1; $$.val.px.len |= LEN_MINUS; } | fprefix_s '{' NUM ',' NUM '}' { - if (! ((0 <= $3) && ($3 <= $5) && ($5 <= MAX_PREFIX_LENGTH))) cf_error("Invalid prefix pattern range: {%d, %d}.", $3, $5); + if (! ((0 <= $3) && ($3 <= $5) && ($5 <= (ipa_is_ip4($1.val.px.ip) ? IP4_MAX_PREFIX_LENGTH : IP6_MAX_PREFIX_LENGTH)))) cf_error("Invalid prefix pattern range: {%d, %d}.", $3, $5); $$ = $1; $$.val.px.len |= LEN_RANGE | ($3 << 16) | ($5 << 8); } ; diff --git a/filter/filter.c b/filter/filter.c index 1383961c..0e17a8e5 100644 --- a/filter/filter.c +++ b/filter/filter.c @@ -218,7 +218,7 @@ fprefix_get_bounds(struct f_prefix *px, int *l, int *h) *l = 0; else if (px->len & LEN_PLUS) - *h = MAX_PREFIX_LENGTH; + *h = ipa_is_ip4(px->ip) ? IP4_MAX_PREFIX_LENGTH : IP6_MAX_PREFIX_LENGTH; else if (px->len & LEN_RANGE) { @@ -43,12 +43,8 @@ #define UDP_HEADER_LENGTH 8 #ifdef IPV6 -#define MAX_PREFIX_LENGTH 128 -#define BITS_PER_IP_ADDRESS 128 #define STD_ADDRESS_P_LENGTH 39 #else -#define MAX_PREFIX_LENGTH 32 -#define BITS_PER_IP_ADDRESS 32 #define STD_ADDRESS_P_LENGTH 15 #endif @@ -3,6 +3,7 @@ #include "lib/ip.h" #include "lib/net.h" + const u16 net_addr_length[] = { [NET_IP4] = sizeof(net_addr_ip4), [NET_IP6] = sizeof(net_addr_ip6), @@ -10,6 +11,14 @@ const u16 net_addr_length[] = { [NET_VPN6] = sizeof(net_addr_vpn6) }; +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] = IP4_MAX_PREFIX_LENGTH +}; + + int net_format(const net_addr *N, char *buf, int buflen) { @@ -31,7 +40,6 @@ net_format(const net_addr *N, char *buf, int buflen) return 0; } - ip_addr net_pxmask(const net_addr *a) { @@ -19,7 +19,6 @@ #define NET_VPN6 4 #define NET_MAX 5 - typedef struct net_addr { u8 type; u8 pxlen; @@ -69,7 +68,7 @@ typedef union net_addr_union { extern const u16 net_addr_length[]; - +extern const u8 net_max_prefix_length[]; #define NET_ADDR_IP4(prefix,pxlen) \ ((net_addr_ip4) { NET_IP4, pxlen, sizeof(net_addr_ip4), prefix }) diff --git a/nest/config.Y b/nest/config.Y index 537a363c..e5a6e0bb 100644 --- a/nest/config.Y +++ b/nest/config.Y @@ -75,10 +75,8 @@ CF_ENUM(T_ENUM_ROA, ROA_, UNKNOWN, VALID, INVALID) %type <r> rtable %type <s> optsym %type <ra> r_args -%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_mode roa_mode limit_action table_type table_sorted tos +%type <i> proto_start echo_mask echo_size debug_mask debug_list debug_flag mrtdump_mask mrtdump_list mrtdump_flag export_mode limit_action table_type table_sorted tos %type <ps> proto_patt proto_patt2 %type <g> limit_spec @@ -156,24 +154,6 @@ table: table_type TABLE SYM table_sorted { } ; -CF_ADDTO(conf, roa_table) - -roa_table_start: ROA TABLE SYM { - this_roa_table = roa_new_table_config($3); -}; - -roa_table_opts: - /* empty */ - | roa_table_opts ROA prefix MAX NUM AS NUM ';' { - roa_add_item_config(this_roa_table, $3.addr, $3.len, $5, $7); - } - ; - -roa_table: - roa_table_start - | roa_table_start '{' roa_table_opts '}' - ; - /* Definition of protocols */ CF_ADDTO(conf, proto) @@ -469,20 +449,17 @@ CF_CLI(SHOW ROUTE, r_args, [[[<prefix>|for <prefix>|for <ip>] [table <t>] [filte r_args: /* empty */ { $$ = cfg_allocz(sizeof(struct rt_show_data)); - $$->pxlen = 256; $$->filter = FILTER_ACCEPT; } - | r_args prefix { + | r_args net_any { $$ = $1; - if ($$->pxlen != 256) cf_error("Only one prefix expected"); - $$->prefix = $2.addr; - $$->pxlen = $2.len; + if ($$->prefix) cf_error("Only one prefix expected"); + $$->prefix = $2; } | r_args FOR net_or_ipa { $$ = $1; - if ($$->pxlen != 256) cf_error("Only one prefix expected"); - $$->prefix = IPA_NONE; /* XXXX */ - $$->pxlen = 0; /* XXXX */ + if ($$->prefix) cf_error("Only one prefix expected"); + $$->prefix = &($3.n); $$->show_for = 1; } | r_args TABLE SYM { @@ -546,45 +523,8 @@ export_mode: ; -CF_CLI_HELP(SHOW ROA, ..., [[Show ROA table]]) -CF_CLI(SHOW ROA, roa_args, [<prefix> | in <prefix> | for <prefix>] [as <num>] [table <t>], [[Show ROA table]]) -{ roa_show($3); } ; - -roa_args: - /* empty */ { - $$ = cfg_allocz(sizeof(struct roa_show_data)); - $$->mode = ROA_SHOW_ALL; - $$->table = roa_table_default; - if (roa_table_default == NULL) - cf_error("No ROA table defined"); - } - | roa_args roa_mode prefix { - $$ = $1; - if ($$->mode != ROA_SHOW_ALL) cf_error("Only one prefix expected"); - $$->prefix = $3.addr; - $$->pxlen = $3.len; - $$->mode = $2; - } - | roa_args AS NUM { - $$ = $1; - $$->asn = $3; - } - | roa_args TABLE SYM { - $$ = $1; - if ($3->class != SYM_ROA) cf_error("%s is not a ROA table", $3->name); - $$->table = ((struct roa_table_config *)$3->def)->table; - } - ; - -roa_mode: - { $$ = ROA_SHOW_PX; } - | IN { $$ = ROA_SHOW_IN; } - | FOR { $$ = ROA_SHOW_FOR; } - ; - - CF_CLI_HELP(SHOW SYMBOLS, ..., [[Show all known symbolic names]]) -CF_CLI(SHOW SYMBOLS, sym_args, [table|filter|function|protocol|template|roa|<symbol>], [[Show all known symbolic names]]) +CF_CLI(SHOW SYMBOLS, sym_args, [table|filter|function|protocol|template|<symbol>], [[Show all known symbolic names]]) { cmd_show_symbols($3); } ; sym_args: @@ -596,46 +536,10 @@ sym_args: | sym_args FILTER { $$ = $1; $$->type = SYM_FILTER; } | sym_args PROTOCOL { $$ = $1; $$->type = SYM_PROTO; } | sym_args TEMPLATE { $$ = $1; $$->type = SYM_TEMPLATE; } - | sym_args ROA { $$ = $1; $$->type = SYM_ROA; } | sym_args SYM { $$ = $1; $$->sym = $2; } ; -roa_table_arg: - /* empty */ { - if (roa_table_default == NULL) - cf_error("No ROA table defined"); - $$ = roa_table_default; - } - | TABLE SYM { - if ($2->class != SYM_ROA) - cf_error("%s is not a ROA table", $2->name); - $$ = ((struct roa_table_config *)$2->def)->table; - } - ; - -CF_CLI_HELP(ADD, roa ..., [[Add ROA record]]) -CF_CLI(ADD ROA, prefix MAX NUM AS NUM roa_table_arg, <prefix> max <num> as <num> [table <name>], [[Add ROA record]]) -{ - if (! cli_access_restricted()) - { roa_add_item($8, $3.addr, $3.len, $5, $7, ROA_SRC_DYNAMIC); cli_msg(0, ""); } -}; - -CF_CLI_HELP(DELETE, roa ..., [[Delete ROA record]]) -CF_CLI(DELETE ROA, prefix MAX NUM AS NUM roa_table_arg, <prefix> max <num> as <num> [table <name>], [[Delete ROA record]]) -{ - if (! cli_access_restricted()) - { roa_delete_item($8, $3.addr, $3.len, $5, $7, ROA_SRC_DYNAMIC); cli_msg(0, ""); } -}; - -CF_CLI_HELP(FLUSH, roa [table <name>], [[Removes all dynamic ROA records]]) -CF_CLI(FLUSH ROA, roa_table_arg, [table <name>], [[Removes all dynamic ROA records]]) -{ - if (! cli_access_restricted()) - { roa_flush($3, ROA_SRC_DYNAMIC); cli_msg(0, ""); } -}; - - CF_CLI_HELP(DUMP, ..., [[Dump debugging information]]) CF_CLI(DUMP RESOURCES,,, [[Dump all allocated resource]]) { rdump(&root_pool); cli_msg(0, ""); } ; diff --git a/nest/neighbor.c b/nest/neighbor.c index 14a6b113..5b525fa9 100644 --- a/nest/neighbor.c +++ b/nest/neighbor.c @@ -83,7 +83,7 @@ if_connected(ip_addr *a, struct iface *i, struct ifa **ap) { /* Do not allow IPv4 network and broadcast addresses */ if (ipa_is_ip4(*a) && - (net_pxlen(&b->prefix) < (BITS_PER_IP_ADDRESS - 1)) && + (net_pxlen(&b->prefix) < (IP4_MAX_PREFIX_LENGTH - 1)) && (ipa_equal(*a, net_prefix(&b->prefix)) || /* Network address */ ipa_equal(*a, b->brd))) /* Broadcast */ { diff --git a/nest/route.h b/nest/route.h index 4480d17b..7d9485f1 100644 --- a/nest/route.h +++ b/nest/route.h @@ -304,8 +304,7 @@ rt_mark_for_prune(rtable *tab) } struct rt_show_data { - ip_addr prefix; - unsigned pxlen; + net_addr *prefix; rtable *table; struct filter *filter; int verbose; diff --git a/nest/rt-table.c b/nest/rt-table.c index 0a148f45..05073ce0 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -2293,9 +2293,13 @@ rt_update_hostentry(rtable *tab, struct hostentry *he) he->igp_metric = rt_get_igp_metric(e); } + /* XXXX */ done: /* Add a prefix range to the trie */ - trie_add_prefix(tab->hostcache->trie, he->addr, MAX_PREFIX_LENGTH, pxlen, MAX_PREFIX_LENGTH); + if (ipa_is_ip4(he->addr)) + trie_add_prefix(tab->hostcache->trie, he->addr, IP4_MAX_PREFIX_LENGTH, pxlen, IP4_MAX_PREFIX_LENGTH); + else + trie_add_prefix(tab->hostcache->trie, he->addr, IP6_MAX_PREFIX_LENGTH, pxlen, IP6_MAX_PREFIX_LENGTH); rta_free(old_src); return old_src != he->src; @@ -2580,7 +2584,7 @@ rt_show(struct rt_show_data *d) if (d->filtered && (d->export_mode || d->primary_only)) cli_msg(0, ""); - if (d->pxlen == 256) + if (!d->prefix) { FIB_ITERATE_INIT(&d->fit, &d->table->fib); this_cli->cont = rt_show_cont; diff --git a/proto/bfd/packets.c b/proto/bfd/packets.c index cb40bcda..2200acfa 100644 --- a/proto/bfd/packets.c +++ b/proto/bfd/packets.c @@ -202,9 +202,7 @@ bfd_open_rx_sk(struct bfd_proto *p, int multihop) sk->priority = sk_priority_control; sk->flags = SKF_THREAD | SKF_LADDR_RX | (!multihop ? SKF_TTL_RX : 0); -#ifdef IPV6 - sk->flags |= SKF_V6ONLY; -#endif + sk->af = AF_INET6; if (sk_open(sk) < 0) goto err; @@ -237,9 +235,7 @@ bfd_open_tx_sk(struct bfd_proto *p, ip_addr local, struct iface *ifa) sk->ttl = ifa ? 255 : -1; sk->flags = SKF_THREAD | SKF_BIND | SKF_HIGH_PORT; -#ifdef IPV6 - sk->flags |= SKF_V6ONLY; -#endif + sk->af = AF_INET6; if (sk_open(sk) < 0) goto err; diff --git a/proto/ospf/iface.c b/proto/ospf/iface.c index 5d37b005..91e22266 100644 --- a/proto/ospf/iface.c +++ b/proto/ospf/iface.c @@ -111,6 +111,7 @@ ospf_sk_open(struct ospf_iface *ifa) sk->dport = OSPF_PROTO; sk->saddr = ifa->addr->ip; sk->iface = ifa->iface; + sk->af = ospf_is_v2(p) ? AF_INET : AF_INET6; sk->tos = ifa->cf->tx_tos; sk->priority = ifa->cf->tx_priority; @@ -193,6 +194,7 @@ ospf_open_vlink_sk(struct ospf_proto *p) sock *sk = sk_new(p->p.pool); sk->type = SK_IP; sk->dport = OSPF_PROTO; + sk->af = ospf_is_v2(p) ? AF_INET : AF_INET6; /* FIXME: configurable tos/priority ? */ sk->tos = IP_PREC_INTERNET_CONTROL; diff --git a/proto/ospf/lsalib.c b/proto/ospf/lsalib.c index 9a6b0457..5564bee7 100644 --- a/proto/ospf/lsalib.c +++ b/proto/ospf/lsalib.c @@ -493,7 +493,7 @@ lsa_validate_ext3(struct ospf_lsa_header *lsa, struct ospf_lsa_ext3 *body) return 0; int len = IPV6_PREFIX_SPACE(pxl); - if (body->metric & LSA_EXT3_FBIT) // forwardinf address + if (body->metric & LSA_EXT3_FBIT) // forwarding address len += 16; if (body->metric & LSA_EXT3_TBIT) // route tag len += 4; diff --git a/proto/ospf/ospf.h b/proto/ospf/ospf.h index 6291ae1a..3e96b511 100644 --- a/proto/ospf/ospf.h +++ b/proto/ospf/ospf.h @@ -726,9 +726,16 @@ lsa_net_count(struct ospf_lsa_header *lsa) #define IPV6_PREFIX_SPACE(x) ((((x) + 63) / 32) * 4) #define IPV6_PREFIX_WORDS(x) (((x) + 63) / 32) -/* FIXME: these four functions should be significantly redesigned w.r.t. integration, +/* FIXME: these functions should be significantly redesigned w.r.t. integration, also should be named as ospf3_* instead of *_ipv6_* */ +static inline int +ospf_valid_prefix(net_addr *n) +{ + /* In OSPFv2, prefix is stored as netmask; ip4_masklen() returns 255 for invalid one */ + return n->pxlen <= IP6_MAX_PREFIX_LENGTH; +} + static inline u32 * ospf_get_ipv6_prefix(u32 *buf, net_addr *N, u8 *pxopts, u16 *rest) { diff --git a/proto/ospf/rt.c b/proto/ospf/rt.c index aee0368a..0adc3871 100644 --- a/proto/ospf/rt.c +++ b/proto/ospf/rt.c @@ -412,7 +412,7 @@ add_network(struct ospf_area *oa, net_addr *net, int metric, struct top_hash_ent .nhs = en->nhs }; - if (net->pxlen > MAX_PREFIX_LENGTH) + if (!ospf_valid_prefix(net)) { log(L_WARN "%s: Invalid prefix in LSA (Type: %04x, Id: %R, Rt: %R)", p->p.name, en->lsa_type, en->lsa.id, en->lsa.rt); @@ -765,16 +765,16 @@ ospf_rt_sum(struct ospf_area *oa) { lsa_parse_sum_net(en, ospf_is_v2(p), &net, &pxopts, &metric); - if (pxopts & OPT_PX_NU) - continue; - - if (net.pxlen > MAX_PREFIX_LENGTH) + if (!ospf_valid_prefix(&net)) { log(L_WARN "%s: Invalid prefix in LSA (Type: %04x, Id: %R, Rt: %R)", p->p.name, en->lsa_type, en->lsa.id, en->lsa.rt); continue; } + if (pxopts & OPT_PX_NU) + continue; + options = 0; type = ORT_NET; } @@ -862,16 +862,16 @@ ospf_rt_sum_tr(struct ospf_area *oa) lsa_parse_sum_net(en, ospf_is_v2(p), &net, &pxopts, &metric); - if (pxopts & OPT_PX_NU) - continue; - - if (net.pxlen > MAX_PREFIX_LENGTH) + if (!ospf_valid_prefix(&net)) { log(L_WARN "%s: Invalid prefix in LSA (Type: %04x, Id: %R, Rt: %R)", p->p.name, en->lsa_type, en->lsa.id, en->lsa.rt); continue; } + if (pxopts & OPT_PX_NU) + continue; + re = fib_find(&p->rtf, &net); } else // en->lsa_type == LSA_T_SUM_RT @@ -1466,19 +1466,18 @@ ospf_ext_spf(struct ospf_proto *p) lsa_parse_ext(en, ospf_is_v2(p), &rt); - if (rt.metric == LSINFINITY) - continue; - - if (rt.pxopts & OPT_PX_NU) - continue; - - if (rt.net.pxlen > MAX_PREFIX_LENGTH) + if (!ospf_valid_prefix(&rt.net)) { log(L_WARN "%s: Invalid prefix in LSA (Type: %04x, Id: %R, Rt: %R)", p->p.name, en->lsa_type, en->lsa.id, en->lsa.rt); continue; } + if (rt.metric == LSINFINITY) + continue; + + if (rt.pxopts & OPT_PX_NU) + continue; /* 16.4. (3) */ /* If there are more areas, we already precomputed preferred ASBR diff --git a/proto/radv/packets.c b/proto/radv/packets.c index a38b58b2..3bb38221 100644 --- a/proto/radv/packets.c +++ b/proto/radv/packets.c @@ -412,6 +412,7 @@ radv_sk_open(struct radv_iface *ifa) sk->type = SK_IP; sk->dport = ICMPV6_PROTO; sk->saddr = ifa->addr->ip; + sk->af = AF_INET6; sk->ttl = 255; /* Mandatory for Neighbor Discovery packets */ sk->rx_hook = radv_rx_hook; diff --git a/proto/rip/packets.c b/proto/rip/packets.c index 4fc832d5..85f0bea5 100644 --- a/proto/rip/packets.c +++ b/proto/rip/packets.c @@ -715,6 +715,7 @@ rip_open_socket(struct rip_iface *ifa) sock *sk = sk_new(p->p.pool); sk->type = SK_UDP; + sk->af = rip_is_v2(p) ? AF_INET : AF_INET6; sk->sport = ifa->cf->port; sk->dport = ifa->cf->port; sk->iface = ifa->iface; diff --git a/sysdep/bsd/krt-sock.c b/sysdep/bsd/krt-sock.c index 1db39493..19e82047 100644 --- a/sysdep/bsd/krt-sock.c +++ b/sysdep/bsd/krt-sock.c @@ -207,7 +207,8 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e) msg.rtm.rtm_addrs = RTA_DST; msg.rtm.rtm_flags = RTF_UP | RTF_PROTO1; - if (net_prefix(net->n.addr) == MAX_PREFIX_LENGTH) + /* XXXX */ + if (net_pxlen(net->n.addr) == net_max_prefix_length[net->n.addr->type]) msg.rtm.rtm_flags |= RTF_HOST; else msg.rtm.rtm_addrs |= RTA_NETMASK; @@ -296,7 +297,7 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e) return -1; } - sockaddr_fill(&gate, BIRD_AF, i->addr->ip, NULL, 0); + sockaddr_fill(&gate, ipa_is_ip4(i->addr->ip) ? AF_INET : AF_INET6, i->addr->ip, NULL, 0); msg.rtm.rtm_addrs |= RTA_GATEWAY; } break; @@ -383,12 +384,17 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan) GETADDR(&gate, RTA_GATEWAY); GETADDR(&mask, RTA_NETMASK); - if (dst.sa.sa_family != BIRD_AF) - SKIP("invalid DST"); + + switch (dst.sa.sa_family) { + case AF_INET: + case AF_INET6: break; + default: + SKIP("invalid DST"); + } idst = ipa_from_sa(&dst); - imask = ipa_from_sa(&mask); - igate = (gate.sa.sa_family == BIRD_AF) ? ipa_from_sa(&gate) : IPA_NONE; + imask = ipa_from_sa(&mask); /* XXXX broken, see below */ + igate = (gate.sa.sa_family == dst.sa.sa_family) ? ipa_from_sa(&gate) : IPA_NONE; /* We do not test family for RTA_NETMASK, because BSD sends us some strange values, but interpreting them as IPv4/IPv6 works */ @@ -398,7 +404,7 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan) if ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK)) SKIP("strange class/scope\n"); - int pxlen = (flags & RTF_HOST) ? MAX_PREFIX_LENGTH : ipa_masklen(imask); + int pxlen = (flags & RTF_HOST) ? (ipa_is_ip4(imask) ? IP4_MAX_PREFIX_LENGTH : IP6_MAX_PREFIX_LENGTH) : ipa_masklen(imask); if (pxlen < 0) { log(L_ERR "%s (%I) - netmask %I", errmsg, idst, imask); return; } @@ -663,9 +669,13 @@ krt_read_addr(struct ks_msg *msg, int scan) GETADDR (&null, RTA_AUTHOR); GETADDR (&brd, RTA_BRD); - /* Some other family address */ - if (addr.sa.sa_family != BIRD_AF) - return; + /* Is addr family IP4 or IP6? */ + int ipv6; + switch (addr.sa.sa_family) { + case AF_INET: ipv6 = 0; break; + case AF_INET6: ipv6 = 1; break; + default: return; + } iaddr = ipa_from_sa(&addr); imask = ipa_from_sa(&mask); @@ -701,16 +711,16 @@ krt_read_addr(struct ks_msg *msg, int scan) } ifa.scope = scope & IADDR_SCOPE_MASK; - if (masklen < BITS_PER_IP_ADDRESS) + if (masklen < (ipv6 ? IP6_MAX_PREFIX_LENGTH : IP4_MAX_PREFIX_LENGTH)) { net_fill_ipa(&ifa.prefix, ifa.ip, masklen); net_normalize(&ifa.prefix); - if (masklen == (BITS_PER_IP_ADDRESS - 1)) + if (masklen == ((ipv6 ? IP6_MAX_PREFIX_LENGTH : IP4_MAX_PREFIX_LENGTH) - 1)) ifa.opposite = ipa_opposite_m1(ifa.ip); #ifndef IPV6 - if (masklen == (BITS_PER_IP_ADDRESS - 2)) + if (!ipv6 && masklen == IP4_MAX_PREFIX_LENGTH - 2) ifa.opposite = ipa_opposite_m2(ifa.ip); #endif @@ -722,13 +732,13 @@ krt_read_addr(struct ks_msg *msg, int scan) } else if (!(iface->flags & IF_MULTIACCESS) && ipa_nonzero(ibrd)) { - net_fill_ipa(&ifa.prefix, ibrd, BITS_PER_IP_ADDRESS); + net_fill_ipa(&ifa.prefix, ibrd, (ipv6 ? IP6_MAX_PREFIX_LENGTH : IP4_MAX_PREFIX_LENGTH)); ifa.opposite = ibrd; ifa.flags |= IA_PEER; } else { - net_fill_ipa(&ifa.prefix, ifa.ip, BITS_PER_IP_ADDRESS); + net_fill_ipa(&ifa.prefix, ifa.ip, (ipv6 ? IP6_MAX_PREFIX_LENGTH : IP4_MAX_PREFIX_LENGTH)); ifa.flags |= IA_HOST; } @@ -825,7 +835,12 @@ krt_sysctl_scan(struct proto *p, int cmd, int table_id) mib[0] = CTL_NET; mib[1] = PF_ROUTE; mib[2] = 0; - mib[3] = BIRD_AF; + /* XXX: This value should be given from the caller */ +#ifdef IPV6 + mib[3] = AF_INET6; +#else + mib[3] = AF_INET; +#endif mib[4] = cmd; mib[5] = 0; mcnt = 6; diff --git a/sysdep/linux/netlink.c b/sysdep/linux/netlink.c index 7c4c4b2b..d5c8a2ab 100644 --- a/sysdep/linux/netlink.c +++ b/sysdep/linux/netlink.c @@ -646,12 +646,12 @@ nl_parse_addr4(struct ifaddrmsg *i, int scan, int new) ifa.ip = rta_get_ipa(a[IFA_LOCAL]); - if (i->ifa_prefixlen > BITS_PER_IP_ADDRESS) + if (i->ifa_prefixlen > IP4_MAX_PREFIX_LENGTH) { log(L_ERR "KIF: Invalid prefix length for interface %s: %d", ifi->name, i->ifa_prefixlen); new = 0; } - if (i->ifa_prefixlen == BITS_PER_IP_ADDRESS) + if (i->ifa_prefixlen == IP4_MAX_PREFIX_LENGTH) { ifa.brd = rta_get_ipa(a[IFA_ADDRESS]); net_fill_ip4(&ifa.prefix, rta_get_ip4(a[IFA_ADDRESS]), i->ifa_prefixlen); @@ -670,10 +670,10 @@ nl_parse_addr4(struct ifaddrmsg *i, int scan, int new) net_fill_ip4(&ifa.prefix, ipa_to_ip4(ifa.ip), i->ifa_prefixlen); net_normalize(&ifa.prefix); - if (i->ifa_prefixlen == BITS_PER_IP_ADDRESS - 1) + if (i->ifa_prefixlen == IP4_MAX_PREFIX_LENGTH - 1) ifa.opposite = ipa_opposite_m1(ifa.ip); - if (i->ifa_prefixlen == BITS_PER_IP_ADDRESS - 2) + if (i->ifa_prefixlen == IP4_MAX_PREFIX_LENGTH - 2) ifa.opposite = ipa_opposite_m2(ifa.ip); if ((ifi->flags & IF_BROADCAST) && a[IFA_BROADCAST]) @@ -746,12 +746,12 @@ nl_parse_addr6(struct ifaddrmsg *i, int scan, int new) ifa.ip = rta_get_ipa(a[IFA_LOCAL] ? : a[IFA_ADDRESS]); - if (i->ifa_prefixlen > BITS_PER_IP_ADDRESS) + if (i->ifa_prefixlen > IP6_MAX_PREFIX_LENGTH) { log(L_ERR "KIF: Invalid prefix length for interface %s: %d", ifi->name, i->ifa_prefixlen); new = 0; } - if (i->ifa_prefixlen == BITS_PER_IP_ADDRESS) + if (i->ifa_prefixlen == IP6_MAX_PREFIX_LENGTH) { ifa.brd = rta_get_ipa(a[IFA_ADDRESS]); net_fill_ip6(&ifa.prefix, rta_get_ip6(a[IFA_ADDRESS]), i->ifa_prefixlen); @@ -770,7 +770,7 @@ nl_parse_addr6(struct ifaddrmsg *i, int scan, int new) net_fill_ip6(&ifa.prefix, ipa_to_ip6(ifa.ip), i->ifa_prefixlen); net_normalize(&ifa.prefix); - if (i->ifa_prefixlen == BITS_PER_IP_ADDRESS - 1) + if (i->ifa_prefixlen == IP6_MAX_PREFIX_LENGTH - 1) ifa.opposite = ipa_opposite_m1(ifa.ip); } @@ -831,14 +831,21 @@ kif_do_scan(struct kif_proto *p UNUSED) nl_parse_link(h, 1); else log(L_DEBUG "nl_scan_ifaces: Unknown packet received (type=%d)", h->nlmsg_type); - - nl_request_dump(BIRD_AF, RTM_GETADDR); +#ifndef IPV6 + nl_request_dump(AF_INET, RTM_GETADDR); while (h = nl_get_scan()) if (h->nlmsg_type == RTM_NEWADDR || h->nlmsg_type == RTM_DELADDR) nl_parse_addr(h, 1); else log(L_DEBUG "nl_scan_ifaces: Unknown packet received (type=%d)", h->nlmsg_type); - +#else + nl_request_dump(AF_INET6, RTM_GETADDR); + while (h = nl_get_scan()) + if (h->nlmsg_type == RTM_NEWADDR || h->nlmsg_type == RTM_DELADDR) + nl_parse_addr(h, 1); + else + log(L_DEBUG "nl_scan_ifaces: Unknown packet received (type=%d)", h->nlmsg_type); +#endif if_end_update(); } @@ -1280,12 +1287,21 @@ krt_do_scan(struct krt_proto *p UNUSED) /* CONFIG_ALL_TABLES_AT_ONCE => p is NUL { struct nlmsghdr *h; - nl_request_dump(BIRD_AF, RTM_GETROUTE); +#ifndef IPV6 + nl_request_dump(AF_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); +#else + nl_request_dump(AF_INET6, 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); +#endif } /* diff --git a/sysdep/unix/io.c b/sysdep/unix/io.c index b636e799..bc00def9 100644 --- a/sysdep/unix/io.c +++ b/sysdep/unix/io.c @@ -1311,8 +1311,8 @@ sk_passive_connected(sock *s, int type) sock *t = sk_new(s->pool); t->type = type; - t->fd = fd; t->af = s->af; + t->fd = fd; t->ttl = s->ttl; t->tos = s->tos; t->rbsize = s->rbsize; @@ -1371,7 +1371,6 @@ sk_passive_connected(sock *s, int type) int sk_open(sock *s) { - int af = BIRD_AF; int fd = -1; int do_bind = 0; int bind_port = 0; @@ -1384,28 +1383,28 @@ sk_open(sock *s) s->ttx = ""; /* Force s->ttx != s->tpos */ /* Fall thru */ case SK_TCP_PASSIVE: - fd = socket(af, SOCK_STREAM, IPPROTO_TCP); + fd = socket(s->af, SOCK_STREAM, IPPROTO_TCP); bind_port = s->sport; bind_addr = s->saddr; do_bind = bind_port || ipa_nonzero(bind_addr); break; case SK_UDP: - fd = socket(af, SOCK_DGRAM, IPPROTO_UDP); + fd = socket(s->af, SOCK_DGRAM, IPPROTO_UDP); bind_port = s->sport; bind_addr = (s->flags & SKF_BIND) ? s->saddr : IPA_NONE; do_bind = 1; break; case SK_IP: - fd = socket(af, SOCK_RAW, s->dport); + fd = socket(s->af, SOCK_RAW, s->dport); bind_port = 0; bind_addr = (s->flags & SKF_BIND) ? s->saddr : IPA_NONE; do_bind = ipa_nonzero(bind_addr); break; case SK_MAGIC: - af = 0; + s->af = 0; fd = s->fd; break; @@ -1419,7 +1418,6 @@ sk_open(sock *s) if (fd >= FD_SETSIZE) ERR2("FD_SETSIZE limit reached"); - s->af = af; s->fd = fd; if (sk_setup(s) < 0) @@ -1448,7 +1446,7 @@ sk_open(sock *s) if (sk_set_high_port(s) < 0) log(L_WARN "Socket error: %s%#m", s->err); - sockaddr_fill(&sa, af, bind_addr, s->iface, bind_port); + sockaddr_fill(&sa, s->af, bind_addr, s->iface, bind_port); if (bind(fd, &sa.sa, SA_LEN(sa)) < 0) ERR2("bind"); } @@ -1460,7 +1458,7 @@ sk_open(sock *s) switch (s->type) { case SK_TCP_ACTIVE: - sockaddr_fill(&sa, af, s->daddr, s->iface, s->dport); + sockaddr_fill(&sa, s->af, s->daddr, s->iface, s->dport); if (connect(fd, &sa.sa, SA_LEN(sa)) >= 0) sk_tcp_connected(s); else if (errno != EINTR && errno != EAGAIN && errno != EINPROGRESS && diff --git a/sysdep/unix/unix.h b/sysdep/unix/unix.h index 4e0ff841..58ceab1e 100644 --- a/sysdep/unix/unix.h +++ b/sysdep/unix/unix.h @@ -47,14 +47,6 @@ typedef struct sockaddr_bird { } sockaddr; -#ifdef IPV6 -#define BIRD_AF AF_INET6 -#define ipa_from_sa(x) ipa_from_sa6(x) -#else -#define BIRD_AF AF_INET -#define ipa_from_sa(x) ipa_from_sa4(x) -#endif - /* This is sloppy hack, it should be detected by configure script */ /* Linux systems have it defined so this is definition for BSD systems */ @@ -75,6 +67,16 @@ static inline ip_addr ipa_from_sa4(sockaddr *sa) static inline ip_addr ipa_from_sa6(sockaddr *sa) { return ipa_from_in6(((struct sockaddr_in6 *) sa)->sin6_addr); } +static inline ip_addr ipa_from_sa(sockaddr *sa) +{ + switch (sa->sa.sa_family) + { + case AF_INET: return ipa_from_sa4(sa); + case AF_INET6: return ipa_from_sa6(sa); + default: return IPA_NONE; + } +} + static inline struct in_addr ipa_to_in4(ip_addr a) { return (struct in_addr) { htonl(ipa_to_u32(a)) }; } |