Module Name:    src
Committed By:   kefren
Date:           Thu Jul 18 06:07:45 UTC 2013

Modified Files:
        src/usr.sbin/ldpd: label.c label.h ldp_command.c ldp_command.h
            ldp_peer.c mpls_interface.c mpls_interface.h mpls_routes.c
            socketops.c tlv_stack.c

Log Message:
Make sure labels are always updated when a route is added and when a peer
is added
Rework mpls_add_label according to that so no route refresh is done anymore
Use poll when reading the PF_ROUTE socket
setsockopt SO_USELOOPBACK on the PF_ROUTE socket
Output some information on SIGINFO
Allow map changing for a ldp peer
Finally fix the connected routes admission into labels
Correct the route trigger when a label map is received


To generate a diff of this commit:
cvs rdiff -u -r1.7 -r1.8 src/usr.sbin/ldpd/label.c
cvs rdiff -u -r1.4 -r1.5 src/usr.sbin/ldpd/label.h
cvs rdiff -u -r1.11 -r1.12 src/usr.sbin/ldpd/ldp_command.c
cvs rdiff -u -r1.2 -r1.3 src/usr.sbin/ldpd/ldp_command.h
cvs rdiff -u -r1.13 -r1.14 src/usr.sbin/ldpd/ldp_peer.c
cvs rdiff -u -r1.9 -r1.10 src/usr.sbin/ldpd/mpls_interface.c \
    src/usr.sbin/ldpd/tlv_stack.c
