xref: /netbsd/usr.sbin/ldpd/mpls_routes.c (revision d920bea6)
1 /* $NetBSD: mpls_routes.c,v 1.11 2013/07/11 09:11:35 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@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 	struct in_addr addr;
233 	uint8_t plen = 0;
234 
235 	if (inet_aton(mask, &addr) != 0)
236 		for (; addr.s_addr; plen++)
237 			addr.s_addr &= addr.s_addr - 1;
238 	return plen;
239 }
240 
241 uint8_t
242 from_union_to_cidr(union sockunion *so_pref)
243 {
244 	struct sockaddr_in *sin = (struct sockaddr_in*)so_pref;
245 	uint32_t a;
246 	uint8_t r;
247 
248 	a = ntohl(sin->sin_addr.s_addr);
249 	for (r=0; a ; a = a << 1, r++);
250 
251 	return r;
252 }
253 
254 /* returns in mask the netmask created from CIDR prefixlen */
255 void
256 from_cidr_to_mask(uint8_t prefixlen, char *mask)
257 {
258 	uint32_t a = 0;
259 	uint8_t plen = prefixlen < 32 ? prefixlen : 32;
260 
261 	if (plen != 0)
262 		a = (0xffffffff >> (32 - plen)) << (32 - plen);
263 	snprintf(mask, 16, "%d.%d.%d.%d", a >> 24, (a << 8) >> 24,
264 	    (a << 16) >> 24, (a << 24) >> 24);
265 }
266 
267 char *
268 mpls_ntoa(union mpls_shim ms)
269 {
270 	static char     ret[255];
271 	union mpls_shim ms2;
272 
273 	ms2.s_addr = ntohl(ms.s_addr);
274 	snprintf(ret, sizeof(ret), "%d", ms2.shim.label);
275 	return ret;
276 }
277 
278 char           *
279 union_ntoa(union sockunion * so)
280 {
281 	static char     defret[] = "Unknown family address";
282 	switch (so->sa.sa_family) {
283 	case AF_INET:
284 		return inet_ntoa(so->sin.sin_addr);
285 	case AF_LINK:
286 		return link_ntoa(&so->sdl);
287 	case AF_MPLS:
288 		return mpls_ntoa(so->smpls.smpls_addr);
289 	}
290 	fatalp("Unknown family address in union_ntoa: %d\n",
291 	       so->sa.sa_family);
292 	return defret;
293 }
294 
295 /* From src/sbin/route/route.c */
296 static const char *
297 route_strerror(int error)
298 {
299 
300 	switch (error) {
301 	case ESRCH:
302 		return "not in table";
303 	case EBUSY:
304 		return "entry in use";
305 	case ENOBUFS:
306 		return "routing table overflow";
307 	default:
308 		return strerror(error);
309 	}
310 }
311 
312 
313 /* Adds a route. Or changes it. */
314 int
315 add_route(union sockunion *so_dest, union sockunion *so_prefix,
316     union sockunion *so_gate, union sockunion *so_ifa, union sockunion *so_tag,
317     int fr, int optype)
318 {
319 	int             l, rlen, rv = LDP_E_OK;
320 	struct rt_msg   rm;
321 	char           *cp;
322 
323 	if(dont_catch)
324 		return LDP_E_OK;
325 
326 	memset(&rm, 0, sizeof(rm));
327 	cp = rm.m_space;
328 
329 	rm.m_rtm.rtm_type = (optype == RTM_READD) ? RTM_ADD : optype;
330 	rm.m_rtm.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC;
331 
332 	rm.m_rtm.rtm_version = RTM_VERSION;
333 	rm.m_rtm.rtm_seq = ++rt_seq;
334 	rm.m_rtm.rtm_addrs = RTA_DST;
335 	if (so_gate)
336 		rm.m_rtm.rtm_addrs |= RTA_GATEWAY;
337 
338 	assert(so_dest);
339 
340 	/* Order is: destination, gateway, netmask, genmask, ifp, ifa, tag */
341 	NEXTADDR(so_dest);
342 	if (so_gate)
343 		NEXTADDR(so_gate);
344 
345 	if (so_prefix) {
346 		mask_addr(so_prefix);
347 		NEXTADDR(so_prefix);
348 		/* XXX: looks like nobody cares about this */
349 		rm.m_rtm.rtm_flags |= RTF_MASK;
350 		rm.m_rtm.rtm_addrs |= RTA_NETMASK;
351 	} else
352 		rm.m_rtm.rtm_flags |= RTF_HOST;
353 
354 	/* route to mpls interface */
355 	if (optype != RTM_READD && so_dest->sa.sa_family != AF_MPLS) {
356 		NEXTADDR2(mplssockaddr);
357 		rm.m_rtm.rtm_addrs |= RTA_IFP;
358 	}
359 
360 	if (so_ifa != NULL) {
361 		NEXTADDR(so_ifa);
362 		rm.m_rtm.rtm_addrs |= RTA_IFA;
363 	}
364 
365 	if (so_tag) {
366 		NEXTADDR(so_tag);
367 		rm.m_rtm.rtm_addrs |= RTA_TAG;
368 	}
369 
370 	rm.m_rtm.rtm_msglen = l = cp - (char *) &rm;
371 
372 	if ((rlen = write(route_socket, (char *) &rm, l)) < l) {
373 		warnp("Error adding a route: %s\n", route_strerror(errno));
374 		warnp("Destination was: %s\n", union_ntoa(so_dest));
375 		if (so_prefix)
376 			warnp("Prefix was: %s\n", union_ntoa(so_prefix));
377 		if (so_gate)
378 			warnp("Gateway was: %s\n", union_ntoa(so_gate));
379 		rv = LDP_E_ROUTE_ERROR;
380 	}
381 	if (fr) {
382 		free(so_dest);
383 		if (so_prefix)
384 			free(so_prefix);
385 		if (so_gate)
386 			free(so_gate);
387 		if (so_ifa)
388 			free(so_ifa);
389 		if (so_tag)
390 			free(so_tag);
391 	}
392 
393 	return rv;
394 }
395 
396 /* Deletes a route */
397 int
398 delete_route(union sockunion * so_dest, union sockunion * so_pref, int freeso)
399 {
400 	int             l, rlen;
401 	struct rt_msg   rm;
402 	char           *cp;
403 
404 	if(dont_catch)
405 		return LDP_E_OK;
406 
407 	memset(&rm, 0, sizeof(struct rt_msg));
408 	cp = rm.m_space;
409 
410 	rm.m_rtm.rtm_type = RTM_DELETE;
411 	rm.m_rtm.rtm_version = RTM_VERSION;
412 	rm.m_rtm.rtm_seq = ++rt_seq;
413 	if (so_pref)
414 		rm.m_rtm.rtm_addrs = RTA_DST | RTA_NETMASK;
415 	else
416 		rm.m_rtm.rtm_addrs = RTA_DST;
417 
418 	/* destination, gateway, netmask, genmask, ifp, ifa */
419 
420 	NEXTADDR(so_dest);
421 
422 	if (so_pref) {
423 		mask_addr(so_pref);
424 		NEXTADDR(so_pref);
425 	}
426 	rm.m_rtm.rtm_msglen = l = cp - (char *) &rm;
427 
428 	if (freeso == FREESO) {
429 		free(so_dest);
430 		if (so_pref)
431 			free(so_pref);
432 	}
433 	if ((rlen = write(route_socket, (char *) &rm, l)) < l) {
434 	    if(so_pref) {
435 		char spreftmp[INET_ADDRSTRLEN];
436 		strlcpy(spreftmp, inet_ntoa(so_pref->sin.sin_addr),
437 		    INET_ADDRSTRLEN);
438 		warnp("Error deleting route(%s): %s/%s",
439 		    route_strerror(errno), union_ntoa(so_dest),
440 		    spreftmp);
441 	    } else
442 		warnp("Error deleting route(%s) : %s",
443 		    route_strerror(errno), union_ntoa(so_dest));
444 	    return LDP_E_NO_SUCH_ROUTE;
445 	}
446 	return LDP_E_OK;
447 }
448 
449 /*
450  * Check for a route and returns it in rg
451  * If exact_match is set it compares also the so_dest and so_pref
452  * with the returned result
453  */
454 int
455 get_route(struct rt_msg * rg, union sockunion * so_dest,
456     union sockunion * so_pref, int exact_match)
457 {
458 	int             l, rlen, myseq;
459 	struct rt_msg   rm;
460 	char           *cp;
461 	union sockunion *su;
462 
463 	memset(&rm, 0, sizeof(struct rt_msg));
464 	cp = rm.m_space;
465 
466 	myseq = ++rt_seq;
467 
468 	rm.m_rtm.rtm_type = RTM_GET;
469 	rm.m_rtm.rtm_version = RTM_VERSION;
470 	rm.m_rtm.rtm_seq = myseq;
471 
472 	/*
473 	 * rtm_addrs should contain what we provide into this message but
474 	 * RTA_DST | RTA_IFP trick is allowed in order to find out the
475 	 * interface.
476 	 */
477 
478 	rm.m_rtm.rtm_addrs = RTA_DST | RTA_IFP;
479 
480 	/*
481 	 * ORDER of fields is: destination, gateway, netmask, genmask, ifp,
482 	 * ifa
483 	 */
484 
485 	NEXTADDR(so_dest);
486 	if (so_pref) {
487 		rm.m_rtm.rtm_addrs |= RTA_NETMASK;
488 		mask_addr(so_pref);
489 		NEXTADDR(so_pref);
490 	}
491 	rm.m_rtm.rtm_msglen = l = cp - (char *) &rm;
492 
493 	if ((rlen = write(route_socket, (char *) &rm, l)) < l) {
494 		debugp("Cannot get a route !(rlen=%d instead of %d) - %s\n",
495 		    rlen, l, strerror(errno));
496 		return LDP_E_NO_SUCH_ROUTE;
497 	} else
498 		for ( ; ; ) {
499 			rlen = read_route_socket((char *) rg,
500 			    sizeof(struct rt_msg));
501 			if (rlen < 1)
502 				break;
503 			/*
504 			 * We might lose important messages here. WORKAROUND:
505 			 * For now I just try to save this messages and replay
506 			 * them later
507 			 */
508 			if (rg->m_rtm.rtm_pid == getpid() &&
509 			    rg->m_rtm.rtm_seq == myseq)
510 				break;
511 			debugp("Added to replay PID: %d, SEQ: %d\n",
512 			    rg->m_rtm.rtm_pid, rg->m_rtm.rtm_seq);
513 			memcpy(&replay_rt[replay_index], rg,
514 			    sizeof(struct rt_msg));
515 			if (replay_index < REPLAY_MAX - 1)
516 				replay_index++;
517 			else
518 				fatalp("Replay index is full\n");
519 		}
520 
521 	if (rlen <= (int)sizeof(struct rt_msghdr)) {
522 		debugp("Got only %d bytes, expecting at least %zu\n", rlen,
523 		    sizeof(struct rt_msghdr));
524 		return LDP_E_ROUTE_ERROR;
525 	}
526 
527 	/* Check if we don't have a less specific route */
528 	if (exact_match) {
529 		su = (union sockunion*)(rg->m_space);
530 		if (compare_sockunion(so_dest, su)) {
531 			debugp("Dest %s ", union_ntoa(so_dest));
532 			debugp("not like %s\n", union_ntoa(su));
533 			return LDP_E_NO_SUCH_ROUTE;
534 		}
535 	}
536 
537 	return LDP_E_OK;
538 }
539 
540 
541 /* triggered when a route event occurs */
542 int
543 check_route(struct rt_msg * rg, uint rlen)
544 {
545 	union sockunion *so_dest = NULL, *so_gate = NULL, *so_pref = NULL;
546 	int             so_pref_allocated = 0;
547 	int             prefixlen;
548 	struct peer_map *pm;
549 	struct label	*lab;
550 	char            dest[50], gate[50], pref[50], oper[50];
551 	dest[0] = 0;
552 	gate[0] = 0;
553 	pref[0] = 0;
554 
555 	if (rlen <= sizeof(struct rt_msghdr))
556 		return LDP_E_ROUTE_ERROR;
557 
558 	if (rg->m_rtm.rtm_version != RTM_VERSION)
559 		return LDP_E_ROUTE_ERROR;
560 
561 	if ((rg->m_rtm.rtm_flags & RTF_DONE) == 0)
562 		return LDP_E_OK;
563 
564 	if (rg->m_rtm.rtm_pid == getpid())	/* We did it.. */
565 		return LDP_E_OK;
566 	else
567 		debugp("Check route triggered by PID: %d\n", rg->m_rtm.rtm_pid);
568 
569 	so_dest = (union sockunion *) rg->m_space;
570 
571 	if (so_dest->sa.sa_family != AF_INET)
572 		return LDP_E_OK;/* We don't care about non-IP changes */
573 
574 	if (rg->m_rtm.rtm_addrs & RTA_GATEWAY) {
575 		so_gate = GETNEXT(so_dest);
576 		if ((so_gate->sa.sa_family != AF_INET) &&
577 		    (so_gate->sa.sa_family != AF_MPLS))
578 			return LDP_E_OK;
579 	}
580 	if (rg->m_rtm.rtm_addrs & RTA_NETMASK) {
581 		if (so_gate)
582 			so_pref = so_gate;
583 		else
584 			so_pref = so_dest;
585 		so_pref = GETNEXT(so_pref);
586 	}
587 	if (!(rg->m_rtm.rtm_flags & RTF_GATEWAY)) {
588 		if (rg->m_rtm.rtm_addrs & RTA_GENMASK) {
589 			debugp("Used GENMASK\n");
590 		} else
591 			debugp("No GENMASK to use\n");
592 	}
593 	/* Calculate prefixlen */
594 	if (so_pref)
595 		prefixlen = from_mask_to_cidr(inet_ntoa(so_pref->sin.sin_addr));
596 	else {
597 		prefixlen = 32;
598 		if ((so_pref = from_cidr_to_union(32)) == NULL)
599 			return LDP_E_MEMORY;
600 		so_pref_allocated = 1;
601 	}
602 
603 	so_pref->sa.sa_family = AF_INET;
604 	so_pref->sa.sa_len = sizeof(struct sockaddr_in);
605 
606 	switch (rg->m_rtm.rtm_type) {
607 	case RTM_CHANGE:
608 		lab = label_get(so_dest, so_pref);
609 		if (lab) {
610 			send_withdraw_tlv_to_all(&so_dest->sa,
611 			    prefixlen);
612 			label_reattach_route(lab, LDP_READD_NODEL);
613 			label_del(lab);
614 		}
615 	/* Fallthrough */
616 	case RTM_ADD:
617 		/*
618 		 * Check if the route is connected. If so, bind it to
619 		 * POP_LABEL and send announce. If not, check if the prefix
620 		 * was announced by a LDP neighbour and route it there
621 		 */
622 
623 		/* First of all check if we already know this one */
624 		if (label_get(so_dest, so_pref) == NULL) {
625 			if (!(rg->m_rtm.rtm_flags & RTF_GATEWAY))
626 				label_add(so_dest, so_pref, NULL,
627 					MPLS_LABEL_IMPLNULL, NULL, 0);
628 			else {
629 				pm = ldp_test_mapping(&so_dest->sa,
630 					 prefixlen, &so_gate->sa);
631 				if (pm) {
632 					label_add(so_dest, so_pref,
633 						so_gate, 0, NULL, 0);
634 					mpls_add_label(pm->peer, rg,
635 					  &so_dest->sa, prefixlen,
636 					  pm->lm->label, ROUTE_LOOKUP_LOOP);
637 					free(pm);
638 				} else
639 					label_add(so_dest, so_pref, so_gate,
640 					    MPLS_LABEL_IMPLNULL, NULL, 0);
641 			}
642 		} else	/* We already know about this prefix */
643 			debugp("Binding already there for prefix %s/%d !\n",
644 			      union_ntoa(so_dest), prefixlen);
645 		break;
646 	case RTM_DELETE:
647 		if (!so_gate)
648 			break;	/* Non-existent route  XXX ?! */
649 		/*
650 		 * Send withdraw check the binding, delete the route, delete
651 		 * the binding
652 		 */
653 		lab = label_get(so_dest, so_pref);
654 		if (!lab)
655 			break;
656 		send_withdraw_tlv_to_all(&so_dest->sa, prefixlen);
657 		/* No readd or delete IP route. Just delete the MPLS route */
658 		label_reattach_route(lab, LDP_READD_NODEL);
659 		label_del(lab);
660 		break;
661 	}
662 
663 	if (!debug_f && !warn_f) {
664 		if(so_pref_allocated)
665 			free(so_pref);
666 		return LDP_E_OK;
667 	}
668 
669 	/* Rest is just for debug */
670 
671 	if (so_dest)
672 		strlcpy(dest, union_ntoa(so_dest), 16);
673 	if (so_pref)
674 		snprintf(pref, 3, "%d", prefixlen);
675 	if (so_gate)
676 		strlcpy(gate, union_ntoa(so_gate), 16);
677 
678 	switch (rg->m_rtm.rtm_type) {
679 	case RTM_ADD:
680 		strlcpy(oper, "added", 20);
681 		break;
682 	case RTM_DELETE:
683 		strlcpy(oper, "delete", 20);
684 		break;
685 	case RTM_GET:
686 		strlcpy(oper, "get", 20);
687 		break;
688 	case RTM_CHANGE:
689 		strlcpy(oper, "change", 20);
690 		break;
691 	case RTM_LOSING:
692 		strlcpy(oper, "losing", 20);
693 		break;
694 	case RTM_NEWADDR:
695 		strlcpy(oper, "new address", 20);
696 		break;
697 	case RTM_DELADDR:
698 		strlcpy(oper, "del address", 20);
699 		break;
700 	default:
701 		snprintf(oper, 50, "unknown 0x%X operation",
702 		    rg->m_rtm.rtm_type);
703 	}
704 
705 	warnp("[check_route] Route %s: %s / %s -> %s by PID:%d\n", oper, dest,
706 		pref, gate, rg->m_rtm.rtm_pid);
707 
708 	if(so_pref_allocated)
709 		free(so_pref);
710 	return LDP_E_OK;
711 }
712 
713 int
714 bind_current_routes()
715 {
716 	size_t          needed;
717 	int             mib[6];
718 	char           *buf, *next, *lim;
719 	struct rt_msghdr *rtmes;
720 	union sockunion *so_dst, *so_pref, *so_gate;
721 
722 	mib[0] = CTL_NET;
723 	mib[1] = PF_ROUTE;
724 	mib[2] = 0;
725 	mib[3] = 0;
726 	mib[4] = NET_RT_DUMP;
727 	mib[5] = 0;
728 	if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
729 		fatalp("route-sysctl-estimate: %s",
730 		    strerror(errno));
731 		return LDP_E_ROUTE_ERROR;
732 	}
733 	if ((buf = malloc(needed)) == 0)
734 		return LDP_E_ROUTE_ERROR;
735 	if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
736 		free(buf);
737 		return LDP_E_ROUTE_ERROR;
738 	}
739 	lim = buf + needed;
740 
741 	for (next = buf; next < lim; next += rtmes->rtm_msglen) {
742 		rtmes = (struct rt_msghdr *) next;
743 		so_pref = NULL;
744 		so_gate = NULL;
745 		if (rtmes->rtm_flags & RTF_LLINFO)	/* No need for arps */
746 			continue;
747 		if (!(rtmes->rtm_addrs & RTA_DST)) {
748 			debugp("No dst\n");
749 			continue;
750 		}
751 
752 		so_dst = (union sockunion *) & rtmes[1];
753 
754 		/*
755 		 * This function is called only at startup, so use
756 		 * this ocassion to delete all MPLS routes
757 		 */
758 		if (so_dst->sa.sa_family == AF_MPLS) {
759 			delete_route(so_dst, NULL, NO_FREESO);
760 			debugp("MPLS route deleted.\n");
761 			continue;
762 		}
763 
764 		if (so_dst->sa.sa_family != AF_INET) {
765 			/*debugp("sa_dst is not AF_INET\n");*/
766 			continue;
767 		}
768 
769 		/* Check if it's the default gateway */
770 		if (so_dst->sin.sin_addr.s_addr == 0 && no_default_route != 0)
771 			continue;
772 
773 		/* XXX: Check if it's loopback */
774 		if ((ntohl(so_dst->sin.sin_addr.s_addr) >> 24)==IN_LOOPBACKNET)
775 			continue;
776 
777 		/* Get Gateway */
778 		if (rtmes->rtm_addrs & RTA_GATEWAY)
779 			so_gate = GETNEXT(so_dst);
780 
781 		/* Get prefix */
782 		if (rtmes->rtm_flags & RTF_HOST) {
783 			if ((so_pref = from_cidr_to_union(32)) == NULL)
784 				return LDP_E_MEMORY;
785 		} else if (rtmes->rtm_addrs & RTA_GATEWAY)
786 			so_pref = GETNEXT(so_gate);
787 		else
788 			so_pref = GETNEXT(so_dst);
789 
790 		so_pref->sa.sa_family = AF_INET;
791 		so_pref->sa.sa_len = sizeof(struct sockaddr_in);
792 
793 		/* Also deletes when dest is IPv4 and gateway MPLS */
794 		if ((rtmes->rtm_addrs & RTA_GATEWAY) &&
795 		    (so_gate->sa.sa_family == AF_MPLS)) {
796 			debugp("MPLS route to %s deleted.\n",
797 			    inet_ntoa(so_dst->sin.sin_addr));
798 			delete_route(so_dst, so_pref, NO_FREESO);
799 			if (rtmes->rtm_flags & RTF_HOST)
800 				free(so_pref);
801 			continue;
802 		}
803 		if (so_gate->sa.sa_family == AF_INET)
804 			label_add(so_dst, so_pref, so_gate,
805 			    MPLS_LABEL_IMPLNULL, NULL, 0);
806 
807 		if (rtmes->rtm_flags & RTF_HOST)
808 			free(so_pref);
809 	}
810 	free(buf);
811 	return LDP_E_OK;
812 }
813 
814 int
815 flush_mpls_routes()
816 {
817 	size_t          needed;
818 	int             mib[6];
819 	char           *buf, *next, *lim;
820 	struct rt_msghdr *rtm;
821 	union sockunion *so_dst, *so_pref, *so_gate;
822 
823 	mib[0] = CTL_NET;
824 	mib[1] = PF_ROUTE;
825 	mib[2] = 0;
826 	mib[3] = 0;
827 	mib[4] = NET_RT_DUMP;
828 	mib[5] = 0;
829 	if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
830 		fatalp("route-sysctl-estimate: %s", strerror(errno));
831 		return LDP_E_ROUTE_ERROR;
832 	}
833 	if ((buf = malloc(needed)) == NULL) {
834 		fatalp("route-sysctl-estimate: %s", strerror(errno));
835 		return LDP_E_MEMORY;
836 	}
837 	if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
838 		free(buf);
839 		return LDP_E_ROUTE_ERROR;
840 	}
841 	lim = buf + needed;
842 
843 	for (next = buf; next < lim; next += rtm->rtm_msglen) {
844 		rtm = (struct rt_msghdr *) next;
845 		so_pref = NULL;
846 		so_gate = NULL;
847 		if (rtm->rtm_flags & RTF_LLINFO)	/* No need for arps */
848 			continue;
849 		if (!(rtm->rtm_addrs & RTA_DST)) {
850 			debugp("No dst\n");
851 			continue;
852 		}
853 		so_dst = (union sockunion *) & rtm[1];
854 
855 		if (so_dst->sa.sa_family == AF_MPLS) {
856 			delete_route(so_dst, NULL, NO_FREESO);
857 			debugp("MPLS route deleted.\n");
858 			continue;
859 		}
860 
861 		if (rtm->rtm_addrs & RTA_GATEWAY) {
862 			so_gate = GETNEXT(so_dst);
863 			so_pref = GETNEXT(so_gate);
864 		} else
865 			so_pref = GETNEXT(so_dst);
866 
867 		if (so_gate->sa.sa_family == AF_MPLS) {
868 			if (so_dst->sa.sa_family == AF_INET)
869 				debugp("MPLS route to %s deleted.\n",
870 				    inet_ntoa(so_dst->sin.sin_addr));
871 			delete_route(so_dst, so_pref, NO_FREESO);
872 			continue;
873 		}
874 
875 	}
876 	free(buf);
877 	return LDP_E_OK;
878 }
879