NetBSD/sys/compat/darwin/darwin_route.c

255 lines
7.9 KiB
C

/* $NetBSD: darwin_route.c,v 1.2 2004/07/21 20:57:30 manu Exp $ */
/*-
* Copyright (c) 2004 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Emmanuel Dreyfus.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: darwin_route.c,v 1.2 2004/07/21 20:57:30 manu Exp $");
#include <sys/errno.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <net/if.h>
#include <compat/darwin/darwin_socket.h>
#include <compat/darwin/darwin_route.h>
#define ALIGN(a) (((a) + 3) & ~0x3UL)
int
darwin_ifaddrs(af, dst, sizep)
int af;
char *dst;
size_t *sizep;
{
struct darwin_if_msghdr dim;
struct ifnet *ifp;
int error;
int index = 1;
size_t size = 0;
size_t maxsize = *sizep;
TAILQ_FOREACH(ifp, &ifnet, if_list) {
struct ifaddr *ifa;
size += sizeof(struct darwin_if_msghdr);
TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
size += sizeof(struct darwin_ifa_msghdr);
if (ifa->ifa_addr)
size += ALIGN(ifa->ifa_addr->sa_len);
if (ifa->ifa_netmask)
size += ALIGN(ifa->ifa_netmask->sa_len);
if ((ifa->ifa_dstaddr != NULL) &&
(ifp->if_flags & IFF_POINTOPOINT))
size += ALIGN(ifa->ifa_dstaddr->sa_len);
if ((ifa->ifa_broadaddr != NULL) &&
(ifp->if_flags & IFF_BROADCAST))
size += ALIGN(ifa->ifa_broadaddr->sa_len);
}
}
*sizep = size;
if (dst == NULL)
return 0;
if (size > maxsize)
return ENOMEM;
af = darwin_to_native_af[af];
TAILQ_FOREACH(ifp, &ifnet, if_list) {
struct ifaddr *ifa;
dim.dim_len = sizeof(dim);
dim.dim_vers = DARWIN_RTM_VERSION;
dim.dim_type = DARWIN_RTM_IFINFO;
dim.dim_addrs = DARWIN_RTA_IFP;
dim.dim_flags = ifp->if_flags & 0xffff;
dim.dim_index = index++;
dim.dim_data.did_type = ifp->if_data.ifi_type; /* XXX */
dim.dim_data.did_typelen = 0 ;/* XXX */
dim.dim_data.did_physical = 0; /* XXX */
dim.dim_data.did_addrlen = ifp->if_data.ifi_addrlen;
dim.dim_data.did_hdrlen = ifp->if_data.ifi_hdrlen;
dim.dim_data.did_recquota = 0; /* XXX */
dim.dim_data.did_xmitquota = 0; /* XXX */
dim.dim_data.did_mtu = ifp->if_data.ifi_mtu;
dim.dim_data.did_metric = ifp->if_data.ifi_metric;
dim.dim_data.did_baudrate = ifp->if_data.ifi_baudrate;
dim.dim_data.did_ipackets = ifp->if_data.ifi_ipackets;
dim.dim_data.did_ierrors = ifp->if_data.ifi_ierrors;
dim.dim_data.did_opackets = ifp->if_data.ifi_opackets;
dim.dim_data.did_oerrors = ifp->if_data.ifi_oerrors;
dim.dim_data.did_collisions = ifp->if_data.ifi_collisions;
dim.dim_data.did_ibytes = ifp->if_data.ifi_ibytes;
dim.dim_data.did_obytes = ifp->if_data.ifi_obytes;
dim.dim_data.did_imcasts = ifp->if_data.ifi_imcasts;
dim.dim_data.did_omcasts = ifp->if_data.ifi_omcasts;
dim.dim_data.did_iqdrops = ifp->if_data.ifi_iqdrops;
dim.dim_data.did_noproto = ifp->if_data.ifi_noproto;
dim.dim_data.did_lastchange.tv_sec =
ifp->if_data.ifi_lastchange.tv_sec;
dim.dim_data.did_lastchange.tv_usec =
ifp->if_data.ifi_lastchange.tv_usec;
dim.dim_data.did_default_proto = 0; /* XXX */
dim.dim_data.did_hwassist = 0; /* XXX */
dim.dim_index2 = dim.dim_index;
dim.dim_type2 = dim.dim_data.did_type;
dim.dim_xnamelen = strlen(ifp->if_xname);
strlcpy(&dim.dim_xname[0], &ifp->if_xname[0], IFNAMSIZ);
#ifdef DEBUG_DARWIN
printf("copyout dim 0x%x@%p\n", sizeof(dim), dst);
#endif
if ((error = copyout(&dim, dst, sizeof(dim))) != 0)
return error;
dst += sizeof(dim);
TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
struct darwin_ifa_msghdr diam;
if (ifa->ifa_addr) {
if ((af != 0) &&
(ifa->ifa_addr->sa_family != af))
continue;
if (ifa->ifa_addr->sa_family > AF_MAX)
continue;
if (ifa->ifa_addr->sa_family == 0);
continue;
}
bzero(&diam, sizeof(diam));
diam.diam_len = sizeof(diam);
diam.diam_vers = DARWIN_RTM_VERSION;
diam.diam_type = DARWIN_RTM_NEWADDR;
if (ifa->ifa_addr) {
diam.diam_addrs |= DARWIN_RTA_IFA;
diam.diam_len += ALIGN(ifa->ifa_addr->sa_len);
}
if (ifa->ifa_netmask) {
diam.diam_addrs |= DARWIN_RTA_NETMASK;
diam.diam_len +=
ALIGN(ifa->ifa_netmask->sa_len);
}
if ((ifa->ifa_dstaddr != NULL) &&
(ifp->if_flags & IFF_POINTOPOINT)) {
diam.diam_addrs |= DARWIN_RTA_DST;
diam.diam_len +=
ALIGN(ifa->ifa_dstaddr->sa_len);
}
if ((ifa->ifa_broadaddr != NULL) &&
(ifp->if_flags & IFF_BROADCAST)) {
diam.diam_addrs |= DARWIN_RTA_BRD;
diam.diam_len +=
ALIGN(ifa->ifa_broadaddr->sa_len);
}
diam.diam_flags = (int)ifa->ifa_flags;
diam.diam_index = dim.dim_index;
diam.diam_metric = ifa->ifa_metric;
#ifdef DEBUG_DARWIN
printf("copyout diam 0x%x@%p\n", sizeof(diam), dst);
#endif
if ((error = copyout(&diam, dst, sizeof(diam))) != 0)
return error;
dst += sizeof(diam);
/* Interface netmask */
if (diam.diam_addrs & DARWIN_RTA_NETMASK) {
struct sockaddr_storage sa;
size_t len = ifa->ifa_netmask->sa_len;
native_to_darwin_socket(ifa->ifa_netmask, &sa);
#ifdef DEBUG_DARWIN
printf("copyout netmask 0x%x@%p\n", len, dst);
#endif
if ((error = copyout(&sa, dst, len)) != 0)
return error;
dst += ALIGN(len);
}
/* Interface address */
if (diam.diam_addrs & DARWIN_RTA_IFA) {
struct sockaddr_storage sa;
size_t len = ifa->ifa_addr->sa_len;
native_to_darwin_socket(ifa->ifa_addr, &sa);
#ifdef DEBUG_DARWIN
printf("copyout ifa 0x%x@%p\n", len, dst);
#endif
if ((error = copyout(&sa, dst, len)) != 0)
return error;
dst += ALIGN(len);
}
/* Interface remote address */
if (diam.diam_addrs & DARWIN_RTA_DST) {
struct sockaddr_storage sa;
size_t len = ifa->ifa_dstaddr->sa_len;
native_to_darwin_socket(ifa->ifa_dstaddr, &sa);
#ifdef DEBUG_DARWIN
printf("copyout dst 0x%x@%p\n", len, dst);
#endif
if ((error = copyout(&sa, dst, len)) != 0)
return error;
dst += len;
}
/* Interface broadcast address */
if (diam.diam_addrs & DARWIN_RTA_BRD) {
struct sockaddr_storage sa;
size_t len = ifa->ifa_broadaddr->sa_len;
native_to_darwin_socket(ifa->ifa_broadaddr,
&sa);
#ifdef DEBUG_DARWIN
printf("copyout broad 0x%x@%p\n", len, dst);
#endif
if ((error = copyout(&sa, dst, len)) != 0)
return error;
dst += len;
}
}
}
return 0;
}