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