Sync usage with man page.
[netbsd-mini2440.git] / sys / compat / darwin / darwin_route.c
blob46a06db1990c2998aeac8b88c4e0f21d060e0444
1 /* $NetBSD: darwin_route.c,v 1.15 2009/01/11 02:45:47 christos Exp $ */
3 /*-
4 * Copyright (c) 2004 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Emmanuel Dreyfus.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: darwin_route.c,v 1.15 2009/01/11 02:45:47 christos Exp $");
35 #include <sys/errno.h>
36 #include <sys/systm.h>
37 #include <sys/malloc.h>
39 #include <net/if.h>
41 #include <compat/darwin/darwin_types.h>
42 #include <compat/darwin/darwin_socket.h>
43 #include <compat/darwin/darwin_route.h>
45 static int darwin_copyout_sockaddr(struct sockaddr *, char **, size_t *, size_t);
47 #define ALIGN(a) (((a) + 3) & ~0x3UL)
48 int
49 darwin_ifaddrs(int af, char *dst, size_t *sizep)
51 struct darwin_if_msghdr dim;
52 struct ifnet *ifp;
53 int error;
54 int index = 1;
55 size_t size = 0;
56 size_t maxsize = *sizep;
57 uint8_t family;
59 af = darwin_to_native_af[af];
61 IFNET_FOREACH(ifp) {
62 struct ifaddr *ifa;
63 struct sockaddr *laddr = NULL;
66 * Find the link layer info as it is needed
67 * for computing darwin_if_msghdr's dim_len
69 IFADDR_FOREACH(ifa, ifp) {
70 if ((ifa->ifa_addr) &&
71 (ifa->ifa_addr->sa_family == AF_LINK)) {
72 laddr = (struct sockaddr *)ifa->ifa_addr;
73 break;
77 if (laddr == NULL) {
78 #ifdef DEBUG_DARWIN
79 printf("darwin_ifaddrs: cannot find link address\n");
80 #endif
81 continue;
84 dim.dim_len = sizeof(dim) + ALIGN(laddr->sa_len);
85 dim.dim_vers = DARWIN_RTM_VERSION;
86 dim.dim_type = DARWIN_RTM_IFINFO;
87 dim.dim_addrs = DARWIN_RTA_IFP;
88 dim.dim_flags = ifp->if_flags & 0xffff;
89 dim.dim_index = index++;
91 dim.dim_data.did_type = ifp->if_data.ifi_type; /* XXX */
92 dim.dim_data.did_typelen = 0 ;/* XXX */
93 dim.dim_data.did_physical = 0; /* XXX */
94 dim.dim_data.did_addrlen = ifp->if_data.ifi_addrlen;
95 dim.dim_data.did_hdrlen = ifp->if_data.ifi_hdrlen;
96 dim.dim_data.did_recquota = 0; /* XXX */
97 dim.dim_data.did_xmitquota = 0; /* XXX */
98 dim.dim_data.did_mtu = ifp->if_data.ifi_mtu;
99 dim.dim_data.did_metric = ifp->if_data.ifi_metric;
100 dim.dim_data.did_baudrate = ifp->if_data.ifi_baudrate;
101 dim.dim_data.did_ipackets = ifp->if_data.ifi_ipackets;
102 dim.dim_data.did_ierrors = ifp->if_data.ifi_ierrors;
103 dim.dim_data.did_opackets = ifp->if_data.ifi_opackets;
104 dim.dim_data.did_oerrors = ifp->if_data.ifi_oerrors;
105 dim.dim_data.did_collisions = ifp->if_data.ifi_collisions;
106 dim.dim_data.did_ibytes = ifp->if_data.ifi_ibytes;
107 dim.dim_data.did_obytes = ifp->if_data.ifi_obytes;
108 dim.dim_data.did_imcasts = ifp->if_data.ifi_imcasts;
109 dim.dim_data.did_omcasts = ifp->if_data.ifi_omcasts;
110 dim.dim_data.did_iqdrops = ifp->if_data.ifi_iqdrops;
111 dim.dim_data.did_noproto = ifp->if_data.ifi_noproto;
112 dim.dim_data.did_lastchange.tv_sec =
113 ifp->if_data.ifi_lastchange.tv_sec;
114 dim.dim_data.did_lastchange.tv_usec =
115 ifp->if_data.ifi_lastchange.tv_nsec * 1000;
116 dim.dim_data.did_default_proto = 0; /* XXX */
117 dim.dim_data.did_hwassist = 0; /* XXX */
119 size += sizeof(dim);
120 if (dst && (size <= maxsize)) {
121 if ((error = copyout(&dim, dst, sizeof(dim))) != 0)
122 return error;
123 dst += sizeof(dim);
126 /* Copy the link sockaddr. */
127 size += ALIGN(laddr->sa_len);
128 if (dst && (size <= maxsize)) {
129 if ((error = copyout(laddr, dst, laddr->sa_len)) != 0)
130 return error;
131 family = native_to_darwin_af[laddr->sa_family];
132 error = copyout(&family,
133 &((struct sockaddr *)dst)->sa_family, 1);
134 if (error != 0)
135 return error;
136 dst += ALIGN(laddr->sa_len);
139 IFADDR_FOREACH(ifa, ifp) {
140 struct darwin_ifa_msghdr diam;
141 int iaf;
143 if (ifa->ifa_addr) {
144 iaf = ifa->ifa_addr->sa_family;
145 if ((af != 0) && (iaf != af))
146 continue;
147 if (iaf > AF_MAX)
148 continue;
149 if (iaf == 0)
150 continue;
151 if (native_to_darwin_af[iaf] == 0)
152 continue;
153 /* Already handled earlier */
154 if (iaf == AF_LINK)
155 continue;
158 memset(&diam, 0, sizeof(diam));
160 diam.diam_len = sizeof(diam);
161 diam.diam_vers = DARWIN_RTM_VERSION;
162 diam.diam_type = DARWIN_RTM_NEWADDR;
165 * XXX the following code assumes that
166 * Darwin sockaddr have the same size as
167 * the original.
169 if (ifa->ifa_addr) {
170 diam.diam_addrs |= DARWIN_RTA_IFA;
171 diam.diam_len += ALIGN(ifa->ifa_addr->sa_len);
173 if (ifa->ifa_netmask) {
174 diam.diam_addrs |= DARWIN_RTA_NETMASK;
175 diam.diam_len +=
176 ALIGN(ifa->ifa_netmask->sa_len);
178 if ((ifa->ifa_dstaddr != NULL) &&
179 (ifp->if_flags & IFF_POINTOPOINT)) {
180 diam.diam_addrs |= DARWIN_RTA_DST;
181 diam.diam_len +=
182 ALIGN(ifa->ifa_dstaddr->sa_len);
184 if ((ifa->ifa_broadaddr != NULL) &&
185 (ifp->if_flags & IFF_BROADCAST)) {
186 diam.diam_addrs |= DARWIN_RTA_BRD;
187 diam.diam_len +=
188 ALIGN(ifa->ifa_broadaddr->sa_len);
191 diam.diam_flags = (int)ifa->ifa_flags;
192 diam.diam_index = dim.dim_index;
193 diam.diam_metric = ifa->ifa_metric;
195 size += sizeof(diam);
196 if (dst && (size <= maxsize)) {
197 error = copyout(&diam, dst, sizeof(diam));
198 if (error != 0)
199 return error;
200 dst += sizeof(diam);
204 * Interface netmask
205 * We sometime lack the af in native version:
206 * copy it from ifa_addr.
208 if (diam.diam_addrs & DARWIN_RTA_NETMASK) {
209 struct sockaddr_storage ss;
211 memcpy(&ss, ifa->ifa_netmask,
212 ifa->ifa_netmask->sa_len);
213 if ((ss.ss_family == 0) &&
214 (ifa->ifa_addr != NULL) &&
215 (ifa->ifa_addr->sa_family != 0))
216 ss.ss_family =
217 ifa->ifa_addr->sa_family;
219 if ((error = darwin_copyout_sockaddr(
220 (struct sockaddr *)&ss, &dst,
221 &size, maxsize)) != 0)
222 return error;
225 /* Interface address */
226 if (diam.diam_addrs & DARWIN_RTA_IFA)
227 if ((error = darwin_copyout_sockaddr(ifa->ifa_addr,
228 &dst, &size, maxsize)) != 0)
229 return error;
231 /* Interface remote address */
232 if (diam.diam_addrs & DARWIN_RTA_DST)
233 if ((error = darwin_copyout_sockaddr(ifa->ifa_dstaddr,
234 &dst, &size, maxsize)) != 0)
235 return error;
237 /* Interface broadcast address */
238 if (diam.diam_addrs & DARWIN_RTA_BRD)
239 if ((error =
240 darwin_copyout_sockaddr(ifa->ifa_broadaddr,
241 &dst, &size, maxsize)) != 0)
242 return error;
246 *sizep = size;
248 if (dst && (size > maxsize))
249 return ENOMEM;
251 return 0;
255 static int
256 darwin_copyout_sockaddr(struct sockaddr *sap, char **dstp, size_t *sizep, size_t maxsize)
258 size_t len;
259 int error;
260 uint8_t family;
262 len = sap->sa_len;
264 *sizep += ALIGN(len);
265 if (*dstp && (*sizep <= maxsize)) {
266 if ((error = copyout(sap, *dstp, len)) != 0)
267 return error;
268 family = native_to_darwin_af[sap->sa_family];
269 error = copyout(&family,
270 &((struct sockaddr *)*dstp)->sa_family, 1);
271 if (error != 0)
272 return error;
273 *dstp += ALIGN(len);
276 return 0;