tell pfctl(8) route-to and reply-to accept next-hop only
Hello, proposed diff follows stuff discussed here [1] (pf route-to issues). I think we've reached a consensus to change route-to/reply-to such the only supported option will be next-hop (and list and table of next-hop addresses). I think bluhm@ and dlg@ have committed part of that change already. the proposed diff updates pfctl(8) so parser will do 'a right thing', namely: specifying host using form as 1.2.3.4@em0 is not supporte anymore diff introduces a next_hop() function, which is a clone of existing host(). unlike host(), the next_hop() does not accept a name of local network interface. the diff also breaks existing regression tests. We can update them once, we will agree on proposed diff. thanks and regards sashan [1] https://marc.info/?l=openbsd-tech&m=160308583701259&w=2 8<---8<---8<--8< diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y index 2b3e62b1a7e..536aec3286b 100644 --- a/sbin/pfctl/parse.y +++ b/sbin/pfctl/parse.y @@ -3745,23 +3745,13 @@ pool_opt: BITMASK { ; route_host : STRING{ - /* try to find @if0 address specs */ - if (strrchr($1, '@') != NULL) { - if (($$ = host($1, pf->opts)) == NULL) { - yyerror("invalid host for route spec"); - YYERROR; - } + if (($$ = next_hop($1, pf->opts)) == NULL) { + /* error. "any" is handled elsewhere */ free($1); - } else { - $$ = calloc(1, sizeof(struct node_host)); - if ($$ == NULL) - err(1, "route_host: calloc"); - $$->ifname = $1; - $$->addr.type = PF_ADDR_NONE; - set_ipmask($$, 128); - $$->next = NULL; - $$->tail = $$; + yyerror("could not parse host specification"); + YYERROR; } + free($1); } | STRING '/' STRING { char*buf; @@ -3769,7 +3759,7 @@ route_host: STRING{ if (asprintf(&buf, "%s/%s", $1, $3) == -1) err(1, "host: asprintf"); free($1); - if (($$ = host(buf, pf->opts)) == NULL) { + if (($$ = next_hop(buf, pf->opts)) == NULL) { /* error. "any" is handled elsewhere */ free(buf); yyerror("could not parse host specification"); @@ -3795,33 +3785,6 @@ route_host : STRING{ $$->next = NULL; $$->tail = $$; } - | dynaddr '/' NUMBER{ - struct node_host*n; - - if ($3 < 0 || $3 > 128) { - yyerror("bit number too big"); - YYERROR; - } - $$ = $1; - for (n = $1; n != NULL; n = n->next) - set_ipmask(n, $3); - } - | '(' STRING host ')' { - struct node_host*n; - - $$ = $3; - /* XXX check masks, only full mask should be allowed */ - for (n = $3; n != NULL; n = n->next) { - if ($$->ifname) { - yyerror("cannot specify interface twice " - "in route spec"); - YYERROR; - } - if (($$->ifname = strdup($2)) == NULL) - errx(1, "host: strdup"); - } - free($2); - } ; route_host_list: route_host optweight optnl{ diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c index 03317844e91..534b53b1198 100644 --- a/sbin/pfctl/pfctl_parser.c +++ b/sbin/pfctl/pfctl_parser.c @@ -1615,17 +1615,16 @@ host(const char *s, int opts) { struct node_host*h = NULL, *n; int mask = -1; - char*p, *ps, *if_name; + char*p, *ps; const char *errstr; + if (strchr(s, '@') !
bgpd refactor route decision process
This diff changes two things: - First, it move the kroute update into rde_generate_updates() simplifying prefix_evaluate a little bit. - Second, it changes prefix_evaluate to take an additional argument for the old prefix (to be removed). Instead of doing this outside of prefix_evaluate() with some drawbacks in case the same prefix is removed and readded, the code is now in prefix_evaluate() and does all the magic itself. This is a necessary step to finally fix MED sorting. -- :wq Claudio Index: rde.c === RCS file: /cvs/src/usr.sbin/bgpd/rde.c,v retrieving revision 1.511 diff -u -p -r1.511 rde.c --- rde.c 9 Jan 2021 16:49:41 - 1.511 +++ rde.c 12 Jan 2021 16:17:31 - @@ -2825,6 +2825,9 @@ rde_generate_updates(struct rib *rib, st if (old == NULL && new == NULL) return; + if ((rib->flags & F_RIB_NOFIB) == 0) + rde_send_kroute(rib, new, old); + if (new) aid = new->pt->aid; else @@ -3533,8 +3536,7 @@ rde_softreconfig_sync_reeval(struct rib_ /* need to re-link the nexthop if not already linked */ if ((p->flags & PREFIX_NEXTHOP_LINKED) == 0) nexthop_link(p); - LIST_REMOVE(p, entry.list.rib); - prefix_evaluate(p, re); + prefix_evaluate(re, p, p); } } Index: rde.h === RCS file: /cvs/src/usr.sbin/bgpd/rde.h,v retrieving revision 1.235 diff -u -p -r1.235 rde.h --- rde.h 4 Dec 2020 11:57:13 - 1.235 +++ rde.h 12 Jan 2021 16:17:31 - @@ -483,10 +483,10 @@ communities_unref(struct rde_community * communities_unlink(comm); } -int community_to_rd(struct community *, u_int64_t *); +intcommunity_to_rd(struct community *, u_int64_t *); /* rde_decide.c */ -voidprefix_evaluate(struct prefix *, struct rib_entry *); +void prefix_evaluate(struct rib_entry *, struct prefix *, struct prefix *); /* rde_filter.c */ void rde_apply_set(struct filter_set_head *, struct rde_peer *, Index: rde_decide.c === RCS file: /cvs/src/usr.sbin/bgpd/rde_decide.c,v retrieving revision 1.78 diff -u -p -r1.78 rde_decide.c --- rde_decide.c9 Aug 2019 13:44:27 - 1.78 +++ rde_decide.c12 Jan 2021 16:24:36 - @@ -238,14 +238,16 @@ prefix_cmp(struct prefix *p1, struct pre * The to evaluate prefix must not be in the prefix list. */ void -prefix_evaluate(struct prefix *p, struct rib_entry *re) +prefix_evaluate(struct rib_entry *re, struct prefix *new, struct prefix *old) { struct prefix *xp; if (re_rib(re)->flags & F_RIB_NOEVALUATE) { /* decision process is turned off */ - if (p != NULL) - LIST_INSERT_HEAD(&re->prefix_h, p, entry.list.rib); + if (old != NULL) + LIST_REMOVE(old, entry.list.rib); + if (new != NULL) + LIST_INSERT_HEAD(&re->prefix_h, new, entry.list.rib); if (re->active) { /* * During reloads it is possible that the decision @@ -259,19 +261,22 @@ prefix_evaluate(struct prefix *p, struct return; } - if (p != NULL) { + if (old != NULL) + LIST_REMOVE(old, entry.list.rib); + + if (new != NULL) { if (LIST_EMPTY(&re->prefix_h)) - LIST_INSERT_HEAD(&re->prefix_h, p, entry.list.rib); + LIST_INSERT_HEAD(&re->prefix_h, new, entry.list.rib); else { LIST_FOREACH(xp, &re->prefix_h, entry.list.rib) { - if (prefix_cmp(p, xp) > 0) { - LIST_INSERT_BEFORE(xp, p, + if (prefix_cmp(new, xp) > 0) { + LIST_INSERT_BEFORE(xp, new, entry.list.rib); break; } else if (LIST_NEXT(xp, entry.list.rib) == NULL) { /* if xp last element ... */ - LIST_INSERT_AFTER(xp, p, + LIST_INSERT_AFTER(xp, new, entry.list.rib); break; } @@ -290,18 +295,17 @@ prefix_evaluate(struct prefix *p, struct xp = NULL; } - if (re->active != xp) { - /* need to generate an update */ - + /* +* If the active prefix changed or the active prefix was remo
uvm_fault: access_type fixup for wired mapping
Diff below moves `access_type' to the context structure passed down to the various routines and fix a regression introduced in a previous refactoring. `access_type' is overwritten for wired mapping and the value of `enter_prot' is used instead. ok? Index: uvm/uvm_fault.c === RCS file: /cvs/src/sys/uvm/uvm_fault.c,v retrieving revision 1.111 diff -u -p -r1.111 uvm_fault.c --- uvm/uvm_fault.c 2 Jan 2021 02:39:59 - 1.111 +++ uvm/uvm_fault.c 12 Jan 2021 12:36:38 - @@ -477,6 +477,7 @@ struct uvm_faultctx { * read-only after that. */ vm_prot_t enter_prot; + vm_prot_t access_type; vaddr_t startva; int npages; int centeridx; @@ -486,7 +487,7 @@ struct uvm_faultctx { }; intuvm_fault_lower(struct uvm_faultinfo *, struct uvm_faultctx *, - struct vm_page **, vm_fault_t, vm_prot_t); + struct vm_page **, vm_fault_t); /* * uvm_fault_check: check prot, handle needs-copy, etc. @@ -505,7 +506,7 @@ int uvm_fault_lower(struct uvm_faultinfo */ int uvm_fault_check(struct uvm_faultinfo *ufi, struct uvm_faultctx *flt, -struct vm_anon ***ranons, vm_prot_t access_type) +struct vm_anon ***ranons) { struct vm_amap *amap; struct uvm_object *uobj; @@ -523,7 +524,7 @@ uvm_fault_check(struct uvm_faultinfo *uf #endif /* check protection */ - if ((ufi->entry->protection & access_type) != access_type) { + if ((ufi->entry->protection & flt->access_type) != flt->access_type) { uvmfault_unlockmaps(ufi, FALSE); return (EACCES); } @@ -539,11 +540,11 @@ uvm_fault_check(struct uvm_faultinfo *uf flt->pa_flags = UVM_ET_ISWC(ufi->entry) ? PMAP_WC : 0; flt->wired = VM_MAPENT_ISWIRED(ufi->entry) || (flt->narrow == TRUE); if (flt->wired) - access_type = flt->enter_prot; /* full access for wired */ + flt->access_type = flt->enter_prot; /* full access for wired */ /* handle "needs_copy" case. */ if (UVM_ET_ISNEEDSCOPY(ufi->entry)) { - if ((access_type & PROT_WRITE) || + if ((flt->access_type & PROT_WRITE) || (ufi->entry->object.uvm_obj == NULL)) { /* need to clear */ uvmfault_unlockmaps(ufi, FALSE); @@ -648,7 +649,7 @@ uvm_fault_check(struct uvm_faultinfo *uf */ int uvm_fault_upper(struct uvm_faultinfo *ufi, struct uvm_faultctx *flt, - struct vm_anon **anons, vm_fault_t fault_type, vm_prot_t access_type) + struct vm_anon **anons, vm_fault_t fault_type) { struct vm_amap *amap = ufi->entry->aref.ar_amap; struct vm_anon *oanon, *anon = anons[flt->centeridx]; @@ -699,7 +700,7 @@ uvm_fault_upper(struct uvm_faultinfo *uf * if we are out of anon VM we wait for RAM to become available. */ - if ((access_type & PROT_WRITE) != 0 && anon->an_ref > 1) { + if ((flt->access_type & PROT_WRITE) != 0 && anon->an_ref > 1) { counters_inc(uvmexp_counters, flt_acow); oanon = anon; /* oanon = old */ anon = uvm_analloc(); @@ -761,7 +762,7 @@ uvm_fault_upper(struct uvm_faultinfo *uf */ if (pmap_enter(ufi->orig_map->pmap, ufi->orig_rvaddr, VM_PAGE_TO_PHYS(pg) | flt->pa_flags, flt->enter_prot, - access_type | PMAP_CANFAIL | (flt->wired ? PMAP_WIRED : 0)) != 0) { + flt->access_type | PMAP_CANFAIL | (flt->wired ? PMAP_WIRED : 0)) != 0) { /* * No need to undo what we did; we can simply think of * this as the pmap throwing away the mapping information. @@ -922,6 +923,7 @@ uvm_fault(vm_map_t orig_map, vaddr_t vad * pages on wire */ else flt.narrow = FALSE; /* normal fault */ + flt.access_type = access_type; /* @@ -930,7 +932,7 @@ uvm_fault(vm_map_t orig_map, vaddr_t vad while (error == ERESTART) { anons = anons_store; - error = uvm_fault_check(&ufi, &flt, &anons, access_type); + error = uvm_fault_check(&ufi, &flt, &anons); if (error != 0) continue; @@ -938,13 +940,11 @@ uvm_fault(vm_map_t orig_map, vaddr_t vad shadowed = uvm_fault_upper_lookup(&ufi, &flt, anons, pages); if (shadowed == TRUE) { /* case 1: fault on an anon in our amap */ - error = uvm_fault_upper(&ufi, &flt, anons, fault_type, - access_type); + error = uvm_fault_upper(&ufi, &flt, anons, fault_type); } else { /* case 2: fault on backing object or zero fill */ KERNEL_LOCK(); - error = uvm_fault_low
Re: Make ospf6d work on point-to-point links
Claudio Jeker(cje...@diehard.n-r-g.com) on 2021.01.12 10:07:57 +0100: > On Wed, Jan 06, 2021 at 01:02:50PM +0100, Claudio Jeker wrote: > > The code in ospf6d is a bit broken when it comes to point-to-point links. > > This diff fixes this by a) using the neighbor address instead of the unset > > interface destination address and by b) matching the incomming packet > > against all possible IPs of that interface. > > > > I tripped on b) because my P2P interface has more than one link-local > > address and the code just likes to select the wrong one. > > > > This works for my case, please check I did not break something else. > > So this seems to work. Anyone wants to OK else I will commit this later > today. Code reads ok. Did not get around to testing it. > > > -- > > :wq Claudio > > > > Index: lsupdate.c > > === > > RCS file: /cvs/src/usr.sbin/ospf6d/lsupdate.c,v > > retrieving revision 1.18 > > diff -u -p -r1.18 lsupdate.c > > --- lsupdate.c 15 Jul 2020 14:47:41 - 1.18 > > +++ lsupdate.c 6 Jan 2021 11:28:43 - > > @@ -474,7 +474,7 @@ ls_retrans_timer(int fd, short event, vo > > /* ls_retrans_list_free retriggers the timer */ > > return; > > } else if (nbr->iface->type == IF_TYPE_POINTOPOINT) > > - memcpy(&addr, &nbr->iface->dst, sizeof(addr)); > > + memcpy(&addr, &nbr->addr, sizeof(addr)); > > else > > inet_pton(AF_INET6, AllDRouters, &addr); > > } else > > Index: packet.c > > === > > RCS file: /cvs/src/usr.sbin/ospf6d/packet.c,v > > retrieving revision 1.17 > > diff -u -p -r1.17 packet.c > > --- packet.c23 Dec 2019 07:33:49 - 1.17 > > +++ packet.c6 Jan 2021 11:52:08 - > > @@ -82,12 +82,9 @@ send_packet(struct iface *iface, struct > > struct in6_addr *dst) > > { > > struct sockaddr_in6 sa6; > > - struct msghdr msg; > > - struct ioveciov[1]; > > > > - /* setup buffer */ > > + /* setup sockaddr */ > > bzero(&sa6, sizeof(sa6)); > > - > > sa6.sin6_family = AF_INET6; > > sa6.sin6_len = sizeof(sa6); > > sa6.sin6_addr = *dst; > > @@ -104,15 +101,8 @@ send_packet(struct iface *iface, struct > > return (-1); > > } > > > > - bzero(&msg, sizeof(msg)); > > - msg.msg_name = &sa6; > > - msg.msg_namelen = sizeof(sa6); > > - iov[0].iov_base = buf->buf; > > - iov[0].iov_len = ibuf_size(buf); > > - msg.msg_iov = iov; > > - msg.msg_iovlen = 1; > > - > > - if (sendmsg(iface->fd, &msg, 0) == -1) { > > + if (sendto(iface->fd, buf->buf, ibuf_size(buf), 0, > > + (struct sockaddr *)&sa6, sizeof(sa6)) == -1) { > > log_warn("send_packet: error sending packet on interface %s", > > iface->name); > > return (-1); > > @@ -186,11 +176,16 @@ recv_packet(int fd, short event, void *b > > * AllDRouters is only valid for DR and BDR but this is checked later. > > */ > > inet_pton(AF_INET6, AllSPFRouters, &addr); > > - > > if (!IN6_ARE_ADDR_EQUAL(&dest, &addr)) { > > inet_pton(AF_INET6, AllDRouters, &addr); > > if (!IN6_ARE_ADDR_EQUAL(&dest, &addr)) { > > - if (!IN6_ARE_ADDR_EQUAL(&dest, &iface->addr)) { > > + struct iface_addr *ia; > > + > > + TAILQ_FOREACH(ia, &iface->ifa_list, entry) { > > + if (IN6_ARE_ADDR_EQUAL(&dest, &ia->addr)) > > + break; > > + } > > + if (ia == NULL) { > > log_debug("recv_packet: packet sent to wrong " > > "address %s, interface %s", > > log_in6addr(&dest), iface->name); > > >
Re: Make ospf6d work on point-to-point links
On Wed, Jan 06, 2021 at 01:02:50PM +0100, Claudio Jeker wrote: > The code in ospf6d is a bit broken when it comes to point-to-point links. > This diff fixes this by a) using the neighbor address instead of the unset > interface destination address and by b) matching the incomming packet > against all possible IPs of that interface. > > I tripped on b) because my P2P interface has more than one link-local > address and the code just likes to select the wrong one. > > This works for my case, please check I did not break something else. So this seems to work. Anyone wants to OK else I will commit this later today. > -- > :wq Claudio > > Index: lsupdate.c > === > RCS file: /cvs/src/usr.sbin/ospf6d/lsupdate.c,v > retrieving revision 1.18 > diff -u -p -r1.18 lsupdate.c > --- lsupdate.c15 Jul 2020 14:47:41 - 1.18 > +++ lsupdate.c6 Jan 2021 11:28:43 - > @@ -474,7 +474,7 @@ ls_retrans_timer(int fd, short event, vo > /* ls_retrans_list_free retriggers the timer */ > return; > } else if (nbr->iface->type == IF_TYPE_POINTOPOINT) > - memcpy(&addr, &nbr->iface->dst, sizeof(addr)); > + memcpy(&addr, &nbr->addr, sizeof(addr)); > else > inet_pton(AF_INET6, AllDRouters, &addr); > } else > Index: packet.c > === > RCS file: /cvs/src/usr.sbin/ospf6d/packet.c,v > retrieving revision 1.17 > diff -u -p -r1.17 packet.c > --- packet.c 23 Dec 2019 07:33:49 - 1.17 > +++ packet.c 6 Jan 2021 11:52:08 - > @@ -82,12 +82,9 @@ send_packet(struct iface *iface, struct > struct in6_addr *dst) > { > struct sockaddr_in6 sa6; > - struct msghdr msg; > - struct ioveciov[1]; > > - /* setup buffer */ > + /* setup sockaddr */ > bzero(&sa6, sizeof(sa6)); > - > sa6.sin6_family = AF_INET6; > sa6.sin6_len = sizeof(sa6); > sa6.sin6_addr = *dst; > @@ -104,15 +101,8 @@ send_packet(struct iface *iface, struct > return (-1); > } > > - bzero(&msg, sizeof(msg)); > - msg.msg_name = &sa6; > - msg.msg_namelen = sizeof(sa6); > - iov[0].iov_base = buf->buf; > - iov[0].iov_len = ibuf_size(buf); > - msg.msg_iov = iov; > - msg.msg_iovlen = 1; > - > - if (sendmsg(iface->fd, &msg, 0) == -1) { > + if (sendto(iface->fd, buf->buf, ibuf_size(buf), 0, > + (struct sockaddr *)&sa6, sizeof(sa6)) == -1) { > log_warn("send_packet: error sending packet on interface %s", > iface->name); > return (-1); > @@ -186,11 +176,16 @@ recv_packet(int fd, short event, void *b >* AllDRouters is only valid for DR and BDR but this is checked later. >*/ > inet_pton(AF_INET6, AllSPFRouters, &addr); > - > if (!IN6_ARE_ADDR_EQUAL(&dest, &addr)) { > inet_pton(AF_INET6, AllDRouters, &addr); > if (!IN6_ARE_ADDR_EQUAL(&dest, &addr)) { > - if (!IN6_ARE_ADDR_EQUAL(&dest, &iface->addr)) { > + struct iface_addr *ia; > + > + TAILQ_FOREACH(ia, &iface->ifa_list, entry) { > + if (IN6_ARE_ADDR_EQUAL(&dest, &ia->addr)) > + break; > + } > + if (ia == NULL) { > log_debug("recv_packet: packet sent to wrong " > "address %s, interface %s", > log_in6addr(&dest), iface->name); >
Re: Change bgpd_addr encoding of VPN v4 and v6 addresses
On Tue, Jan 05, 2021 at 11:17:22AM +0100, Claudio Jeker wrote: > While changing log_addr() I noticed that struct bgpd_addr could benefit > from changing the encoding of AID_VPN_IPv4 and AID_VPN_IPv6 addrs. > Instead of having independent route distinguishers and labelstacks use > common fields for those and use the v4 and v6 addresses for the prefix. > This is a bit more compact but also simplifies some code since the > handling of AID_VPN_IPv4 and AID_VPN_IPv6 can be handled in the same > switch case. > > I reduced the labelstack size from 21 to 18 (6 instead of 7 labels). Now > in theory you could pack 7 labels into an IPv4 VPN NLRI (8bit prefixlen + > 64bit RD + 16bit prefix + 21 * 8bit label = 256) but that is quite silly. > Even 6 labels is more than enough. bgpd itself only allows a single MPLS > label when announcing such networks. Ping -- :wq Claudio PS: diff is based of /usr/src/usr.sbin Index: bgpctl/mrtparser.c === RCS file: /cvs/src/usr.sbin/bgpctl/mrtparser.c,v retrieving revision 1.13 diff -u -p -r1.13 mrtparser.c --- bgpctl/mrtparser.c 3 Jul 2019 06:22:01 - 1.13 +++ bgpctl/mrtparser.c 5 Jan 2021 09:19:09 - @@ -833,14 +833,14 @@ mrt_extract_attr(struct mrt_rib_entry *r re->nexthop.aid = aid; memcpy(&tmp, a + 1 + sizeof(u_int64_t), sizeof(tmp)); - re->nexthop.vpn4.addr.s_addr = tmp; + re->nexthop.v4.s_addr = tmp; break; case AID_VPN_IPv6: if (attr_len < sizeof(u_int64_t) + sizeof(struct in6_addr)) return (-1); re->nexthop.aid = aid; - memcpy(&re->nexthop.vpn6.addr, + memcpy(&re->nexthop.v6, a + 1 + sizeof(u_int64_t), sizeof(struct in6_addr)); break; @@ -979,7 +979,7 @@ mrt_extract_addr(void *msg, u_int len, s return (-1); addr->aid = aid; /* XXX labelstack and rd missing */ - memcpy(&addr->vpn4.addr, b + sizeof(u_int64_t), + memcpy(&addr->v4, b + sizeof(u_int64_t), sizeof(struct in_addr)); return (sizeof(u_int64_t) + sizeof(struct in_addr)); case AID_VPN_IPv6: @@ -987,7 +987,7 @@ mrt_extract_addr(void *msg, u_int len, s return (-1); addr->aid = aid; /* XXX labelstack and rd missing */ - memcpy(&addr->vpn6.addr, b + sizeof(u_int64_t), + memcpy(&addr->v6, b + sizeof(u_int64_t), sizeof(struct in6_addr)); return (sizeof(u_int64_t) + sizeof(struct in6_addr)); default: Index: bgpd/bgpd.h === RCS file: /cvs/src/usr.sbin/bgpd/bgpd.h,v retrieving revision 1.409 diff -u -p -r1.409 bgpd.h --- bgpd/bgpd.h 4 Jan 2021 13:40:32 - 1.409 +++ bgpd/bgpd.h 5 Jan 2021 08:23:39 - @@ -176,23 +176,6 @@ extern const struct aid aid_vals[]; sizeof(struct pt_entry_vpn6)\ } -struct vpn4_addr { - u_int64_t rd; - struct in_addr addr; - u_int8_tlabelstack[21]; /* max that makes sense */ - u_int8_tlabellen; - u_int8_tpad1; - u_int8_tpad2; -}; - -struct vpn6_addr { - u_int64_t rd; - struct in6_addr addr; - u_int8_tlabelstack[21]; /* max that makes sense */ - u_int8_tlabellen; - u_int8_tpad1; - u_int8_tpad2; -}; #define BGP_MPLS_BOS 0x01 @@ -200,22 +183,15 @@ struct bgpd_addr { union { struct in_addr v4; struct in6_addr v6; - struct vpn4_addrvpn4; - struct vpn6_addrvpn6; /* maximum size for a prefix is 256 bits */ - u_int8_taddr8[32]; - u_int16_t addr16[16]; - u_int32_t addr32[8]; } ba; /* 128-bit address */ + u_int64_t rd; /* route distinguisher for VPN addrs */ u_int32_t scope_id; /* iface scope id for v6 */ u_int8_taid; + u_int8_tlabellen; /* size of the labelstack */ + u_int8_tlabelstack[18]; /* max that makes sense */ #definev4 ba.v4 #definev6 ba.v6 -#definevpn4ba.vpn4 -#definevpn6ba.vpn6 -#defineaddr8 ba.addr8 -#defineaddr16 ba.addr1