6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * CDDL HEADER START
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * The contents of this file are subject to the terms of the
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Common Development and Distribution License (the "License").
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * You may not use this file except in compliance with the License.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * or http://www.opensolaris.org/os/licensing.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * See the License for the specific language governing permissions
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * and limitations under the License.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * When distributing Covered Code, include this CDDL HEADER in each
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * If applicable, add the following below this CDDL HEADER, with the
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * fields enclosed by brackets "[]" replaced with your own identifying
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * information: Portions Copyright [yyyy] [name of copyright owner]
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * CDDL HEADER END
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * routing_events.c - this file contains routines to retrieve routing socket
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * events and package them for high level processing.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#define RTMBUFSZ sizeof (struct rt_msghdr) + \
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (RTAX_MAX * sizeof (struct sockaddr_storage))
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic void printaddrs(int, void *);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic char *printaddr(void **);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic void *getaddr(int, int, void *);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic void setaddr(int, int *, void *, struct sockaddr *);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* Routing information. */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* Interface information. */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* Interface address information. */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic const char *
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey static char typestr[12]; /* strlen("type ") + enough for an int */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return ("NEWADDR");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return ("DELADDR");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return ("CHGADDR");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return ("FREEADDR");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) snprintf(typestr, sizeof (typestr), "type %d", type);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/* ARGSUSED0 */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "v4 routing socket %d", v4_sock);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey n = read(v4_sock, &buffer, sizeof (buffer));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else if (n == -1) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "error reading routing socket "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* Low likelihood. What's recovery path? */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "routing socket but message claims to be "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "tossing routing message of "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "routing message of %d size came from "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "read of %d on socket %d", rtm->rtm_msglen,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "index %d flags %x", rtmtype_str(rtm->rtm_type),
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((addr = (struct sockaddr *)getaddr(RTA_IFA,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* Ignore routing socket messages for 0.0.0.0 */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (((struct sockaddr_in *)addr)->sin_addr.s_addr
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "tossing message for 0.0.0.0");
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if ((netmask = (struct sockaddr *)getaddr(RTA_NETMASK,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((addr_dl = (struct sockaddr_dl *)getaddr
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (RTA_IFP, ifa->ifam_addrs, addrs)) == NULL)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * We don't use the lladdr in this structure so we can
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * run over it.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if_name = addr_dl->sdl_data; /* no lifnum */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "tossing index 0 message");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "routing_events_v4: unhandled type %d",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* Create and enqueue IF_STATE event */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ip_event = nwamd_event_init_if_state(if_name,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey rtm->rtm_type == RTM_CHGADDR ? B_TRUE : B_FALSE),
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* NOTREACHED */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/* ARGSUSED0 */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "v6 routing socket %d", v6_sock);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey n = read(v6_sock, &buffer, sizeof (buffer));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else if (n == -1) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "error reading routing socket "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* Low likelihood. What's recovery path? */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "routing socket but message claims to be "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "tossing routing message of "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "routing message of %d size came from "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "read of %d on socket %d", rtm->rtm_msglen,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "index %d flags %x", rtmtype_str(rtm->rtm_type),
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((addr = (struct sockaddr *)getaddr(RTA_IFA,
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey /* Ignore routing socket messages for :: & linklocal */
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey &((struct sockaddr_in6 *)addr)->sin6_addr)) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey "tossing message for ::");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey &((struct sockaddr_in6 *)addr)->sin6_addr)) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "tossing message for link local address");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((addr_dl = (struct sockaddr_dl *)getaddr
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (RTA_IFP, ifa->ifam_addrs, addrs)) == NULL)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * We don't use the lladdr in this structure so we can
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * run over it.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if_name = addr_dl->sdl_data; /* no lifnum */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "tossing index 0 message");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "routing_events_v6: unhandled type %d",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* Create and enqueue IF_STATE event */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ip_event = nwamd_event_init_if_state(if_name,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey rtm->rtm_type == RTM_CHGADDR ? B_TRUE : B_FALSE),
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* NOTREACHED */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Initialize routing sockets here so that we know the routing threads
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * (and any requests to add a route) will be working with a valid socket
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * by the time we start handling events.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey v4_sock = socket(AF_ROUTE, SOCK_RAW, AF_INET);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey pfail("failed to open v4 routing socket: %m");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey v6_sock = socket(AF_ROUTE, SOCK_RAW, AF_INET6);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey pfail("failed to open v6 routing socket: %m");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (pthread_create(&v4_routing, &attr, routing_events_v4, NULL) != 0 ||
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey pthread_create(&v6_routing, &attr, routing_events_v6, NULL) != 0)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwamd_add_route(struct sockaddr *dest, struct sockaddr *mask,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct sockaddr *gateway, const char *ifname)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* LINTED E_BAD_PTR_CAST_ALIGN */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct rt_msghdr *rtm = (struct rt_msghdr *)rtbuf;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey void *addrs = rtbuf + sizeof (struct rt_msghdr);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey /* retrieve the index value for the interface */
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if ((index = if_nametoindex(ifname)) == 0) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nlog(LOG_ERR, "nwamd_add_route: if_nametoindex failed on %s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) bzero(&sdl, sizeof (struct sockaddr_dl));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey rtm->rtm_flags = RTF_UP | RTF_STATIC | RTF_GATEWAY;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey setaddr(RTA_DST, &rtm->rtm_addrs, &addrs, dest);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey setaddr(RTA_GATEWAY, &rtm->rtm_addrs, &addrs, gateway);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey setaddr(RTA_NETMASK, &rtm->rtm_addrs, &addrs, mask);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey setaddr(RTA_IFP, &rtm->rtm_addrs, &addrs, (struct sockaddr *)&sdl);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((rlen = write(af == AF_INET ? v4_sock : v6_sock,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "got error %s writing to routing socket", strerror(errno));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "only wrote %d bytes of %d to routing socket\n",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey sa_family_t family = *(sa_family_t *)*address;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) inet_ntop(AF_UNSPEC, &s4->sin_addr, buffer,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey *address = (char *)*address + sizeof (*s4);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) inet_ntop(AF_INET, &s4->sin_addr, buffer,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey *address = (char *)*address + sizeof (*s4);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) inet_ntop(AF_INET6, &s6->sin6_addr, buffer,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey *address = (char *)*address + sizeof (*s6);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) snprintf(buffer, sizeof (buffer), "link %.*s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey *address = (char *)*address + sizeof (*dl);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * We can't reliably update the size of this thing
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * because we don't know what its type is. So bump
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * it by a sockaddr_in and see what happens. The
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * caller should really make sure this never happens.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey *address = (char *)*address + sizeof (*s4);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "destination address: %s", printaddr(&address));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "gateway address: %s", printaddr(&address));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "netmask: %s", printaddr(&address));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "cloning mask: %s", printaddr(&address));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "interface name: %s", printaddr(&address));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "interface address: %s", printaddr(&address));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "author: %s", printaddr(&address));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "broadcast address: %s", printaddr(&address));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey sa_family_t family = *(sa_family_t *)*address;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey *address = (char *)*address + sizeof (struct sockaddr_in);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey *address = (char *)*address + sizeof (struct sockaddr_in6);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey *address = (char *)*address + sizeof (struct sockaddr_dl);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "unknown af (%d) while parsing rtm", family);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeygetaddr(int addrid, int mask, void *addresses)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeysetaddr(int addrid, int *maskp, void *addressesp, struct sockaddr *address)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct sockaddr *p = *((struct sockaddr **)addressesp);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) memcpy(p, address, sizeof (struct sockaddr_in));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) memcpy(p, address, sizeof (struct sockaddr_in6));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) memcpy(p, address, sizeof (struct sockaddr_dl));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "setaddr: unknown af (%d) while setting addr",