]>
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 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
23 * This file is not normally used.
24 * It can be conditionally compiled in by defining RUN_ON_PUMA_WITHOUT_IFADDRS
25 * in CFSocket.c. It is included mainly as sample code for people building
26 * for other platforms that (like Puma) lack the getifaddrs() call.
27 * NOTE: YOU CANNOT use this code to build an mDNSResponder daemon for Puma
28 * that works just like the Jaguar one, because Puma lacks other necessary
29 * functionality (like the LibInfo support to receive MIG messages from clients).
31 Change History (most recent first):
33 $Log: CFSocketPuma.c,v $
34 Revision 1.4 2003/08/12 19:56:25 cheshire
37 Revision 1.3 2003/07/02 21:19:51 cheshire
38 <rdar://problem/3313413> Update copyright notices, etc., in source code comments
40 Revision 1.2 2002/09/21 20:44:51 zarzycki
43 Revision 1.1 2002/09/17 01:36:23 cheshire
44 Move Puma support to CFSocketPuma.c
48 #include <sys/ioctl.h>
49 #include <sys/sockio.h>
50 #define ifaddrs ifa_info
52 #define ifa_broadaddr ifa_dstaddr /* broadcast address interface */
54 #include <sys/cdefs.h>
56 /* Our own header for the programs that need interface configuration info.
57 Include this file, instead of "unp.h". */
59 #define IFA_NAME 16 /* same as IFNAMSIZ in <net/if.h> */
60 #define IFA_HADDR 8 /* allow for 64-bit EUI-64 in future */
63 char ifa_name
[IFA_NAME
]; /* interface name, null terminated */
64 u_char ifa_haddr
[IFA_HADDR
]; /* hardware address */
65 u_short ifa_hlen
; /* #bytes in hardware address: 0, 6, 8 */
66 short ifa_flags
; /* IFF_xxx constants from <net/if.h> */
67 short ifa_myflags
; /* our own IFI_xxx flags */
68 struct sockaddr
*ifa_addr
; /* primary address */
69 struct sockaddr
*ifa_brdaddr
;/* broadcast address */
70 struct sockaddr
*ifa_dstaddr
;/* destination address */
71 struct ifa_info
*ifa_next
; /* next of these structures */
74 #define IFI_ALIAS 1 /* ifa_addr is an alias */
76 /* function prototypes */
77 struct ifa_info
*get_ifa_info(int, int);
78 struct ifa_info
*Get_ifa_info(int, int);
79 void free_ifa_info(struct ifa_info
*);
81 #define HAVE_SOCKADDR_SA_LEN 1
84 get_ifa_info(int family
, int doaliases
)
86 struct ifa_info
*ifi
, *ifihead
, **ifipnext
;
87 int sockfd
, len
, lastlen
, flags
, myflags
;
88 char *ptr
, *buf
, lastname
[IFNAMSIZ
], *cptr
;
90 struct ifreq
*ifr
, ifrcopy
;
91 struct sockaddr_in
*sinptr
;
93 sockfd
= socket(AF_INET
, SOCK_DGRAM
, 0);
96 len
= 100 * sizeof(struct ifreq
); /* initial buffer size guess */
98 buf
= (char *) malloc(len
);
101 if (ioctl(sockfd
, SIOCGIFCONF
, &ifc
) < 0) {
102 if (errno
!= EINVAL
|| lastlen
!= 0)
103 debugf("ioctl error");
105 if (ifc
.ifc_len
== lastlen
)
106 break; /* success, len has not changed */
107 lastlen
= ifc
.ifc_len
;
109 len
+= 10 * sizeof(struct ifreq
); /* increment */
115 /* end get_ifa_info1 */
117 /* include get_ifa_info2 */
118 for (ptr
= buf
; ptr
< buf
+ ifc
.ifc_len
; ) {
119 ifr
= (struct ifreq
*) ptr
;
121 #ifdef HAVE_SOCKADDR_SA_LEN
122 len
= MAX(sizeof(struct sockaddr
), ifr
->ifr_addr
.sa_len
);
124 switch (ifr
->ifr_addr
.sa_family
) {
127 len
= sizeof(struct sockaddr_in6
);
132 len
= sizeof(struct sockaddr
);
135 #endif /* HAVE_SOCKADDR_SA_LEN */
136 ptr
+= sizeof(ifr
->ifr_name
) + len
; /* for next one in buffer */
138 if (ifr
->ifr_addr
.sa_family
!= family
)
139 continue; /* ignore if not desired address family */
142 if ( (cptr
= strchr(ifr
->ifr_name
, ':')) != NULL
)
143 *cptr
= 0; /* replace colon will null */
144 if (strncmp(lastname
, ifr
->ifr_name
, IFNAMSIZ
) == 0) {
146 continue; /* already processed this interface */
149 memcpy(lastname
, ifr
->ifr_name
, IFNAMSIZ
);
152 ioctl(sockfd
, SIOCGIFFLAGS
, &ifrcopy
);
153 flags
= ifrcopy
.ifr_flags
;
154 if ((flags
& IFF_UP
) == 0)
155 continue; /* ignore if interface not up */
157 ifi
= (struct ifa_info
*) calloc(1, sizeof(struct ifa_info
));
158 *ifipnext
= ifi
; /* prev points to this new one */
159 ifipnext
= &ifi
->ifa_next
; /* pointer to next one goes here */
161 ifi
->ifa_flags
= flags
; /* IFF_xxx values */
162 ifi
->ifa_myflags
= myflags
; /* IFI_xxx values */
163 memcpy(ifi
->ifa_name
, ifr
->ifr_name
, IFA_NAME
);
164 ifi
->ifa_name
[IFA_NAME
-1] = '\0';
165 /* end get_ifa_info2 */
166 /* include get_ifa_info3 */
167 switch (ifr
->ifr_addr
.sa_family
) {
169 sinptr
= (struct sockaddr_in
*) &ifr
->ifr_addr
;
170 if (ifi
->ifa_addr
== NULL
) {
171 ifi
->ifa_addr
= (struct sockaddr
*) calloc(1, sizeof(struct sockaddr_in
));
172 memcpy(ifi
->ifa_addr
, sinptr
, sizeof(struct sockaddr_in
));
174 #ifdef SIOCGIFBRDADDR
175 if (flags
& IFF_BROADCAST
) {
176 ioctl(sockfd
, SIOCGIFBRDADDR
, &ifrcopy
);
177 sinptr
= (struct sockaddr_in
*) &ifrcopy
.ifr_broadaddr
;
178 ifi
->ifa_brdaddr
= (struct sockaddr
*) calloc(1, sizeof(struct sockaddr_in
));
179 memcpy(ifi
->ifa_brdaddr
, sinptr
, sizeof(struct sockaddr_in
));
183 #ifdef SIOCGIFDSTADDR
184 if (flags
& IFF_POINTOPOINT
) {
185 ioctl(sockfd
, SIOCGIFDSTADDR
, &ifrcopy
);
186 sinptr
= (struct sockaddr_in
*) &ifrcopy
.ifr_dstaddr
;
187 ifi
->ifa_dstaddr
= (struct sockaddr
*) calloc(1, sizeof(struct sockaddr_in
));
188 memcpy(ifi
->ifa_dstaddr
, sinptr
, sizeof(struct sockaddr_in
));
199 return(ifihead
); /* pointer to first structure in linked list */
201 /* end get_ifa_info3 */
203 /* include free_ifa_info */
204 mDNSlocal
void freeifaddrs(struct ifa_info
*ifihead
)
206 struct ifa_info
*ifi
, *ifinext
;
208 for (ifi
= ifihead
; ifi
!= NULL
; ifi
= ifinext
) {
209 if (ifi
->ifa_addr
!= NULL
)
211 if (ifi
->ifa_brdaddr
!= NULL
)
212 free(ifi
->ifa_brdaddr
);
213 if (ifi
->ifa_dstaddr
!= NULL
)
214 free(ifi
->ifa_dstaddr
);
215 ifinext
= ifi
->ifa_next
; /* can't fetch ifa_next after free() */
216 free(ifi
); /* the ifa_info{} itself */
219 /* end free_ifa_info */
222 Get_ifa_info(int family
, int doaliases
)
224 struct ifa_info
*ifi
;
226 if ( (ifi
= get_ifa_info(family
, doaliases
)) == NULL
)
227 debugf("get_ifa_info error");
231 mDNSlocal
int getifaddrs(struct ifa_info
**ifalist
)
233 *ifalist
= get_ifa_info(PF_INET
, false);