]> git.ipfire.org Git - thirdparty/cups.git/blob - cups/getifaddrs.c
Load cups into easysw/current.
[thirdparty/cups.git] / cups / getifaddrs.c
1 /*
2 * "$Id: getifaddrs.c 6649 2007-07-11 21:46:42Z mike $"
3 *
4 * Network interface functions for the Common UNIX Printing System
5 * (CUPS) scheduler.
6 *
7 * Copyright 2007 by Apple Inc.
8 * Copyright 1997-2006 by Easy Software Products, all rights reserved.
9 *
10 * These coded instructions, statements, and computer programs are the
11 * property of Apple Inc. and are protected by Federal copyright
12 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
13 * "LICENSE" which should have been included with this file. If this
14 * file is missing or damaged, see the license at "http://www.cups.org/".
15 *
16 * Contents:
17 *
18 * _cups_getifaddrs() - Get a list of network interfaces on the system.
19 * _cups_freeifaddrs() - Free an interface list...
20 */
21
22 /*
23 * Include necessary headers.
24 */
25
26 #include "http-private.h"
27
28
29 #ifndef HAVE_GETIFADDRS
30 /*
31 * '_cups_getifaddrs()' - Get a list of network interfaces on the system.
32 */
33
34 int /* O - 0 on success, -1 on error */
35 _cups_getifaddrs(struct ifaddrs **addrs)/* O - List of interfaces */
36 {
37 int sock; /* Socket */
38 char buffer[65536], /* Buffer for address info */
39 *bufptr, /* Pointer into buffer */
40 *bufend; /* End of buffer */
41 struct ifconf conf; /* Interface configurations */
42 struct sockaddr addr; /* Address data */
43 struct ifreq *ifp; /* Interface data */
44 int ifpsize; /* Size of interface data */
45 struct ifaddrs *temp; /* Pointer to current interface */
46 struct ifreq request; /* Interface request */
47
48
49 /*
50 * Start with an empty list...
51 */
52
53 if (addrs == NULL)
54 return (-1);
55
56 *addrs = NULL;
57
58 /*
59 * Create a UDP socket to get the interface data...
60 */
61
62 memset (&addr, 0, sizeof(addr));
63 if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
64 return (-1);
65
66 /*
67 * Try to get the list of interfaces...
68 */
69
70 conf.ifc_len = sizeof(buffer);
71 conf.ifc_buf = buffer;
72
73 if (ioctl(sock, SIOCGIFCONF, &conf) < 0)
74 {
75 /*
76 * Couldn't get the list of interfaces...
77 */
78
79 close(sock);
80 return (-1);
81 }
82
83 /*
84 * OK, got the list of interfaces, now lets step through the
85 * buffer to pull them out...
86 */
87
88 # ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
89 # define sockaddr_len(a) ((a)->sa_len)
90 # else
91 # define sockaddr_len(a) (sizeof(struct sockaddr))
92 # endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
93
94 for (bufptr = buffer, bufend = buffer + conf.ifc_len;
95 bufptr < bufend;
96 bufptr += ifpsize)
97 {
98 /*
99 * Get the current interface information...
100 */
101
102 ifp = (struct ifreq *)bufptr;
103 ifpsize = sizeof(ifp->ifr_name) + sockaddr_len(&(ifp->ifr_addr));
104
105 if (ifpsize < sizeof(struct ifreq))
106 ifpsize = sizeof(struct ifreq);
107
108 memset(&request, 0, sizeof(request));
109 memcpy(request.ifr_name, ifp->ifr_name, sizeof(ifp->ifr_name));
110
111 /*
112 * Check the status of the interface...
113 */
114
115 if (ioctl(sock, SIOCGIFFLAGS, &request) < 0)
116 continue;
117
118 /*
119 * Allocate memory for a single interface record...
120 */
121
122 if ((temp = calloc(1, sizeof(struct ifaddrs))) == NULL)
123 {
124 /*
125 * Unable to allocate memory...
126 */
127
128 close(sock);
129 return (-1);
130 }
131
132 /*
133 * Add this record to the front of the list and copy the name, flags,
134 * and network address...
135 */
136
137 temp->ifa_next = *addrs;
138 *addrs = temp;
139 temp->ifa_name = strdup(ifp->ifr_name);
140 temp->ifa_flags = request.ifr_flags;
141 if ((temp->ifa_addr = calloc(1, sockaddr_len(&(ifp->ifr_addr)))) != NULL)
142 memcpy(temp->ifa_addr, &(ifp->ifr_addr), sockaddr_len(&(ifp->ifr_addr)));
143
144 /*
145 * Try to get the netmask for the interface...
146 */
147
148 if (!ioctl(sock, SIOCGIFNETMASK, &request))
149 {
150 /*
151 * Got it, make a copy...
152 */
153
154 if ((temp->ifa_netmask = calloc(1, sizeof(request.ifr_netmask))) != NULL)
155 memcpy(temp->ifa_netmask, &(request.ifr_netmask),
156 sizeof(request.ifr_netmask));
157 }
158
159 /*
160 * Then get the broadcast or point-to-point (destination) address,
161 * if applicable...
162 */
163
164 if (temp->ifa_flags & IFF_BROADCAST)
165 {
166 /*
167 * Have a broadcast address, so get it!
168 */
169
170 if (!ioctl(sock, SIOCGIFBRDADDR, &request))
171 {
172 /*
173 * Got it, make a copy...
174 */
175
176 if ((temp->ifa_broadaddr =
177 calloc(1, sizeof(request.ifr_broadaddr))) != NULL)
178 memcpy(temp->ifa_broadaddr, &(request.ifr_broadaddr),
179 sizeof(request.ifr_broadaddr));
180 }
181 }
182 else if (temp->ifa_flags & IFF_POINTOPOINT)
183 {
184 /*
185 * Point-to-point interface; grab the remote address...
186 */
187
188 if (!ioctl(sock, SIOCGIFDSTADDR, &request))
189 {
190 temp->ifa_dstaddr = malloc(sizeof(request.ifr_dstaddr));
191 memcpy(temp->ifa_dstaddr, &(request.ifr_dstaddr),
192 sizeof(request.ifr_dstaddr));
193 }
194 }
195 }
196
197 /*
198 * OK, we're done with the socket, close it and return 0...
199 */
200
201 close(sock);
202
203 return (0);
204 }
205
206
207 /*
208 * '_cups_freeifaddrs()' - Free an interface list...
209 */
210
211 void
212 _cups_freeifaddrs(struct ifaddrs *addrs)/* I - Interface list to free */
213 {
214 struct ifaddrs *next; /* Next interface in list */
215
216
217 while (addrs != NULL)
218 {
219 /*
220 * Make a copy of the next interface pointer...
221 */
222
223 next = addrs->ifa_next;
224
225 /*
226 * Free data values as needed...
227 */
228
229 if (addrs->ifa_name)
230 {
231 free(addrs->ifa_name);
232 addrs->ifa_name = NULL;
233 }
234
235 if (addrs->ifa_addr)
236 {
237 free(addrs->ifa_addr);
238 addrs->ifa_addr = NULL;
239 }
240
241 if (addrs->ifa_netmask)
242 {
243 free(addrs->ifa_netmask);
244 addrs->ifa_netmask = NULL;
245 }
246
247 if (addrs->ifa_dstaddr)
248 {
249 free(addrs->ifa_dstaddr);
250 addrs->ifa_dstaddr = NULL;
251 }
252
253 /*
254 * Free this node and continue to the next...
255 */
256
257 free(addrs);
258
259 addrs = next;
260 }
261 }
262 #endif /* !HAVE_GETIFADDRS */
263
264
265 /*
266 * End of "$Id: getifaddrs.c 6649 2007-07-11 21:46:42Z mike $".
267 */