Home | History | Annotate | Line # | Download | only in ldpd
mpls_routes.c revision 1.10
      1 /* $NetBSD: mpls_routes.c,v 1.10 2013/01/26 17:29:55 kefren Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 2010 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Mihai Chelaru <kefren (at) NetBSD.org>
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #include <sys/types.h>
     33 #include <sys/socket.h>
     34 #include <sys/param.h>
     35 #include <sys/sysctl.h>
     36 #include <net/if.h>
     37 #include <net/route.h>
     38 #include <netinet/in.h>
     39 #include <netmpls/mpls.h>
     40 
     41 #include <arpa/inet.h>
     42 
     43 #include <assert.h>
     44 #include <stdlib.h>
     45 #include <errno.h>
     46 #include <stdio.h>
     47 #include <string.h>
     48 #include <unistd.h>
     49 
     50 #include "ldp.h"
     51 #include "ldp_errors.h"
     52 #include "ldp_peer.h"
     53 #include "mpls_interface.h"
     54 #include "tlv_stack.h"
     55 #include "label.h"
     56 #include "mpls_routes.h"
     57 
     58 extern int      route_socket;
     59 int             rt_seq = 0;
     60 int		dont_catch = 0;
     61 extern int	no_default_route;
     62 extern int	debug_f, warn_f;
     63 
     64 struct rt_msg   replay_rt[REPLAY_MAX];
     65 int             replay_index = 0;
     66 
     67 static int read_route_socket(char *, int);
     68 void	mask_addr(union sockunion *);
     69 int	compare_sockunion(union sockunion *, union sockunion *);
     70 char *	mpls_ntoa(union mpls_shim);
     71 
     72 extern struct sockaddr mplssockaddr;
     73 
     74 /* Many lines inspired or shamelessly stolen from sbin/route/route.c */
     75 
     76 #define NEXTADDR(u) \
     77 	do { l = RT_ROUNDUP(u->sa.sa_len); memcpy(cp, u, l); cp += l; } while(0);
     78 #define NEXTADDR2(u) \
     79 	do { l = RT_ROUNDUP(u.sa_len); memcpy(cp, &u, l); cp += l; } while(0);
     80 #define GETNEXT(sunion) \
     81 	(union sockunion *) ((char *) (sunion)  + RT_ROUNDUP((sunion)->sa.sa_len))
     82 
     83 static int
     84 read_route_socket(char *s, int max)
     85 {
     86 	int             rv, to_read;
     87 	fd_set          fs;
     88 	struct timeval  tv;
     89 	struct rt_msghdr *rhdr;
     90 
     91 	tv.tv_sec = 0;
     92 	tv.tv_usec = 5000;
     93 
     94 	FD_ZERO(&fs);
     95 	FD_SET(route_socket, &fs);
     96 
     97 	errno = 0;
     98 
     99 	do {
    100 		rv = select(route_socket + 1, &fs, NULL, &fs, &tv);
    101 	} while ((rv == -1) && (errno == EINTR));
    102 
    103 	if (rv < 1) {
    104 		if (rv == 0) {
    105 			fatalp("read_route_socket: select timeout\n");
    106 		} else
    107 			fatalp("read_route_socket: select: %s",
    108 			    strerror(errno));
    109 		return 0;
    110 	}
    111 
    112 	do {
    113 		rv = recv(route_socket, s, max, MSG_PEEK);
    114 	} while((rv == -1) && (errno == EINTR));
    115 
    116 	if (rv < 1) {
    117 		debugp("read_route_socket: recv error\n");
    118 		return 0;
    119 	}
    120 	if (rv > max) {
    121 		rv = max;
    122 		debugp("read_route_socket: rv > max\n");
    123 	}
    124 
    125 	rhdr = (struct rt_msghdr *)s;
    126 	to_read = rhdr->rtm_msglen > max ? max : rhdr->rtm_msglen;
    127 	rv = 0;
    128 
    129 	do {
    130 		rv += recv(route_socket, s, to_read - rv, 0);
    131 	} while (rv != to_read);
    132 
    133 	return rv;
    134 }
    135 
    136 /* Recalculate length */
    137 void
    138 mask_addr(union sockunion * su)
    139 {
    140 /*
    141 	int             olen = su->sa.sa_len;
    142 	char           *cp1 = olen + (char *) su;
    143 
    144 	for (su->sa.sa_len = 0; cp1 > (char *) su;)
    145 		if (*--cp1 != 0) {
    146 			su->sa.sa_len = 1 + cp1 - (char *) su;
    147 			break;
    148 		}
    149 */
    150 /* Let's use INET only version for the moment */
    151 su->sa.sa_len = 4 + from_union_to_cidr(su) / 8 +
    152     ( from_union_to_cidr(su) % 8 ? 1 : 0 );
    153 }
    154 
    155 /* creates a sockunion from an IP address */
    156 union sockunion *
    157 make_inet_union(const char *s)
    158 {
    159 	union sockunion *so_inet;
    160 
    161 	so_inet = calloc(1, sizeof(*so_inet));
    162 
    163 	if (!so_inet) {
    164 		fatalp("make_inet_union: malloc problem\n");
    165 		return NULL;
    166 	}
    167 
    168 	so_inet->sin.sin_len = sizeof(struct sockaddr_in);
    169 	so_inet->sin.sin_family = AF_INET;
    170 	inet_aton(s, &so_inet->sin.sin_addr);
    171 
    172 	return so_inet;
    173 }
    174 
    175 /* creates a sockunion from a label */
    176 union sockunion *
    177 make_mpls_union(uint32_t label)
    178 {
    179 	union sockunion *so_mpls;
    180 
    181 	so_mpls = calloc(1, sizeof(*so_mpls));
    182 
    183 	if (!so_mpls) {
    184 		fatalp("make_mpls_union: malloc problem\n");
    185 		return NULL;
    186 	}
    187 
    188 	so_mpls->smpls.smpls_len = sizeof(struct sockaddr_mpls);
    189 	so_mpls->smpls.smpls_family = AF_MPLS;
    190 	so_mpls->smpls.smpls_addr.shim.label = label;
    191 
    192 	so_mpls->smpls.smpls_addr.s_addr =
    193 		htonl(so_mpls->smpls.smpls_addr.s_addr);
    194 
    195 	return so_mpls;
    196 }
    197 
    198 int
    199 compare_sockunion(union sockunion * __restrict a,
    200     union sockunion * __restrict b)
    201 {
    202 	if (a->sa.sa_len != b->sa.sa_len)
    203 		return 1;
    204 	return memcmp(a, b, a->sa.sa_len);
    205 }
    206 
    207 union sockunion *
    208 from_cidr_to_union(uint8_t prefixlen)
    209 {
    210 	union sockunion *u;
    211 	uint32_t m = 0xFFFFFFFF;
    212 
    213 	u = calloc(1, sizeof(*u));
    214 
    215 	if (!u) {
    216 		fatalp("from_cidr_to_union: malloc problem\n");
    217 		return NULL;
    218 	}
    219 	u->sin.sin_len = sizeof(struct sockaddr_in);
    220 	u->sin.sin_family = AF_INET;
    221 	if (prefixlen != 0) {
    222 		m = (m >> (32 - prefixlen) ) << (32 - prefixlen);
    223 		m = ntohl(m);
    224 		u->sin.sin_addr.s_addr = m;
    225 	}
    226 	return u;
    227 }
    228 
    229 uint8_t
    230 from_mask_to_cidr(char *mask)
    231 {
    232 	/* LoL (although I don't think about something faster right now) */
    233 	char            mtest[20];
    234 	uint8_t        i;
    235 
    236 	for (i = 1; i < 32; i++) {
    237 		from_cidr_to_mask(i, mtest);
    238 		if (!strcmp(mask, mtest))
    239 			break;
    240 	}
    241 	return i;
    242 }
    243 
    244 uint8_t
    245 from_union_to_cidr(union sockunion *so_pref)
    246 {
    247 	struct sockaddr_in *sin = (struct sockaddr_in*)so_pref;
    248 	uint32_t a;
    249 	uint8_t r;
    250 
    251 	a = ntohl(sin->sin_addr.s_addr);
    252 	for (r=0; a ; a = a << 1, r++);
    253 
    254 	return r;
    255 }
    256 
    257 /* returns in mask the netmask created from CIDR prefixlen */
    258 void
    259 from_cidr_to_mask(uint8_t prefixlen, char *mask)
    260 {
    261 	uint32_t       a = 0, p = prefixlen;
    262 	if (prefixlen > 32) {
    263 		strlcpy(mask, "255.255.255.255", 16);
    264 		return;
    265 	}
    266 	for (; p > 0; p--) {
    267 		a = a >> (p - 1);
    268 		a += 1;
    269 		a = a << (p - 1);
    270 	}
    271 	/* is this OK ? */
    272 #if _BYTE_ORDER == _LITTLE_ENDIAN
    273 	a = a << (32 - prefixlen);
    274 #endif
    275 
    276 	snprintf(mask, 16, "%d.%d.%d.%d", a >> 24, (a << 8) >> 24,
    277 	    (a << 16) >> 24, (a << 24) >> 24);
    278 }
    279 
    280 char *
    281 mpls_ntoa(union mpls_shim ms)
    282 {
    283 	static char     ret[255];
    284 	union mpls_shim ms2;
    285 
    286 	ms2.s_addr = ntohl(ms.s_addr);
    287 	snprintf(ret, sizeof(ret), "%d", ms2.shim.label);
    288 	return ret;
    289 }
    290 
    291 char           *
    292 union_ntoa(union sockunion * so)
    293 {
    294 	static char     defret[] = "Unknown family address";
    295 	switch (so->sa.sa_family) {
    296 	case AF_INET:
    297 		return inet_ntoa(so->sin.sin_addr);
    298 	case AF_LINK:
    299 		return link_ntoa(&so->sdl);
    300 	case AF_MPLS:
    301 		return mpls_ntoa(so->smpls.smpls_addr);
    302 	}
    303 	fatalp("Unknown family address in union_ntoa: %d\n",
    304 	       so->sa.sa_family);
    305 	return defret;
    306 }
    307 
    308 /* From src/sbin/route/route.c */
    309 static const char *
    310 route_strerror(int error)
    311 {
    312 
    313 	switch (error) {
    314 	case ESRCH:
    315 		return "not in table";
    316 	case EBUSY:
    317 		return "entry in use";
    318 	case ENOBUFS:
    319 		return "routing table overflow";
    320 	default:
    321 		return strerror(error);
    322 	}
    323 }
    324 
    325 
    326 /* Adds a route. Or changes it. */
    327 int
    328 add_route(union sockunion *so_dest, union sockunion *so_prefix,
    329     union sockunion *so_gate, union sockunion *so_ifa, union sockunion *so_tag,
    330     int fr, int optype)
    331 {
    332 	int             l, rlen, rv = LDP_E_OK;
    333 	struct rt_msg   rm;
    334 	char           *cp;
    335 
    336 	if(dont_catch)
    337 		return LDP_E_OK;
    338 
    339 	memset(&rm, 0, sizeof(rm));
    340 	cp = rm.m_space;
    341 
    342 	rm.m_rtm.rtm_type = (optype == RTM_READD) ? RTM_ADD : optype;
    343 	rm.m_rtm.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC;
    344 
    345 	rm.m_rtm.rtm_version = RTM_VERSION;
    346 	rm.m_rtm.rtm_seq = ++rt_seq;
    347 	rm.m_rtm.rtm_addrs = RTA_DST;
    348 	if (so_gate)
    349 		rm.m_rtm.rtm_addrs |= RTA_GATEWAY;
    350 
    351 	assert(so_dest);
    352 
    353 	/* Order is: destination, gateway, netmask, genmask, ifp, ifa, tag */
    354 	NEXTADDR(so_dest);
    355 	if (so_gate)
    356 		NEXTADDR(so_gate);
    357 
    358 	if (so_prefix) {
    359 		mask_addr(so_prefix);
    360 		NEXTADDR(so_prefix);
    361 		/* XXX: looks like nobody cares about this */
    362 		rm.m_rtm.rtm_flags |= RTF_MASK;
    363 		rm.m_rtm.rtm_addrs |= RTA_NETMASK;
    364 	} else
    365 		rm.m_rtm.rtm_flags |= RTF_HOST;
    366 
    367 	/* route to mpls interface */
    368 	if (optype != RTM_READD && so_dest->sa.sa_family != AF_MPLS) {
    369 		NEXTADDR2(mplssockaddr);
    370 		rm.m_rtm.rtm_addrs |= RTA_IFP;
    371 	}
    372 
    373 	if (so_ifa != NULL) {
    374 		NEXTADDR(so_ifa);
    375 		rm.m_rtm.rtm_addrs |= RTA_IFA;
    376 	}
    377 
    378 	if (so_tag) {
    379 		NEXTADDR(so_tag);
    380 		rm.m_rtm.rtm_addrs |= RTA_TAG;
    381 	}
    382 
    383 	rm.m_rtm.rtm_msglen = l = cp - (char *) &rm;
    384 
    385 	if ((rlen = write(route_socket, (char *) &rm, l)) < l) {
    386 		warnp("Error adding a route: %s\n", route_strerror(errno));
    387 		warnp("Destination was: %s\n", union_ntoa(so_dest));
    388 		if (so_prefix)
    389 			warnp("Prefix was: %s\n", union_ntoa(so_prefix));
    390 		if (so_gate)
    391 			warnp("Gateway was: %s\n", union_ntoa(so_gate));
    392 		rv = LDP_E_ROUTE_ERROR;
    393 	}
    394 	if (fr) {
    395 		free(so_dest);
    396 		if (so_prefix)
    397 			free(so_prefix);
    398 		if (so_gate)
    399 			free(so_gate);
    400 		if (so_ifa)
    401 			free(so_ifa);
    402 		if (so_tag)
    403 			free(so_tag);
    404 	}
    405 
    406 	return rv;
    407 }
    408 
    409 /* Deletes a route */
    410 int
    411 delete_route(union sockunion * so_dest, union sockunion * so_pref, int freeso)
    412 {
    413 	int             l, rlen;
    414 	struct rt_msg   rm;
    415 	char           *cp;
    416 
    417 	if(dont_catch)
    418 		return LDP_E_OK;
    419 
    420 	memset(&rm, 0, sizeof(struct rt_msg));
    421 	cp = rm.m_space;
    422 
    423 	rm.m_rtm.rtm_type = RTM_DELETE;
    424 	rm.m_rtm.rtm_version = RTM_VERSION;
    425 	rm.m_rtm.rtm_seq = ++rt_seq;
    426 	if (so_pref)
    427 		rm.m_rtm.rtm_addrs = RTA_DST | RTA_NETMASK;
    428 	else
    429 		rm.m_rtm.rtm_addrs = RTA_DST;
    430 
    431 	/* destination, gateway, netmask, genmask, ifp, ifa */
    432 
    433 	NEXTADDR(so_dest);
    434 
    435 	if (so_pref) {
    436 		mask_addr(so_pref);
    437 		NEXTADDR(so_pref);
    438 	}
    439 	rm.m_rtm.rtm_msglen = l = cp - (char *) &rm;
    440 
    441 	if (freeso == FREESO) {
    442 		free(so_dest);
    443 		if (so_pref)
    444 			free(so_pref);
    445 	}
    446 	if ((rlen = write(route_socket, (char *) &rm, l)) < l) {
    447 	    if(so_pref) {
    448 		char spreftmp[INET_ADDRSTRLEN];
    449 		strlcpy(spreftmp, inet_ntoa(so_pref->sin.sin_addr),
    450 		    INET_ADDRSTRLEN);
    451 		warnp("Error deleting route(%s): %s/%s",
    452 		    route_strerror(errno), union_ntoa(so_dest),
    453 		    spreftmp);
    454 	    } else
    455 		warnp("Error deleting route(%s) : %s",
    456 		    route_strerror(errno), union_ntoa(so_dest));
    457 	    return LDP_E_NO_SUCH_ROUTE;
    458 	}
    459 	return LDP_E_OK;
    460 }
    461 
    462 /*
    463  * Check for a route and returns it in rg
    464  * If exact_match is set it compares also the so_dest and so_pref
    465  * with the returned result
    466  */
    467 int
    468 get_route(struct rt_msg * rg, union sockunion * so_dest,
    469     union sockunion * so_pref, int exact_match)
    470 {
    471 	int             l, rlen, myseq;
    472 	struct rt_msg   rm;
    473 	char           *cp;
    474 	union sockunion *su;
    475 
    476 	memset(&rm, 0, sizeof(struct rt_msg));
    477 	cp = rm.m_space;
    478 
    479 	myseq = ++rt_seq;
    480 
    481 	rm.m_rtm.rtm_type = RTM_GET;
    482 	rm.m_rtm.rtm_version = RTM_VERSION;
    483 	rm.m_rtm.rtm_seq = myseq;
    484 
    485 	/*
    486 	 * rtm_addrs should contain what we provide into this message but
    487 	 * RTA_DST | RTA_IFP trick is allowed in order to find out the
    488 	 * interface.
    489 	 */
    490 
    491 	rm.m_rtm.rtm_addrs = RTA_DST | RTA_IFP;
    492 
    493 	/*
    494 	 * ORDER of fields is: destination, gateway, netmask, genmask, ifp,
    495 	 * ifa
    496 	 */
    497 
    498 	NEXTADDR(so_dest);
    499 	if (so_pref) {
    500 		rm.m_rtm.rtm_addrs |= RTA_NETMASK;
    501 		mask_addr(so_pref);
    502 		NEXTADDR(so_pref);
    503 	}
    504 	rm.m_rtm.rtm_msglen = l = cp - (char *) &rm;
    505 
    506 	if ((rlen = write(route_socket, (char *) &rm, l)) < l) {
    507 		debugp("Cannot get a route !(rlen=%d instead of %d) - %s\n",
    508 		    rlen, l, strerror(errno));
    509 		return LDP_E_NO_SUCH_ROUTE;
    510 	} else
    511 		for ( ; ; ) {
    512 			rlen = read_route_socket((char *) rg,
    513 			    sizeof(struct rt_msg));
    514 			if (rlen < 1)
    515 				break;
    516 			/*
    517 			 * We might lose important messages here. WORKAROUND:
    518 			 * For now I just try to save this messages and replay
    519 			 * them later
    520 			 */
    521 			if (rg->m_rtm.rtm_pid == getpid() &&
    522 			    rg->m_rtm.rtm_seq == myseq)
    523 				break;
    524 			debugp("Added to replay PID: %d, SEQ: %d\n",
    525 			    rg->m_rtm.rtm_pid, rg->m_rtm.rtm_seq);
    526 			memcpy(&replay_rt[replay_index], rg,
    527 			    sizeof(struct rt_msg));
    528 			if (replay_index < REPLAY_MAX - 1)
    529 				replay_index++;
    530 			else
    531 				fatalp("Replay index is full\n");
    532 		}
    533 
    534 	if (rlen <= (int)sizeof(struct rt_msghdr)) {
    535 		debugp("Got only %d bytes, expecting at least %zu\n", rlen,
    536 		    sizeof(struct rt_msghdr));
    537 		return LDP_E_ROUTE_ERROR;
    538 	}
    539 
    540 	/* Check if we don't have a less specific route */
    541 	if (exact_match) {
    542 		su = (union sockunion*)(rg->m_space);
    543 		if (compare_sockunion(so_dest, su)) {
    544 			debugp("Dest %s ", union_ntoa(so_dest));
    545 			debugp("not like %s\n", union_ntoa(su));
    546 			return LDP_E_NO_SUCH_ROUTE;
    547 		}
    548 	}
    549 
    550 	return LDP_E_OK;
    551 }
    552 
    553 
    554 /* triggered when a route event occurs */
    555 int
    556 check_route(struct rt_msg * rg, uint rlen)
    557 {
    558 	union sockunion *so_dest = NULL, *so_gate = NULL, *so_pref = NULL;
    559 	int             so_pref_allocated = 0;
    560 	int             prefixlen;
    561 	struct peer_map *pm;
    562 	struct label	*lab;
    563 	char            dest[50], gate[50], pref[50], oper[50];
    564 	dest[0] = 0;
    565 	gate[0] = 0;
    566 	pref[0] = 0;
    567 
    568 	if (rlen <= sizeof(struct rt_msghdr))
    569 		return LDP_E_ROUTE_ERROR;
    570 
    571 	if (rg->m_rtm.rtm_version != RTM_VERSION)
    572 		return LDP_E_ROUTE_ERROR;
    573 
    574 	if ((rg->m_rtm.rtm_flags & RTF_DONE) == 0)
    575 		return LDP_E_OK;
    576 
    577 	if (rg->m_rtm.rtm_pid == getpid())	/* We did it.. */
    578 		return LDP_E_OK;
    579 	else
    580 		debugp("Check route triggered by PID: %d\n", rg->m_rtm.rtm_pid);
    581 
    582 	so_dest = (union sockunion *) rg->m_space;
    583 
    584 	if (so_dest->sa.sa_family != AF_INET)
    585 		return LDP_E_OK;/* We don't care about non-IP changes */
    586 
    587 	if (rg->m_rtm.rtm_addrs & RTA_GATEWAY) {
    588 		so_gate = GETNEXT(so_dest);
    589 		if ((so_gate->sa.sa_family != AF_INET) &&
    590 		    (so_gate->sa.sa_family != AF_MPLS))
    591 			return LDP_E_OK;
    592 	}
    593 	if (rg->m_rtm.rtm_addrs & RTA_NETMASK) {
    594 		if (so_gate)
    595 			so_pref = so_gate;
    596 		else
    597 			so_pref = so_dest;
    598 		so_pref = GETNEXT(so_pref);
    599 	}
    600 	if (!(rg->m_rtm.rtm_flags & RTF_GATEWAY)) {
    601 		if (rg->m_rtm.rtm_addrs & RTA_GENMASK) {
    602 			debugp("Used GENMASK\n");
    603 		} else
    604 			debugp("No GENMASK to use\n");
    605 	}
    606 	/* Calculate prefixlen */
    607 	if (so_pref)
    608 		prefixlen = from_mask_to_cidr(inet_ntoa(so_pref->sin.sin_addr));
    609 	else {
    610 		prefixlen = 32;
    611 		if ((so_pref = from_cidr_to_union(32)) == NULL)
    612 			return LDP_E_MEMORY;
    613 		so_pref_allocated = 1;
    614 	}
    615 
    616 	so_pref->sa.sa_family = AF_INET;
    617 	so_pref->sa.sa_len = sizeof(struct sockaddr_in);
    618 
    619 	switch (rg->m_rtm.rtm_type) {
    620 	case RTM_CHANGE:
    621 		lab = label_get(so_dest, so_pref);
    622 		if (lab) {
    623 			send_withdraw_tlv_to_all(&so_dest->sa,
    624 			    prefixlen);
    625 			label_reattach_route(lab, LDP_READD_NODEL);
    626 			label_del(lab);
    627 		}
    628 	/* Fallthrough */
    629 	case RTM_ADD:
    630 		/*
    631 		 * Check if the route is connected. If so, bind it to
    632 		 * POP_LABEL and send announce. If not, check if the prefix
    633 		 * was announced by a LDP neighbour and route it there
    634 		 */
    635 
    636 		/* First of all check if we already know this one */
    637 		if (label_get(so_dest, so_pref) == NULL) {
    638 			if (!(rg->m_rtm.rtm_flags & RTF_GATEWAY))
    639 				label_add(so_dest, so_pref, NULL,
    640 					MPLS_LABEL_IMPLNULL, NULL, 0);
    641 			else {
    642 				pm = ldp_test_mapping(&so_dest->sa,
    643 					 prefixlen, &so_gate->sa);
    644 				if (pm) {
    645 					label_add(so_dest, so_pref,
    646 						so_gate, 0, NULL, 0);
    647 					mpls_add_label(pm->peer, rg,
    648 					  &so_dest->sa, prefixlen,
    649 					  pm->lm->label, ROUTE_LOOKUP_LOOP);
    650 					free(pm);
    651 				} else
    652 					label_add(so_dest, so_pref, so_gate,
    653 					    MPLS_LABEL_IMPLNULL, NULL, 0);
    654 			}
    655 		} else	/* We already know about this prefix */
    656 			debugp("Binding already there for prefix %s/%d !\n",
    657 			      union_ntoa(so_dest), prefixlen);
    658 		break;
    659 	case RTM_DELETE:
    660 		if (!so_gate)
    661 			break;	/* Non-existent route  XXX ?! */
    662 		/*
    663 		 * Send withdraw check the binding, delete the route, delete
    664 		 * the binding
    665 		 */
    666 		lab = label_get(so_dest, so_pref);
    667 		if (!lab)
    668 			break;
    669 		send_withdraw_tlv_to_all(&so_dest->sa, prefixlen);
    670 		/* No readd or delete IP route. Just delete the MPLS route */
    671 		label_reattach_route(lab, LDP_READD_NODEL);
    672 		label_del(lab);
    673 		break;
    674 	}
    675 
    676 	if (!debug_f && !warn_f) {
    677 		if(so_pref_allocated)
    678 			free(so_pref);
    679 		return LDP_E_OK;
    680 	}
    681 
    682 	/* Rest is just for debug */
    683 
    684 	if (so_dest)
    685 		strlcpy(dest, union_ntoa(so_dest), 16);
    686 	if (so_pref)
    687 		snprintf(pref, 3, "%d", prefixlen);
    688 	if (so_gate)
    689 		strlcpy(gate, union_ntoa(so_gate), 16);
    690 
    691 	switch (rg->m_rtm.rtm_type) {
    692 	case RTM_ADD:
    693 		strlcpy(oper, "added", 20);
    694 		break;
    695 	case RTM_DELETE:
    696 		strlcpy(oper, "delete", 20);
    697 		break;
    698 	case RTM_GET:
    699 		strlcpy(oper, "get", 20);
    700 		break;
    701 	case RTM_CHANGE:
    702 		strlcpy(oper, "change", 20);
    703 		break;
    704 	case RTM_LOSING:
    705 		strlcpy(oper, "losing", 20);
    706 		break;
    707 	case RTM_NEWADDR:
    708 		strlcpy(oper, "new address", 20);
    709 		break;
    710 	case RTM_DELADDR:
    711 		strlcpy(oper, "del address", 20);
    712 		break;
    713 	default:
    714 		snprintf(oper, 50, "unknown 0x%X operation",
    715 		    rg->m_rtm.rtm_type);
    716 	}
    717 
    718 	warnp("[check_route] Route %s: %s / %s -> %s by PID:%d\n", oper, dest,
    719 		pref, gate, rg->m_rtm.rtm_pid);
    720 
    721 	if(so_pref_allocated)
    722 		free(so_pref);
    723 	return LDP_E_OK;
    724 }
    725 
    726 int
    727 bind_current_routes()
    728 {
    729 	size_t          needed;
    730 	int             mib[6];
    731 	char           *buf, *next, *lim;
    732 	struct rt_msghdr *rtmes;
    733 	union sockunion *so_dst, *so_pref, *so_gate;
    734 
    735 	mib[0] = CTL_NET;
    736 	mib[1] = PF_ROUTE;
    737 	mib[2] = 0;
    738 	mib[3] = 0;
    739 	mib[4] = NET_RT_DUMP;
    740 	mib[5] = 0;
    741 	if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
    742 		fatalp("route-sysctl-estimate: %s",
    743 		    strerror(errno));
    744 		return LDP_E_ROUTE_ERROR;
    745 	}
    746 	if ((buf = malloc(needed)) == 0)
    747 		return LDP_E_ROUTE_ERROR;
    748 	if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
    749 		free(buf);
    750 		return LDP_E_ROUTE_ERROR;
    751 	}
    752 	lim = buf + needed;
    753 
    754 	for (next = buf; next < lim; next += rtmes->rtm_msglen) {
    755 		rtmes = (struct rt_msghdr *) next;
    756 		so_pref = NULL;
    757 		so_gate = NULL;
    758 		if (rtmes->rtm_flags & RTF_LLINFO)	/* No need for arps */
    759 			continue;
    760 		if (!(rtmes->rtm_addrs & RTA_DST)) {
    761 			debugp("No dst\n");
    762 			continue;
    763 		}
    764 
    765 		so_dst = (union sockunion *) & rtmes[1];
    766 
    767 		/*
    768 		 * This function is called only at startup, so use
    769 		 * this ocassion to delete all MPLS routes
    770 		 */
    771 		if (so_dst->sa.sa_family == AF_MPLS) {
    772 			delete_route(so_dst, NULL, NO_FREESO);
    773 			debugp("MPLS route deleted.\n");
    774 			continue;
    775 		}
    776 
    777 		if (so_dst->sa.sa_family != AF_INET) {
    778 			/*debugp("sa_dst is not AF_INET\n");*/
    779 			continue;
    780 		}
    781 
    782 		/* Check if it's the default gateway */
    783 		if (so_dst->sin.sin_addr.s_addr == 0 && no_default_route != 0)
    784 			continue;
    785 
    786 		/* XXX: Check if it's loopback */
    787 		if ((ntohl(so_dst->sin.sin_addr.s_addr) >> 24)==IN_LOOPBACKNET)
    788 			continue;
    789 
    790 		/* Get Gateway */
    791 		if (rtmes->rtm_addrs & RTA_GATEWAY)
    792 			so_gate = GETNEXT(so_dst);
    793 
    794 		/* Get prefix */
    795 		if (rtmes->rtm_flags & RTF_HOST) {
    796 			if ((so_pref = from_cidr_to_union(32)) == NULL)
    797 				return LDP_E_MEMORY;
    798 		} else if (rtmes->rtm_addrs & RTA_GATEWAY)
    799 			so_pref = GETNEXT(so_gate);
    800 		else
    801 			so_pref = GETNEXT(so_dst);
    802 
    803 		so_pref->sa.sa_family = AF_INET;
    804 		so_pref->sa.sa_len = sizeof(struct sockaddr_in);
    805 
    806 		/* Also deletes when dest is IPv4 and gateway MPLS */
    807 		if ((rtmes->rtm_addrs & RTA_GATEWAY) &&
    808 		    (so_gate->sa.sa_family == AF_MPLS)) {
    809 			debugp("MPLS route to %s deleted.\n",
    810 			    inet_ntoa(so_dst->sin.sin_addr));
    811 			delete_route(so_dst, so_pref, NO_FREESO);
    812 			if (rtmes->rtm_flags & RTF_HOST)
    813 				free(so_pref);
    814 			continue;
    815 		}
    816 		if (so_gate->sa.sa_family == AF_INET)
    817 			label_add(so_dst, so_pref, so_gate,
    818 			    MPLS_LABEL_IMPLNULL, NULL, 0);
    819 
    820 		if (rtmes->rtm_flags & RTF_HOST)
    821 			free(so_pref);
    822 	}
    823 	free(buf);
    824 	return LDP_E_OK;
    825 }
    826 
    827 int
    828 flush_mpls_routes()
    829 {
    830 	size_t          needed;
    831 	int             mib[6];
    832 	char           *buf, *next, *lim;
    833 	struct rt_msghdr *rtm;
    834 	union sockunion *so_dst, *so_pref, *so_gate;
    835 
    836 	mib[0] = CTL_NET;
    837 	mib[1] = PF_ROUTE;
    838 	mib[2] = 0;
    839 	mib[3] = 0;
    840 	mib[4] = NET_RT_DUMP;
    841 	mib[5] = 0;
    842 	if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
    843 		fatalp("route-sysctl-estimate: %s", strerror(errno));
    844 		return LDP_E_ROUTE_ERROR;
    845 	}
    846 	if ((buf = malloc(needed)) == NULL) {
    847 		fatalp("route-sysctl-estimate: %s", strerror(errno));
    848 		return LDP_E_MEMORY;
    849 	}
    850 	if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
    851 		free(buf);
    852 		return LDP_E_ROUTE_ERROR;
    853 	}
    854 	lim = buf + needed;
    855 
    856 	for (next = buf; next < lim; next += rtm->rtm_msglen) {
    857 		rtm = (struct rt_msghdr *) next;
    858 		so_pref = NULL;
    859 		so_gate = NULL;
    860 		if (rtm->rtm_flags & RTF_LLINFO)	/* No need for arps */
    861 			continue;
    862 		if (!(rtm->rtm_addrs & RTA_DST)) {
    863 			debugp("No dst\n");
    864 			continue;
    865 		}
    866 		so_dst = (union sockunion *) & rtm[1];
    867 
    868 		if (so_dst->sa.sa_family == AF_MPLS) {
    869 			delete_route(so_dst, NULL, NO_FREESO);
    870 			debugp("MPLS route deleted.\n");
    871 			continue;
    872 		}
    873 
    874 		if (rtm->rtm_addrs & RTA_GATEWAY) {
    875 			so_gate = GETNEXT(so_dst);
    876 			so_pref = GETNEXT(so_gate);
    877 		} else
    878 			so_pref = GETNEXT(so_dst);
    879 
    880 		if (so_gate->sa.sa_family == AF_MPLS) {
    881 			if (so_dst->sa.sa_family == AF_INET)
    882 				debugp("MPLS route to %s deleted.\n",
    883 				    inet_ntoa(so_dst->sin.sin_addr));
    884 			delete_route(so_dst, so_pref, NO_FREESO);
    885 			continue;
    886 		}
    887 
    888 	}
    889 	free(buf);
    890 	return LDP_E_OK;
    891 }
    892