cvs rdiff -u -r1.3 -r1.4 src/usr.sbin/ldpd/mpls_interface.h
cvs rdiff -u -r1.16 -r1.17 src/usr.sbin/ldpd/mpls_routes.c
cvs rdiff -u -r1.28 -r1.29 src/usr.sbin/ldpd/socketops.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/usr.sbin/ldpd/label.c
diff -u src/usr.sbin/ldpd/label.c:1.7 src/usr.sbin/ldpd/label.c:1.8
--- src/usr.sbin/ldpd/label.c:1.7	Tue Jul 16 02:54:32 2013
+++ src/usr.sbin/ldpd/label.c	Thu Jul 18 06:07:45 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: label.c,v 1.7 2013/07/16 02:54:32 kefren Exp $ */
+/* $NetBSD: label.c,v 1.8 2013/07/18 06:07:45 kefren Exp $ */
 
 /*-
  * Copyright (c) 2010 The NetBSD Foundation, Inc.
@@ -70,12 +70,13 @@ label_add(const union sockunion * so_des
 	assert(so_dest);
 	assert(so_pref);
 	assert(so_dest->sa.sa_family == so_pref->sa.sa_family);
+	assert(label_get(so_dest, so_pref) == NULL);
 
-	memcpy(&l->so_dest, so_dest, sizeof(union sockunion));
-	memcpy(&l->so_pref, so_pref, sizeof(union sockunion));
+	memcpy(&l->so_dest, so_dest, so_dest->sa.sa_len);
+	memcpy(&l->so_pref, so_pref, so_pref->sa.sa_len);
 
 	if (so_gate)
-		memcpy(&l->so_gate, so_gate, sizeof(union sockunion));
+		memcpy(&l->so_gate, so_gate, so_gate->sa.sa_len);
 	if (binding)
 		l->binding = binding;
 	else
@@ -130,8 +131,8 @@ label_reattach_route(struct label *l, in
 	/* Delete and re-add IPv4 route */
 		if (get_route(&rg, &l->so_dest, &l->so_pref, 1) == LDP_E_OK) {
 			delete_route(&l->so_dest, &l->so_pref, NO_FREESO);
-			add_route(&l->so_dest, &l->so_pref, &l->so_gate, NULL, NULL,
-			    NO_FREESO, RTM_READD);
+			add_route(&l->so_dest, &l->so_pref, &l->so_gate, NULL,
+			    NULL, NO_FREESO, RTM_READD);
 		} else if (from_union_to_cidr(&l->so_pref) == 32 &&
 		    l->so_dest.sa.sa_family == AF_INET &&
 		    get_route(&rg, &l->so_dest, NULL, 1) == LDP_E_OK) {
@@ -225,15 +226,15 @@ label_del_by_binding(uint32_t binding, i
 struct label*
 label_get_by_prefix(const struct sockaddr *a, int prefixlen)
 {
-	union sockunion *so_dest, *so_pref;
+	const union sockunion *so_dest;
+	union sockunion *so_pref;
 	struct label *l;
 
-	so_dest = make_inet_union(satos(a));	// XXX: grobian
+	so_dest = (const union sockunion *)a;
 	so_pref = from_cidr_to_union(prefixlen);
 
 	l = label_get(so_dest, so_pref);
 
-	free(so_dest);
 	free(so_pref);
 
 	return l;
@@ -271,3 +272,20 @@ change_local_label(struct label *l, uint
 		from_union_to_cidr(&(l->so_pref)),
 		l->binding);
 }
+
+void
+label_check_assoc(struct ldp_peer *p)
+{
+	struct label *l;
+	struct ldp_peer_address *wp;
+
+	SLIST_FOREACH (l, &label_head, labels)
+		if (l->p == NULL && l->so_gate.sa.sa_family != 0)
+			SLIST_FOREACH(wp, &p->ldp_peer_address_head, addresses)
+				if (sockaddr_cmp(&l->so_gate.sa,
+				    &wp->address.sa) == 0){
+					l->p = p;
+					l->label = MPLS_LABEL_IMPLNULL;
+					break;
+				}
+}

Index: src/usr.sbin/ldpd/label.h
diff -u src/usr.sbin/ldpd/label.h:1.4 src/usr.sbin/ldpd/label.h:1.5
--- src/usr.sbin/ldpd/label.h:1.4	Thu Jul 11 10:46:19 2013
+++ src/usr.sbin/ldpd/label.h	Thu Jul 18 06:07:45 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: label.h,v 1.4 2013/07/11 10:46:19 kefren Exp $ */
+/* $NetBSD: label.h,v 1.5 2013/07/18 06:07:45 kefren Exp $ */
 
 /*-
  * Copyright (c) 2010 The NetBSD Foundation, Inc.
@@ -69,5 +69,6 @@ struct label *	label_get_by_prefix(const
 uint32_t	get_free_local_label(void);
 void		change_local_label(struct label*, uint32_t);
 void		label_reattach_route(struct label*, int);
+void		label_check_assoc(struct ldp_peer *p);
 
 #endif /* !_LABEL_H_ */

Index: src/usr.sbin/ldpd/ldp_command.c
diff -u src/usr.sbin/ldpd/ldp_command.c:1.11 src/usr.sbin/ldpd/ldp_command.c:1.12
--- src/usr.sbin/ldpd/ldp_command.c:1.11	Tue Jul 16 02:54:32 2013
+++ src/usr.sbin/ldpd/ldp_command.c	Thu Jul 18 06:07:45 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: ldp_command.c,v 1.11 2013/07/16 02:54:32 kefren Exp $ */
+/* $NetBSD: ldp_command.c,v 1.12 2013/07/18 06:07:45 kefren Exp $ */
 
 /*-
  * Copyright (c) 2010 The NetBSD Foundation, Inc.
@@ -74,11 +74,8 @@ static int set_func(int, char *);
 static int exit_func(int, char *);
  
 /* Show functions */
-static int show_neighbours(int, char *);
-static int show_bindings(int, char *);
 static int show_debug(int, char *);
 static int show_hellos(int, char *);
-static int show_labels(int, char *);
 static int show_parameters(int, char *);
 static int show_version(int, char *);
 static int show_warning(int, char *);
@@ -402,7 +399,7 @@ exit_func(int s, char *recvspace)
 /*
  * Show functions
  */
-static int
+int
 show_neighbours(int s, char *recvspace)
 {
 	struct ldp_peer *p;
@@ -480,7 +477,7 @@ show_neighbours(int s, char *recvspace)
 }
 
 /* Shows labels grabbed from unsolicited label maps */
-static int
+int
 show_labels(int s, char *recvspace)
 {
 	struct ldp_peer *p;
@@ -504,7 +501,7 @@ show_labels(int s, char *recvspace)
 	return 1;
 }
 
-static int
+int
 show_bindings(int s, char *recvspace)
 {
 	struct label *l;

Index: src/usr.sbin/ldpd/ldp_command.h
diff -u src/usr.sbin/ldpd/ldp_command.h:1.2 src/usr.sbin/ldpd/ldp_command.h:1.3
--- src/usr.sbin/ldpd/ldp_command.h:1.2	Thu Jun 16 08:27:28 2011
+++ src/usr.sbin/ldpd/ldp_command.h	Thu Jul 18 06:07:45 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: ldp_command.h,v 1.2 2011/06/16 08:27:28 kefren Exp $ */
+/* $NetBSD: ldp_command.h,v 1.3 2013/07/18 06:07:45 kefren Exp $ */
 
 /*-
  * Copyright (c) 2010 The NetBSD Foundation, Inc.
@@ -53,4 +53,9 @@ int	add_command_socket(int);
 void	command_dispatch(struct com_sock *);
 void	command_close(int);
 
+/* Used by SIGINFO handler */
+int show_bindings(int, char *);
+int show_labels(int, char *);
+int show_neighbours(int, char *);
+
 #endif	/* !_LDP_COMMAND_H_ */

Index: src/usr.sbin/ldpd/ldp_peer.c
diff -u src/usr.sbin/ldpd/ldp_peer.c:1.13 src/usr.sbin/ldpd/ldp_peer.c:1.14
--- src/usr.sbin/ldpd/ldp_peer.c:1.13	Thu Jul 11 05:55:13 2013
+++ src/usr.sbin/ldpd/ldp_peer.c	Thu Jul 18 06:07:45 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: ldp_peer.c,v 1.13 2013/07/11 05:55:13 kefren Exp $ */
+/* $NetBSD: ldp_peer.c,v 1.14 2013/07/18 06:07:45 kefren Exp $ */
 
 /*
  * Copyright (c) 2010 The NetBSD Foundation, Inc.
@@ -428,8 +428,11 @@ ldp_peer_add_mapping(struct ldp_peer * p
 
 	if (!p)
 		return -1;
-	if (ldp_peer_get_lm(p, a, prefix))
-		return LDP_E_ALREADY_DONE;
+	if ((lma = ldp_peer_get_lm(p, a, prefix)) != NULL) {
+		/* Change the current label */
+		lma->label = label;
+		return LDP_E_OK;
+	}
 
 	lma = malloc(sizeof(*lma));
 

Index: src/usr.sbin/ldpd/mpls_interface.c
diff -u src/usr.sbin/ldpd/mpls_interface.c:1.9 src/usr.sbin/ldpd/mpls_interface.c:1.10
--- src/usr.sbin/ldpd/mpls_interface.c:1.9	Thu Jul 11 05:45:23 2013
+++ src/usr.sbin/ldpd/mpls_interface.c	Thu Jul 18 06:07:45 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: mpls_interface.c,v 1.9 2013/07/11 05:45:23 kefren Exp $ */
+/* $NetBSD: mpls_interface.c,v 1.10 2013/07/18 06:07:45 kefren Exp $ */
 
 /*-
  * Copyright (c) 2010 The NetBSD Foundation, Inc.
@@ -53,104 +53,43 @@
 extern int no_default_route;
 
 int
-mpls_add_label(const struct ldp_peer * p, struct rt_msg * inh_rg,
-    struct sockaddr * addr, int len, int label, int rlookup)
+mpls_add_label(struct label *lab)
 {
-	char            padd[20];
-	int             kount = 0, rv;
-	union sockunion *so_dest, *so_pref = NULL, *so_gate, *so_nexthop,
-		*so_tag, *so_oldifa = NULL, *so_ifa;
-	struct rt_msg   rg;
-	struct rt_msg	*rgp = &rg;
-	struct label	*lab;
-
-	strlcpy(padd, satos(p->address), 20);
-	debugp("Trying to add %s/%d as label %d to peer %s\n", satos(addr),
-		len, label, padd);
+	char            p_str[20];
+	union sockunion *so_dest, *so_nexthop, *so_tag, so_ifa;
+	uint8_t prefixlen;
+	uint32_t oldbinding;
+
+	assert(lab != NULL);
+
+	oldbinding = lab->binding;
+	prefixlen = from_union_to_cidr(&lab->so_pref);
+
+	strlcpy(p_str, satos(lab->p->address), sizeof(p_str));
+	warnp("Trying to add %s/%d as label %d (oldlocal %d) to peer %s\n",
+	    satos(&lab->so_dest.sa), prefixlen, lab->label, lab->binding,p_str);
 
 	/* Check if we should accept default route */
-	if (!len && no_default_route != 0)
+	if (prefixlen == 0 && no_default_route != 0)
 		return LDP_E_BAD_AF;
 
-	/* Is there a label mapping for this ? */
-	if (ldp_peer_get_lm(p, addr, len) == NULL)
+	/* double check if there is a label mapping for this */
+	if (ldp_peer_get_lm(lab->p, &lab->so_dest.sa, prefixlen) == NULL)
 		return LDP_E_NOENT;
 
-	if (!inh_rg || (inh_rg->m_rtm.rtm_addrs & RTA_IFA) == 0) {
-		/*
-		 * XXX: Check if we have a route for that.
-		 * Why the hell isn't kernel inserting the route immediatly ?
-		 * let's loop until we have it..
-		 */
-
-		if ((so_dest = make_inet_union(satos(addr))) == NULL) // XXX
-			return LDP_E_MEMORY;
-		if (len != 32 && (so_pref = from_cidr_to_union(len)) == NULL) {
-			free(so_dest);
-			return LDP_E_MEMORY;
-		}
-		do {
-			if (kount == rlookup) {
-				debugp("No route for this prefix\n");
-				return LDP_E_NO_SUCH_ROUTE;
-			}
-			if (kount > 0)
-				debugp("Route test hit: %d\n", kount);
-			kount++;
-			/* Last time give it a higher chance */
-			if (kount == rlookup)
-				usleep(5000);
-
-			rv = get_route(rgp, so_dest, so_pref, 1);
-			if (rv != LDP_E_OK && len == 32)
-				/* Host maybe ? */
-				rv = get_route(rgp, so_dest, NULL, 1);
-		} while (rv != LDP_E_OK);
-
-		free(so_dest);
-		if (so_pref)
-			free(so_pref);
-
-	} else
-		rgp = inh_rg;
-
-	/* Check if it's an IPv4 route */
-
-	so_gate = (union sockunion *) rgp->m_space;
-	so_gate = (union sockunion *)((char*)so_gate +
-	    RT_ROUNDUP(so_gate->sa.sa_len));
-	if (rgp->m_rtm.rtm_addrs & RTA_IFA) {
-		int li = 1;
-		so_oldifa = so_gate;
-		if (rgp->m_rtm.rtm_addrs & RTA_NETMASK)
-			li++;
-		if (rgp->m_rtm.rtm_addrs & RTA_GENMASK)
-			li++;
-		if (rgp->m_rtm.rtm_addrs & RTA_IFP)
-			li++;
-		for (int i = 0; i < li; i++)
-			so_oldifa = (union sockunion *)((char*)so_oldifa +
-			    RT_ROUNDUP(so_oldifa->sa.sa_len));
-	}
-
-	if (so_gate->sa.sa_family != AF_INET &&
-	    so_gate->sa.sa_family != AF_INET6) {
-		debugp("mpls_add_label: so_gate is not IP or IPv6\n");
+	if (lab->so_gate.sa.sa_family != AF_INET &&
+	    lab->so_gate.sa.sa_family != AF_INET6) {
+		warnp("mpls_add_label: so_gate is not IP or IPv6\n");
 		return LDP_E_BAD_AF;
 	}
 
 	/* Check if the address is bounded to the peer */
-	if (check_ifaddr(p, &so_gate->sa) == NULL) {
-		debugp("Failed at next-hop check\n");
+	if (check_ifaddr(lab->p, &lab->so_gate.sa) == NULL) {
+		warnp("Failed at next-hop check\n");
 		return LDP_E_ROUTE_ERROR;
 	}
 
-	/* Verify if we have a binding for this prefix */
-	lab = label_get_by_prefix(addr, len);
-
-	/* And we should have one because we have a route for it */
-	assert (lab);
-
+	/* if binding is implicit null we need to generate a new one */
 	if (lab->binding == MPLS_LABEL_IMPLNULL) {
 		change_local_label(lab, get_free_local_label());
 		if (!lab->binding) {
@@ -159,63 +98,46 @@ mpls_add_label(const struct ldp_peer * p
 		}
 	}
 
-	warnp("[mpls_add_label] Adding %s/%d as local binding %d, label %d"
-	    " to peer %s\n",
-		satos(addr), len, lab->binding, label, padd);
-
-	/* Modify existing label */
-	lab->label = label;
-	lab->p = p;
+	warnp("[mpls_add_label] Adding %s/%d as local binding %d (%d), label %d"
+	    " to peer %s\n", satos(&lab->so_dest.sa), prefixlen, lab->binding,
+	    oldbinding, lab->label, p_str);
 
 	/* Add switching route */
-	so_dest = make_mpls_union(lab->binding);
-	so_nexthop = malloc(sizeof(*so_nexthop));
-	if (!so_nexthop) {
+	if ((so_dest = make_mpls_union(lab->binding)) == NULL)
+		return LDP_E_MEMORY;
+	if ((so_tag = make_mpls_union(lab->label)) == NULL) {
 		free(so_dest);
 		fatalp("Out of memory\n");
 		return LDP_E_MEMORY;
 	}
-	memcpy(so_nexthop, so_gate, so_gate->sa.sa_len);
-	if ((so_tag = make_mpls_union(label)) == NULL) {
+	if ((so_nexthop = malloc(lab->so_gate.sa.sa_len)) == NULL) {
 		free(so_dest);
-		free(so_nexthop);
+		free(so_tag);
 		fatalp("Out of memory\n");
 		return LDP_E_MEMORY;
 	}
-	if (add_route(so_dest, NULL, so_nexthop, NULL, so_tag,
-	    FREESO, RTM_ADD) != LDP_E_OK)
+	memcpy(so_nexthop, &lab->so_gate, lab->so_gate.sa.sa_len);
+
+	if (add_route(so_dest, NULL, so_nexthop, NULL, so_tag, FREESO,
+	    oldbinding == MPLS_LABEL_IMPLNULL ? RTM_ADD : RTM_CHANGE)
+	    != LDP_E_OK) {
+		fatalp("[mpls_add_label] MPLS route error\n");
 		return LDP_E_ROUTE_ERROR;
+	}
 
 	/* Now, let's add tag to IP route and point it to mpls interface */
-	if ((so_dest = make_inet_union(satos(addr))) == NULL) {	// XXX: grobian
-		fatalp("Out of memory\n");
-		return LDP_E_MEMORY;
-	}
 
-	/*
-	* if prefixlen == 32 check if it's inserted as host
- 	* and treat it as host. It may also be set as /32 prefix
- 	* (thanks mlelstv for heads-up about this)
- 	*/
-	if ((len == 32) && (rgp->m_rtm.rtm_flags & RTF_HOST))
-		so_pref = NULL;
-	else if ((so_pref = from_cidr_to_union(len)) == NULL) {
-		free(so_dest);
-		fatalp("Out of memory\n");
-		return LDP_E_MEMORY;
-	}
+	if (getsockname(lab->p->socket, &so_ifa.sa,
+	    & (socklen_t) { sizeof(union sockunion) } )) {
+		fatalp("[mpls_add_label]: getsockname\n");
+                return LDP_E_ROUTE_ERROR;
+        }
 
-	/* Add tag to route */
-	so_nexthop = malloc(sizeof(*so_nexthop));
-	if (!so_nexthop) {
-		free(so_dest);
-		if (so_pref != NULL)
-			free(so_pref);
+	if ((so_tag = make_mpls_union(lab->label)) == NULL) {
 		fatalp("Out of memory\n");
 		return LDP_E_MEMORY;
 	}
-	memcpy(so_nexthop, so_gate, so_gate->sa.sa_len);
-	so_tag = make_mpls_union(label);
+/*
 	if (so_oldifa != NULL) {
 		so_ifa = malloc(sizeof(*so_ifa));
 		if (so_ifa == NULL) {
@@ -230,12 +152,16 @@ mpls_add_label(const struct ldp_peer * p
 		memcpy(so_ifa, so_oldifa, so_oldifa->sa.sa_len);
 	} else
 		so_ifa = NULL;
-	if (add_route(so_dest, so_pref, so_nexthop, so_ifa, so_tag,
-	    FREESO, RTM_CHANGE) != LDP_E_OK)
+*/
+	if (add_route(&lab->so_dest, &lab->so_pref, &lab->so_gate, &so_ifa,
+	    so_tag, NO_FREESO, RTM_CHANGE) != LDP_E_OK) {
+		free(so_tag);
+		fatalp("[mpls_add_label]: INET route failure\n");
 		return LDP_E_ROUTE_ERROR;
+	}
+	free(so_tag);
 
-	debugp("Added %s/%d as label %d to peer %s\n", satos(addr), len,
-	    label, padd);
+	warnp("[mpls_add_label]: SUCCESS\n");
 
 	return LDP_E_OK;
 }
Index: src/usr.sbin/ldpd/tlv_stack.c
diff -u src/usr.sbin/ldpd/tlv_stack.c:1.9 src/usr.sbin/ldpd/tlv_stack.c:1.10
--- src/usr.sbin/ldpd/tlv_stack.c:1.9	Tue Jul 16 19:40:01 2013
+++ src/usr.sbin/ldpd/tlv_stack.c	Thu Jul 18 06:07:45 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: tlv_stack.c,v 1.9 2013/07/16 19:40:01 kefren Exp $ */
+/* $NetBSD: tlv_stack.c,v 1.10 2013/07/18 06:07:45 kefren Exp $ */
 
 /*-
  * Copyright (c) 2010 The NetBSD Foundation, Inc.
@@ -63,6 +63,7 @@ map_label(struct ldp_peer * p, struct fe
 	int n;
 	struct prefix_tlv *pref;
 	union sockunion socktmp;
+	struct label *lbl_check;
 
 	if (ntohs(f->type) != TLV_FEC) {
 		debugp("Invalid FEC TLV !\n");
@@ -118,17 +119,24 @@ map_label(struct ldp_peer * p, struct fe
 			else
 				memcpy(&socktmp.sin6.sin6_addr, &pref->prefix,
 				    ldp_ceil8(pref->prelen));
-			debugp("Prefix/Host add: %s/%d\n", satos(&socktmp.sa),
+			warnp("Prefix/Host add from %s: %s/%d\n",
+			    inet_ntoa(p->ldp_id), satos(&socktmp.sa),
 			    pref->prelen);
 
 			ldp_peer_add_mapping(p, &socktmp.sa, pref->prelen,
 			    ntohl(l->label));
 
 			/* Try to change RIB only if label is installed */
-			if (label_get_by_prefix(&socktmp.sa, pref->prelen)
-			    != NULL)
-				mpls_add_label(p, NULL, &socktmp.sa,
-				    pref->prelen, ntohl(l->label), 1);
+			lbl_check = label_get_by_prefix(&socktmp.sa,
+			    pref->prelen);
+			if (lbl_check != NULL && lbl_check->p == p) {
+				lbl_check->label = ntohl(l->label);
+				mpls_add_label(lbl_check);
+			} else
+				warnp("[map_label] lbl check failed: %s\n",
+				    lbl_check == NULL ? "(null)" :
+				    lbl_check->p == NULL ? "(null peer)" :
+				    inet_ntoa(lbl_check->p->ldp_id));
 			break;
 		    case FEC_WILDCARD:
 			fatalp("LDP: Wildcard add from peer %s\n",
@@ -238,6 +246,9 @@ send_label_tlv(const struct ldp_peer * p
 	struct prefix_tlv *p;
 	struct label_tlv *l;
 
+	debugp("SENDING LABEL TLV %s TO %s\n", satos(addr),
+	    inet_ntoa(peer->ldp_id));
+
 	/*
 	 * Ok, so we have label map tlv that contains fec tlvs and label tlv
 	 * but fec tlv contains prefix or host tlvs and prefix or host tlvs
@@ -245,7 +256,7 @@ send_label_tlv(const struct ldp_peer * p
 	 * Got it ?
 	 */
 
-	lmt = malloc(
+	lmt = calloc(1,
 		sizeof(struct label_map_tlv) +
 		sizeof(struct fec_tlv) +
 		sizeof(struct prefix_tlv) - sizeof(struct in_addr) +
@@ -255,7 +266,7 @@ send_label_tlv(const struct ldp_peer * p
 	 	(lrt != NULL ? sizeof(struct label_request_tlv) : 0) );
 
 	if (!lmt) {
-		fatalp("send_label_tlv: malloc problem\n");
+		fatalp("send_label_tlv: calloc problem\n");
 		return;
 	}
 
@@ -271,8 +282,7 @@ send_label_tlv(const struct ldp_peer * p
 	/* FEC TLV */
 	fec = (struct fec_tlv *) & lmt[1];
 	fec->type = htons(TLV_FEC);
-	fec->length = htons(sizeof(struct fec_tlv) - TLV_TYPE_LENGTH
-	    + sizeof(struct prefix_tlv) - sizeof(struct in_addr) +
+	fec->length = htons(sizeof(struct prefix_tlv) - sizeof(struct in_addr) +
 		ldp_ceil8(prefixlen));
 
 	/* Now let's do the even a dirtier job: PREFIX TLV */

Index: src/usr.sbin/ldpd/mpls_interface.h
diff -u src/usr.sbin/ldpd/mpls_interface.h:1.3 src/usr.sbin/ldpd/mpls_interface.h:1.4
--- src/usr.sbin/ldpd/mpls_interface.h:1.3	Thu Jul 11 05:45:23 2013
+++ src/usr.sbin/ldpd/mpls_interface.h	Thu Jul 18 06:07:45 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: mpls_interface.h,v 1.3 2013/07/11 05:45:23 kefren Exp $ */
+/* $NetBSD: mpls_interface.h,v 1.4 2013/07/18 06:07:45 kefren Exp $ */
 
 /*-
  * Copyright (c) 2010 The NetBSD Foundation, Inc.
@@ -32,10 +32,10 @@
 #ifndef _MPLS_INTERFACE_H_
 #define _MPLS_INTERFACE_H_
 
+#include "label.h"
 #include "mpls_routes.h"
 
-int             mpls_add_label(const struct ldp_peer *, struct rt_msg *,
-				struct sockaddr *, int, int, int);
+int             mpls_add_label(struct label *);
 int             mpls_add_ldp_peer(const struct ldp_peer *);
 int             mpls_delete_ldp_peer(const struct ldp_peer *);
 int             mpls_start_ldp(void);

Index: src/usr.sbin/ldpd/mpls_routes.c
diff -u src/usr.sbin/ldpd/mpls_routes.c:1.16 src/usr.sbin/ldpd/mpls_routes.c:1.17
--- src/usr.sbin/ldpd/mpls_routes.c:1.16	Tue Jul 16 16:55:01 2013
+++ src/usr.sbin/ldpd/mpls_routes.c	Thu Jul 18 06:07:45 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: mpls_routes.c,v 1.16 2013/07/16 16:55:01 kefren Exp $ */
+/* $NetBSD: mpls_routes.c,v 1.17 2013/07/18 06:07:45 kefren Exp $ */
 
 /*-
  * Copyright (c) 2010 The NetBSD Foundation, Inc.
@@ -43,6 +43,7 @@
 #include <assert.h>
 #include <stdlib.h>
 #include <errno.h>
+#include <poll.h>
 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>
@@ -57,7 +58,7 @@
 #include "socketops.h"
 
 extern int      route_socket;
-int             rt_seq = 0;
+int             rt_seq = 200;
 int		dont_catch = 0;
 extern int	no_default_route;
 extern int	debug_f, warn_f;
@@ -102,34 +103,31 @@ static int 
 read_route_socket(char *s, int max)
 {
 	int             rv, to_read;
-	fd_set          fs;
-	struct timeval  tv;
 	struct rt_msghdr *rhdr;
+	struct pollfd pfd;
 
-	tv.tv_sec = 0;
-	tv.tv_usec = 5000;
-
-	FD_ZERO(&fs);
-	FD_SET(route_socket, &fs);
+	pfd.fd = route_socket;
+	pfd.events = POLLRDNORM;
+	pfd.revents = 0;
 
 	errno = 0;
 
 	do {
-		rv = select(route_socket + 1, &fs, NULL, &fs, &tv);
-	} while ((rv == -1) && (errno == EINTR));
+		rv = poll(&pfd, 1, 100);
+	} while (rv == -1 && errno == EINTR);
 
 	if (rv < 1) {
 		if (rv == 0) {
-			fatalp("read_route_socket: select timeout\n");
+			fatalp("read_route_socket: poll timeout\n");
 		} else
-			fatalp("read_route_socket: select: %s",
+			fatalp("read_route_socket: poll: %s",
 			    strerror(errno));
 		return 0;
 	}
 
 	do {
 		rv = recv(route_socket, s, max, MSG_PEEK);
-	} while((rv == -1) && (errno == EINTR));
+	} while(rv == -1 && errno == EINTR);
 
 	if (rv < 1) {
 		debugp("read_route_socket: recv error\n");
@@ -507,7 +505,13 @@ get_route(struct rt_msg * rg, const unio
 	}
 	rm.m_rtm.rtm_msglen = l = cp - (char *) &rm;
 
-	if ((rlen = write(route_socket, (char *) &rm, l)) < l) {
+	setsockopt(route_socket, SOL_SOCKET, SO_USELOOPBACK, &(int){1},
+	    sizeof(int));
+	rlen = write(route_socket, (char *) &rm, l);
+	setsockopt(route_socket, SOL_SOCKET, SO_USELOOPBACK, &(int){0},
+	    sizeof(int));
+
+	if (rlen < l) {
 		debugp("Cannot get a route !(rlen=%d instead of %d) - %s\n",
 		    rlen, l, strerror(errno));
 		return LDP_E_NO_SUCH_ROUTE;
@@ -525,7 +529,14 @@ get_route(struct rt_msg * rg, const unio
 			if (rg->m_rtm.rtm_pid == getpid() &&
 			    rg->m_rtm.rtm_seq == myseq)
 				break;
-			debugp("Added to replay PID: %d, SEQ: %d\n",
+			/* Fast skip */
+			if (rg->m_rtm.rtm_type != RTM_ADD &&
+			    rg->m_rtm.rtm_type != RTM_DELETE &&
+			    rg->m_rtm.rtm_type != RTM_CHANGE &&
+			    rg->m_rtm.rtm_type != RTM_NEWADDR &&
+			    rg->m_rtm.rtm_type != RTM_DELADDR)
+				continue;
+			warnp("Added to replay PID: %d, SEQ: %d\n",
 			    rg->m_rtm.rtm_pid, rg->m_rtm.rtm_seq);
 			memcpy(&replay_rt[replay_index], rg,
 			    sizeof(struct rt_msg));
@@ -599,21 +610,14 @@ check_route(struct rt_msg * rg, uint rle
 			return LDP_E_OK;
 	}
 	if (rg->m_rtm.rtm_addrs & RTA_NETMASK) {
-		if (so_gate)
-			so_pref = so_gate;
-		else
-			so_pref = so_dest;
-		GETNEXT(so_pref, so_pref);
-	}
-	if (!(rg->m_rtm.rtm_flags & RTF_GATEWAY)) {
-		if (rg->m_rtm.rtm_addrs & RTA_GENMASK) {
-			debugp("Used GENMASK\n");
+		if (so_gate != NULL) {
+			GETNEXT(so_pref, so_gate);
 		} else
-			debugp("No GENMASK to use\n");
+			GETNEXT(so_pref, so_dest);
 	}
 	/* Calculate prefixlen */
 	if (so_pref)
-		prefixlen = from_mask_to_cidr(inet_ntoa(so_pref->sin.sin_addr));
+		prefixlen = from_union_to_cidr(so_pref);
 	else {
 		prefixlen = 32;
 		if ((so_pref = from_cidr_to_union(32)) == NULL)
@@ -643,25 +647,25 @@ check_route(struct rt_msg * rg, uint rle
 
 		/* First of all check if we already know this one */
 		if (label_get(so_dest, so_pref) == NULL) {
-			if (!(rg->m_rtm.rtm_flags & RTF_GATEWAY))
+			/* Just add an IMPLNULL label */
+			if (so_gate == NULL)
 				label_add(so_dest, so_pref, NULL,
 					MPLS_LABEL_IMPLNULL, NULL, 0);
 			else {
 				pm = ldp_test_mapping(&so_dest->sa,
 					 prefixlen, &so_gate->sa);
 				if (pm) {
-					label_add(so_dest, so_pref,
-						so_gate, 0, NULL, 0);
-					mpls_add_label(pm->peer, rg,
-					  &so_dest->sa, prefixlen,
-					  pm->lm->label, ROUTE_LOOKUP_LOOP);
+					lab = label_add(so_dest, so_pref,
+					   so_gate, 0, pm->peer, pm->lm->label);
+					if (lab != NULL)
+						mpls_add_label(lab);
 					free(pm);
 				} else
 					label_add(so_dest, so_pref, so_gate,
 					    MPLS_LABEL_IMPLNULL, NULL, 0);
 			}
 		} else	/* We already know about this prefix */
-			debugp("Binding already there for prefix %s/%d !\n",
+			fatalp("Binding already there for prefix %s/%d !\n",
 			      satos(&so_dest->sa), prefixlen);
 		break;
 	case RTM_DELETE:
@@ -818,8 +822,7 @@ bind_current_routes()
 		rtmes = (struct rt_msghdr *) next;
 		rlen = rtmes->rtm_msglen;
 		size_cp = sizeof(struct rt_msghdr);
-		so_pref = NULL;
-		so_gate = NULL;
+		so_gate = so_pref = NULL;
 		if (rtmes->rtm_flags & RTF_LLINFO)	/* No need for arps */
 			continue;
 		if (!(rtmes->rtm_addrs & RTA_DST)) {
@@ -830,6 +833,7 @@ bind_current_routes()
 		CHECK_MINSA;
 		so_dst = (union sockunion *) & rtmes[1];
 		CHECK_LEN(so_dst);
+
 		/*
 		 * This function is called only at startup, so use
 		 * this ocassion to delete all MPLS routes
@@ -879,6 +883,10 @@ bind_current_routes()
 				free(so_pref);
 			continue;
 		}
+
+		if (so_gate != NULL && so_gate->sa.sa_family == AF_LINK)
+			so_gate = NULL;	/* connected route */
+
 		if (so_gate == NULL || so_gate->sa.sa_family == AF_INET)
 			label_add(so_dst, so_pref, so_gate,
 			    MPLS_LABEL_IMPLNULL, NULL, 0);

Index: src/usr.sbin/ldpd/socketops.c
diff -u src/usr.sbin/ldpd/socketops.c:1.28 src/usr.sbin/ldpd/socketops.c:1.29
--- src/usr.sbin/ldpd/socketops.c:1.28	Thu Jul 11 05:45:23 2013
+++ src/usr.sbin/ldpd/socketops.c	Thu Jul 18 06:07:45 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: socketops.c,v 1.28 2013/07/11 05:45:23 kefren Exp $ */
+/* $NetBSD: socketops.c,v 1.29 2013/07/18 06:07:45 kefren Exp $ */
 
 /*
  * Copyright (c) 2010 The NetBSD Foundation, Inc.
@@ -80,6 +80,7 @@ bool	may_connect;
 void	recv_pdu(int);
 void	send_hello_alarm(int);
 __dead static void bail_out(int);
+static void print_info(int);
 static int bind_socket(int s, int stype);
 static int set_tos(int); 
 static int socket_reuse_port(int);
@@ -774,6 +775,19 @@ bail_out(int x)
 	exit(0);
 }
 
+static void
+print_info(int x)
+{
+	printf("Info for %s\n-------\n", LDP_ID);
+	printf("Neighbours:\n");
+	show_neighbours(1, NULL);
+	printf("Bindings:\n");
+	show_bindings(1, NULL);
+	printf("Labels:\n");
+	show_labels(1, NULL);
+	printf("--------\n");
+}
+
 /*
  * The big poll that catches every single event
  * on every socket.
@@ -798,12 +812,15 @@ the_big_loop(void)
 	signal(SIGPIPE, SIG_IGN);
 	signal(SIGINT, bail_out);
 	signal(SIGTERM, bail_out);
+	signal(SIGINFO, print_info);
 
 	/* Send first hellos in 5 seconds. Avoid No hello notifications */
 	may_connect = false;
 	alarm(5);
 
 	route_socket = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC);
+	setsockopt(route_socket, SOL_SOCKET, SO_USELOOPBACK, &(int){0},
+		sizeof(int));
 
 	sock_error = bind_current_routes();
 	if (sock_error != LDP_E_OK) {
@@ -996,7 +1013,7 @@ new_peer_connection()
 		}
 	}
 	if (peer_ldp_id == NULL) {
-		fatalp("Got connection from %s, but no hello info exists\n",
+		warnp("Got connection from %s, but no hello info exists\n",
 		    satos(&peer_address.sa));
 		close(s);
 		return;
@@ -1036,10 +1053,12 @@ keep_alive(const struct ldp_peer * p)
 	kt.messageid = htonl(get_message_id());
 
 	send_tlv(p, (struct tlv *) (void *) &kt);
-
 }
 
-void 
+/*
+ * Process a message received from a peer
+ */
+void
 recv_session_pdu(struct ldp_peer * p)
 {
 	struct ldp_pdu *rpdu;
@@ -1181,6 +1200,11 @@ recv_session_pdu(struct ldp_peer * p)
 			atlv = (struct address_tlv *) ttmp;
 			altlv = (struct al_tlv *) (&atlv[1]);
 			add_ifaddresses(p, altlv);
+			/*
+			 * try to see if we have labels with null peer that
+			 * would match the new peer
+			 */
+			label_check_assoc(p);
 			print_bounded_addresses(p);
 			break;
 		case LDP_ADDRESS_WITHDRAW:

Reply via email to