1 /* $NetBSD: mpls_routes.c,v 1.9 2012/03/15 02:02:24 joerg 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(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->sin.sin_addr, 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->sin.sin_addr, 643 prefixlen, &so_gate->sin.sin_addr); 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->sin.sin_addr, 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->sin.sin_addr, 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 * As this function is call only at startup use this ocassion 769 * 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