A new batch of patches for ldpd(8)

2015-03-06 Thread Renato Westphal
Hi all,

I've done a lot of work on ldpd(8) a long time ago but only now I
found time to organize my patches and send them to review. The patches
can be found here:
https://github.com/rwestphal/openbsd-ldpd/commits/renato-2015

The major changes introduced are:
* VPLS signaling;
* Configuration reload support (sighup);
* MD5 authentication as per RFC 5036;
* Major rework of the label mapping algorithms.

Along with that there are a lot of bug fixes, code simplification and
removal of dead code.

Rafael Zalamena is working on the datapath implementation of the VPLS
solution and will release his patches anytime soon.

Suggestions, comments and feedback are welcome.

Regards,
-- 
Renato Westphal



[PATCH 4/6] Don't try to send address withdraws to neighbors that are unreachable after an address removal in the system.

2015-03-11 Thread Renato Westphal
---
 ldpe.c | 11 ++-
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/ldpe.c b/ldpe.c
index f643272..d422603 100644
--- a/ldpe.c
+++ b/ldpe.c
@@ -414,17 +414,18 @@ ldpe_dispatch_main(int fd, short event, void *bula)
break;
 
LIST_REMOVE(if_addr, global_entry);
+   iface = if_lookup(kaddr->ifindex);
+   if (iface) {
+   LIST_REMOVE(if_addr, iface_entry);
+   if_fsm(iface, IF_EVT_DELADDR);
+   }
+
RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
if (nbr->state != NBR_STA_OPER)
continue;
send_address_withdraw(nbr, if_addr);
}
 
-   iface = if_lookup(kaddr->ifindex);
-   if (iface) {
-   LIST_REMOVE(if_addr, iface_entry);
-   if_fsm(iface, IF_EVT_DELADDR);
-   }
free(if_addr);
break;
case IMSG_RECONF_CONF:
-- 
1.9.1



[PATCH 3/6] Remove attached adjacencies whenever an interface is disabled for whatever reason.

