]> git.ipfire.org Git - thirdparty/cups.git/blame - scheduler/network.c
This commit was manufactured by cvs2svn to create branch 'branch-1.2'.
[thirdparty/cups.git] / scheduler / network.c
CommitLineData
2123c23a 1/*
2 * "$Id: network.c,v 1.5 2002/03/27 18:36:18 mike Exp $"
3 *
4 * Network interface functions for the Common UNIX Printing System
5 * (CUPS) scheduler.
6 *
7 * Copyright 1997-2002 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-3111 USA
20 *
21 * Voice: (301) 373-9603
22 * EMail: cups-info@cups.org
23 * WWW: http://www.cups.org
24 */
25
26/*
27 * Include necessary headers.
28 */
29
30#include "cupsd.h"
31
32#ifdef HAVE_GETIFADDRS
33/*
34 * Use native getifaddrs() function...
35 */
36# include <ifaddrs.h>
37#else
38/*
39 * Use getifaddrs() emulation...
40 */
41
42# include <net/if.h>
43# include <sys/ioctl.h>
44# ifdef HAVE_SYS_SOCKIO_H
45# include <sys/sockio.h>
46# endif
47
48# ifdef ifa_dstaddr
49# undef ifa_dstaddr
50# endif /* ifa_dstaddr */
51# ifndef ifr_netmask
52# define ifr_netmask ifr_addr
53# endif /* !ifr_netmask */
54
55struct ifaddrs /**** Interface Structure ****/
56{
57 struct ifaddrs *ifa_next; /* Next interface in list */
58 char *ifa_name; /* Name of interface */
59 unsigned int ifa_flags; /* Flags (up, point-to-point, etc.) */
60 struct sockaddr *ifa_addr, /* Network address */
61 *ifa_netmask, /* Address mask */
62 *ifa_dstaddr; /* Broadcast or destination address */
63 void *ifa_data; /* Interface statistics */
64};
65
66int getifaddrs(struct ifaddrs **addrs);
67void freeifaddrs(struct ifaddrs *addrs);
68#endif /* HAVE_GETIFADDRS */
69
70
71/*
72 * 'NetIFFind()' - Find a network interface.
73 */
74
75cups_netif_t * /* O - Network interface data */
76NetIFFind(const char *name) /* I - Name of interface */
77{
78 cups_netif_t *temp; /* Current network interface */
79
80
81 /*
82 * Update the interface list as needed...
83 */
84
85 NetIFUpdate();
86
87 /*
88 * Search for the named interface...
89 */
90
91 for (temp = NetIFList; temp != NULL; temp = temp->next)
92 if (strcasecmp(name, temp->name) == 0)
93 return (temp);
94
95 return (NULL);
96}
97
98
99/*
100 * 'NetIFFree()' - Free the current network interface list.
101 */
102
103void
104NetIFFree(void)
105{
106 cups_netif_t *next; /* Next interface in list */
107
108
109 /*
110 * Loop through the interface list and free all the records...
111 */
112
113 while (NetIFList != NULL)
114 {
115 next = NetIFList->next;
116
117 free(NetIFList);
118
119 NetIFList = next;
120 }
121}
122
123
124/*
125 * 'NetIFUpdate()' - Update the network interface list as needed...
126 */
127
128void
129NetIFUpdate(void)
130{
131 cups_netif_t *temp; /* Current interface */
132 struct ifaddrs *addrs, /* Interface address list */
133 *addr; /* Current interface address */
134
135
136 /*
137 * Update the network interface list no more often than once a
138 * minute...
139 */
140
141 if ((time(NULL) - NetIFTime) < 60)
142 return;
143
144 /*
145 * Free the old interfaces...
146 */
147
148 NetIFFree();
149
150 /*
151 * Grab a new list of interfaces...
152 */
153
154 if (getifaddrs(&addrs) < 0)
155 return;
156
157 for (addr = addrs; addr != NULL; addr = addr->ifa_next)
158 {
159 /*
160 * See if this interface address is IPv4...
161 */
162
163 if (addr->ifa_addr == NULL || addr->ifa_addr->sa_family != AF_INET ||
164 addr->ifa_netmask == NULL || addr->ifa_name == NULL)
165 continue;
166
167 /*
168 * OK, we have an IPv4 address, so create a new list node...
169 */
170
171 if ((temp = calloc(1, sizeof(cups_netif_t))) == NULL)
172 break;
173
174 temp->next = NetIFList;
175 NetIFList = temp;
176
177 /*
178 * Then copy all of the information...
179 */
180
181 strncpy(temp->name, addr->ifa_name, sizeof(temp->name) - 1);
182 memcpy(&(temp->address), addr->ifa_addr, sizeof(temp->address));
183 memcpy(&(temp->mask), addr->ifa_netmask, sizeof(temp->mask));
184
185 if (addr->ifa_dstaddr)
186 memcpy(&(temp->broadcast), addr->ifa_dstaddr, sizeof(temp->broadcast));
187
188 if (!(addr->ifa_flags & IFF_POINTOPOINT))
189 temp->is_local = 1;
190
191 /*
192 * Finally, try looking up the hostname for the address as needed...
193 */
194
195 if (HostNameLookups)
196 {
197 strncpy(temp->hostname, ServerName, sizeof(temp->hostname) - 1);
198 }
199 else
200 strncpy(temp->hostname, ServerName, sizeof(temp->hostname) - 1);
201 }
202
203 freeifaddrs(addrs);
204}
205
206
207#ifndef HAVE_GETIFADDRS
208/*
209 * 'getifaddrs()' - Get a list of network interfaces on the system.
210 */
211
212int /* O - 0 on success, -1 on error */
213getifaddrs(struct ifaddrs **addrs) /* O - List of interfaces */
214{
215 int sock; /* Socket */
216 char buffer[65536], /* Buffer for address info */
217 *bufptr, /* Pointer into buffer */
218 *bufend; /* End of buffer */
219 struct ifconf conf; /* Interface configurations */
220 struct sockaddr addr; /* Address data */
221 struct ifreq *ifp; /* Interface data */
222 int ifpsize; /* Size of interface data */
223 struct ifaddrs *temp; /* Pointer to current interface */
224 struct ifreq request; /* Interface request */
225
226
227 /*
228 * Start with an empty list...
229 */
230
231 if (addrs == NULL)
232 return (-1);
233
234 *addrs = NULL;
235
236 /*
237 * Create a UDP socket to get the interface data...
238 */
239
240 memset (&addr, 0, sizeof(addr));
241 if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
242 return (-1);
243
244 /*
245 * Try to get the list of interfaces...
246 */
247
248 conf.ifc_len = sizeof(buffer);
249 conf.ifc_buf = buffer;
250
251 if (ioctl(sock, SIOCGIFCONF, &conf) < 0)
252 {
253 /*
254 * Couldn't get the list of interfaces...
255 */
256
257 close(sock);
258 return (-1);
259 }
260
261 /*
262 * OK, got the list of interfaces, now lets step through the
263 * buffer to pull them out...
264 */
265
266# ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
267# define sockaddr_len(a) ((a)->sa_len)
268# else
269# define sockaddr_len(a) (sizeof(struct sockaddr))
270# endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
271
272 for (bufptr = buffer, bufend = buffer + conf.ifc_len;
273 bufptr < bufend;
274 bufptr += ifpsize)
275 {
276 /*
277 * Get the current interface information...
278 */
279
280 ifp = (struct ifreq *)bufptr;
281 ifpsize = sizeof(ifp->ifr_name) + sockaddr_len(&(ifp->ifr_addr));
282
283 if (ifpsize < sizeof(struct ifreq))
284 ifpsize = sizeof(struct ifreq);
285
286 memset(&request, 0, sizeof(request));
287 memcpy(request.ifr_name, ifp->ifr_name, sizeof(ifp->ifr_name));
288
289 /*
290 * Check the status of the interface...
291 */
292
293 if (ioctl(sock, SIOCGIFFLAGS, &request) < 0)
294 continue;
295
296 /*
297 * Allocate memory for a single interface record...
298 */
299
300 if ((temp = calloc(1, sizeof(struct ifaddrs))) == NULL)
301 {
302 /*
303 * Unable to allocate memory...
304 */
305
306 close(sock);
307 return (-1);
308 }
309
310 /*
311 * Add this record to the front of the list and copy the name, flags,
312 * and network address...
313 */
314
315 temp->ifa_next = *addrs;
316 *addrs = temp;
317 temp->ifa_name = strdup(ifp->ifr_name);
318 temp->ifa_flags = request.ifr_flags;
319 if ((temp->ifa_addr = calloc(1, sockaddr_len(&(ifp->ifr_addr)))) != NULL)
320 memcpy(temp->ifa_addr, &(ifp->ifr_addr), sockaddr_len(&(ifp->ifr_addr)));
321
322 /*
323 * Try to get the netmask for the interface...
324 */
325
326 if (!ioctl(sock, SIOCGIFNETMASK, &request))
327 {
328 /*
329 * Got it, make a copy...
330 */
331
332 if ((temp->ifa_netmask = calloc(1, sizeof(request.ifr_netmask))) != NULL)
333 memcpy(temp->ifa_netmask, &(request.ifr_netmask),
334 sizeof(request.ifr_netmask));
335 }
336
337 /*
338 * Then get the broadcast or point-to-point (destination) address,
339 * if applicable...
340 */
341
342 if (temp->ifa_flags & IFF_BROADCAST)
343 {
344 /*
345 * Have a broadcast address, so get it!
346 */
347
348 if (!ioctl(sock, SIOCGIFBRDADDR, &request))
349 {
350 /*
351 * Got it, make a copy...
352 */
353
354 if ((temp->ifa_dstaddr = calloc(1, sizeof(request.ifr_broadaddr))) != NULL)
355 memcpy(temp->ifa_dstaddr, &(request.ifr_broadaddr),
356 sizeof(request.ifr_broadaddr));
357 }
358 }
359 else if (temp->ifa_flags & IFF_POINTOPOINT)
360 {
361 /*
362 * Point-to-point interface; grab the remote address...
363 */
364
365 if (!ioctl(sock, SIOCGIFDSTADDR, &request))
366 {
367 temp->ifa_dstaddr = malloc(sizeof(request.ifr_dstaddr));
368 memcpy(temp->ifa_dstaddr, &(request.ifr_dstaddr),
369 sizeof(request.ifr_dstaddr));
370 }
371 }
372 }
373
374 /*
375 * OK, we're done with the socket, close it and return 0...
376 */
377
378 close(sock);
379
380 return (0);
381}
382
383
384/*
385 * 'freeifaddrs()' - Free an interface list...
386 */
387
388void
389freeifaddrs(struct ifaddrs *addrs) /* I - Interface list to free */
390{
391 struct ifaddrs *next; /* Next interface in list */
392
393
394 while (addrs != NULL)
395 {
396 /*
397 * Make a copy of the next interface pointer...
398 */
399
400 next = addrs->ifa_next;
401
402 /*
403 * Free data values as needed...
404 */
405
406 if (addrs->ifa_name)
407 {
408 free(addrs->ifa_name);
409 addrs->ifa_name = NULL;
410 }
411
412 if (addrs->ifa_addr)
413 {
414 free(addrs->ifa_addr);
415 addrs->ifa_addr = NULL;
416 }
417
418 if (addrs->ifa_netmask)
419 {
420 free(addrs->ifa_netmask);
421 addrs->ifa_netmask = NULL;
422 }
423
424 if (addrs->ifa_dstaddr)
425 {
426 free(addrs->ifa_dstaddr);
427 addrs->ifa_dstaddr = NULL;
428 }
429
430 /*
431 * Free this node and continue to the next...
432 */
433
434 free(addrs);
435
436 addrs = next;
437 }
438}
439
440#endif /* !HAVE_GETIFADDRS */
441
442
443/*
444 * End of "$Id: network.c,v 1.5 2002/03/27 18:36:18 mike Exp $".
445 */