]>
git.ipfire.org Git - thirdparty/cups.git/blob - scheduler/network.c
2 * Network interface functions for the CUPS scheduler.
4 * Copyright © 2007-2014 by Apple Inc.
5 * Copyright © 1997-2006 by Easy Software Products, all rights reserved.
7 * Licensed under Apache License v2.0. See the file "LICENSE" for more
12 * Include necessary headers.
15 #include <cups/http-private.h>
23 static void cupsdNetIFFree(void);
24 static int compare_netif(cupsd_netif_t
*a
, cupsd_netif_t
*b
);
28 * 'cupsdNetIFFind()' - Find a network interface.
31 cupsd_netif_t
* /* O - Network interface data */
32 cupsdNetIFFind(const char *name
) /* I - Name of interface */
34 cupsd_netif_t key
; /* Search key */
38 * Update the interface list as needed...
45 * Search for the named interface...
48 strlcpy(key
.name
, name
, sizeof(key
.name
));
50 return ((cupsd_netif_t
*)cupsArrayFind(NetIFList
, &key
));
55 * 'cupsdNetIFFree()' - Free the current network interface list.
61 cupsd_netif_t
*current
; /* Current interface in array */
65 * Loop through the interface list and free all the records...
68 for (current
= (cupsd_netif_t
*)cupsArrayFirst(NetIFList
);
70 current
= (cupsd_netif_t
*)cupsArrayNext(NetIFList
))
72 cupsArrayRemove(NetIFList
, current
);
79 * 'cupsdNetIFUpdate()' - Update the network interface list as needed...
83 cupsdNetIFUpdate(void)
85 int match
; /* Matching address? */
86 cupsd_listener_t
*lis
; /* Listen address */
87 cupsd_netif_t
*temp
; /* New interface */
88 struct ifaddrs
*addrs
, /* Interface address list */
89 *addr
; /* Current interface address */
90 char hostname
[1024]; /* Hostname for address */
91 size_t hostlen
; /* Length of hostname */
95 * Only update the list if we need to...
104 * Free the old interfaces...
110 * Make sure we have an array...
114 NetIFList
= cupsArrayNew((cups_array_func_t
)compare_netif
, NULL
);
120 * Grab a new list of interfaces...
123 if (getifaddrs(&addrs
) < 0)
125 cupsdLogMessage(CUPSD_LOG_DEBUG
, "cupsdNetIFUpdate: Unable to get interface list - %s", strerror(errno
));
129 for (addr
= addrs
; addr
!= NULL
; addr
= addr
->ifa_next
)
132 * See if this interface address is IPv4 or IPv6...
135 if (addr
->ifa_addr
== NULL
||
136 (addr
->ifa_addr
->sa_family
!= AF_INET
138 && addr
->ifa_addr
->sa_family
!= AF_INET6
141 addr
->ifa_netmask
== NULL
|| addr
->ifa_name
== NULL
)
143 cupsdLogMessage(CUPSD_LOG_DEBUG
, "cupsdNetIFUpdate: Ignoring \"%s\".", addr
->ifa_name
);
148 * Try looking up the hostname for the address as needed...
152 httpAddrLookup((http_addr_t
*)(addr
->ifa_addr
), hostname
,
157 * Map the default server address and localhost to the server name
158 * and localhost, respectively; for all other addresses, use the
162 if (httpAddrLocalhost((http_addr_t
*)(addr
->ifa_addr
)))
163 strlcpy(hostname
, "localhost", sizeof(hostname
));
165 httpAddrString((http_addr_t
*)(addr
->ifa_addr
), hostname
,
170 * Create a new address element...
173 hostlen
= strlen(hostname
);
174 if ((temp
= calloc(1, sizeof(cupsd_netif_t
) + hostlen
)) == NULL
)
176 cupsdLogMessage(CUPSD_LOG_DEBUG
, "cupsdNetIFUpdate: Unable to allocate memory for interface.");
181 * Copy all of the information...
184 strlcpy(temp
->name
, addr
->ifa_name
, sizeof(temp
->name
));
185 temp
->hostlen
= hostlen
;
186 memcpy(temp
->hostname
, hostname
, hostlen
+ 1);
188 if (addr
->ifa_addr
->sa_family
== AF_INET
)
191 * Copy IPv4 addresses...
194 memcpy(&(temp
->address
), addr
->ifa_addr
, sizeof(struct sockaddr_in
));
195 memcpy(&(temp
->mask
), addr
->ifa_netmask
, sizeof(struct sockaddr_in
));
197 if (addr
->ifa_dstaddr
)
198 memcpy(&(temp
->broadcast
), addr
->ifa_dstaddr
,
199 sizeof(struct sockaddr_in
));
205 * Copy IPv6 addresses...
208 memcpy(&(temp
->address
), addr
->ifa_addr
, sizeof(struct sockaddr_in6
));
209 memcpy(&(temp
->mask
), addr
->ifa_netmask
, sizeof(struct sockaddr_in6
));
211 if (addr
->ifa_dstaddr
)
212 memcpy(&(temp
->broadcast
), addr
->ifa_dstaddr
,
213 sizeof(struct sockaddr_in6
));
215 #endif /* AF_INET6 */
217 if (!(addr
->ifa_flags
& IFF_POINTOPOINT
) &&
218 !httpAddrLocalhost(&(temp
->address
)))
222 * Determine which port to use when advertising printers...
225 for (lis
= (cupsd_listener_t
*)cupsArrayFirst(Listeners
);
227 lis
= (cupsd_listener_t
*)cupsArrayNext(Listeners
))
231 if (httpAddrAny(&(lis
->address
)))
233 else if (addr
->ifa_addr
->sa_family
== AF_INET
&&
234 lis
->address
.addr
.sa_family
== AF_INET
&&
235 (lis
->address
.ipv4
.sin_addr
.s_addr
&
236 temp
->mask
.ipv4
.sin_addr
.s_addr
) ==
237 (temp
->address
.ipv4
.sin_addr
.s_addr
&
238 temp
->mask
.ipv4
.sin_addr
.s_addr
))
241 else if (addr
->ifa_addr
->sa_family
== AF_INET6
&&
242 lis
->address
.addr
.sa_family
== AF_INET6
&&
243 (lis
->address
.ipv6
.sin6_addr
.s6_addr
[0] &
244 temp
->mask
.ipv6
.sin6_addr
.s6_addr
[0]) ==
245 (temp
->address
.ipv6
.sin6_addr
.s6_addr
[0] &
246 temp
->mask
.ipv6
.sin6_addr
.s6_addr
[0]) &&
247 (lis
->address
.ipv6
.sin6_addr
.s6_addr
[1] &
248 temp
->mask
.ipv6
.sin6_addr
.s6_addr
[1]) ==
249 (temp
->address
.ipv6
.sin6_addr
.s6_addr
[1] &
250 temp
->mask
.ipv6
.sin6_addr
.s6_addr
[1]) &&
251 (lis
->address
.ipv6
.sin6_addr
.s6_addr
[2] &
252 temp
->mask
.ipv6
.sin6_addr
.s6_addr
[2]) ==
253 (temp
->address
.ipv6
.sin6_addr
.s6_addr
[2] &
254 temp
->mask
.ipv6
.sin6_addr
.s6_addr
[2]) &&
255 (lis
->address
.ipv6
.sin6_addr
.s6_addr
[3] &
256 temp
->mask
.ipv6
.sin6_addr
.s6_addr
[3]) ==
257 (temp
->address
.ipv6
.sin6_addr
.s6_addr
[3] &
258 temp
->mask
.ipv6
.sin6_addr
.s6_addr
[3]))
260 #endif /* AF_INET6 */
264 temp
->port
= httpAddrPort(&(lis
->address
));
270 * Add it to the array...
273 cupsArrayAdd(NetIFList
, temp
);
275 cupsdLogMessage(CUPSD_LOG_DEBUG
, "cupsdNetIFUpdate: \"%s\" = %s:%d",
276 temp
->name
, temp
->hostname
, temp
->port
);
284 * 'compare_netif()' - Compare two network interfaces.
287 static int /* O - Result of comparison */
288 compare_netif(cupsd_netif_t
*a
, /* I - First network interface */
289 cupsd_netif_t
*b
) /* I - Second network interface */
291 return (strcmp(a
->name
, b
->name
));