]>
git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSMacOSX/CFSocketPuma.c
2 * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
25 * This file is not normally used.
26 * It can be conditionally compiled in by defining RUN_ON_PUMA_WITHOUT_IFADDRS
27 * in CFSocket.c. It is included mainly as sample code for people building
28 * for other platforms that (like Puma) lack the getifaddrs() call.
29 * NOTE: YOU CANNOT use this code to build an mDNSResponder daemon for Puma
30 * that works just like the Jaguar one, because Puma lacks other necessary
31 * functionality (like the LibInfo support to receive MIG messages from clients).
33 Change History (most recent first):
35 $Log: CFSocketPuma.c,v $
36 Revision 1.4 2003/08/12 19:56:25 cheshire
39 Revision 1.3 2003/07/02 21:19:51 cheshire
40 <rdar://problem/3313413> Update copyright notices, etc., in source code comments
42 Revision 1.2 2002/09/21 20:44:51 zarzycki
45 Revision 1.1 2002/09/17 01:36:23 cheshire
46 Move Puma support to CFSocketPuma.c
50 #include <sys/ioctl.h>
51 #include <sys/sockio.h>
52 #define ifaddrs ifa_info
54 #define ifa_broadaddr ifa_dstaddr /* broadcast address interface */
56 #include <sys/cdefs.h>
58 /* Our own header for the programs that need interface configuration info.
59 Include this file, instead of "unp.h". */
61 #define IFA_NAME 16 /* same as IFNAMSIZ in <net/if.h> */
62 #define IFA_HADDR 8 /* allow for 64-bit EUI-64 in future */
65 char ifa_name
[IFA_NAME
]; /* interface name, null terminated */
66 u_char ifa_haddr
[IFA_HADDR
]; /* hardware address */
67 u_short ifa_hlen
; /* #bytes in hardware address: 0, 6, 8 */
68 short ifa_flags
; /* IFF_xxx constants from <net/if.h> */
69 short ifa_myflags
; /* our own IFI_xxx flags */
70 struct sockaddr
*ifa_addr
; /* primary address */
71 struct sockaddr
*ifa_brdaddr
;/* broadcast address */
72 struct sockaddr
*ifa_dstaddr
;/* destination address */
73 struct ifa_info
*ifa_next
; /* next of these structures */
76 #define IFI_ALIAS 1 /* ifa_addr is an alias */
78 /* function prototypes */
79 struct ifa_info
*get_ifa_info(int, int);
80 struct ifa_info
*Get_ifa_info(int, int);
81 void free_ifa_info(struct ifa_info
*);
83 #define HAVE_SOCKADDR_SA_LEN 1
86 get_ifa_info(int family
, int doaliases
)
88 struct ifa_info
*ifi
, *ifihead
, **ifipnext
;
89 int sockfd
, len
, lastlen
, flags
, myflags
;
90 char *ptr
, *buf
, lastname
[IFNAMSIZ
], *cptr
;
92 struct ifreq
*ifr
, ifrcopy
;
93 struct sockaddr_in
*sinptr
;
95 sockfd
= socket(AF_INET
, SOCK_DGRAM
, 0);
98 len
= 100 * sizeof(struct ifreq
); /* initial buffer size guess */
100 buf
= (char *) malloc(len
);
103 if (ioctl(sockfd
, SIOCGIFCONF
, &ifc
) < 0) {
104 if (errno
!= EINVAL
|| lastlen
!= 0)
105 debugf("ioctl error");
107 if (ifc
.ifc_len
== lastlen
)
108 break; /* success, len has not changed */
109 lastlen
= ifc
.ifc_len
;
111 len
+= 10 * sizeof(struct ifreq
); /* increment */
117 /* end get_ifa_info1 */
119 /* include get_ifa_info2 */
120 for (ptr
= buf
; ptr
< buf
+ ifc
.ifc_len
; ) {
121 ifr
= (struct ifreq
*) ptr
;
123 #ifdef HAVE_SOCKADDR_SA_LEN
124 len
= MAX(sizeof(struct sockaddr
), ifr
->ifr_addr
.sa_len
);
126 switch (ifr
->ifr_addr
.sa_family
) {
129 len
= sizeof(struct sockaddr_in6
);
134 len
= sizeof(struct sockaddr
);
137 #endif /* HAVE_SOCKADDR_SA_LEN */
138 ptr
+= sizeof(ifr
->ifr_name
) + len
; /* for next one in buffer */
140 if (ifr
->ifr_addr
.sa_family
!= family
)
141 continue; /* ignore if not desired address family */
144 if ( (cptr
= strchr(ifr
->ifr_name
, ':')) != NULL
)
145 *cptr
= 0; /* replace colon will null */
146 if (strncmp(lastname
, ifr
->ifr_name
, IFNAMSIZ
) == 0) {
148 continue; /* already processed this interface */
151 memcpy(lastname
, ifr
->ifr_name
, IFNAMSIZ
);
154 ioctl(sockfd
, SIOCGIFFLAGS
, &ifrcopy
);
155 flags
= ifrcopy
.ifr_flags
;
156 if ((flags
& IFF_UP
) == 0)
157 continue; /* ignore if interface not up */
159 ifi
= (struct ifa_info
*) calloc(1, sizeof(struct ifa_info
));
160 *ifipnext
= ifi
; /* prev points to this new one */
161 ifipnext
= &ifi
->ifa_next
; /* pointer to next one goes here */
163 ifi
->ifa_flags
= flags
; /* IFF_xxx values */
164 ifi
->ifa_myflags
= myflags
; /* IFI_xxx values */
165 memcpy(ifi
->ifa_name
, ifr
->ifr_name
, IFA_NAME
);
166 ifi
->ifa_name
[IFA_NAME
-1] = '\0';
167 /* end get_ifa_info2 */
168 /* include get_ifa_info3 */
169 switch (ifr
->ifr_addr
.sa_family
) {
171 sinptr
= (struct sockaddr_in
*) &ifr
->ifr_addr
;
172 if (ifi
->ifa_addr
== NULL
) {
173 ifi
->ifa_addr
= (struct sockaddr
*) calloc(1, sizeof(struct sockaddr_in
));
174 memcpy(ifi
->ifa_addr
, sinptr
, sizeof(struct sockaddr_in
));
176 #ifdef SIOCGIFBRDADDR
177 if (flags
& IFF_BROADCAST
) {
178 ioctl(sockfd
, SIOCGIFBRDADDR
, &ifrcopy
);
179 sinptr
= (struct sockaddr_in
*) &ifrcopy
.ifr_broadaddr
;
180 ifi
->ifa_brdaddr
= (struct sockaddr
*) calloc(1, sizeof(struct sockaddr_in
));
181 memcpy(ifi
->ifa_brdaddr
, sinptr
, sizeof(struct sockaddr_in
));
185 #ifdef SIOCGIFDSTADDR
186 if (flags
& IFF_POINTOPOINT
) {
187 ioctl(sockfd
, SIOCGIFDSTADDR
, &ifrcopy
);
188 sinptr
= (struct sockaddr_in
*) &ifrcopy
.ifr_dstaddr
;
189 ifi
->ifa_dstaddr
= (struct sockaddr
*) calloc(1, sizeof(struct sockaddr_in
));
190 memcpy(ifi
->ifa_dstaddr
, sinptr
, sizeof(struct sockaddr_in
));
201 return(ifihead
); /* pointer to first structure in linked list */
203 /* end get_ifa_info3 */
205 /* include free_ifa_info */
206 mDNSlocal
void freeifaddrs(struct ifa_info
*ifihead
)
208 struct ifa_info
*ifi
, *ifinext
;
210 for (ifi
= ifihead
; ifi
!= NULL
; ifi
= ifinext
) {
211 if (ifi
->ifa_addr
!= NULL
)
213 if (ifi
->ifa_brdaddr
!= NULL
)
214 free(ifi
->ifa_brdaddr
);
215 if (ifi
->ifa_dstaddr
!= NULL
)
216 free(ifi
->ifa_dstaddr
);
217 ifinext
= ifi
->ifa_next
; /* can't fetch ifa_next after free() */
218 free(ifi
); /* the ifa_info{} itself */
221 /* end free_ifa_info */
224 Get_ifa_info(int family
, int doaliases
)
226 struct ifa_info
*ifi
;
228 if ( (ifi
= get_ifa_info(family
, doaliases
)) == NULL
)
229 debugf("get_ifa_info error");
233 mDNSlocal
int getifaddrs(struct ifa_info
**ifalist
)
235 *ifalist
= get_ifa_info(PF_INET
, false);