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