1 /* $NetBSD: darwin_route.c,v 1.15 2009/01/11 02:45:47 christos Exp $ */
4 * Copyright (c) 2004 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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>
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)
49 darwin_ifaddrs(int af
, char *dst
, size_t *sizep
)
51 struct darwin_if_msghdr dim
;
56 size_t maxsize
= *sizep
;
59 af
= darwin_to_native_af
[af
];
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
;
79 printf("darwin_ifaddrs: cannot find link address\n");
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 */
120 if (dst
&& (size
<= maxsize
)) {
121 if ((error
= copyout(&dim
, dst
, sizeof(dim
))) != 0)
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)
131 family
= native_to_darwin_af
[laddr
->sa_family
];
132 error
= copyout(&family
,
133 &((struct sockaddr
*)dst
)->sa_family
, 1);
136 dst
+= ALIGN(laddr
->sa_len
);
139 IFADDR_FOREACH(ifa
, ifp
) {
140 struct darwin_ifa_msghdr diam
;
144 iaf
= ifa
->ifa_addr
->sa_family
;
145 if ((af
!= 0) && (iaf
!= af
))
151 if (native_to_darwin_af
[iaf
] == 0)
153 /* Already handled earlier */
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
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
;
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
;
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
;
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
));
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))
217 ifa
->ifa_addr
->sa_family
;
219 if ((error
= darwin_copyout_sockaddr(
220 (struct sockaddr
*)&ss
, &dst
,
221 &size
, maxsize
)) != 0)
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)
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)
237 /* Interface broadcast address */
238 if (diam
.diam_addrs
& DARWIN_RTA_BRD
)
240 darwin_copyout_sockaddr(ifa
->ifa_broadaddr
,
241 &dst
, &size
, maxsize
)) != 0)
248 if (dst
&& (size
> maxsize
))
256 darwin_copyout_sockaddr(struct sockaddr
*sap
, char **dstp
, size_t *sizep
, size_t maxsize
)
264 *sizep
+= ALIGN(len
);
265 if (*dstp
&& (*sizep
<= maxsize
)) {
266 if ((error
= copyout(sap
, *dstp
, len
)) != 0)
268 family
= native_to_darwin_af
[sap
->sa_family
];
269 error
= copyout(&family
,
270 &((struct sockaddr
*)*dstp
)->sa_family
, 1);