6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * CDDL HEADER START
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey *
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 *
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 *
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 *
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * CDDL HEADER END
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <arpa/inet.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <assert.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <errno.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <fcntl.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <net/if.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <net/route.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <pthread.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <stdio.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <stdlib.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <string.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <strings.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <sys/fcntl.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <unistd.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <libnwam.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include "events.h"
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include "ncp.h"
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include "ncu.h"
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include "util.h"
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
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 */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#define RTMBUFSZ sizeof (struct rt_msghdr) + \
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (RTAX_MAX * sizeof (struct sockaddr_storage))
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
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
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyunion rtm_buf
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* Routing information. */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct rt_msghdr rtm;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct sockaddr_storage addr[RTAX_MAX];
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } r;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* Interface information. */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct if_msghdr ifm;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct sockaddr_storage addr[RTAX_MAX];
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } im;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* Interface address information. */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct ifa_msghdr ifa;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct sockaddr_storage addr[RTAX_MAX];
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } ia;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey};
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic int v4_sock = -1;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic int v6_sock = -1;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic pthread_t v4_routing, v6_routing;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic int seq = 0;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic const char *
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyrtmtype_str(int type)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey static char typestr[12]; /* strlen("type ") + enough for an int */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey switch (type) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey case RTM_NEWADDR:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return ("NEWADDR");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey case RTM_DELADDR:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return ("DELADDR");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey case RTM_CHGADDR:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return ("CHGADDR");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey case RTM_FREEADDR:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return ("FREEADDR");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey default:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) snprintf(typestr, sizeof (typestr), "type %d", type);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (typestr);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/* ARGSUSED0 */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic void *
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyrouting_events_v4(void *arg)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey int n;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey union rtm_buf buffer;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct rt_msghdr *rtm;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct ifa_msghdr *ifa;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char *addrs, *if_name;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct sockaddr_dl *addr_dl;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey struct sockaddr *addr, *netmask;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_event_t ip_event;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "v4 routing socket %d", v4_sock);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey for (;;) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey rtm = &buffer.r.rtm;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey n = read(v4_sock, &buffer, sizeof (buffer));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (n == -1 && errno == EAGAIN) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey continue;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else if (n == -1) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "error reading routing socket "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "%d: %m", v4_sock);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* Low likelihood. What's recovery path? */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey continue;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (rtm->rtm_msglen < n) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "only read %d bytes from "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "routing socket but message claims to be "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "of length %d", rtm->rtm_msglen);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey continue;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (rtm->rtm_version != RTM_VERSION) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "tossing routing message of "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "version %d type %d", rtm->rtm_version,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey rtm->rtm_type);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey continue;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (rtm->rtm_msglen != n) {
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 n, v4_sock);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey switch (rtm->rtm_type) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey case RTM_NEWADDR:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey case RTM_DELADDR:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey case RTM_CHGADDR:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey case RTM_FREEADDR:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ifa = (void *)rtm;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey addrs = (char *)ifa + sizeof (*ifa);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "v4 routing message %s: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "index %d flags %x", rtmtype_str(rtm->rtm_type),
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ifa->ifam_index, ifa->ifam_flags);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((addr = (struct sockaddr *)getaddr(RTA_IFA,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ifa->ifam_addrs, addrs)) == NULL)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* Ignore routing socket messages for 0.0.0.0 */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*LINTED*/
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (((struct sockaddr_in *)addr)->sin_addr.s_addr
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey == INADDR_ANY) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "routing_events_v4: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "tossing message for 0.0.0.0");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if ((netmask = (struct sockaddr *)getaddr(RTA_NETMASK,
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ifa->ifam_addrs, addrs)) == NULL)
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey break;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((addr_dl = (struct sockaddr_dl *)getaddr
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (RTA_IFP, ifa->ifam_addrs, addrs)) == NULL)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * We don't use the lladdr in this structure so we can
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * run over it.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey addr_dl->sdl_data[addr_dl->sdl_nlen] = 0;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if_name = addr_dl->sdl_data; /* no lifnum */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (ifa->ifam_index == 0) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "tossing index 0 message");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (ifa->ifam_type != rtm->rtm_type) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_INFO,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "routing_events_v4: unhandled type %d",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ifa->ifam_type);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey printaddrs(ifa->ifam_addrs, addrs);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* Create and enqueue IF_STATE event */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ip_event = nwamd_event_init_if_state(if_name,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ifa->ifam_flags,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (rtm->rtm_type == RTM_NEWADDR ||
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey rtm->rtm_type == RTM_CHGADDR ? B_TRUE : B_FALSE),
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey addr, netmask);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (ip_event != NULL)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_event_enqueue(ip_event);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* NOTREACHED */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (NULL);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/* ARGSUSED0 */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic void *
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyrouting_events_v6(void *arg)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey int n;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey union rtm_buf buffer;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct rt_msghdr *rtm;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct ifa_msghdr *ifa;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char *addrs, *if_name;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct sockaddr_dl *addr_dl;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey struct sockaddr *addr, *netmask;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_event_t ip_event;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "v6 routing socket %d", v6_sock);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey for (;;) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey rtm = &buffer.r.rtm;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey n = read(v6_sock, &buffer, sizeof (buffer));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (n == -1 && errno == EAGAIN) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey continue;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else if (n == -1) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "error reading routing socket "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "%d: %m", v6_sock);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* Low likelihood. What's recovery path? */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey continue;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (rtm->rtm_msglen < n) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "only read %d bytes from "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "routing socket but message claims to be "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "of length %d", rtm->rtm_msglen);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey continue;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (rtm->rtm_version != RTM_VERSION) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "tossing routing message of "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "version %d type %d", rtm->rtm_version,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey rtm->rtm_type);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey continue;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (rtm->rtm_msglen != n) {
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 n, v6_sock);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey switch (rtm->rtm_type) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey case RTM_NEWADDR:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey case RTM_DELADDR:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey case RTM_CHGADDR:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey case RTM_FREEADDR:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ifa = (void *)rtm;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey addrs = (char *)ifa + sizeof (*ifa);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "v6 routing message %s: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "index %d flags %x", rtmtype_str(rtm->rtm_type),
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ifa->ifam_index, ifa->ifam_flags);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((addr = (struct sockaddr *)getaddr(RTA_IFA,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ifa->ifam_addrs, addrs)) == NULL)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey /* Ignore routing socket messages for :: & linklocal */
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey /*LINTED*/
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (IN6_IS_ADDR_UNSPECIFIED(
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey &((struct sockaddr_in6 *)addr)->sin6_addr)) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nlog(LOG_INFO, "routing_events_v6: "
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey "tossing message for ::");
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey break;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*LINTED*/
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (IN6_IS_ADDR_LINKLOCAL(
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey &((struct sockaddr_in6 *)addr)->sin6_addr)) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_INFO, "routing_events_v6: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "tossing message for link local address");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if ((netmask =
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey (struct sockaddr *)getaddr(RTA_NETMASK,
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ifa->ifam_addrs, addrs)) == NULL)
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey break;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((addr_dl = (struct sockaddr_dl *)getaddr
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (RTA_IFP, ifa->ifam_addrs, addrs)) == NULL)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * We don't use the lladdr in this structure so we can
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * run over it.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey addr_dl->sdl_data[addr_dl->sdl_nlen] = 0;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if_name = addr_dl->sdl_data; /* no lifnum */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (ifa->ifam_index == 0) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "tossing index 0 message");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (ifa->ifam_type != rtm->rtm_type) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "routing_events_v6: unhandled type %d",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ifa->ifam_type);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey printaddrs(ifa->ifam_addrs, addrs);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* Create and enqueue IF_STATE event */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ip_event = nwamd_event_init_if_state(if_name,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ifa->ifam_flags,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (rtm->rtm_type == RTM_NEWADDR ||
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey rtm->rtm_type == RTM_CHGADDR ? B_TRUE : B_FALSE),
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey addr, netmask);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (ip_event != NULL)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_event_enqueue(ip_event);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* NOTREACHED */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (NULL);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyvoid
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwamd_routing_events_init(void)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey pthread_attr_t attr;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
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 */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey v4_sock = socket(AF_ROUTE, SOCK_RAW, AF_INET);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (v4_sock == -1)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey pfail("failed to open v4 routing socket: %m");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey v6_sock = socket(AF_ROUTE, SOCK_RAW, AF_INET6);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (v6_sock == -1)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey pfail("failed to open v6 routing socket: %m");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) pthread_attr_init(&attr);
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. Maskey pfail("routing thread creation failed");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) pthread_attr_destroy(&attr);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyvoid
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwamd_routing_events_fini(void)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) pthread_cancel(v4_routing);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) pthread_cancel(v6_routing);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyvoid
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwamd_add_route(struct sockaddr *dest, struct sockaddr *mask,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct sockaddr *gateway, const char *ifname)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char rtbuf[RTMBUFSZ];
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);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct sockaddr_dl sdl;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey int rlen, index;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey int af;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey af = gateway->sa_family;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
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",
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ifname);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) bzero(&sdl, sizeof (struct sockaddr_dl));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey sdl.sdl_family = AF_LINK;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey sdl.sdl_index = index;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) bzero(rtm, RTMBUFSZ);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey rtm->rtm_pid = getpid();
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey rtm->rtm_type = RTM_ADD;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey rtm->rtm_flags = RTF_UP | RTF_STATIC | RTF_GATEWAY;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey rtm->rtm_version = RTM_VERSION;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey rtm->rtm_seq = ++seq;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey rtm->rtm_msglen = sizeof (rtbuf);
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
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((rlen = write(af == AF_INET ? v4_sock : v6_sock,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey rtbuf, rtm->rtm_msglen)) < 0) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "nwamd_add_route: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "got error %s writing to routing socket", strerror(errno));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else if (rlen < rtm->rtm_msglen) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "nwamd_add_route: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "only wrote %d bytes of %d to routing socket\n",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey rlen, rtm->rtm_msglen);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic char *
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyprintaddr(void **address)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey static char buffer[80];
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey sa_family_t family = *(sa_family_t *)*address;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct sockaddr_in *s4 = *address;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct sockaddr_in6 *s6 = *address;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct sockaddr_dl *dl = *address;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey switch (family) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey case AF_UNSPEC:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) inet_ntop(AF_UNSPEC, &s4->sin_addr, buffer,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey sizeof (buffer));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey *address = (char *)*address + sizeof (*s4);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey case AF_INET:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) inet_ntop(AF_INET, &s4->sin_addr, buffer,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey sizeof (buffer));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey *address = (char *)*address + sizeof (*s4);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey case AF_INET6:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) inet_ntop(AF_INET6, &s6->sin6_addr, buffer,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey sizeof (buffer));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey *address = (char *)*address + sizeof (*s6);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey case AF_LINK:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) snprintf(buffer, sizeof (buffer), "link %.*s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey dl->sdl_nlen, dl->sdl_data);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey *address = (char *)*address + sizeof (*dl);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey default:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
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 */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey *address = (char *)*address + sizeof (*s4);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) snprintf(buffer, sizeof (buffer),
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "unknown address family %d", family);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (buffer);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic void
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyprintaddrs(int mask, void *address)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (mask == 0)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (mask & RTA_DST)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "destination address: %s", printaddr(&address));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (mask & RTA_GATEWAY)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "gateway address: %s", printaddr(&address));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (mask & RTA_NETMASK)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "netmask: %s", printaddr(&address));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (mask & RTA_GENMASK)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "cloning mask: %s", printaddr(&address));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (mask & RTA_IFP)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "interface name: %s", printaddr(&address));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (mask & RTA_IFA)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "interface address: %s", printaddr(&address));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (mask & RTA_AUTHOR)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "author: %s", printaddr(&address));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (mask & RTA_BRD)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "broadcast address: %s", printaddr(&address));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic void
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynextaddr(void **address)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey sa_family_t family = *(sa_family_t *)*address;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey switch (family) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey case AF_UNSPEC:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey case AF_INET:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey *address = (char *)*address + sizeof (struct sockaddr_in);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey case AF_INET6:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey *address = (char *)*address + sizeof (struct sockaddr_in6);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey case AF_LINK:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey *address = (char *)*address + sizeof (struct sockaddr_dl);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey default:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "unknown af (%d) while parsing rtm", family);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic void *
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeygetaddr(int addrid, int mask, void *addresses)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey int i;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey void *p = addresses;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((mask & addrid) == 0)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (NULL);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey for (i = 1; i < addrid; i <<= 1) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (i & mask)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nextaddr(&p);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (p);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic void
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeysetaddr(int addrid, int *maskp, void *addressesp, struct sockaddr *address)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct sockaddr *p = *((struct sockaddr **)addressesp);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey *maskp |= addrid;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey switch (address->sa_family) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey case AF_INET:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) memcpy(p, address, sizeof (struct sockaddr_in));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey case AF_INET6:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) memcpy(p, address, sizeof (struct sockaddr_in6));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey case AF_LINK:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) memcpy(p, address, sizeof (struct sockaddr_dl));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey default:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "setaddr: unknown af (%d) while setting addr",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey address->sa_family);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nextaddr(addressesp);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}