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