1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <arpa/inet.h> 28 #include <assert.h> 29 #include <errno.h> 30 #include <fcntl.h> 31 #include <net/if.h> 32 #include <net/route.h> 33 #include <pthread.h> 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <string.h> 37 #include <strings.h> 38 #include <sys/fcntl.h> 39 #include <unistd.h> 40 41 #include <inetcfg.h> 42 #include <libnwam.h> 43 #include "events.h" 44 #include "ncp.h" 45 #include "ncu.h" 46 #include "util.h" 47 48 /* 49 * routing_events.c - this file contains routines to retrieve routing socket 50 * events and package them for high level processing. 51 */ 52 53 #define RTMBUFSZ sizeof (struct rt_msghdr) + \ 54 (RTAX_MAX * sizeof (struct sockaddr_storage)) 55 56 static void printaddrs(int, void *); 57 static char *printaddr(void **); 58 static void *getaddr(int, int, void *); 59 static void setaddr(int, int *, void *, struct sockaddr *); 60 61 union rtm_buf 62 { 63 /* Routing information. */ 64 struct 65 { 66 struct rt_msghdr rtm; 67 struct sockaddr_storage addr[RTAX_MAX]; 68 } r; 69 70 /* Interface information. */ 71 struct 72 { 73 struct if_msghdr ifm; 74 struct sockaddr_storage addr[RTAX_MAX]; 75 } im; 76 77 /* Interface address information. */ 78 struct 79 { 80 struct ifa_msghdr ifa; 81 struct sockaddr_storage addr[RTAX_MAX]; 82 } ia; 83 }; 84 85 static int v4_sock = -1; 86 static int v6_sock = -1; 87 static pthread_t v4_routing, v6_routing; 88 static int seq = 0; 89 90 static const char * 91 rtmtype_str(int type) 92 { 93 static char typestr[12]; /* strlen("type ") + enough for an int */ 94 95 switch (type) { 96 case RTM_NEWADDR: 97 return ("NEWADDR"); 98 case RTM_DELADDR: 99 return ("DELADDR"); 100 case RTM_CHGADDR: 101 return ("CHGADDR"); 102 case RTM_FREEADDR: 103 return ("FREEADDR"); 104 case RTM_IFINFO: 105 return ("IFINFO"); 106 default: 107 (void) snprintf(typestr, sizeof (typestr), "type %d", type); 108 return (typestr); 109 } 110 } 111 112 /* ARGSUSED0 */ 113 static void * 114 routing_events_v4(void *arg) 115 { 116 int n; 117 union rtm_buf buffer; 118 struct rt_msghdr *rtm; 119 struct ifa_msghdr *ifa; 120 struct if_msghdr *ifm; 121 char *addrs, *if_name; 122 struct sockaddr_dl *addr_dl; 123 struct sockaddr *addr; 124 nwamd_event_t ip_event; 125 126 nlog(LOG_DEBUG, "v4 routing socket %d", v4_sock); 127 128 for (;;) { 129 rtm = &buffer.r.rtm; 130 n = read(v4_sock, &buffer, sizeof (buffer)); 131 if (n == -1 && errno == EAGAIN) { 132 continue; 133 } else if (n == -1) { 134 nlog(LOG_ERR, "error reading routing socket " 135 "%d: %m", v4_sock); 136 /* Low likelihood. What's recovery path? */ 137 continue; 138 } 139 140 if (rtm->rtm_msglen < n) { 141 nlog(LOG_ERR, "only read %d bytes from " 142 "routing socket but message claims to be " 143 "of length %d", rtm->rtm_msglen); 144 continue; 145 } 146 147 if (rtm->rtm_version != RTM_VERSION) { 148 nlog(LOG_ERR, "tossing routing message of " 149 "version %d type %d", rtm->rtm_version, 150 rtm->rtm_type); 151 continue; 152 } 153 154 if (rtm->rtm_msglen != n) { 155 nlog(LOG_DEBUG, "routing message of %d size came from " 156 "read of %d on socket %d", rtm->rtm_msglen, 157 n, v4_sock); 158 } 159 160 switch (rtm->rtm_type) { 161 case RTM_NEWADDR: 162 case RTM_DELADDR: 163 case RTM_CHGADDR: 164 case RTM_FREEADDR: 165 166 ifa = (void *)rtm; 167 addrs = (char *)ifa + sizeof (*ifa); 168 169 nlog(LOG_DEBUG, "v4 routing message %s: " 170 "index %d flags %x", rtmtype_str(rtm->rtm_type), 171 ifa->ifam_index, ifa->ifam_flags); 172 printaddrs(ifa->ifam_addrs, addrs); 173 174 if ((addr = (struct sockaddr *)getaddr(RTA_IFA, 175 ifa->ifam_addrs, addrs)) == NULL) 176 break; 177 178 /* Ignore routing socket messages for 0.0.0.0 */ 179 /*LINTED*/ 180 if (((struct sockaddr_in *)addr)->sin_addr.s_addr 181 == INADDR_ANY) { 182 nlog(LOG_DEBUG, "routing_events_v4: " 183 "tossing message for 0.0.0.0"); 184 break; 185 } 186 187 if ((addr_dl = (struct sockaddr_dl *)getaddr 188 (RTA_IFP, ifa->ifam_addrs, addrs)) == NULL) 189 break; 190 /* 191 * We don't use the lladdr in this structure so we can 192 * run over it. 193 */ 194 addr_dl->sdl_data[addr_dl->sdl_nlen] = 0; 195 if_name = addr_dl->sdl_data; /* no lifnum */ 196 197 if (ifa->ifam_index == 0) { 198 nlog(LOG_DEBUG, "tossing index 0 message"); 199 break; 200 } 201 if (ifa->ifam_type != rtm->rtm_type) { 202 nlog(LOG_INFO, 203 "routing_events_v4: unhandled type %d", 204 ifa->ifam_type); 205 break; 206 } 207 208 /* Create and enqueue IF_STATE event */ 209 ip_event = nwamd_event_init_if_state(if_name, 210 ifa->ifam_flags, 211 (rtm->rtm_type == RTM_NEWADDR || 212 rtm->rtm_type == RTM_CHGADDR ? B_TRUE : B_FALSE), 213 ifa->ifam_index, addr); 214 if (ip_event != NULL) 215 nwamd_event_enqueue(ip_event); 216 break; 217 218 case RTM_IFINFO: 219 220 ifm = (void *)rtm; 221 addrs = (char *)ifm + sizeof (*ifm); 222 nlog(LOG_DEBUG, "v4 routing message %s: " 223 "index %d flags %x", rtmtype_str(rtm->rtm_type), 224 ifm->ifm_index, ifm->ifm_flags); 225 printaddrs(ifm->ifm_addrs, addrs); 226 227 if ((addr_dl = (struct sockaddr_dl *)getaddr(RTA_IFP, 228 ifm->ifm_addrs, addrs)) == NULL) 229 break; 230 /* 231 * We don't use the lladdr in this structure so we can 232 * run over it. 233 */ 234 addr_dl->sdl_data[addr_dl->sdl_nlen] = 0; 235 if_name = addr_dl->sdl_data; /* no lifnum */ 236 237 if (ifm->ifm_index == 0) { 238 nlog(LOG_DEBUG, "tossing index 0 message"); 239 break; 240 } 241 if (ifm->ifm_type != RTM_IFINFO) { 242 nlog(LOG_DEBUG, 243 "routing_events_v4: unhandled type %d", 244 ifm->ifm_type); 245 break; 246 } 247 248 /* Create and enqueue IF_STATE event */ 249 ip_event = nwamd_event_init_if_state(if_name, 250 ifm->ifm_flags, B_FALSE, ifm->ifm_index, NULL); 251 if (ip_event != NULL) 252 nwamd_event_enqueue(ip_event); 253 break; 254 255 default: 256 nlog(LOG_DEBUG, "v4 routing message %s discarded", 257 rtmtype_str(rtm->rtm_type)); 258 break; 259 } 260 } 261 /* NOTREACHED */ 262 return (NULL); 263 } 264 265 /* ARGSUSED0 */ 266 static void * 267 routing_events_v6(void *arg) 268 { 269 int n; 270 union rtm_buf buffer; 271 struct rt_msghdr *rtm; 272 struct ifa_msghdr *ifa; 273 struct if_msghdr *ifm; 274 char *addrs, *if_name; 275 struct sockaddr_dl *addr_dl; 276 struct sockaddr *addr; 277 nwamd_event_t ip_event; 278 279 nlog(LOG_DEBUG, "v6 routing socket %d", v6_sock); 280 281 for (;;) { 282 283 rtm = &buffer.r.rtm; 284 n = read(v6_sock, &buffer, sizeof (buffer)); 285 if (n == -1 && errno == EAGAIN) { 286 continue; 287 } else if (n == -1) { 288 nlog(LOG_ERR, "error reading routing socket " 289 "%d: %m", v6_sock); 290 /* Low likelihood. What's recovery path? */ 291 continue; 292 } 293 294 if (rtm->rtm_msglen < n) { 295 nlog(LOG_ERR, "only read %d bytes from " 296 "routing socket but message claims to be " 297 "of length %d", rtm->rtm_msglen); 298 continue; 299 } 300 301 if (rtm->rtm_version != RTM_VERSION) { 302 nlog(LOG_ERR, "tossing routing message of " 303 "version %d type %d", rtm->rtm_version, 304 rtm->rtm_type); 305 continue; 306 } 307 308 if (rtm->rtm_msglen != n) { 309 nlog(LOG_DEBUG, "routing message of %d size came from " 310 "read of %d on socket %d", rtm->rtm_msglen, 311 n, v6_sock); 312 } 313 314 switch (rtm->rtm_type) { 315 case RTM_NEWADDR: 316 case RTM_DELADDR: 317 case RTM_CHGADDR: 318 case RTM_FREEADDR: 319 320 ifa = (void *)rtm; 321 addrs = (char *)ifa + sizeof (*ifa); 322 323 nlog(LOG_DEBUG, "v6 routing message %s: " 324 "index %d flags %x", rtmtype_str(rtm->rtm_type), 325 ifa->ifam_index, ifa->ifam_flags); 326 printaddrs(ifa->ifam_addrs, addrs); 327 328 if ((addr = (struct sockaddr *)getaddr(RTA_IFA, 329 ifa->ifam_addrs, addrs)) == NULL) 330 break; 331 332 /* Ignore messages for link local address */ 333 /*LINTED*/ 334 if (IN6_IS_ADDR_LINKLOCAL( 335 &((struct sockaddr_in6 *)addr)->sin6_addr)) { 336 nlog(LOG_INFO, "routing_events_v6: " 337 "tossing message for link local address"); 338 break; 339 } 340 341 if ((addr_dl = (struct sockaddr_dl *)getaddr 342 (RTA_IFP, ifa->ifam_addrs, addrs)) == NULL) 343 break; 344 /* 345 * We don't use the lladdr in this structure so we can 346 * run over it. 347 */ 348 addr_dl->sdl_data[addr_dl->sdl_nlen] = 0; 349 if_name = addr_dl->sdl_data; /* no lifnum */ 350 351 if (ifa->ifam_index == 0) { 352 nlog(LOG_DEBUG, "tossing index 0 message"); 353 break; 354 } 355 if (ifa->ifam_type != rtm->rtm_type) { 356 nlog(LOG_DEBUG, 357 "routing_events_v6: unhandled type %d", 358 ifa->ifam_type); 359 break; 360 } 361 362 /* Create and enqueue IF_STATE event */ 363 ip_event = nwamd_event_init_if_state(if_name, 364 ifa->ifam_flags, 365 (rtm->rtm_type == RTM_NEWADDR || 366 rtm->rtm_type == RTM_CHGADDR ? B_TRUE : B_FALSE), 367 ifa->ifam_index, addr); 368 if (ip_event != NULL) 369 nwamd_event_enqueue(ip_event); 370 break; 371 372 case RTM_IFINFO: 373 374 ifm = (void *)rtm; 375 addrs = (char *)ifm + sizeof (*ifm); 376 nlog(LOG_DEBUG, "v6 routing message %s: " 377 "index %d flags %x", rtmtype_str(rtm->rtm_type), 378 ifm->ifm_index, ifm->ifm_flags); 379 printaddrs(ifm->ifm_addrs, addrs); 380 381 if ((addr_dl = (struct sockaddr_dl *)getaddr(RTA_IFP, 382 ifm->ifm_addrs, addrs)) == NULL) 383 break; 384 /* 385 * We don't use the lladdr in this structure so we can 386 * run over it. 387 */ 388 addr_dl->sdl_data[addr_dl->sdl_nlen] = 0; 389 if_name = addr_dl->sdl_data; /* no lifnum */ 390 391 if (ifm->ifm_index == 0) { 392 nlog(LOG_DEBUG, "tossing index 0 message"); 393 break; 394 } 395 if (ifm->ifm_type != RTM_IFINFO) { 396 nlog(LOG_DEBUG, 397 "routing_events_v6: unhandled type %d", 398 ifm->ifm_type); 399 break; 400 } 401 402 /* Create and enqueue IF_STATE event */ 403 ip_event = nwamd_event_init_if_state(if_name, 404 ifm->ifm_flags, B_FALSE, ifm->ifm_index, NULL); 405 if (ip_event != NULL) 406 nwamd_event_enqueue(ip_event); 407 break; 408 409 default: 410 nlog(LOG_DEBUG, "v6 routing message %s discarded", 411 rtmtype_str(rtm->rtm_type)); 412 break; 413 } 414 } 415 /* NOTREACHED */ 416 return (NULL); 417 } 418 419 void 420 nwamd_routing_events_init(void) 421 { 422 pthread_attr_t attr; 423 424 /* 425 * Initialize routing sockets here so that we know the routing threads 426 * (and any requests to add a route) will be working with a valid socket 427 * by the time we start handling events. 428 */ 429 v4_sock = socket(AF_ROUTE, SOCK_RAW, AF_INET); 430 if (v4_sock == -1) 431 pfail("failed to open v4 routing socket: %m"); 432 433 v6_sock = socket(AF_ROUTE, SOCK_RAW, AF_INET6); 434 if (v6_sock == -1) 435 pfail("failed to open v6 routing socket: %m"); 436 437 (void) pthread_attr_init(&attr); 438 (void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 439 if (pthread_create(&v4_routing, &attr, routing_events_v4, NULL) != 0 || 440 pthread_create(&v6_routing, &attr, routing_events_v6, NULL) != 0) 441 pfail("routing thread creation failed"); 442 (void) pthread_attr_destroy(&attr); 443 } 444 445 void 446 nwamd_routing_events_fini(void) 447 { 448 (void) pthread_cancel(v4_routing); 449 (void) pthread_cancel(v6_routing); 450 } 451 452 void 453 nwamd_add_route(struct sockaddr *dest, struct sockaddr *mask, 454 struct sockaddr *gateway, const char *ifname) 455 { 456 char rtbuf[RTMBUFSZ]; 457 /* LINTED E_BAD_PTR_CAST_ALIGN */ 458 struct rt_msghdr *rtm = (struct rt_msghdr *)rtbuf; 459 void *addrs = rtbuf + sizeof (struct rt_msghdr); 460 struct sockaddr_dl sdl; 461 icfg_if_t intf; 462 icfg_handle_t h; 463 int rlen, index; 464 int af; 465 466 af = gateway->sa_family; 467 468 /* set interface for default route to be associated with */ 469 (void) strlcpy(intf.if_name, ifname, sizeof (intf.if_name)); 470 intf.if_protocol = af; 471 if (icfg_open(&h, &intf) != ICFG_SUCCESS) { 472 nlog(LOG_ERR, "nwamd_add_route: " 473 "icfg_open failed on %s", ifname); 474 return; 475 } 476 if (icfg_get_index(h, &index) != ICFG_SUCCESS) { 477 nlog(LOG_ERR, "nwamd_add_route: " 478 "icfg_get_index failed on %s", ifname); 479 } 480 icfg_close(h); 481 (void) bzero(&sdl, sizeof (struct sockaddr_dl)); 482 sdl.sdl_family = AF_LINK; 483 sdl.sdl_index = index; 484 485 (void) bzero(rtm, RTMBUFSZ); 486 rtm->rtm_pid = getpid(); 487 rtm->rtm_type = RTM_ADD; 488 rtm->rtm_flags = RTF_UP | RTF_STATIC | RTF_GATEWAY; 489 rtm->rtm_version = RTM_VERSION; 490 rtm->rtm_seq = ++seq; 491 rtm->rtm_msglen = sizeof (rtbuf); 492 setaddr(RTA_DST, &rtm->rtm_addrs, &addrs, dest); 493 setaddr(RTA_GATEWAY, &rtm->rtm_addrs, &addrs, gateway); 494 setaddr(RTA_NETMASK, &rtm->rtm_addrs, &addrs, mask); 495 setaddr(RTA_IFP, &rtm->rtm_addrs, &addrs, (struct sockaddr *)&sdl); 496 497 if ((rlen = write(af == AF_INET ? v4_sock : v6_sock, 498 rtbuf, rtm->rtm_msglen)) < 0) { 499 nlog(LOG_ERR, "nwamd_add_route: " 500 "got error %s writing to routing socket", strerror(errno)); 501 } else if (rlen < rtm->rtm_msglen) { 502 nlog(LOG_ERR, "nwamd_add_route: " 503 "only wrote %d bytes of %d to routing socket\n", 504 rlen, rtm->rtm_msglen); 505 } 506 } 507 508 static char * 509 printaddr(void **address) 510 { 511 static char buffer[80]; 512 sa_family_t family = *(sa_family_t *)*address; 513 struct sockaddr_in *s4 = *address; 514 struct sockaddr_in6 *s6 = *address; 515 struct sockaddr_dl *dl = *address; 516 517 switch (family) { 518 case AF_UNSPEC: 519 (void) inet_ntop(AF_UNSPEC, &s4->sin_addr, buffer, 520 sizeof (buffer)); 521 *address = (char *)*address + sizeof (*s4); 522 break; 523 case AF_INET: 524 (void) inet_ntop(AF_INET, &s4->sin_addr, buffer, 525 sizeof (buffer)); 526 *address = (char *)*address + sizeof (*s4); 527 break; 528 case AF_INET6: 529 (void) inet_ntop(AF_INET6, &s6->sin6_addr, buffer, 530 sizeof (buffer)); 531 *address = (char *)*address + sizeof (*s6); 532 break; 533 case AF_LINK: 534 (void) snprintf(buffer, sizeof (buffer), "link %.*s", 535 dl->sdl_nlen, dl->sdl_data); 536 *address = (char *)*address + sizeof (*dl); 537 break; 538 default: 539 /* 540 * We can't reliably update the size of this thing 541 * because we don't know what its type is. So bump 542 * it by a sockaddr_in and see what happens. The 543 * caller should really make sure this never happens. 544 */ 545 *address = (char *)*address + sizeof (*s4); 546 (void) snprintf(buffer, sizeof (buffer), 547 "unknown address family %d", family); 548 break; 549 } 550 return (buffer); 551 } 552 553 static void 554 printaddrs(int mask, void *address) 555 { 556 if (mask == 0) 557 return; 558 if (mask & RTA_DST) 559 nlog(LOG_DEBUG, "destination address: %s", printaddr(&address)); 560 if (mask & RTA_GATEWAY) 561 nlog(LOG_DEBUG, "gateway address: %s", printaddr(&address)); 562 if (mask & RTA_NETMASK) 563 nlog(LOG_DEBUG, "netmask: %s", printaddr(&address)); 564 if (mask & RTA_GENMASK) 565 nlog(LOG_DEBUG, "cloning mask: %s", printaddr(&address)); 566 if (mask & RTA_IFP) 567 nlog(LOG_DEBUG, "interface name: %s", printaddr(&address)); 568 if (mask & RTA_IFA) 569 nlog(LOG_DEBUG, "interface address: %s", printaddr(&address)); 570 if (mask & RTA_AUTHOR) 571 nlog(LOG_DEBUG, "author: %s", printaddr(&address)); 572 if (mask & RTA_BRD) 573 nlog(LOG_DEBUG, "broadcast address: %s", printaddr(&address)); 574 } 575 576 static void 577 nextaddr(void **address) 578 { 579 sa_family_t family = *(sa_family_t *)*address; 580 581 switch (family) { 582 case AF_UNSPEC: 583 case AF_INET: 584 *address = (char *)*address + sizeof (struct sockaddr_in); 585 break; 586 case AF_INET6: 587 *address = (char *)*address + sizeof (struct sockaddr_in6); 588 break; 589 case AF_LINK: 590 *address = (char *)*address + sizeof (struct sockaddr_dl); 591 break; 592 default: 593 nlog(LOG_ERR, "unknown af (%d) while parsing rtm", family); 594 break; 595 } 596 } 597 598 static void * 599 getaddr(int addrid, int mask, void *addresses) 600 { 601 int i; 602 void *p = addresses; 603 604 if ((mask & addrid) == 0) 605 return (NULL); 606 607 for (i = 1; i < addrid; i <<= 1) { 608 if (i & mask) 609 nextaddr(&p); 610 } 611 return (p); 612 } 613 614 static void 615 setaddr(int addrid, int *maskp, void *addressesp, struct sockaddr *address) 616 { 617 struct sockaddr *p = *((struct sockaddr **)addressesp); 618 619 *maskp |= addrid; 620 621 switch (address->sa_family) { 622 case AF_INET: 623 (void) memcpy(p, address, sizeof (struct sockaddr_in)); 624 break; 625 case AF_INET6: 626 (void) memcpy(p, address, sizeof (struct sockaddr_in6)); 627 break; 628 case AF_LINK: 629 (void) memcpy(p, address, sizeof (struct sockaddr_dl)); 630 break; 631 default: 632 nlog(LOG_ERR, "setaddr: unknown af (%d) while setting addr", 633 address->sa_family); 634 break; 635 } 636 nextaddr(addressesp); 637 } 638