1/* Kernel communication using routing socket. 2 * Copyright (C) 1999 Kunihiro Ishiguro 3 * 4 * This file is part of GNU Zebra. 5 * 6 * GNU Zebra is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License as published by the 8 * Free Software Foundation; either version 2, or (at your option) any 9 * later version. 10 * 11 * GNU Zebra is distributed in the hope that it will be useful, but 12 * WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with GNU Zebra; see the file COPYING. If not, write to the Free 18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 19 * 02111-1307, USA. 20 */ 21 22#include <zebra.h> 23 24#include "if.h" 25#include "prefix.h" 26#include "sockunion.h" 27#include "connected.h" 28#include "memory.h" 29#include "ioctl.h" 30#include "log.h" 31#include "str.h" 32#include "table.h" 33#include "rib.h" 34 35#include "zebra/interface.h" 36#include "zebra/zserv.h" 37#include "zebra/debug.h" 38 39/* Socket length roundup function. */ 40#define ROUNDUP(a) \ 41 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 42 43/* And this macro is wrapper for handling sa_len. */ 44#ifdef HAVE_SA_LEN 45#define WRAPUP(X) ROUNDUP(((struct sockaddr *)(X))->sa_len) 46#else 47#define WRAPUP(X) ROUNDUP(sizeof (struct sockaddr)) 48#endif /* HAVE_SA_LEN */ 49 50/* Routing socket message types. */ 51struct message rtm_type_str[] = 52{ 53 {RTM_ADD, "RTM_ADD"}, 54 {RTM_DELETE, "RTM_DELETE"}, 55 {RTM_CHANGE, "RTM_CHANGE"}, 56 {RTM_GET, "RTM_GET"}, 57 {RTM_LOSING, "RTM_LOSING"}, 58 {RTM_REDIRECT, "RTM_REDIRECT"}, 59 {RTM_MISS, "RTM_MISS"}, 60 {RTM_LOCK, "RTM_LOCK"}, 61 {RTM_OLDADD, "RTM_OLDADD"}, 62 {RTM_OLDDEL, "RTM_OLDDEL"}, 63 {RTM_RESOLVE, "RTM_RESOLVE"}, 64 {RTM_NEWADDR, "RTM_NEWADDR"}, 65 {RTM_DELADDR, "RTM_DELADDR"}, 66 {RTM_IFINFO, "RTM_IFINFO"}, 67#ifdef RTM_OIFINFO 68 {RTM_OIFINFO, "RTM_OIFINFO"}, 69#endif /* RTM_OIFINFO */ 70#ifdef RTM_NEWMADDR 71 {RTM_NEWMADDR, "RTM_NEWMADDR"}, 72#endif /* RTM_NEWMADDR */ 73#ifdef RTM_DELMADDR 74 {RTM_DELMADDR, "RTM_DELMADDR"}, 75#endif /* RTM_DELMADDR */ 76#ifdef RTM_IFANNOUNCE 77 {RTM_IFANNOUNCE, "RTM_IFANNOUNCE"}, 78#endif /* RTM_IFANNOUNCE */ 79 {0, NULL} 80}; 81 82struct message rtm_flag_str[] = 83{ 84 {RTF_UP, "UP"}, 85 {RTF_GATEWAY, "GATEWAY"}, 86 {RTF_HOST, "HOST"}, 87 {RTF_REJECT, "REJECT"}, 88 {RTF_DYNAMIC, "DYNAMIC"}, 89 {RTF_MODIFIED, "MODIFIED"}, 90 {RTF_DONE, "DONE"}, 91#ifdef RTF_MASK 92 {RTF_MASK, "MASK"}, 93#endif /* RTF_MASK */ 94 {RTF_CLONING, "CLONING"}, 95 {RTF_XRESOLVE, "XRESOLVE"}, 96 {RTF_LLINFO, "LLINFO"}, 97 {RTF_STATIC, "STATIC"}, 98 {RTF_BLACKHOLE, "BLACKHOLE"}, 99 {RTF_PROTO1, "PROTO1"}, 100 {RTF_PROTO2, "PROTO2"}, 101#ifdef RTF_PRCLONING 102 {RTF_PRCLONING, "PRCLONING"}, 103#endif /* RTF_PRCLONING */ 104#ifdef RTF_WASCLONED 105 {RTF_WASCLONED, "WASCLONED"}, 106#endif /* RTF_WASCLONED */ 107#ifdef RTF_PROTO3 108 {RTF_PROTO3, "PROTO3"}, 109#endif /* RTF_PROTO3 */ 110#ifdef RTF_PINNED 111 {RTF_PINNED, "PINNED"}, 112#endif /* RTF_PINNED */ 113#ifdef RTF_LOCAL 114 {RTF_LOCAL, "LOCAL"}, 115#endif /* RTF_LOCAL */ 116#ifdef RTF_BROADCAST 117 {RTF_BROADCAST, "BROADCAST"}, 118#endif /* RTF_BROADCAST */ 119#ifdef RTF_MULTICAST 120 {RTF_MULTICAST, "MULTICAST"}, 121#endif /* RTF_MULTICAST */ 122 {0, NULL} 123}; 124 125/* Kernel routing update socket. */ 126int routing_sock = -1; 127 128/* Yes I'm checking ugly routing socket behavior. */ 129/* #define DEBUG */ 130 131/* Supported address family check. */ 132static int 133af_check (int family) 134{ 135 if (family == AF_INET) 136 return 1; 137#ifdef HAVE_IPV6 138 if (family == AF_INET6) 139 return 1; 140#endif /* HAVE_IPV6 */ 141 return 0; 142} 143 144/* Dump routing table flag for debug purpose. */ 145void 146rtm_flag_dump (int flag) 147{ 148 struct message *mes; 149 static char buf[BUFSIZ]; 150 151 for (mes = rtm_flag_str; mes->key != 0; mes++) 152 { 153 if (mes->key & flag) 154 { 155 strlcat (buf, mes->str, BUFSIZ); 156 strlcat (buf, " ", BUFSIZ); 157 } 158 } 159 zlog_info ("Kernel: %s", buf); 160} 161 162#ifdef RTM_IFANNOUNCE 163/* Interface adding function */ 164int 165ifan_read (struct if_announcemsghdr *ifan) 166{ 167 struct interface *ifp; 168 169 ifp = if_lookup_by_index (ifan->ifan_index); 170 if (ifp == NULL && ifan->ifan_what == IFAN_ARRIVAL) 171 { 172 /* Create Interface */ 173 ifp = if_get_by_name (ifan->ifan_name); 174 ifp->ifindex = ifan->ifan_index; 175 176 if_add_update (ifp); 177 } 178 else if (ifp != NULL && ifan->ifan_what == IFAN_DEPARTURE) 179 { 180 if_delete_update (ifp); 181 if_delete (ifp); 182 } 183 184 if_get_flags (ifp); 185 if_get_mtu (ifp); 186 if_get_metric (ifp); 187 188 if (IS_ZEBRA_DEBUG_KERNEL) 189 zlog_info ("interface %s index %d", ifp->name, ifp->ifindex); 190 191 return 0; 192} 193#endif /* RTM_IFANNOUNCE */ 194 195/* Interface adding function called from interface_list. */ 196int 197ifm_read (struct if_msghdr *ifm) 198{ 199 struct interface *ifp; 200 struct sockaddr_dl *sdl = NULL; 201 202 sdl = (struct sockaddr_dl *)(ifm + 1); 203 204 /* Use sdl index. */ 205 ifp = if_lookup_by_index (ifm->ifm_index); 206 207 if (ifp == NULL) 208 { 209 /* Check interface's address.*/ 210 if (! (ifm->ifm_addrs & RTA_IFP)) 211 { 212 zlog_warn ("There must be RTA_IFP address for ifindex %d\n", 213 ifm->ifm_index); 214 return -1; 215 } 216 217 ifp = if_create (); 218 219 strncpy (ifp->name, sdl->sdl_data, sdl->sdl_nlen); 220 ifp->ifindex = ifm->ifm_index; 221 ifp->flags = ifm->ifm_flags; 222#if defined(__bsdi__) 223 if_kvm_get_mtu (ifp); 224#else 225 if_get_mtu (ifp); 226#endif /* __bsdi__ */ 227 if_get_metric (ifp); 228 229 /* Fetch hardware address. */ 230 if (sdl->sdl_family != AF_LINK) 231 { 232 zlog_warn ("sockaddr_dl->sdl_family is not AF_LINK"); 233 return -1; 234 } 235 memcpy (&ifp->sdl, sdl, sizeof (struct sockaddr_dl)); 236 237 if_add_update (ifp); 238 } 239 else 240 { 241 /* There is a case of promisc, allmulti flag modification. */ 242 if (if_is_up (ifp)) 243 { 244 ifp->flags = ifm->ifm_flags; 245 if (! if_is_up (ifp)) 246 if_down (ifp); 247 } 248 else 249 { 250 ifp->flags = ifm->ifm_flags; 251 if (if_is_up (ifp)) 252 if_up (ifp); 253 } 254 } 255 256#ifdef HAVE_NET_RT_IFLIST 257 ifp->stats = ifm->ifm_data; 258#endif /* HAVE_NET_RT_IFLIST */ 259 260 if (IS_ZEBRA_DEBUG_KERNEL) 261 zlog_info ("interface %s index %d", ifp->name, ifp->ifindex); 262 263 return 0; 264} 265 266/* Address read from struct ifa_msghdr. */ 267void 268ifam_read_mesg (struct ifa_msghdr *ifm, 269 union sockunion *addr, 270 union sockunion *mask, 271 union sockunion *dest) 272{ 273 caddr_t pnt, end; 274 275 pnt = (caddr_t)(ifm + 1); 276 end = ((caddr_t)ifm) + ifm->ifam_msglen; 277 278#define IFAMADDRGET(X,R) \ 279 if (ifm->ifam_addrs & (R)) \ 280 { \ 281 int len = WRAPUP(pnt); \ 282 if (((X) != NULL) && af_check (((struct sockaddr *)pnt)->sa_family)) \ 283 memcpy ((caddr_t)(X), pnt, len); \ 284 pnt += len; \ 285 } 286#define IFAMMASKGET(X,R) \ 287 if (ifm->ifam_addrs & (R)) \ 288 { \ 289 int len = WRAPUP(pnt); \ 290 if ((X) != NULL) \ 291 memcpy ((caddr_t)(X), pnt, len); \ 292 pnt += len; \ 293 } 294 295 /* Be sure structure is cleared */ 296 memset (mask, 0, sizeof (union sockunion)); 297 memset (addr, 0, sizeof (union sockunion)); 298 memset (dest, 0, sizeof (union sockunion)); 299 300 /* We fetch each socket variable into sockunion. */ 301 IFAMADDRGET (NULL, RTA_DST); 302 IFAMADDRGET (NULL, RTA_GATEWAY); 303 IFAMMASKGET (mask, RTA_NETMASK); 304 IFAMADDRGET (NULL, RTA_GENMASK); 305 IFAMADDRGET (NULL, RTA_IFP); 306 IFAMADDRGET (addr, RTA_IFA); 307 IFAMADDRGET (NULL, RTA_AUTHOR); 308 IFAMADDRGET (dest, RTA_BRD); 309 310 /* Assert read up end point matches to end point */ 311 if (pnt != end) 312 zlog_warn ("ifam_read() does't read all socket data"); 313} 314 315/* Interface's address information get. */ 316int 317ifam_read (struct ifa_msghdr *ifam) 318{ 319 struct interface *ifp; 320 union sockunion addr, mask, gate; 321 322 /* Check does this interface exist or not. */ 323 ifp = if_lookup_by_index (ifam->ifam_index); 324 if (ifp == NULL) 325 { 326 zlog_warn ("no interface for index %d", ifam->ifam_index); 327 return -1; 328 } 329 330 /* Allocate and read address information. */ 331 ifam_read_mesg (ifam, &addr, &mask, &gate); 332 333 /* Check interface flag for implicit up of the interface. */ 334 if_refresh (ifp); 335 336 /* Add connected address. */ 337 switch (sockunion_family (&addr)) 338 { 339 case AF_INET: 340 if (ifam->ifam_type == RTM_NEWADDR) 341 connected_add_ipv4 (ifp, 0, &addr.sin.sin_addr, 342 ip_masklen (mask.sin.sin_addr), 343 &gate.sin.sin_addr, NULL); 344 else 345 connected_delete_ipv4 (ifp, 0, &addr.sin.sin_addr, 346 ip_masklen (mask.sin.sin_addr), 347 &gate.sin.sin_addr, NULL); 348 break; 349#ifdef HAVE_IPV6 350 case AF_INET6: 351 /* Unset interface index from link-local address when IPv6 stack 352 is KAME. */ 353 if (IN6_IS_ADDR_LINKLOCAL (&addr.sin6.sin6_addr)) 354 SET_IN6_LINKLOCAL_IFINDEX (addr.sin6.sin6_addr, 0); 355 356 if (ifam->ifam_type == RTM_NEWADDR) 357 connected_add_ipv6 (ifp, 358 &addr.sin6.sin6_addr, 359 ip6_masklen (mask.sin6.sin6_addr), 360 &gate.sin6.sin6_addr); 361 else 362 connected_delete_ipv6 (ifp, 363 &addr.sin6.sin6_addr, 364 ip6_masklen (mask.sin6.sin6_addr), 365 &gate.sin6.sin6_addr); 366 break; 367#endif /* HAVE_IPV6 */ 368 default: 369 /* Unsupported family silently ignore... */ 370 break; 371 } 372 return 0; 373} 374 375/* Interface function for reading kernel routing table information. */ 376int 377rtm_read_mesg (struct rt_msghdr *rtm, 378 union sockunion *dest, 379 union sockunion *mask, 380 union sockunion *gate) 381{ 382 caddr_t pnt, end; 383 384 /* Pnt points out socket data start point. */ 385 pnt = (caddr_t)(rtm + 1); 386 end = ((caddr_t)rtm) + rtm->rtm_msglen; 387 388 /* rt_msghdr version check. */ 389 if (rtm->rtm_version != RTM_VERSION) 390 zlog (NULL, LOG_WARNING, 391 "Routing message version different %d should be %d." 392 "This may cause problem\n", rtm->rtm_version, RTM_VERSION); 393 394#define RTMADDRGET(X,R) \ 395 if (rtm->rtm_addrs & (R)) \ 396 { \ 397 int len = WRAPUP (pnt); \ 398 if (((X) != NULL) && af_check (((struct sockaddr *)pnt)->sa_family)) \ 399 memcpy ((caddr_t)(X), pnt, len); \ 400 pnt += len; \ 401 } 402#define RTMMASKGET(X,R) \ 403 if (rtm->rtm_addrs & (R)) \ 404 { \ 405 int len = WRAPUP (pnt); \ 406 if ((X) != NULL) \ 407 memcpy ((caddr_t)(X), pnt, len); \ 408 pnt += len; \ 409 } 410 411 /* Be sure structure is cleared */ 412 memset (dest, 0, sizeof (union sockunion)); 413 memset (gate, 0, sizeof (union sockunion)); 414 memset (mask, 0, sizeof (union sockunion)); 415 416 /* We fetch each socket variable into sockunion. */ 417 RTMADDRGET (dest, RTA_DST); 418 RTMADDRGET (gate, RTA_GATEWAY); 419 RTMMASKGET (mask, RTA_NETMASK); 420 RTMADDRGET (NULL, RTA_GENMASK); 421 RTMADDRGET (NULL, RTA_IFP); 422 RTMADDRGET (NULL, RTA_IFA); 423 RTMADDRGET (NULL, RTA_AUTHOR); 424 RTMADDRGET (NULL, RTA_BRD); 425 426 /* If there is netmask information set it's family same as 427 destination family*/ 428 if (rtm->rtm_addrs & RTA_NETMASK) 429 mask->sa.sa_family = dest->sa.sa_family; 430 431 /* Assert read up to the end of pointer. */ 432 if (pnt != end) 433 zlog (NULL, LOG_WARNING, "rtm_read() does't read all socket data."); 434 435 return rtm->rtm_flags; 436} 437 438void 439rtm_read (struct rt_msghdr *rtm) 440{ 441 int flags; 442 u_char zebra_flags; 443 union sockunion dest, mask, gate; 444 445 zebra_flags = 0; 446 447 /* Discard self send message. */ 448 if (rtm->rtm_type != RTM_GET 449 && (rtm->rtm_pid == pid || rtm->rtm_pid == old_pid)) 450 return; 451 452 /* Read destination and netmask and gateway from rtm message 453 structure. */ 454 flags = rtm_read_mesg (rtm, &dest, &mask, &gate); 455 456#ifdef RTF_CLONED /*bsdi, netbsd 1.6*/ 457 if (flags & RTF_CLONED) 458 return; 459#endif 460#ifdef RTF_WASCLONED /*freebsd*/ 461 if (flags & RTF_WASCLONED) 462 return; 463#endif 464 465 if ((rtm->rtm_type == RTM_ADD) && ! (flags & RTF_UP)) 466 return; 467 468 /* Ignore route which has both HOST and GATEWAY attribute. */ 469 if ((flags & RTF_GATEWAY) && (flags & RTF_HOST)) 470 return; 471 472 /* This is connected route. */ 473 if (! (flags & RTF_GATEWAY)) 474 return; 475 476 if (flags & RTF_PROTO1) 477 SET_FLAG (zebra_flags, ZEBRA_FLAG_SELFROUTE); 478 479 /* This is persistent route. */ 480 if (flags & RTF_STATIC) 481 SET_FLAG (zebra_flags, ZEBRA_FLAG_STATIC); 482 483 if (dest.sa.sa_family == AF_INET) 484 { 485 struct prefix_ipv4 p; 486 487 p.family = AF_INET; 488 p.prefix = dest.sin.sin_addr; 489 p.prefixlen = ip_masklen (mask.sin.sin_addr); 490 491 if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD) 492 rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, 493 &p, &gate.sin.sin_addr, 0, 0, 0, 0); 494 else 495 rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, 496 &p, &gate.sin.sin_addr, 0, 0); 497 } 498#ifdef HAVE_IPV6 499 if (dest.sa.sa_family == AF_INET6) 500 { 501 struct prefix_ipv6 p; 502 unsigned int ifindex = 0; 503 504 p.family = AF_INET6; 505 p.prefix = dest.sin6.sin6_addr; 506 p.prefixlen = ip6_masklen (mask.sin6.sin6_addr); 507 508#ifdef KAME 509 if (IN6_IS_ADDR_LINKLOCAL (&gate.sin6.sin6_addr)) 510 { 511 ifindex = IN6_LINKLOCAL_IFINDEX (gate.sin6.sin6_addr); 512 SET_IN6_LINKLOCAL_IFINDEX (gate.sin6.sin6_addr, 0); 513 } 514#endif /* KAME */ 515 516 if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD) 517 rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags, 518 &p, &gate.sin6.sin6_addr, ifindex, 0); 519 else 520 rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags, 521 &p, &gate.sin6.sin6_addr, ifindex, 0); 522 } 523#endif /* HAVE_IPV6 */ 524} 525 526/* Interface function for the kernel routing table updates. Support 527 for RTM_CHANGE will be needed. */ 528int 529rtm_write (int message, 530 union sockunion *dest, 531 union sockunion *mask, 532 union sockunion *gate, 533 unsigned int index, 534 int zebra_flags, 535 int metric) 536{ 537 int ret; 538 caddr_t pnt; 539 struct interface *ifp; 540 struct sockaddr_in tmp_gate; 541#ifdef HAVE_IPV6 542 struct sockaddr_in6 tmp_gate6; 543#endif /* HAVE_IPV6 */ 544 545 /* Sequencial number of routing message. */ 546 static int msg_seq = 0; 547 548 /* Struct of rt_msghdr and buffer for storing socket's data. */ 549 struct 550 { 551 struct rt_msghdr rtm; 552 char buf[512]; 553 } msg; 554 555 memset (&tmp_gate, 0, sizeof (struct sockaddr_in)); 556 tmp_gate.sin_family = AF_INET; 557#ifdef HAVE_SIN_LEN 558 tmp_gate.sin_len = sizeof (struct sockaddr_in); 559#endif /* HAVE_SIN_LEN */ 560 561#ifdef HAVE_IPV6 562 memset (&tmp_gate6, 0, sizeof (struct sockaddr_in6)); 563 tmp_gate6.sin6_family = AF_INET6; 564#ifdef SIN6_LEN 565 tmp_gate6.sin6_len = sizeof (struct sockaddr_in6); 566#endif /* SIN6_LEN */ 567#endif /* HAVE_IPV6 */ 568 569 if (routing_sock < 0) 570 return ZEBRA_ERR_EPERM; 571 572 /* Clear and set rt_msghdr values */ 573 memset (&msg, 0, sizeof (struct rt_msghdr)); 574 msg.rtm.rtm_version = RTM_VERSION; 575 msg.rtm.rtm_type = message; 576 msg.rtm.rtm_seq = msg_seq++; 577 msg.rtm.rtm_addrs = RTA_DST; 578 msg.rtm.rtm_addrs |= RTA_GATEWAY; 579 msg.rtm.rtm_flags = RTF_UP; 580 msg.rtm.rtm_index = index; 581 582 if (metric != 0) 583 { 584 msg.rtm.rtm_rmx.rmx_hopcount = metric; 585 msg.rtm.rtm_inits |= RTV_HOPCOUNT; 586 } 587 588 ifp = if_lookup_by_index (index); 589 590 if (gate && message == RTM_ADD) 591 msg.rtm.rtm_flags |= RTF_GATEWAY; 592 593 if (! gate && message == RTM_ADD && ifp && 594 (ifp->flags & IFF_POINTOPOINT) == 0) 595 msg.rtm.rtm_flags |= RTF_CLONING; 596 597 /* If no protocol specific gateway is specified, use link 598 address for gateway. */ 599 if (! gate) 600 { 601 if (!ifp) 602 { 603 zlog_warn ("no gateway found for interface index %d", index); 604 return -1; 605 } 606 gate = (union sockunion *) & ifp->sdl; 607 } 608 609 if (mask) 610 msg.rtm.rtm_addrs |= RTA_NETMASK; 611 else if (message == RTM_ADD) 612 msg.rtm.rtm_flags |= RTF_HOST; 613 614 /* Tagging route with flags */ 615 msg.rtm.rtm_flags |= (RTF_PROTO1); 616 617 /* Additional flags. */ 618 if (zebra_flags & ZEBRA_FLAG_BLACKHOLE) 619 msg.rtm.rtm_flags |= RTF_BLACKHOLE; 620 621#ifdef HAVE_SIN_LEN 622#define SOCKADDRSET(X,R) \ 623 if (msg.rtm.rtm_addrs & (R)) \ 624 { \ 625 int len = ROUNDUP ((X)->sa.sa_len); \ 626 memcpy (pnt, (caddr_t)(X), len); \ 627 pnt += len; \ 628 } 629#else 630#define SOCKADDRSET(X,R) \ 631 if (msg.rtm.rtm_addrs & (R)) \ 632 { \ 633 int len = ROUNDUP (sizeof((X)->sa)); \ 634 memcpy (pnt, (caddr_t)(X), len); \ 635 pnt += len; \ 636 } 637#endif /* HAVE_SIN_LEN */ 638 639 pnt = (caddr_t) msg.buf; 640 641 /* Write each socket data into rtm message buffer */ 642 SOCKADDRSET (dest, RTA_DST); 643 SOCKADDRSET (gate, RTA_GATEWAY); 644 SOCKADDRSET (mask, RTA_NETMASK); 645 646 msg.rtm.rtm_msglen = pnt - (caddr_t) &msg; 647 648 ret = write (routing_sock, &msg, msg.rtm.rtm_msglen); 649 650 if (ret != msg.rtm.rtm_msglen) 651 { 652 if (errno == EEXIST) 653 return ZEBRA_ERR_RTEXIST; 654 if (errno == ENETUNREACH) 655 return ZEBRA_ERR_RTUNREACH; 656 657 zlog_warn ("write : %s (%d)", strerror (errno), errno); 658 return -1; 659 } 660 return 0; 661} 662 663 664#include "thread.h" 665#include "zebra/zserv.h" 666 667extern struct thread_master *master; 668 669/* For debug purpose. */ 670void 671rtmsg_debug (struct rt_msghdr *rtm) 672{ 673 char *type = "Unknown"; 674 struct message *mes; 675 676 for (mes = rtm_type_str; mes->str; mes++) 677 if (mes->key == rtm->rtm_type) 678 { 679 type = mes->str; 680 break; 681 } 682 683 zlog_info ("Kernel: Len: %d Type: %s", rtm->rtm_msglen, type); 684 rtm_flag_dump (rtm->rtm_flags); 685 zlog_info ("Kernel: message seq %d", rtm->rtm_seq); 686 zlog_info ("Kernel: pid %d", rtm->rtm_pid); 687} 688 689/* This is pretty gross, better suggestions welcome -- mhandler */ 690#ifndef RTAX_MAX 691#ifdef RTA_NUMBITS 692#define RTAX_MAX RTA_NUMBITS 693#else 694#define RTAX_MAX 8 695#endif /* RTA_NUMBITS */ 696#endif /* RTAX_MAX */ 697 698/* Kernel routing table and interface updates via routing socket. */ 699int 700kernel_read (struct thread *thread) 701{ 702 int sock; 703 int nbytes; 704 struct rt_msghdr *rtm; 705 706 union 707 { 708 /* Routing information. */ 709 struct 710 { 711 struct rt_msghdr rtm; 712 struct sockaddr addr[RTAX_MAX]; 713 } r; 714 715 /* Interface information. */ 716 struct 717 { 718 struct if_msghdr ifm; 719 struct sockaddr addr[RTAX_MAX]; 720 } im; 721 722 /* Interface address information. */ 723 struct 724 { 725 struct ifa_msghdr ifa; 726 struct sockaddr addr[RTAX_MAX]; 727 } ia; 728 729#ifdef RTM_IFANNOUNCE 730 /* Interface arrival/departure */ 731 struct 732 { 733 struct if_announcemsghdr ifan; 734 struct sockaddr addr[RTAX_MAX]; 735 } ian; 736#endif /* RTM_IFANNOUNCE */ 737 738 } buf; 739 740 /* Fetch routing socket. */ 741 sock = THREAD_FD (thread); 742 743 nbytes= read (sock, &buf, sizeof buf); 744 745 if (nbytes <= 0) 746 { 747 if (nbytes < 0 && errno != EWOULDBLOCK) 748 zlog_warn ("routing socket error: %s", strerror (errno)); 749 return 0; 750 } 751 752 thread_add_read (master, kernel_read, NULL, sock); 753 754#ifdef DEBUG 755 rtmsg_debug (&buf.r.rtm); 756#endif /* DEBUG */ 757 758 rtm = &buf.r.rtm; 759 760 switch (rtm->rtm_type) 761 { 762 case RTM_ADD: 763 case RTM_DELETE: 764 rtm_read (rtm); 765 break; 766 case RTM_IFINFO: 767 ifm_read (&buf.im.ifm); 768 break; 769 case RTM_NEWADDR: 770 case RTM_DELADDR: 771 ifam_read (&buf.ia.ifa); 772 break; 773#ifdef RTM_IFANNOUNCE 774 case RTM_IFANNOUNCE: 775 ifan_read (&buf.ian.ifan); 776 break; 777#endif /* RTM_IFANNOUNCE */ 778 default: 779 break; 780 } 781 return 0; 782} 783 784/* Make routing socket. */ 785void 786routing_socket () 787{ 788 routing_sock = socket (AF_ROUTE, SOCK_RAW, 0); 789 790 if (routing_sock < 0) 791 { 792#ifdef FOX_RIP_DEBUG 793 zlog_warn ("Can't init kernel routing socket"); 794#endif /* FOX_RIP_DEBUG */ 795 return; 796 } 797#ifdef FOX_RIP_DEBUG 798 if (fcntl (routing_sock, F_SETFL, O_NONBLOCK) < 0) 799 zlog_warn ("Can't set O_NONBLOCK to routing socket"); 800#endif /* FOX_RIP_DEBUG */ 801 /* kernel_read needs rewrite. */ 802 thread_add_read (master, kernel_read, NULL, routing_sock); 803} 804 805/* Exported interface function. This function simply calls 806 routing_socket (). */ 807void 808kernel_init () 809{ 810 routing_socket (); 811} 812