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