]> git.ipfire.org Git - thirdparty/cups.git/blame - scheduler/network.c
Resolve new compiler warnings.
[thirdparty/cups.git] / scheduler / network.c
CommitLineData
ef416fc2 1/*
84ec3a84 2 * Network interface functions for the CUPS scheduler.
ef416fc2 3 *
9dd1bc98 4 * Copyright © 2007-2018 by Apple Inc.
53f8d64f 5 * Copyright © 1997-2006 by Easy Software Products, all rights reserved.
ef416fc2 6 *
53f8d64f
MS
7 * Licensed under Apache License v2.0. See the file "LICENSE" for more
8 * information.
ef416fc2 9 */
10
11/*
12 * Include necessary headers.
13 */
14
89d46774 15#include <cups/http-private.h>
ef416fc2 16#include "cupsd.h"
9dd1bc98 17#include <cups/getifaddrs-internal.h>
ef416fc2 18
e00b005a 19
20/*
21 * Local functions...
22 */
23
24static void cupsdNetIFFree(void);
25static int compare_netif(cupsd_netif_t *a, cupsd_netif_t *b);
26
27
ef416fc2 28/*
29 * 'cupsdNetIFFind()' - Find a network interface.
30 */
31
32cupsd_netif_t * /* O - Network interface data */
33cupsdNetIFFind(const char *name) /* I - Name of interface */
34{
e00b005a 35 cupsd_netif_t key; /* Search key */
ef416fc2 36
37
38 /*
39 * Update the interface list as needed...
40 */
41
411affcf 42 if (NetIFUpdate)
43 cupsdNetIFUpdate();
ef416fc2 44
45 /*
46 * Search for the named interface...
47 */
48
e00b005a 49 strlcpy(key.name, name, sizeof(key.name));
ef416fc2 50
e00b005a 51 return ((cupsd_netif_t *)cupsArrayFind(NetIFList, &key));
ef416fc2 52}
53
54
55/*
56 * 'cupsdNetIFFree()' - Free the current network interface list.
57 */
58
e00b005a 59static void
ef416fc2 60cupsdNetIFFree(void)
61{
e00b005a 62 cupsd_netif_t *current; /* Current interface in array */
ef416fc2 63
64
65 /*
66 * Loop through the interface list and free all the records...
67 */
68
e00b005a 69 for (current = (cupsd_netif_t *)cupsArrayFirst(NetIFList);
70 current;
71 current = (cupsd_netif_t *)cupsArrayNext(NetIFList))
ef416fc2 72 {
e00b005a 73 cupsArrayRemove(NetIFList, current);
74 free(current);
ef416fc2 75 }
76}
77
78
79/*
80 * 'cupsdNetIFUpdate()' - Update the network interface list as needed...
81 */
82
83void
84cupsdNetIFUpdate(void)
85{
bd7854cb 86 int match; /* Matching address? */
ef416fc2 87 cupsd_listener_t *lis; /* Listen address */
e00b005a 88 cupsd_netif_t *temp; /* New interface */
ef416fc2 89 struct ifaddrs *addrs, /* Interface address list */
90 *addr; /* Current interface address */
e00b005a 91 char hostname[1024]; /* Hostname for address */
e07d4801 92 size_t hostlen; /* Length of hostname */
ef416fc2 93
94
95 /*
411affcf 96 * Only update the list if we need to...
ef416fc2 97 */
98
411affcf 99 if (!NetIFUpdate)
ef416fc2 100 return;
101
411affcf 102 NetIFUpdate = 0;
ef416fc2 103
104 /*
105 * Free the old interfaces...
106 */
107
108 cupsdNetIFFree();
109
e00b005a 110 /*
111 * Make sure we have an array...
112 */
113
114 if (!NetIFList)
115 NetIFList = cupsArrayNew((cups_array_func_t)compare_netif, NULL);
116
117 if (!NetIFList)
118 return;
119
ef416fc2 120 /*
121 * Grab a new list of interfaces...
122 */
123
124 if (getifaddrs(&addrs) < 0)
84ec3a84
MS
125 {
126 cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdNetIFUpdate: Unable to get interface list - %s", strerror(errno));
ef416fc2 127 return;
84ec3a84 128 }
ef416fc2 129
130 for (addr = addrs; addr != NULL; addr = addr->ifa_next)
131 {
132 /*
133 * See if this interface address is IPv4 or IPv6...
134 */
135
136 if (addr->ifa_addr == NULL ||
137 (addr->ifa_addr->sa_family != AF_INET
138#ifdef AF_INET6
139 && addr->ifa_addr->sa_family != AF_INET6
140#endif
141 ) ||
142 addr->ifa_netmask == NULL || addr->ifa_name == NULL)
84ec3a84
MS
143 {
144 cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdNetIFUpdate: Ignoring \"%s\".", addr->ifa_name);
ef416fc2 145 continue;
84ec3a84 146 }
ef416fc2 147
148 /*
e00b005a 149 * Try looking up the hostname for the address as needed...
ef416fc2 150 */
151
ba55dc12 152 if (HostNameLookups)
e00b005a 153 httpAddrLookup((http_addr_t *)(addr->ifa_addr), hostname,
154 sizeof(hostname));
155 else
156 {
157 /*
158 * Map the default server address and localhost to the server name
159 * and localhost, respectively; for all other addresses, use the
cc754834 160 * numeric address...
e00b005a 161 */
ef416fc2 162
e00b005a 163 if (httpAddrLocalhost((http_addr_t *)(addr->ifa_addr)))
82cc1f9a 164 strlcpy(hostname, "localhost", sizeof(hostname));
e00b005a 165 else
d1c13e16
MS
166 httpAddrString((http_addr_t *)(addr->ifa_addr), hostname,
167 sizeof(hostname));
e00b005a 168 }
ef416fc2 169
e00b005a 170 /*
171 * Create a new address element...
172 */
ef416fc2 173
e07d4801
MS
174 hostlen = strlen(hostname);
175 if ((temp = calloc(1, sizeof(cupsd_netif_t) + hostlen)) == NULL)
84ec3a84
MS
176 {
177 cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdNetIFUpdate: Unable to allocate memory for interface.");
e00b005a 178 break;
84ec3a84 179 }
ef416fc2 180
181 /*
e00b005a 182 * Copy all of the information...
ef416fc2 183 */
184
185 strlcpy(temp->name, addr->ifa_name, sizeof(temp->name));
e07d4801 186 temp->hostlen = hostlen;
82cc1f9a 187 memcpy(temp->hostname, hostname, hostlen + 1);
ef416fc2 188
189 if (addr->ifa_addr->sa_family == AF_INET)
190 {
191 /*
192 * Copy IPv4 addresses...
193 */
194
195 memcpy(&(temp->address), addr->ifa_addr, sizeof(struct sockaddr_in));
196 memcpy(&(temp->mask), addr->ifa_netmask, sizeof(struct sockaddr_in));
197
198 if (addr->ifa_dstaddr)
199 memcpy(&(temp->broadcast), addr->ifa_dstaddr,
200 sizeof(struct sockaddr_in));
201 }
202#ifdef AF_INET6
203 else
204 {
205 /*
206 * Copy IPv6 addresses...
207 */
208
209 memcpy(&(temp->address), addr->ifa_addr, sizeof(struct sockaddr_in6));
210 memcpy(&(temp->mask), addr->ifa_netmask, sizeof(struct sockaddr_in6));
211
212 if (addr->ifa_dstaddr)
213 memcpy(&(temp->broadcast), addr->ifa_dstaddr,
214 sizeof(struct sockaddr_in6));
215 }
216#endif /* AF_INET6 */
217
218 if (!(addr->ifa_flags & IFF_POINTOPOINT) &&
219 !httpAddrLocalhost(&(temp->address)))
220 temp->is_local = 1;
221
222 /*
223 * Determine which port to use when advertising printers...
224 */
225
bd7854cb 226 for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners);
227 lis;
228 lis = (cupsd_listener_t *)cupsArrayNext(Listeners))
ef416fc2 229 {
230 match = 0;
231
232 if (httpAddrAny(&(lis->address)))
233 match = 1;
234 else if (addr->ifa_addr->sa_family == AF_INET &&
235 lis->address.addr.sa_family == AF_INET &&
236 (lis->address.ipv4.sin_addr.s_addr &
06d4e77b
MS
237 temp->mask.ipv4.sin_addr.s_addr) ==
238 (temp->address.ipv4.sin_addr.s_addr &
239 temp->mask.ipv4.sin_addr.s_addr))
ef416fc2 240 match = 1;
241#ifdef AF_INET6
242 else if (addr->ifa_addr->sa_family == AF_INET6 &&
243 lis->address.addr.sa_family == AF_INET6 &&
244 (lis->address.ipv6.sin6_addr.s6_addr[0] &
06d4e77b
MS
245 temp->mask.ipv6.sin6_addr.s6_addr[0]) ==
246 (temp->address.ipv6.sin6_addr.s6_addr[0] &
247 temp->mask.ipv6.sin6_addr.s6_addr[0]) &&
ef416fc2 248 (lis->address.ipv6.sin6_addr.s6_addr[1] &
06d4e77b
MS
249 temp->mask.ipv6.sin6_addr.s6_addr[1]) ==
250 (temp->address.ipv6.sin6_addr.s6_addr[1] &
251 temp->mask.ipv6.sin6_addr.s6_addr[1]) &&
ef416fc2 252 (lis->address.ipv6.sin6_addr.s6_addr[2] &
06d4e77b
MS
253 temp->mask.ipv6.sin6_addr.s6_addr[2]) ==
254 (temp->address.ipv6.sin6_addr.s6_addr[2] &
255 temp->mask.ipv6.sin6_addr.s6_addr[2]) &&
ef416fc2 256 (lis->address.ipv6.sin6_addr.s6_addr[3] &
06d4e77b
MS
257 temp->mask.ipv6.sin6_addr.s6_addr[3]) ==
258 (temp->address.ipv6.sin6_addr.s6_addr[3] &
259 temp->mask.ipv6.sin6_addr.s6_addr[3]))
ef416fc2 260 match = 1;
261#endif /* AF_INET6 */
262
263 if (match)
264 {
a469f8a5 265 temp->port = httpAddrPort(&(lis->address));
ef416fc2 266 break;
267 }
268 }
269
270 /*
e00b005a 271 * Add it to the array...
ef416fc2 272 */
273
e00b005a 274 cupsArrayAdd(NetIFList, temp);
ef416fc2 275
06d4e77b
MS
276 cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdNetIFUpdate: \"%s\" = %s:%d",
277 temp->name, temp->hostname, temp->port);
ef416fc2 278 }
279
280 freeifaddrs(addrs);
281}
282
283
e00b005a 284/*
285 * 'compare_netif()' - Compare two network interfaces.
286 */
287
288static int /* O - Result of comparison */
289compare_netif(cupsd_netif_t *a, /* I - First network interface */
290 cupsd_netif_t *b) /* I - Second network interface */
291{
292 return (strcmp(a->name, b->name));
293}