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