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