2015-03-11 Thread Renato Westphal
If one interface is disabled, the holdtimer of the attached adjacencies
will eventually timeout after a few seconds. But there's no need to wait
when we know that the interface is disabled. In these cases, remove the
attached adjacencies to speedup the convergence process.
---
 interface.c | 14 +-
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/interface.c b/interface.c
index e18477b..7c80d1e 100644
--- a/interface.c
+++ b/interface.c
@@ -165,15 +165,13 @@ if_new(struct kif *kif)
 void
 if_del(struct iface *iface)
 {
-   struct adj  *adj;
struct if_addr  *if_addr;
 
+   if (iface->state == IF_STA_ACTIVE)
+   if_act_reset(iface);
+
log_debug("if_del: interface %s", iface->name);
 
-   while ((adj = LIST_FIRST(&iface->adj_list)) != NULL) {
-   LIST_REMOVE(adj, iface_entry);
-   adj_del(adj);
-   }
while ((if_addr = LIST_FIRST(&iface->addr_list)) != NULL)
LIST_REMOVE(if_addr, iface_entry);
 
@@ -262,6 +260,12 @@ int
 if_act_reset(struct iface *iface)
 {
struct in_addr   addr;
+   struct adj  *adj;
+
+   while ((adj = LIST_FIRST(&iface->adj_list)) != NULL) {
+   LIST_REMOVE(adj, iface_entry);
+   adj_del(adj);
+   }
 
if_stop_hello_timer(iface);
 
-- 
1.9.1



[PATCH 5/6] Remove interface finite state machine.

2015-03-11 Thread Renato Westphal
In the name of simplicity, remove the interface FSM that was inherited
from ospfd. In ldpd interfaces are just up or down, so keeping a FSM
for that is an overkill. Now instead of calling if_fsm(), just call
if_update() whenever a relevant event occurs (status change, address
addition/removal).

Additional notes:
1 - s/if_act_/if_/

2 - Remove the IMSG_IFUP and IMSG_IFDOWN events. Now whenever an
interface changes its state a IMSG_IFSTATUS event will be generated
with the new status.
---
 interface.c | 118 +---
 kroute.c|  13 ---
 ldpd.h  |  19 --
 ldpe.c  |  21 ++-
 ldpe.h  |   4 ++-
 5 files changed, 28 insertions(+), 147 deletions(-)

diff --git a/interface.c b/interface.c
index 7c80d1e..62c2766 100644
--- a/interface.c
+++ b/interface.c
@@ -41,98 +41,9 @@
 
 extern struct ldpd_conf*leconf;
 
-int if_act_start(struct iface *);
-int if_act_reset(struct iface *);
-int if_act_update(struct iface *);
 voidif_hello_timer(int, short, void *);
 voidif_start_hello_timer(struct iface *);
 voidif_stop_hello_timer(struct iface *);
-struct nbr *if_elect(struct nbr *, struct nbr *);
-
-struct {
-   int state;
-   enum iface_eventevent;
-   enum iface_action   action;
-   int new_state;
-} iface_fsm[] = {
-/* current state   event that happened action to take  resulting state 
*/
-{IF_STA_DOWN,  IF_EVT_DOWN,IF_ACT_NOTHING, 0},
-{IF_STA_DOWN,  IF_EVT_UP,  IF_ACT_UPDATE,  0},
-{IF_STA_DOWN,  IF_EVT_NEWADDR, IF_ACT_UPDATE,  0},
-{IF_STA_DOWN,  IF_EVT_DELADDR, IF_ACT_NOTHING, 0},
-{IF_STA_ACTIVE,IF_EVT_DOWN,IF_ACT_RST, IF_STA_DOWN},
-{IF_STA_ACTIVE,IF_EVT_NEWADDR, IF_ACT_NOTHING, 0},
-{IF_STA_ACTIVE,IF_EVT_DELADDR, IF_ACT_UPDATE,  0},
-{-1,   IF_EVT_NOTHING, IF_ACT_NOTHING, 0},
-};
-
-const char * const if_event_names[] = {
-   "NOTHING",
-   "UP",
-   "DOWN",
-   "NEWADDR",
-   "DELADDR"
-};
-
-const char * const if_action_names[] = {
-   "NOTHING",
-   "UPDATE",
-   "RESET"
-};
-
-int
-if_fsm(struct iface *iface, enum iface_event event)
-{
-   int old_state;
-   int new_state = 0;
-   int i, ret = 0;
-
-   old_state = iface->state;
-
-   for (i = 0; iface_fsm[i].state != -1; i++)
-   if ((iface_fsm[i].state & old_state) &&
-   (iface_fsm[i].event == event)) {
-   new_state = iface_fsm[i].new_state;
-   break;
-   }
-
-   if (iface_fsm[i].state == -1) {
-   /* event outside of the defined fsm, ignore it. */
-   log_debug("if_fsm: interface %s, "
-   "event %s not expected in state %s", iface->name,
-   if_event_names[event], if_state_name(old_state));
-   return (0);
-   }
-
-   switch (iface_fsm[i].action) {
-   case IF_ACT_UPDATE:
-   ret = if_act_update(iface);
-   break;
-   case IF_ACT_RST:
-   ret = if_act_reset(iface);
-   break;
-   case IF_ACT_NOTHING:
-   /* do nothing */
-   break;
-   }
-
-   if (ret) {
-   log_debug("if_fsm: error changing state for interface %s, "
-   "event %s, state %s", iface->name, if_event_names[event],
-   if_state_name(old_state));
-   return (-1);
-   }
-
-   if (new_state != 0)
-   iface->state = new_state;
-
-   log_debug("if_fsm: event %s resulted in action %s and changing "
-   "state for interface %s from %s to %s",
-   if_event_names[event], if_action_names[iface_fsm[i].action],
-   iface->name, if_state_name(old_state), if_state_name(iface->state));
-
-   return (ret);
-}
 
 struct iface *
 if_new(struct kif *kif)
@@ -168,7 +79,7 @@ if_del(struct iface *iface)
struct if_addr  *if_addr;
 
if (iface->state == IF_STA_ACTIVE)
-   if_act_reset(iface);
+   if_reset(iface);
 
log_debug("if_del: interface %s", iface->name);
 
@@ -237,13 +148,14 @@ if_stop_hello_timer(struct iface *iface)
fatal("if_stop_hello_timer");
 }
 
-/* actions */
 int
-if_act_start(struct iface *iface)
+if_start(struct iface *iface)
 {
struct in_addr   addr;
struct timeval   now;
 
+   log_debug("if_start: %s", iface->name);
+
gettimeofday(&now, NULL);
iface->uptime = now.tv_sec;
 
@@ -257,11 +169,13 @@ if_act_start(struct iface *iface)
 }
 
 int
-if_act_reset(struct iface *iface)
+if_reset(struct iface *iface)
 {
struct in_addr   addr;
struct adj 

[PATCH 6/6] Remove unused variables and functions.

2015-03-11 Thread Renato Westphal
---
 kroute.c   |  2 --
 lde.c  |  5 -
 ldp.h  |  6 --
 ldpe.h |  4 
 neighbor.c | 27 ---
 5 files changed, 44 deletions(-)

diff --git a/kroute.c b/kroute.c
index a962ea1..033 100644
--- a/kroute.c
+++ b/kroute.c
@@ -113,8 +113,6 @@ RB_HEAD(kif_tree, kif_node) kit;
 RB_PROTOTYPE(kif_tree, kif_node, entry, kif_compare)
 RB_GENERATE(kif_tree, kif_node, entry, kif_compare)
 
-intflag_implicit_null = 0;
-
 int
 kif_init(void)
 {
diff --git a/lde.c b/lde.c
index c7cd190..639a290 100644
--- a/lde.c
+++ b/lde.c
@@ -198,10 +198,8 @@ lde_dispatch_imsg(int fd, short event, void *bula)
struct imsg  imsg;
struct lde_nbr   *nbr;
struct map   map;
-   struct timespec  tp;
struct in_addr   addr;
ssize_t  n;
-   time_t   now;
int  shut = 0, verbose;
 
if (event & EV_READ) {
@@ -217,9 +215,6 @@ lde_dispatch_imsg(int fd, short event, void *bula)
shut = 1;
}
 
-   clock_gettime(CLOCK_MONOTONIC, &tp);
-   now = tp.tv_sec;
-
for (;;) {
if ((n = imsg_get(ibuf, &imsg)) == -1)
fatal("lde_dispatch_imsg: imsg_read error");
diff --git a/ldp.h b/ldp.h
index 2ed1f05..75fdbc9 100644
--- a/ldp.h
+++ b/ldp.h
@@ -195,12 +195,6 @@ struct address_list_tlv {
 #defineADDR_IPV4   0x1
 #defineADDR_IPV6   0x2
 
-/* This struct is badly aligned so use two 32 bit fields */
-struct fec_elm {
-   u_int32_t   hdr;
-   u_int32_t   addr;
-};
-
 #define FEC_ELM_MIN_LEN4
 #defineFEC_WILDCARD0x01
 #defineFEC_PREFIX  0x02
diff --git a/ldpe.h b/ldpe.h
index e380d65..9168360 100644
--- a/ldpe.h
+++ b/ldpe.h
@@ -198,10 +198,6 @@ int nbr_establish_connection(struct nbr *);
 
 voidnbr_mapping_add(struct nbr *, struct mapping_head *,
struct map *);
-struct mapping_entry   *nbr_mapping_find(struct nbr *, struct mapping_head *,
-   struct map *);
-voidnbr_mapping_del(struct nbr *, struct mapping_head *,
-   struct map *);
 voidmapping_list_clr(struct mapping_head *);
 
 struct ctl_nbr *nbr_to_ctl(struct nbr *);
diff --git a/neighbor.c b/neighbor.c
index 2a9efb4..b2a1624 100644
--- a/neighbor.c
+++ b/neighbor.c
@@ -553,33 +553,6 @@ nbr_mapping_add(struct nbr *nbr, struct mapping_head *mh, 
struct map *map)
TAILQ_INSERT_TAIL(mh, me, entry);
 }
 
-struct mapping_entry *
-nbr_mapping_find(struct nbr *nbr, struct mapping_head *mh, struct map *map)
-{
-   struct mapping_entry*me = NULL;
-
-   TAILQ_FOREACH(me, mh, entry) {
-   if (me->map.prefix.s_addr == map->prefix.s_addr &&
-   me->map.prefixlen == map->prefixlen)
-   return (me);
-   }
-
-   return (NULL);
-}
-
-void
-nbr_mapping_del(struct nbr *nbr, struct mapping_head *mh, struct map *map)
-{
-   struct mapping_entry*me;
-
-   me = nbr_mapping_find(nbr, mh, map);
-   if (me == NULL)
-   return;
-
-   TAILQ_REMOVE(mh, me, entry);
-   free(me);
-}
-
 void
 mapping_list_clr(struct mapping_head *mh)
 {
-- 
1.9.1



Re: A new batch of patches for ldpd(8)

2015-03-12 Thread Renato Westphal
2015-03-09 12:45 GMT-03:00 Martin Pieuchot :
> Hi Renato,
>
> On 06/03/15(Fri) 15:03, Renato Westphal wrote:
>> Hi all,
>>
>> I've done a lot of work on ldpd(8) a long time ago but only now I
>> found time to organize my patches and send them to review. The patches
>> can be found here:
>> https://github.com/rwestphal/openbsd-ldpd/commits/renato-2015
>>
>> The major changes introduced are:
>> * VPLS signaling;
>> * Configuration reload support (sighup);
>> * MD5 authentication as per RFC 5036;
>> * Major rework of the label mapping algorithms.
>>
>> Along with that there are a lot of bug fixes, code simplification and
>> removal of dead code.
>>
>> Rafael Zalamena is working on the datapath implementation of the VPLS
>> solution and will release his patches anytime soon.
>>
>> Suggestions, comments and feedback are welcome.
>
> Can you send the diffs one by one to tech@ so that people can review
> them and give you oks to commit?  Some of them are trivial and should
> be quickly reviewed.
>
> Please do not flood the list, don't send them all at once :)
>
> Martin

Hi,

Ok, thanks for the suggestion. I'll do that now.

[]s

-- 
Renato Westphal



[PATCH 1/6] Close extended discovery socket on exit.

2015-03-12 Thread Renato Westphal
---
 ldpe.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/ldpe.c b/ldpe.c
index afba919..f643272 100644
--- a/ldpe.c
+++ b/ldpe.c
@@ -279,6 +279,7 @@ ldpe_shutdown(void)
}
 
close(leconf->ldp_discovery_socket);
+   close(leconf->ldp_ediscovery_socket);
close(leconf->ldp_session_socket);
 
/* clean up */
-- 
1.9.1



[PATCH 2/6] Don't assign labels for BGP routes.

2015-03-12 Thread Renato Westphal
Although RFC 5036 is not explicit about this, LDP should not assign
labels for BGP routes. Doing that would be very resource consuming in
some scenarios and unnecessary. The goal is generally only to establish
LSPs among all PEs in the AS since LDP is not used as an end in itself
but as a means to implement advanced solutions like MPLS L2/L3 VPNs. Some
implementations (e.g. JunOS) go further and only assign labels for /32
loopback routes advertised in the IGP.

If Inter-AS LSPs are necessary, BGP itself should be used for distributing
IPv4 labeled routes (e.g. option C. of section 10 in RFC 4364).
---
 kroute.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/kroute.c b/kroute.c
index f5772e7..679f66d 100644
--- a/kroute.c
+++ b/kroute.c
@@ -1250,6 +1250,8 @@ rtmsg_process(char *buf, size_t len)
if (rtm->rtm_flags & RTF_MPATH)
mpath = 1;
prio = rtm->rtm_priority;
+   if (prio == RTP_BGP)
+   continue;
 
switch (sa->sa_family) {
case AF_INET:
-- 
1.9.1



Re: [PATCH 2/6] Don't assign labels for BGP routes.

2015-03-12 Thread Renato Westphal
2015-03-11 22:18 GMT-03:00 Claudio Jeker :
> On Wed, Mar 11, 2015 at 04:41:05PM -0300, Renato Westphal wrote:
>> Although RFC 5036 is not explicit about this, LDP should not assign
>> labels for BGP routes. Doing that would be very resource consuming in
>> some scenarios and unnecessary. The goal is generally only to establish
>> LSPs among all PEs in the AS since LDP is not used as an end in itself
>> but as a means to implement advanced solutions like MPLS L2/L3 VPNs. Some
>> implementations (e.g. JunOS) go further and only assign labels for /32
>> loopback routes advertised in the IGP.
>>
>> If Inter-AS LSPs are necessary, BGP itself should be used for distributing
>> IPv4 labeled routes (e.g. option C. of section 10 in RFC 4364).
>> ---
>>  kroute.c | 2 ++
>>  1 file changed, 2 insertions(+)
>>
>> diff --git a/kroute.c b/kroute.c
>> index f5772e7..679f66d 100644
>> --- a/kroute.c
>> +++ b/kroute.c
>> @@ -1250,6 +1250,8 @@ rtmsg_process(char *buf, size_t len)
>>   if (rtm->rtm_flags & RTF_MPATH)
>>   mpath = 1;
>>   prio = rtm->rtm_priority;
>> + if (prio == RTP_BGP)
>> + continue;
>>
>>   switch (sa->sa_family) {
>>   case AF_INET:
>> --
>> 1.9.1
>>
>
> A few comments:
> - I would prefer that check to be a bit further up as in above the
>   RTF_MPATH check and so next to all the other continues.
> - Add a comment why we skip RTP_BGP

Ok.

> - Shouldn't this be a more generic kind of filter (since the prio can be
>   changed in bgpd)? Or is this overkill?
> - Would be nice to use something like the ROUTE_MSGFILTER to filter these
>   unwanted messages already in the kernel (esp since bgpd can be a very
>   chatty companion)

I agree with you, filtering by the priority sounds more like a hack
than a real solution. Yes, we could create a new sockopt like
ROUTE_PROTOFILTER to filter the unwanted routes already in the kernel,
but that doesn't address the real issue: how to identify the BGP
routes? In Linux the fib_info structure has a field called
"fib_protocol" (RTPROT_*) which stores the type of the route. AFAIK we
don't have anything like that in OpenBSD.

-- 
Renato Westphal



Re: [PATCH 5/6] Remove interface finite state machine.

2015-03-12 Thread Renato Westphal
2015-03-11 22:30 GMT-03:00 Claudio Jeker :
> On Wed, Mar 11, 2015 at 04:41:08PM -0300, Renato Westphal wrote:
>> In the name of simplicity, remove the interface FSM that was inherited
>> from ospfd. In ldpd interfaces are just up or down, so keeping a FSM
>> for that is an overkill. Now instead of calling if_fsm(), just call
>> if_update() whenever a relevant event occurs (status change, address
>> addition/removal).
>>
>> Additional notes:
>> 1 - s/if_act_/if_/
>>
>> 2 - Remove the IMSG_IFUP and IMSG_IFDOWN events. Now whenever an
>> interface changes its state a IMSG_IFSTATUS event will be generated
>> with the new status.
>> ---
>>  interface.c | 118 
>> +---
>>  kroute.c|  13 ---
>>  ldpd.h  |  19 --
>>  ldpe.c  |  21 ++-
>>  ldpe.h  |   4 ++-
>>  5 files changed, 28 insertions(+), 147 deletions(-)
>>
>> diff --git a/interface.c b/interface.c
>> index 7c80d1e..62c2766 100644
>> --- a/interface.c
>> +++ b/interface.c
>> @@ -41,98 +41,9 @@
>>
>>  extern struct ldpd_conf*leconf;
>>
>> -int   if_act_start(struct iface *);
>> -int   if_act_reset(struct iface *);
>> -int   if_act_update(struct iface *);
>>  void  if_hello_timer(int, short, void *);
>>  void  if_start_hello_timer(struct iface *);
>>  void  if_stop_hello_timer(struct iface *);
>> -struct nbr   *if_elect(struct nbr *, struct nbr *);
>> -
>> -struct {
>> - int state;
>> - enum iface_eventevent;
>> - enum iface_action   action;
>> - int new_state;
>> -} iface_fsm[] = {
>> -/* current state event that happened action to take  resulting 
>> state */
>> -{IF_STA_DOWN,IF_EVT_DOWN,IF_ACT_NOTHING, 0},
>> -{IF_STA_DOWN,IF_EVT_UP,  IF_ACT_UPDATE,  0},
>> -{IF_STA_DOWN,IF_EVT_NEWADDR, IF_ACT_UPDATE,  0},
>> -{IF_STA_DOWN,IF_EVT_DELADDR, IF_ACT_NOTHING, 0},
>> -{IF_STA_ACTIVE,  IF_EVT_DOWN,IF_ACT_RST, IF_STA_DOWN},
>> -{IF_STA_ACTIVE,  IF_EVT_NEWADDR, IF_ACT_NOTHING, 0},
>> -{IF_STA_ACTIVE,  IF_EVT_DELADDR, IF_ACT_UPDATE,  0},
>> -{-1, IF_EVT_NOTHING, IF_ACT_NOTHING, 0},
>> -};
>> -
>> -const char * const if_event_names[] = {
>> - "NOTHING",
>> - "UP",
>> - "DOWN",
>> - "NEWADDR",
>> - "DELADDR"
>> -};
>> -
>> -const char * const if_action_names[] = {
>> - "NOTHING",
>> - "UPDATE",
>> - "RESET"
>> -};
>> -
>> -int
>> -if_fsm(struct iface *iface, enum iface_event event)
>> -{
>> - int old_state;
>> - int new_state = 0;
>> - int i, ret = 0;
>> -
>> - old_state = iface->state;
>> -
>> - for (i = 0; iface_fsm[i].state != -1; i++)
>> - if ((iface_fsm[i].state & old_state) &&
>> - (iface_fsm[i].event == event)) {
>> - new_state = iface_fsm[i].new_state;
>> - break;
>> - }
>> -
>> - if (iface_fsm[i].state == -1) {
>> - /* event outside of the defined fsm, ignore it. */
>> - log_debug("if_fsm: interface %s, "
>> - "event %s not expected in state %s", iface->name,
>> - if_event_names[event], if_state_name(old_state));
>> - return (0);
>> - }
>> -
>> - switch (iface_fsm[i].action) {
>> - case IF_ACT_UPDATE:
>> - ret = if_act_update(iface);
>> - break;
>> - case IF_ACT_RST:
>> - ret = if_act_reset(iface);
>> - break;
>> - case IF_ACT_NOTHING:
>> - /* do nothing */
>> - break;
>> - }
>> -
>> - if (ret) {
>> - log_debug("if_fsm: error changing state for interface %s, "
>> - "event %s, state %s", iface->name, if_event_names[event],
>> - if_state_name(old_state));
>> - return (-1);
>> - }
>> -
>> - if (new_state != 0)
>> - iface->state = new_state;
>> -
>> - log_debug("if_fsm: event %s re

Re: [PATCH] #include in parse.y when calloc is used

2015-03-28 Thread Renato Westphal
2015-03-28 8:56 GMT-03:00 Fabian Raetz :
> Hi tech@,
>
> should the stdlib.h header be included in parse.y files when calloc(3)
> is used?
>
> Regards,
> Fabian
>
>
> From ce8307e0bc7541b88a9a9bf949f6585adef46bb6 Mon Sep 17 00:00:00 2001
> From: Fabian Raetz 
> Date: Sat, 28 Mar 2015 12:44:32 +0100
> Subject: [PATCH] include stdlib.h because of calloc(3) usage
>
> ---
>  bin/chio/parse.y  | 1 +
>  sbin/ipsecctl/parse.y | 1 +
>  usr.sbin/bgpd/parse.y | 1 +
>  usr.sbin/dvmrpd/parse.y   | 1 +
>  usr.sbin/httpd/parse.y| 1 +
>  usr.sbin/ifstated/parse.y | 1 +
>  usr.sbin/iscsictl/parse.y | 1 +
>  usr.sbin/ldpd/parse.y | 1 +
>  usr.sbin/ospf6d/parse.y   | 1 +
>  usr.sbin/ospfd/parse.y| 1 +
>  usr.sbin/relayd/parse.y   | 1 +
>  usr.sbin/ripd/parse.y | 1 +
>  usr.sbin/snmpd/parse.y| 1 +
>  13 files changed, 13 insertions(+)
>
> diff --git bin/chio/parse.y bin/chio/parse.y
> index 0d086c9..279d08f 100644
> --- bin/chio/parse.y
> +++ bin/chio/parse.y
> @@ -31,6 +31,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>
>  TAILQ_HEAD(files, file) files = 
> TAILQ_HEAD_INITIALIZER(files);
> diff --git sbin/ipsecctl/parse.y sbin/ipsecctl/parse.y
> index 63d2796..f04ff88 100644
> --- sbin/ipsecctl/parse.y
> +++ sbin/ipsecctl/parse.y
> @@ -40,6 +40,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> diff --git usr.sbin/bgpd/parse.y usr.sbin/bgpd/parse.y
> index 2021fbd..769f6e4 100644
> --- usr.sbin/bgpd/parse.y
> +++ usr.sbin/bgpd/parse.y
> @@ -34,6 +34,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>
> diff --git usr.sbin/dvmrpd/parse.y usr.sbin/dvmrpd/parse.y
> index fabc9cc..56fcac7 100644
> --- usr.sbin/dvmrpd/parse.y
> +++ usr.sbin/dvmrpd/parse.y
> @@ -36,6 +36,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>
> diff --git usr.sbin/httpd/parse.y usr.sbin/httpd/parse.y
> index 006cf4e..ce1e060 100644
> --- usr.sbin/httpd/parse.y
> +++ usr.sbin/httpd/parse.y
> @@ -46,6 +46,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> diff --git usr.sbin/ifstated/parse.y usr.sbin/ifstated/parse.y
> index a010f8c..c1f721e 100644
> --- usr.sbin/ifstated/parse.y
> +++ usr.sbin/ifstated/parse.y
> @@ -36,6 +36,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> diff --git usr.sbin/iscsictl/parse.y usr.sbin/iscsictl/parse.y
> index d199c81..fecde41 100644
> --- usr.sbin/iscsictl/parse.y
> +++ usr.sbin/iscsictl/parse.y
> @@ -38,6 +38,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>
> diff --git usr.sbin/ldpd/parse.y usr.sbin/ldpd/parse.y
> index ee070ca..4821d51 100644
> --- usr.sbin/ldpd/parse.y
> +++ usr.sbin/ldpd/parse.y
> @@ -36,6 +36,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>
> diff --git usr.sbin/ospf6d/parse.y usr.sbin/ospf6d/parse.y
> index 01a2731..1ba57c9 100644
> --- usr.sbin/ospf6d/parse.y
> +++ usr.sbin/ospf6d/parse.y
> @@ -37,6 +37,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>
> diff --git usr.sbin/ospfd/parse.y usr.sbin/ospfd/parse.y
> index 09e6922..1909fa3 100644
> --- usr.sbin/ospfd/parse.y
> +++ usr.sbin/ospfd/parse.y
> @@ -35,6 +35,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>
> diff --git usr.sbin/relayd/parse.y usr.sbin/relayd/parse.y
> index 6bd980b..4092cd6 100644
> --- usr.sbin/relayd/parse.y
> +++ usr.sbin/relayd/parse.y
> @@ -42,6 +42,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> diff --git usr.sbin/ripd/parse.y usr.sbin/ripd/parse.y
> index dacb201..0d224c9 100644
> --- usr.sbin/ripd/parse.y
> +++ usr.sbin/ripd/parse.y
> @@ -36,6 +36,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>
> diff --git usr.sbin/snmpd/parse.y usr.sbin/snmpd/parse.y
> index cea9194..72f020f 100644
> --- usr.sbin/snmpd/parse.y
> +++ usr.sbin/snmpd/parse.y
> @@ -44,6 +44,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> --
> 2.3.3

Hi,

I don't think that this is necessary. Yacc includes a skeleton C code
when generating a parser from a grammar specification file (.y) and
the stdlib header is in there:

char *banner[] =
{
"#include ",
"#include ",
"#define YYBYACC 1",
"#define YYMAJOR 1",
"#define YYMINOR 9",
"#define YYLEX yylex()",
"#define YYEMPTY -1",
"#define yyclearin (yychar=(YYEMPTY))",
"#define yyerrok (yyerrflag=0)",
"#define YYRECOVERING() (yyerrflag!=0)",
NULL
};

If you include the stdlib header in the .y file you will end up with
two includes for the same header in the .c file.

-- 
Renato Westphal



[RFC] Patches for the LDP daemon

2013-05-22 Thread Renato Westphal
Hello everybody,

First of all, let me introduce myself. I am Renato Westphal, I work as a
computer engineer in Brazil and I'm a maintainer of the MPLS-Linux project.
A couple of years ago I accidentally found that OpenBSD already had
built-in support for MPLS and, surprisingly, a fully working implementation
of the LDP daemon. I decided to checkout the code and I really liked what I
saw, the code was beautiful and easy to work with. After that, I took the
decision to port that code to Quagga/Linux and, after some time, it worked
out well*. This year I decided to work again on ldpd to fix all the
existing bugs and make the code more robust. Instead of working directly on
my Quagga port, I decided to fix all the existing bugs in the original
implementation and then re-start the port to Quagga/Linux. This way both
projects would benefit from my work.

With that said, the patches below are the first part of my work:
https://github.com/rwestphal/openbsd-ldpd/commits/renato

Summary of the patches:
* Added support for hello adjacencies and targeted hellos (which is half
the way to implement the draft martini L2VPN and VPLS control plane);
* Added support for multiple addresses per interface;
* Major improvements on session convergence time;
* Many bug fixes, code simplification and removal of dead code.

My next priorities:
* Implement the "reload configuration" (sighup) functionality;
* Review the label mapping algorithms.

I would like to get these patches reviewed and hopefully integrated. Any
comments would be appreciated ;)

Regards,
Renato.

[*] https://github.com/rwestphal/quagga-public/commits/mpls

-- 
Renato Westphal


Re: IPV6_MINHOPCOUNT on UDP sockets

2016-06-27 Thread Renato Westphal
2016-06-27 19:01 GMT-03:00 Alexander Bluhm :
> On Mon, Jun 27, 2016 at 11:57:08PM +0200, J??r??mie Courr??ges-Anglas wrote:
>> Alexander Bluhm  writes:
>> > The man page says IPV6_MINHOPCOUNT is only for unicast packets.
>> > The ugly part of the code is dealing with multicast packets.
>>
>> IIUC Renato also needs multicast support.  I thought it wouldn't be
>> a problem to extend the IPV6_MINHOPCOUNT scope.
>
> If he needs it, just remove the word "unicast" from the man page.
> Then it is OK bluhm@

Yes, I need this to implement support for RFC 7552, which says: "(...)
the LDP Link Hello packets MUST have their IPv6 Hop Limit set to 255,
be checked for the same upon receipt (before any LDP-specific
processing)". And LDP Link Hello packets are multicast UDP packets...

Also, besides removing the word "unicast" from the man page, I'd go
further and rename "datagrams" to "packets", which is a more generic
term.

-- 
Renato Westphal



Re: IPV6_MINHOPCOUNT on UDP sockets

2016-06-27 Thread Renato Westphal
2016-06-27 20:30 GMT-03:00 Jeremie Courreges-Anglas :
> Renato Westphal  writes:
>
>> 2016-06-27 19:01 GMT-03:00 Alexander Bluhm :
>>> On Mon, Jun 27, 2016 at 11:57:08PM +0200, J??r??mie Courr??ges-Anglas wrote:
>>>> Alexander Bluhm  writes:
>>>> > The man page says IPV6_MINHOPCOUNT is only for unicast packets.
>>>> > The ugly part of the code is dealing with multicast packets.
>>>>
>>>> IIUC Renato also needs multicast support.  I thought it wouldn't be
>>>> a problem to extend the IPV6_MINHOPCOUNT scope.
>>>
>>> If he needs it, just remove the word "unicast" from the man page.
>>> Then it is OK bluhm@
>
> Ack, thanks.
>
>> Yes, I need this to implement support for RFC 7552, which says: "(...)
>> the LDP Link Hello packets MUST have their IPv6 Hop Limit set to 255,
>> be checked for the same upon receipt (before any LDP-specific
>> processing)". And LDP Link Hello packets are multicast UDP packets...
>>
>> Also, besides removing the word "unicast" from the man page, I'd go
>> further and rename "datagrams" to "packets", which is a more generic
>> term.
>
> Makes sense.  Updated diff below, I'll probably commit it tomorrow
> (tuesday CEST): let me know if this is enough for ldpd.

Yes, that's all I need. Thank you :)

-- 
Renato Westphal



[PATCH] ldpd: add GTSM support (RFC 6720)

2016-06-29 Thread Renato Westphal
This also finishes the missing bits from our RFC 7552 implementation
because GTSM is mandatory for LDPv6.

To avoid any kind of interoperability problems, I included a few
knobs to enable/disable GTSM on a per-address-family and per-neighbor
basis. Cisco's LDPv6 implementation, for instance, doesn't support GTSM.

Ok?
---
 hello.c |  10 ++
 ldp.h   |   1 +
 ldpd.8  |   8 +
 ldpd.c  |  18 ---
 ldpd.conf.5 |  33 +++
 ldpd.h  |  12 ++-
 ldpe.h  |   6 
 neighbor.c  |  80 ++
 packet.c|   5 +++
 parse.y |  20 +++-
 printconf.c |  15 +
 socket.c| 104 +---
 12 files changed, 293 insertions(+), 19 deletions(-)

diff --git a/hello.c b/hello.c
index 72623ca..446499c 100644
--- a/hello.c
+++ b/hello.c
@@ -53,6 +53,8 @@ send_hello(enum hello_type type, struct iface_af *ia, struct 
tnbr *tnbr)
/* multicast destination address */
switch (af) {
case AF_INET:
+   if (!(leconf->ipv4.flags & F_LDPD_AF_NO_GTSM))
+   flags |= GTSM_HELLO;
dst.v4 = global.mcast_addr_v4;
break;
case AF_INET6:
@@ -363,6 +365,14 @@ recv_hello(struct in_addr lsr_id, struct ldp_msg *lm, int 
af,
(trans_pref == DUAL_STACK_LDPOV6 && af == AF_INET6
nbr = nbr_new(lsr_id, af, ds_tlv, &trans_addr, scope_id);
 
+   /* dynamic LDPv4 GTSM negotiation as per RFC 6720 */
+   if (nbr) {
+   if (flags & GTSM_HELLO)
+   nbr->flags |= F_NBR_GTSM_NEGOTIATED;
+   else
+   nbr->flags &= ~F_NBR_GTSM_NEGOTIATED;
+   }
+
/* update neighbor's configuration sequence number */
if (nbr && (tlvs_rcvd & F_HELLO_TLV_RCVD_CONF)) {
if (conf_seqnum > nbr->conf_seqnum &&
diff --git a/ldp.h b/ldp.h
index 7078681..9c2377b 100644
--- a/ldp.h
+++ b/ldp.h
@@ -142,6 +142,7 @@ struct hello_prms_tlv {
 
 #define TARGETED_HELLO 0x8000
 #define REQUEST_TARG_HELLO 0x4000
+#define GTSM_HELLO 0x2000
 
 struct hello_prms_opt4_tlv {
uint16_ttype;
diff --git a/ldpd.8 b/ldpd.8
index def793a..04414cc 100644
--- a/ldpd.8
+++ b/ldpd.8
@@ -129,6 +129,14 @@ socket used for communication with
 .Re
 .Pp
 .Rs
+.%A C. Pignataro
+.%A R. Asati
+.%D August 2012
+.%R RFC 6720
+.%T The Generalized TTL Security Mechanism (GTSM) for the Label Distribution 
Protocol (LDP)
+.Re
+.Pp
+.Rs
 .%A R. Asati
 .%A C. Pignataro
 .%A K. Raza
diff --git a/ldpd.c b/ldpd.c
index 1c680c0..8de3405 100644
--- a/ldpd.c
+++ b/ldpd.c
@@ -823,10 +823,15 @@ merge_af(int af, struct ldpd_af_conf *af_conf, struct 
ldpd_af_conf *xa)
af_conf->thello_interval = xa->thello_interval;
 
/* update flags */
-   if (ldpd_process == PROC_LDP_ENGINE &&
-   (af_conf->flags & F_LDPD_AF_THELLO_ACCEPT) &&
-   !(xa->flags & F_LDPD_AF_THELLO_ACCEPT))
-   ldpe_remove_dynamic_tnbrs(af);
+   if (ldpd_process == PROC_LDP_ENGINE) {
+   if ((af_conf->flags & F_LDPD_AF_THELLO_ACCEPT) &&
+   !(xa->flags & F_LDPD_AF_THELLO_ACCEPT))
+   ldpe_remove_dynamic_tnbrs(af);
+
+   if ((af_conf->flags & F_LDPD_AF_NO_GTSM) !=
+   (xa->flags & F_LDPD_AF_NO_GTSM))
+   ldpe_reset_nbrs(af);
+   }
 
if ((af_conf->flags & F_LDPD_AF_EXPNULL) !=
(xa->flags & F_LDPD_AF_EXPNULL))
@@ -988,7 +993,10 @@ merge_nbrps(struct ldpd_conf *conf, struct ldpd_conf 
*xconf)
}
 
/* update existing nbrps */
-   if (nbrp->keepalive != xn->keepalive ||
+   if (nbrp->flags != xn->flags ||
+   nbrp->keepalive != xn->keepalive ||
+   nbrp->gtsm_enabled != xn->gtsm_enabled ||
+   nbrp->gtsm_hops != xn->gtsm_hops ||
nbrp->auth.method != xn->auth.method ||
strcmp(nbrp->auth.md5key, xn->auth.md5key) != 0)
nbrp_changed = 1;
diff --git a/ldpd.conf.5 b/ldpd.conf.5
index 62f2350..a8d8aec 100644
--- a/ldpd.conf.5
+++ b/ldpd.conf.5
@@ -145,6 +145,28 @@ connected prefixes.
 The default is
 .Ic no .
 .Pp
+.It Xo
+.Ic gtsm-enable
+.Pq Ic yes Ns | Ns Ic no
+.Xc
+If set to
+.Ic yes ,
+.Xr ldpd 8
+will use the GTSM procedures described in RFC 6720 (for the IPv4 
address-family)
+and RFC 7552 (for the IPv6 address-family).
+.Pp
+Since GTSM is mandatory for LDPv6, the only effect of disabling GTSM for the
+IPv6 address-family is that
+.Xr ldpd 8
+will not check the incoming packets' Hop Limit.
+Outgoing packets will still be sent using a Hop Limit of 255 to guarantee
+interoperability.
+.Pp
+If GTSM is enabled, multi-hop neighbors should have either GTSM disabled
+ind

Re: route6d summer cleanup

2016-07-06 Thread Renato Westphal
M_ADD;
> rtm->rtm_version = RTM_VERSION;
> rtm->rtm_seq = ++seq;
> -   rtm->rtm_pid = pid;
> rtm->rtm_flags = rrt->rrt_flags;
> rtm->rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
> rtm->rtm_inits = RTV_HOPCOUNT;
> @@ -2694,7 +2681,6 @@ delroute(struct netinfo6 *np, struct in6
> rtm->rtm_type = RTM_DELETE;
> rtm->rtm_version = RTM_VERSION;
> rtm->rtm_seq = ++seq;
> -   rtm->rtm_pid = pid;
> rtm->rtm_flags = RTF_UP | RTF_GATEWAY;
> if (np->rip6_plen == sizeof(struct in6_addr) * 8)
> rtm->rtm_flags |= RTF_HOST;
> @@ -2741,7 +2727,6 @@ struct in6_addr *
>  getroute(struct netinfo6 *np, struct in6_addr *gw)
>  {
> u_char buf[BUFSIZ];
> -   int myseq;
> int len;
> struct rt_msghdr *rtm;
> struct sockaddr_in6 *sin6;
> @@ -2751,8 +2736,7 @@ getroute(struct netinfo6 *np, struct in6
> memset(rtm, 0, len);
> rtm->rtm_type = RTM_GET;
> rtm->rtm_version = RTM_VERSION;
> -   myseq = ++seq;
> -   rtm->rtm_seq = myseq;
> +   rtm->rtm_seq = ++seq;
> rtm->rtm_addrs = RTA_DST;
> rtm->rtm_msglen = len;
> sin6 = (struct sockaddr_in6 *)&buf[sizeof(struct rt_msghdr)];
> @@ -2772,7 +2756,7 @@ getroute(struct netinfo6 *np, struct in6
> }
> rtm = (struct rt_msghdr *)buf;
> } while (rtm->rtm_version != RTM_VERSION ||
> -   rtm->rtm_seq != myseq || rtm->rtm_pid != pid);
> +   rtm->rtm_seq != seq || rtm->rtm_pid != pid);
> sin6 = (struct sockaddr_in6 *)&buf[sizeof(struct rt_msghdr)];
> if (rtm->rtm_addrs & RTA_DST) {
> sin6 = (struct sockaddr_in6 *)
>
>
> --

ok renato@

I just think it would make more sense to add v6 capabilities to ripd
and remove route6d from base. But yes, nobody cares about RIP anymore,
motivation would be a problem.

-- 
Renato Westphal



[PATCH 1/7] ldpd: implement support for PWid group wildcards

2017-02-20 Thread Renato Westphal
This was missing from our original RFC 4447 VPLS implementation. Now
ldpd understands group wildcards as mandated by the RFC, but we still
don't send them ourselves. I can't see any case in which sending a group
wildcard would be useful, but nonetheless this patch provides a function
called lde_send_labelwithdraw_pwid_wcard() which is ready to be used in
the future anytime we feel like it might be useful.
---
 l2vpn.c   | 71 ---
 lde.c | 71 ---
 lde.h | 16 ++
 lde_lib.c | 57 +-
 logmsg.c  |  6 +++---
 5 files changed, 167 insertions(+), 54 deletions(-)

diff --git a/l2vpn.c b/l2vpn.c
index 22c9874..e79caa8 100644
--- a/l2vpn.c
+++ b/l2vpn.c
@@ -282,7 +282,7 @@ l2vpn_pw_negotiate(struct lde_nbr *ln, struct fec_node *fn, 
struct map *map)
st.status_code = S_WRONG_CBIT;
st.msg_id = map->msg_id;
st.msg_type = htons(MSG_TYPE_LABELMAPPING);
-   lde_send_labelwithdraw(ln, fn, NO_LABEL, &st);
+   lde_send_labelwithdraw(ln, fn, NULL, &st);
 
pw->flags &= ~F_PW_CWORD;
lde_send_labelmapping(ln, fn, 1);
@@ -305,7 +305,7 @@ l2vpn_pw_negotiate(struct lde_nbr *ln, struct fec_node *fn, 
struct map *map)
 }
 
 void
-l2vpn_send_pw_status(uint32_t peerid, uint32_t status, struct fec *fec)
+l2vpn_send_pw_status(struct lde_nbr *ln, uint32_t status, struct fec *fec)
 {
struct notify_msgnm;
 
@@ -316,8 +316,27 @@ l2vpn_send_pw_status(uint32_t peerid, uint32_t status, 
struct fec *fec)
lde_fec2map(fec, &nm.fec);
nm.flags |= F_NOTIF_FEC;
 
-   lde_imsg_compose_ldpe(IMSG_NOTIFICATION_SEND, peerid, 0,
-   &nm, sizeof(nm));
+   lde_imsg_compose_ldpe(IMSG_NOTIFICATION_SEND, ln->peerid, 0, &nm,
+   sizeof(nm));
+}
+
+void
+l2vpn_send_pw_status_wcard(struct lde_nbr *ln, uint32_t status,
+uint16_t pw_type, uint32_t group_id)
+{
+   struct notify_msgnm;
+
+   memset(&nm, 0, sizeof(nm));
+   nm.status_code = S_PW_STATUS;
+   nm.pw_status = status;
+   nm.flags |= F_NOTIF_PW_STATUS;
+   nm.fec.type = MAP_TYPE_PWID;
+   nm.fec.fec.pwid.type = pw_type;
+   nm.fec.fec.pwid.group_id = group_id;
+   nm.flags |= F_NOTIF_FEC;
+
+   lde_imsg_compose_ldpe(IMSG_NOTIFICATION_SEND, ln->peerid, 0, &nm,
+   sizeof(nm));
 }
 
 void
@@ -328,9 +347,10 @@ l2vpn_recv_pw_status(struct lde_nbr *ln, struct notify_msg 
*nm)
struct fec_nh   *fnh;
struct l2vpn_pw *pw;
 
-   /* TODO group wildcard */
-   if (!(nm->fec.flags & F_MAP_PW_ID))
+   if (!(nm->fec.flags & F_MAP_PW_ID)) {
+   l2vpn_recv_pw_status_wcard(ln, nm);
return;
+   }
 
lde_map2fec(&nm->fec, ln->id, &fec);
fn = (struct fec_node *)fec_find(&ft, &fec);
@@ -349,7 +369,6 @@ l2vpn_recv_pw_status(struct lde_nbr *ln, struct notify_msg 
*nm)
/* remote status didn't change */
if (pw->remote_status == nm->pw_status)
return;
-
pw->remote_status = nm->pw_status;
 
if (l2vpn_pw_ok(pw, fnh))
@@ -358,6 +377,44 @@ l2vpn_recv_pw_status(struct lde_nbr *ln, struct notify_msg 
*nm)
lde_send_delete_klabel(fn, fnh);
 }
 
+/* RFC4447 PWid group wildcard */
+void
+l2vpn_recv_pw_status_wcard(struct lde_nbr *ln, struct notify_msg *nm)
+{
+   struct fec  *f;
+   struct fec_node *fn;
+   struct fec_nh   *fnh;
+   struct l2vpn_pw *pw;
+
+   RB_FOREACH(f, fec_tree, &ft) {
+   fn = (struct fec_node *)f;
+   if (fn->fec.type != FEC_TYPE_PWID)
+   continue;
+   if (fn->fec.u.pwid.type != nm->fec.fec.pwid.type)
+   continue;
+
+   pw = (struct l2vpn_pw *) fn->data;
+   if (pw == NULL)
+   continue;
+   if (pw->remote_group != nm->fec.fec.pwid.group_id)
+   continue;
+
+   fnh = fec_nh_find(fn, AF_INET, (union ldpd_addr *)&ln->id, 0);
+   if (fnh == NULL)
+   continue;
+
+   /* remote status didn't change */
+   if (pw->remote_status == nm->pw_status)
+   continue;
+   pw->remote_status = nm->pw_status;
+
+   if (l2vpn_pw_ok(pw, fnh))
+   lde_send_change_klabel(fn, fnh);
+   else
+   lde_send_delete_klabel(fn, fnh);
+   }
+}
+
 void
 l2vpn_sync_pws(int af, union ldpd_addr *addr)
 {
diff --git a/lde.c b/lde.c
index 8e82523..fe44aa6 100644
--- a/lde.c
+++ b/lde.c
@@ -253,16 +253,10 @@ lde_dispatch_imsg(int fd, short event, void *bula)
 

[PATCH 2/7] ldpd: implement RFC 5561 (LDP Capabilities)

2017-02-20 Thread Renato Westphal
This patch per-se doesn't introduce any useful functionality, but prepares
the ground for new enhancements to ldpd (i.e. implementation of new RFCs
that make use of LDP capabilities).
---
 init.c | 152 +++--
 labelmapping.c |   8 +--
 ldp.h  |  18 +++
 ldpd.8 |  11 +
 ldpd.h |   6 +++
 ldpe.h |   5 ++
 logmsg.c   |   4 ++
 notification.c |  55 +++--
 packet.c   |  13 ++---
 9 files changed, 252 insertions(+), 20 deletions(-)

diff --git a/init.c b/init.c
index 2ba9b37..cc45443 100644
--- a/init.c
+++ b/init.c
@@ -25,6 +25,7 @@
 #include "log.h"
 
 static int gen_init_prms_tlv(struct ibuf *, struct nbr *);
+static int gen_cap_dynamic_tlv(struct ibuf *);
 
 void
 send_init(struct nbr *nbr)
@@ -35,15 +36,16 @@ send_init(struct nbr *nbr)
 
log_debug("%s: lsr-id %s", __func__, inet_ntoa(nbr->id));
 
-   size = LDP_HDR_SIZE + LDP_MSG_SIZE + SESS_PRMS_SIZE;
+   size = LDP_HDR_SIZE + LDP_MSG_SIZE + SESS_PRMS_SIZE +
+   CAP_TLV_DYNAMIC_SIZE;
if ((buf = ibuf_open(size)) == NULL)
fatal(__func__);
 
err |= gen_ldp_hdr(buf, size);
size -= LDP_HDR_SIZE;
err |= gen_msg_hdr(buf, MSG_TYPE_INIT, size);
-   size -= LDP_MSG_SIZE;
err |= gen_init_prms_tlv(buf, nbr);
+   err |= gen_cap_dynamic_tlv(buf);
if (err) {
ibuf_free(buf);
return;
@@ -58,6 +60,7 @@ recv_init(struct nbr *nbr, char *buf, uint16_t len)
struct ldp_msg  msg;
struct sess_prms_tlvsess;
uint16_tmax_pdu_len;
+   int caps_rcvd = 0;
 
log_debug("%s: lsr-id %s", __func__, inet_ntoa(nbr->id));
 
@@ -94,6 +97,7 @@ recv_init(struct nbr *nbr, char *buf, uint16_t len)
/* Optional Parameters */
while (len > 0) {
struct tlv  tlv;
+   uint16_ttlv_type;
uint16_ttlv_len;
 
if (len < sizeof(tlv)) {
@@ -102,6 +106,7 @@ recv_init(struct nbr *nbr, char *buf, uint16_t len)
}
 
memcpy(&tlv, buf, TLV_HDR_SIZE);
+   tlv_type = ntohs(tlv.type);
tlv_len = ntohs(tlv.length);
if (tlv_len + TLV_HDR_SIZE > len) {
session_shutdown(nbr, S_BAD_TLV_LEN, msg.id, msg.type);
@@ -110,17 +115,42 @@ recv_init(struct nbr *nbr, char *buf, uint16_t len)
buf += TLV_HDR_SIZE;
len -= TLV_HDR_SIZE;
 
-   switch (ntohs(tlv.type)) {
+   /*
+* RFC 5561 - Section 6:
+* "The S-bit of a Capability Parameter in an Initialization
+* message MUST be 1 and SHOULD be ignored on receipt".
+*/
+   switch (tlv_type) {
case TLV_TYPE_ATMSESSIONPAR:
session_shutdown(nbr, S_BAD_TLV_VAL, msg.id, msg.type);
return (-1);
case TLV_TYPE_FRSESSION:
session_shutdown(nbr, S_BAD_TLV_VAL, msg.id, msg.type);
return (-1);
+   case TLV_TYPE_DYNAMIC_CAP:
+   if (tlv_len != CAP_TLV_DYNAMIC_LEN) {
+   session_shutdown(nbr, S_BAD_TLV_LEN, msg.id,
+   msg.type);
+   return (-1);
+   }
+
+   if (caps_rcvd & F_CAP_TLV_RCVD_DYNAMIC) {
+   session_shutdown(nbr, S_BAD_TLV_VAL, msg.id,
+   msg.type);
+   return (-1);
+   }
+   caps_rcvd |= F_CAP_TLV_RCVD_DYNAMIC;
+
+   nbr->flags |= F_NBR_CAP_DYNAMIC;
+
+   log_debug("%s: lsr-id %s announced the Dynamic "
+   "Capability Announcement capability", __func__,
+   inet_ntoa(nbr->id));
+   break;
default:
if (!(ntohs(tlv.type) & UNKNOWN_FLAG))
-   send_notification(nbr->tcp, S_UNKNOWN_TLV,
-   msg.id, msg.type);
+   send_notification_rtlvs(nbr, S_UNSSUPORTDCAP,
+   msg.id, msg.type, tlv_type, tlv_len, buf);
/* ignore unknown tlv */
break;
}
@@ -146,6 +176,104 @@ recv_init(struct nbr *nbr, char *buf, uint16_t len)
return (0);
 }
 
+void
+send_capability(struct nbr *nbr, uint16_t capability, int enable)
+{
+   struct ibuf *buf;
+   uint16_t size;
+   int  err = 0;
+
+   log_debug("%s: lsr-id %s", __func__, inet_ntoa(nbr->id));
+
+   size

[PATCH 3/7] ldpd: implement RFC 5918 (Typed Wildcard FEC)

2017-02-20 Thread Renato Westphal
---
 init.c |  68 +++-
 labelmapping.c | 120 -
 lde.c  |  14 +++
 lde.h  |   3 ++
 lde_lib.c  |  56 +++
 ldp.h  |   8 
 ldpd.8 |   9 +
 ldpd.h |   6 +++
 ldpe.h |   1 +
 logmsg.c   |  17 
 10 files changed, 299 insertions(+), 3 deletions(-)

diff --git a/init.c b/init.c
index cc45443..2cc89b8 100644
--- a/init.c
+++ b/init.c
@@ -26,6 +26,7 @@
 
 static int gen_init_prms_tlv(struct ibuf *, struct nbr *);
 static int gen_cap_dynamic_tlv(struct ibuf *);
+static int gen_cap_twcard_tlv(struct ibuf *, int);
 
 void
 send_init(struct nbr *nbr)
@@ -37,7 +38,7 @@ send_init(struct nbr *nbr)
log_debug("%s: lsr-id %s", __func__, inet_ntoa(nbr->id));
 
size = LDP_HDR_SIZE + LDP_MSG_SIZE + SESS_PRMS_SIZE +
-   CAP_TLV_DYNAMIC_SIZE;
+   CAP_TLV_DYNAMIC_SIZE + CAP_TLV_TWCARD_SIZE;
if ((buf = ibuf_open(size)) == NULL)
fatal(__func__);
 
@@ -46,6 +47,7 @@ send_init(struct nbr *nbr)
err |= gen_msg_hdr(buf, MSG_TYPE_INIT, size);
err |= gen_init_prms_tlv(buf, nbr);
err |= gen_cap_dynamic_tlv(buf);
+   err |= gen_cap_twcard_tlv(buf, 1);
if (err) {
ibuf_free(buf);
return;
@@ -147,6 +149,25 @@ recv_init(struct nbr *nbr, char *buf, uint16_t len)
"Capability Announcement capability", __func__,
inet_ntoa(nbr->id));
break;
+   case TLV_TYPE_TWCARD_CAP:
+   if (tlv_len != CAP_TLV_TWCARD_LEN) {
+   session_shutdown(nbr, S_BAD_TLV_LEN, msg.id,
+   msg.type);
+   return (-1);
+   }
+
+   if (caps_rcvd & F_CAP_TLV_RCVD_TWCARD) {
+   session_shutdown(nbr, S_BAD_TLV_VAL, msg.id,
+   msg.type);
+   return (-1);
+   }
+   caps_rcvd |= F_CAP_TLV_RCVD_TWCARD;
+
+   nbr->flags |= F_NBR_CAP_TWCARD;
+
+   log_debug("%s: lsr-id %s announced the Typed Wildcard "
+   "FEC capability", __func__, inet_ntoa(nbr->id));
+   break;
default:
if (!(ntohs(tlv.type) & UNKNOWN_FLAG))
send_notification_rtlvs(nbr, S_UNSSUPORTDCAP,
@@ -194,6 +215,9 @@ send_capability(struct nbr *nbr, uint16_t capability, int 
enable)
err |= gen_msg_hdr(buf, MSG_TYPE_CAPABILITY, size);
 
switch (capability) {
+   case TLV_TYPE_TWCARD_CAP:
+   err |= gen_cap_twcard_tlv(buf, enable);
+   break;
case TLV_TYPE_DYNAMIC_CAP:
/*
 * RFC 5561 - Section 9:
@@ -219,6 +243,8 @@ int
 recv_capability(struct nbr *nbr, char *buf, uint16_t len)
 {
struct ldp_msg   msg;
+   int  enable = 0;
+   int  caps_rcvd = 0;
 
log_debug("%s: lsr-id %s", __func__, inet_ntoa(nbr->id));
 
@@ -231,6 +257,7 @@ recv_capability(struct nbr *nbr, char *buf, uint16_t len)
struct tlv   tlv;
uint16_t tlv_type;
uint16_t tlv_len;
+   uint8_t  reserved;
 
if (len < sizeof(tlv)) {
session_shutdown(nbr, S_BAD_TLV_LEN, msg.id, msg.type);
@@ -248,6 +275,31 @@ recv_capability(struct nbr *nbr, char *buf, uint16_t len)
len -= TLV_HDR_SIZE;
 
switch (tlv_type) {
+   case TLV_TYPE_TWCARD_CAP:
+   if (tlv_len != CAP_TLV_TWCARD_LEN) {
+   session_shutdown(nbr, S_BAD_TLV_LEN, msg.id,
+   msg.type);
+   return (-1);
+   }
+
+   if (caps_rcvd & F_CAP_TLV_RCVD_TWCARD) {
+   session_shutdown(nbr, S_BAD_TLV_VAL, msg.id,
+   msg.type);
+   return (-1);
+   }
+   caps_rcvd |= F_CAP_TLV_RCVD_TWCARD;
+
+   memcpy(&reserved, buf, sizeof(reserved));
+   enable = reserved & STATE_BIT;
+   if (enable)
+   nbr->flags |= F_NBR_CAP_TWCARD;
+   else
+   nbr->flags &= ~F_NBR_CAP_TWCARD;
+
+   log_debug("%s: lsr-id %s %s the Typed Wildcard FEC "
+   "capability", __func__, inet_ntoa(nbr->id),
+   (enable) ? "announced" : "withdrew");
+

[PATCH 4/7] ldpd: implement RFC 6667 (Typed Wildcard FEC for PWid)

2017-02-20 Thread Renato Westphal
---
 l2vpn.c| 22 +-
 labelmapping.c | 23 +++
 lde.c  | 14 ++
 lde.h  |  2 ++
 lde_lib.c  |  7 +++
 ldp.h  |  3 +++
 ldpd.8 |  9 +
 ldpd.h |  1 +
 logmsg.c   |  8 
 9 files changed, 84 insertions(+), 5 deletions(-)

diff --git a/l2vpn.c b/l2vpn.c
index e79caa8..6da3560 100644
--- a/l2vpn.c
+++ b/l2vpn.c
@@ -347,7 +347,8 @@ l2vpn_recv_pw_status(struct lde_nbr *ln, struct notify_msg 
*nm)
struct fec_nh   *fnh;
struct l2vpn_pw *pw;
 
-   if (!(nm->fec.flags & F_MAP_PW_ID)) {
+   if (nm->fec.type == MAP_TYPE_TYPED_WCARD ||
+   !(nm->fec.flags & F_MAP_PW_ID)) {
l2vpn_recv_pw_status_wcard(ln, nm);
return;
}
@@ -385,19 +386,30 @@ l2vpn_recv_pw_status_wcard(struct lde_nbr *ln, struct 
notify_msg *nm)
struct fec_node *fn;
struct fec_nh   *fnh;
struct l2vpn_pw *pw;
+   struct map  *wcard = &nm->fec;
 
RB_FOREACH(f, fec_tree, &ft) {
fn = (struct fec_node *)f;
if (fn->fec.type != FEC_TYPE_PWID)
continue;
-   if (fn->fec.u.pwid.type != nm->fec.fec.pwid.type)
-   continue;
 
pw = (struct l2vpn_pw *) fn->data;
if (pw == NULL)
continue;
-   if (pw->remote_group != nm->fec.fec.pwid.group_id)
-   continue;
+
+   switch (wcard->type) {
+   case MAP_TYPE_TYPED_WCARD:
+   if (wcard->fec.twcard.u.pw_type != PW_TYPE_WILDCARD &&
+   wcard->fec.twcard.u.pw_type != fn->fec.u.pwid.type)
+   continue;
+   break;
+   case MAP_TYPE_PWID:
+   if (wcard->fec.pwid.type != fn->fec.u.pwid.type)
+   continue;
+   if (wcard->fec.pwid.group_id != pw->remote_group)
+   continue;
+   break;
+   }
 
fnh = fec_nh_find(fn, AF_INET, (union ldpd_addr *)&ln->id, 0);
if (fnh == NULL)
diff --git a/labelmapping.c b/labelmapping.c
index b0e7131..64c5a70 100644
--- a/labelmapping.c
+++ b/labelmapping.c
@@ -97,6 +97,7 @@ send_labelmessage(struct nbr *nbr, uint16_t type, struct 
mapping_head *mh)
msg_size += FEC_ELM_TWCARD_MIN_LEN;
switch (me->map.fec.twcard.type) {
case MAP_TYPE_PREFIX:
+   case MAP_TYPE_PWID:
msg_size += sizeof(uint16_t);
break;
default:
@@ -629,6 +630,7 @@ gen_fec_tlv(struct ibuf *buf, struct map *map)
len = FEC_ELM_TWCARD_MIN_LEN;
switch (map->fec.twcard.type) {
case MAP_TYPE_PREFIX:
+   case MAP_TYPE_PWID:
len += sizeof(uint16_t);
break;
default:
@@ -658,6 +660,12 @@ gen_fec_tlv(struct ibuf *buf, struct map *map)
 
err |= ibuf_add(buf, &family, sizeof(uint16_t));
break;
+   case MAP_TYPE_PWID:
+   twcard_len = sizeof(uint16_t);
+   err |= ibuf_add(buf, &twcard_len, sizeof(uint8_t));
+   pw_type = htons(map->fec.twcard.u.pw_type);
+   err |= ibuf_add(buf, &pw_type, sizeof(uint16_t));
+   break;
default:
fatalx("gen_fec_tlv: unexpected fec type");
}
@@ -863,6 +871,21 @@ tlv_decode_fec_elm(struct nbr *nbr, struct ldp_msg *msg, 
char *buf,
return (-1);
}
break;
+   case MAP_TYPE_PWID:
+   if (twcard_len != sizeof(uint16_t)) {
+   session_shutdown(nbr, S_BAD_TLV_LEN, msg->id,
+   msg->type);
+   return (-1);
+   }
+
+   memcpy(&map->fec.twcard.u.pw_type, buf + off,
+   sizeof(uint16_t));
+   map->fec.twcard.u.pw_type =
+   ntohs(map->fec.twcard.u.pw_type);
+   /* ignore the reserved bit as per RFC 6667 */
+   map->fec.twcard.u.pw_type &= ~PW_TWCARD_RESERVED_BIT;
+   off += sizeof(uint16_t);
+   break;
default:
send_notification(nbr->tcp, S_UNKNOWN_FEC, msg->id,
msg->type);
diff --git a/lde.c b/lde.c
index cc8459d..c43801e 100644
--- a/lde.c
+++ b/l

[PATCH 7/7] ldpd: send VPLS MAC withdrawals

2017-02-20 Thread Renato Westphal
RFC 4762 says that MAC address withdrawal messages can be used to
improve convergence time in VPLS networks. This patch makes ldpd send
MAC withdrawals whenever a non-pseudowire interface pertaining to a VPLS
goes down.

The processing of received MAC withdrawals will be implemented later (need
to figure out first a few things about RFC 4762 that are a bit unclear).
---
 address.c | 77 +--
 kroute.c  |  3 +++
 l2vpn.c   | 29 +++-
 lde.h |  1 +
 ldp.h |  1 +
 ldpd.h|  6 -
 ldpe.c| 24 +++-
 ldpe.h|  1 +
 8 files changed, 127 insertions(+), 15 deletions(-)

diff --git a/address.c b/address.c
index e891173..9609876 100644
--- a/address.c
+++ b/address.c
@@ -28,12 +28,14 @@
 
 static void send_address(struct nbr *, int, struct if_addr_head *,
unsigned int, int);
-static int  gen_address_list_tlv(struct ibuf *, uint16_t, int,
-   struct if_addr_head *, unsigned int);
+static int  gen_address_list_tlv(struct ibuf *, int, struct if_addr_head *,
+   unsigned int);
+static int  gen_mac_list_tlv(struct ibuf *, uint8_t *);
 static void address_list_add(struct if_addr_head *, struct if_addr *);
 static void address_list_clr(struct if_addr_head *);
 static void log_msg_address(int, uint16_t, struct nbr *, int,
union ldpd_addr *);
+static void log_msg_mac_withdrawal(int, struct nbr *, uint8_t *);
 
 static void
 send_address(struct nbr *nbr, int af, struct if_addr_head *addr_list,
@@ -87,8 +89,7 @@ send_address(struct nbr *nbr, int af, struct if_addr_head 
*addr_list,
size -= LDP_HDR_SIZE;
err |= gen_msg_hdr(buf, msg_type, size);
size -= LDP_MSG_SIZE;
-   err |= gen_address_list_tlv(buf, size, af, addr_list,
-   tlv_addr_count);
+   err |= gen_address_list_tlv(buf, af, addr_list, tlv_addr_count);
if (err) {
address_list_clr(addr_list);
ibuf_free(buf);
@@ -139,6 +140,40 @@ send_address_all(struct nbr *nbr, int af)
send_address(nbr, af, &addr_list, addr_count, 0);
 }
 
+void
+send_mac_withdrawal(struct nbr *nbr, struct map *fec, uint8_t *mac)
+{
+   struct ibuf *buf;
+   uint16_t size;
+   int  err;
+
+   size = LDP_HDR_SIZE + LDP_MSG_SIZE + ADDR_LIST_SIZE + len_fec_tlv(fec) +
+   TLV_HDR_SIZE;
+   if (mac)
+   size += ETHER_ADDR_LEN;
+
+   if ((buf = ibuf_open(size)) == NULL)
+   fatal(__func__);
+
+   err = gen_ldp_hdr(buf, size);
+   size -= LDP_HDR_SIZE;
+   err |= gen_msg_hdr(buf, MSG_TYPE_ADDRWITHDRAW, size);
+   size -= LDP_MSG_SIZE;
+   err |= gen_address_list_tlv(buf, AF_INET, NULL, 0);
+   err |= gen_fec_tlv(buf, fec);
+   err |= gen_mac_list_tlv(buf, mac);
+   if (err) {
+   ibuf_free(buf);
+   return;
+   }
+
+   log_msg_mac_withdrawal(1, nbr, mac);
+
+   evbuf_enqueue(&nbr->tcp->wbuf, buf);
+
+   nbr_fsm(nbr, NBR_EVT_PDU_SENT);
+}
+
 int
 recv_address(struct nbr *nbr, char *buf, uint16_t len)
 {
@@ -280,8 +315,8 @@ recv_address(struct nbr *nbr, char *buf, uint16_t len)
 }
 
 static int
-gen_address_list_tlv(struct ibuf *buf, uint16_t size, int af,
-struct if_addr_head *addr_list, unsigned int tlv_addr_count)
+gen_address_list_tlv(struct ibuf *buf, int af, struct if_addr_head *addr_list,
+unsigned int tlv_addr_count)
 {
struct address_list_tlv  alt;
uint16_t addr_size;
@@ -290,7 +325,6 @@ gen_address_list_tlv(struct ibuf *buf, uint16_t size, int 
af,
 
memset(&alt, 0, sizeof(alt));
alt.type = htons(TLV_TYPE_ADDRLIST);
-   alt.length = htons(size - TLV_HDR_SIZE);
 
switch (af) {
case AF_INET:
@@ -304,8 +338,12 @@ gen_address_list_tlv(struct ibuf *buf, uint16_t size, int 
af,
default:
fatalx("gen_address_list_tlv: unknown af");
}
+   alt.length = htons(sizeof(alt.family) + addr_size * tlv_addr_count);
 
err |= ibuf_add(buf, &alt, sizeof(alt));
+   if (addr_list == NULL)
+   return (err);
+
LIST_FOREACH(if_addr, addr_list, entry) {
err |= ibuf_add(buf, &if_addr->addr, addr_size);
if (--tlv_addr_count == 0)
@@ -315,6 +353,23 @@ gen_address_list_tlv(struct ibuf *buf, uint16_t size, int 
af,
return (err);
 }
 
+static int
+gen_mac_list_tlv(struct ibuf *buf, uint8_t *mac)
+{
+   struct tlv   tlv;
+   int  err;
+
+   memset(&tlv, 0, sizeof(tlv));
+   tlv.type = htons(TLV_TYPE_MAC_LIST);
+   if (mac)
+   tlv.length = htons(ETHER_ADDR_LEN);
+   err = ibuf_add(buf, &tlv, sizeof(tlv));
+   if (mac)
+   err |= ibuf_add(buf, mac, ETHER_ADDR_LEN);
+
+  

[PATCH 6/7] ldpd: fix parsing of optional tlvs in address messages

2017-02-20 Thread Renato Westphal
We were aborting the session upon receipt of MAC Address Withdrawal
messages. Now make the parser aware that optional TLVs are possible in
address messages.
---
 address.c | 73 +++
 1 file changed, 59 insertions(+), 14 deletions(-)

diff --git a/address.c b/address.c
index 9b65511..e891173 100644
--- a/address.c
+++ b/address.c
@@ -144,11 +144,24 @@ recv_address(struct nbr *nbr, char *buf, uint16_t len)
 {
struct ldp_msg  msg;
uint16_tmsg_type;
-   struct address_list_tlv alt;
enum imsg_type  type;
+   struct address_list_tlv alt;
+   uint16_talt_len;
+   uint16_talt_family;
struct lde_addr lde_addr;
 
memcpy(&msg, buf, sizeof(msg));
+   msg_type = ntohs(msg.type);
+   switch (msg_type) {
+   case MSG_TYPE_ADDR:
+   type = IMSG_ADDRESS_ADD;
+   break;
+   case MSG_TYPE_ADDRWITHDRAW:
+   type = IMSG_ADDRESS_DEL;
+   break;
+   default:
+   fatalx("recv_address: unexpected msg type");
+   }
buf += LDP_MSG_SIZE;
len -= LDP_MSG_SIZE;
 
@@ -157,9 +170,10 @@ recv_address(struct nbr *nbr, char *buf, uint16_t len)
session_shutdown(nbr, S_BAD_MSG_LEN, msg.id, msg.type);
return (-1);
}
-
memcpy(&alt, buf, sizeof(alt));
-   if (ntohs(alt.length) != len - TLV_HDR_SIZE) {
+   alt_len = ntohs(alt.length);
+   alt_family = ntohs(alt.family);
+   if (alt_len > len - TLV_HDR_SIZE) {
session_shutdown(nbr, S_BAD_TLV_LEN, msg.id, msg.type);
return (-1);
}
@@ -167,7 +181,7 @@ recv_address(struct nbr *nbr, char *buf, uint16_t len)
send_notification(nbr->tcp, S_MISS_MSG, msg.id, msg.type);
return (-1);
}
-   switch (ntohs(alt.family)) {
+   switch (alt_family) {
case AF_IPV4:
if (!nbr->v4_enabled)
/* just ignore the message */
@@ -182,19 +196,15 @@ recv_address(struct nbr *nbr, char *buf, uint16_t len)
send_notification(nbr->tcp, S_UNSUP_ADDR, msg.id, msg.type);
return (-1);
}
+   alt_len -= sizeof(alt.family);
buf += sizeof(alt);
len -= sizeof(alt);
 
-   msg_type = ntohs(msg.type);
-   if (msg_type == MSG_TYPE_ADDR)
-   type = IMSG_ADDRESS_ADD;
-   else
-   type = IMSG_ADDRESS_DEL;
-
-   while (len > 0) {
-   switch (ntohs(alt.family)) {
+   /* Process all received addresses */
+   while (alt_len > 0) {
+   switch (alt_family) {
case AF_IPV4:
-   if (len < sizeof(struct in_addr)) {
+   if (alt_len < sizeof(struct in_addr)) {
session_shutdown(nbr, S_BAD_TLV_LEN, msg.id,
msg.type);
return (-1);
@@ -206,9 +216,10 @@ recv_address(struct nbr *nbr, char *buf, uint16_t len)
 
buf += sizeof(struct in_addr);
len -= sizeof(struct in_addr);
+   alt_len -= sizeof(struct in_addr);
break;
case AF_IPV6:
-   if (len < sizeof(struct in6_addr)) {
+   if (alt_len < sizeof(struct in6_addr)) {
session_shutdown(nbr, S_BAD_TLV_LEN, msg.id,
msg.type);
return (-1);
@@ -220,6 +231,7 @@ recv_address(struct nbr *nbr, char *buf, uint16_t len)
 
buf += sizeof(struct in6_addr);
len -= sizeof(struct in6_addr);
+   alt_len -= sizeof(struct in6_addr);
break;
default:
fatalx("recv_address: unknown af");
@@ -231,6 +243,39 @@ recv_address(struct nbr *nbr, char *buf, uint16_t len)
sizeof(lde_addr));
}
 
+   /* Optional Parameters */
+   while (len > 0) {
+   struct tlv  tlv;
+   uint16_ttlv_type;
+   uint16_ttlv_len;
+
+   if (len < sizeof(tlv)) {
+   session_shutdown(nbr, S_BAD_TLV_LEN, msg.id, msg.type);
+   return (-1);
+   }
+
+   memcpy(&tlv, buf, TLV_HDR_SIZE);
+   tlv_type = ntohs(tlv.type);
+   tlv_len = ntohs(tlv.length);
+   if (tlv_len + TLV_HDR_SIZE > len) {
+   session_shutdown(nbr, S_BAD_TLV_LEN, msg.id, msg.type);
+   return (-1);
+   }
+   buf += TLV_HDR_SIZE;
+   len -= TLV_HDR_SIZE;
+
+   switch (tlv_type) {
+   de

[PATCH 5/7] ldpd: implement RFC 5919 (LDP End-of-LIB)

2017-02-20 Thread Renato Westphal
---
 init.c | 67 +-
 labelmapping.c | 72 ++
 lde.c  | 40 
 lde.h  |  3 +++
 lde_lib.c  | 43 +++
 ldp.h  |  8 +++
 ldpd.8 | 10 
 ldpe.h |  2 ++
 logmsg.c   |  2 ++
 neighbor.c |  1 +
 notification.c | 40 ++--
 11 files changed, 245 insertions(+), 43 deletions(-)

diff --git a/init.c b/init.c
index 2cc89b8..b0dcc8e 100644
--- a/init.c
+++ b/init.c
@@ -27,6 +27,7 @@
 static int gen_init_prms_tlv(struct ibuf *, struct nbr *);
 static int gen_cap_dynamic_tlv(struct ibuf *);
 static int gen_cap_twcard_tlv(struct ibuf *, int);
+static int gen_cap_unotif_tlv(struct ibuf *, int);
 
 void
 send_init(struct nbr *nbr)
@@ -38,7 +39,7 @@ send_init(struct nbr *nbr)
log_debug("%s: lsr-id %s", __func__, inet_ntoa(nbr->id));
 
size = LDP_HDR_SIZE + LDP_MSG_SIZE + SESS_PRMS_SIZE +
-   CAP_TLV_DYNAMIC_SIZE + CAP_TLV_TWCARD_SIZE;
+   CAP_TLV_DYNAMIC_SIZE + CAP_TLV_TWCARD_SIZE + CAP_TLV_UNOTIF_SIZE;
if ((buf = ibuf_open(size)) == NULL)
fatal(__func__);
 
@@ -48,6 +49,7 @@ send_init(struct nbr *nbr)
err |= gen_init_prms_tlv(buf, nbr);
err |= gen_cap_dynamic_tlv(buf);
err |= gen_cap_twcard_tlv(buf, 1);
+   err |= gen_cap_unotif_tlv(buf, 1);
if (err) {
ibuf_free(buf);
return;
@@ -168,6 +170,26 @@ recv_init(struct nbr *nbr, char *buf, uint16_t len)
log_debug("%s: lsr-id %s announced the Typed Wildcard "
"FEC capability", __func__, inet_ntoa(nbr->id));
break;
+   case TLV_TYPE_UNOTIF_CAP:
+   if (tlv_len != CAP_TLV_UNOTIF_LEN) {
+   session_shutdown(nbr, S_BAD_TLV_LEN, msg.id,
+   msg.type);
+   return (-1);
+   }
+
+   if (caps_rcvd & F_CAP_TLV_RCVD_UNOTIF) {
+   session_shutdown(nbr, S_BAD_TLV_VAL, msg.id,
+   msg.type);
+   return (-1);
+   }
+   caps_rcvd |= F_CAP_TLV_RCVD_UNOTIF;
+
+   nbr->flags |= F_NBR_CAP_UNOTIF;
+
+   log_debug("%s: lsr-id %s announced the Unrecognized "
+   "Notification capability", __func__,
+   inet_ntoa(nbr->id));
+   break;
default:
if (!(ntohs(tlv.type) & UNKNOWN_FLAG))
send_notification_rtlvs(nbr, S_UNSSUPORTDCAP,
@@ -218,6 +240,9 @@ send_capability(struct nbr *nbr, uint16_t capability, int 
enable)
case TLV_TYPE_TWCARD_CAP:
err |= gen_cap_twcard_tlv(buf, enable);
break;
+   case TLV_TYPE_UNOTIF_CAP:
+   err |= gen_cap_unotif_tlv(buf, enable);
+   break;
case TLV_TYPE_DYNAMIC_CAP:
/*
 * RFC 5561 - Section 9:
@@ -300,6 +325,32 @@ recv_capability(struct nbr *nbr, char *buf, uint16_t len)
"capability", __func__, inet_ntoa(nbr->id),
(enable) ? "announced" : "withdrew");
break;
+   case TLV_TYPE_UNOTIF_CAP:
+   if (tlv_len != CAP_TLV_UNOTIF_LEN) {
+   session_shutdown(nbr, S_BAD_TLV_LEN, msg.id,
+   msg.type);
+   return (-1);
+   }
+
+   if (caps_rcvd & F_CAP_TLV_RCVD_UNOTIF) {
+   session_shutdown(nbr, S_BAD_TLV_VAL, msg.id,
+   msg.type);
+   return (-1);
+   }
+   caps_rcvd |= F_CAP_TLV_RCVD_UNOTIF;
+
+   memcpy(&reserved, buf, sizeof(reserved));
+   enable = reserved & STATE_BIT;
+   if (enable)
+   nbr->flags |= F_NBR_CAP_UNOTIF;
+   else
+   nbr->flags &= ~F_NBR_CAP_UNOTIF;
+
+   log_debug("%s: lsr-id %s %s the Unrecognized "
+   "Notification capability", __func__,
+   inet_ntoa(nbr->id), (enable) ? "announced" :
+   "withdrew");
+   break;
case TLV_TYPE_DYNAMIC_CAP:
/*
 * RFC 5561 - Section 9:
@@ -372,3 +423,17 @@ gen_cap_twcard_tlv(struct ibuf *buf, int enable)
 
return (ibuf

Re: connect(2) EPERM

2017-03-02 Thread Renato Westphal
2017-03-02 12:03 GMT-03:00 Sebastian Benoit :
>
> EPERM on connect(2) can happen in netinet/tcp_output.c on a socket with
> TF_SIGNATURE. As far as i can see its the only EPERM on tcp connect().
>
> how far down the stack do we go when documenting errors?
>
> ok?
>
> diff --git lib/libc/sys/connect.2 lib/libc/sys/connect.2
> index 9c0cfb09d79..6f18e09cddf 100644
> --- lib/libc/sys/connect.2
> +++ lib/libc/sys/connect.2
> @@ -196,6 +196,9 @@ Either the socket is non-blocking or a previous call to
>  .Fn connect
>  was interrupted by a signal, and the connection attempt has not yet
>  been completed.
> +.It Bq Er EPERM
> +A TCP connection on a socket with socket option TCP_MD5SIG was
> +attempted without configuring the security parameters correctly.
>  .El
>  .Pp
>  The following errors are specific to connecting names in the

OK renato@

-- 
Renato Westphal