Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
srohatgi01
GitHub Repository: srohatgi01/cups
Path: blob/master/scheduler/network.c
1090 views
1
/*
2
* Network interface functions for the CUPS scheduler.
3
*
4
* Copyright © 2007-2018 by Apple Inc.
5
* Copyright © 1997-2006 by Easy Software Products, all rights reserved.
6
*
7
* Licensed under Apache License v2.0. See the file "LICENSE" for more
8
* information.
9
*/
10
11
/*
12
* Include necessary headers.
13
*/
14
15
#include <cups/http-private.h>
16
#include "cupsd.h"
17
#include <cups/getifaddrs-internal.h>
18
19
20
/*
21
* Local functions...
22
*/
23
24
static void cupsdNetIFFree(void);
25
static int compare_netif(cupsd_netif_t *a, cupsd_netif_t *b);
26
27
28
/*
29
* 'cupsdNetIFFind()' - Find a network interface.
30
*/
31
32
cupsd_netif_t * /* O - Network interface data */
33
cupsdNetIFFind(const char *name) /* I - Name of interface */
34
{
35
cupsd_netif_t key; /* Search key */
36
37
38
/*
39
* Update the interface list as needed...
40
*/
41
42
if (NetIFUpdate)
43
cupsdNetIFUpdate();
44
45
/*
46
* Search for the named interface...
47
*/
48
49
strlcpy(key.name, name, sizeof(key.name));
50
51
return ((cupsd_netif_t *)cupsArrayFind(NetIFList, &key));
52
}
53
54
55
/*
56
* 'cupsdNetIFFree()' - Free the current network interface list.
57
*/
58
59
static void
60
cupsdNetIFFree(void)
61
{
62
cupsd_netif_t *current; /* Current interface in array */
63
64
65
/*
66
* Loop through the interface list and free all the records...
67
*/
68
69
for (current = (cupsd_netif_t *)cupsArrayFirst(NetIFList);
70
current;
71
current = (cupsd_netif_t *)cupsArrayNext(NetIFList))
72
{
73
cupsArrayRemove(NetIFList, current);
74
free(current);
75
}
76
}
77
78
79
/*
80
* 'cupsdNetIFUpdate()' - Update the network interface list as needed...
81
*/
82
83
void
84
cupsdNetIFUpdate(void)
85
{
86
int match; /* Matching address? */
87
cupsd_listener_t *lis; /* Listen address */
88
cupsd_netif_t *temp; /* New interface */
89
struct ifaddrs *addrs, /* Interface address list */
90
*addr; /* Current interface address */
91
char hostname[1024]; /* Hostname for address */
92
size_t hostlen; /* Length of hostname */
93
94
95
/*
96
* Only update the list if we need to...
97
*/
98
99
if (!NetIFUpdate)
100
return;
101
102
NetIFUpdate = 0;
103
104
/*
105
* Free the old interfaces...
106
*/
107
108
cupsdNetIFFree();
109
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
120
/*
121
* Grab a new list of interfaces...
122
*/
123
124
if (getifaddrs(&addrs) < 0)
125
{
126
cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdNetIFUpdate: Unable to get interface list - %s", strerror(errno));
127
return;
128
}
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)
143
{
144
cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdNetIFUpdate: Ignoring \"%s\".", addr->ifa_name);
145
continue;
146
}
147
148
/*
149
* Try looking up the hostname for the address as needed...
150
*/
151
152
if (HostNameLookups)
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
160
* numeric address...
161
*/
162
163
if (httpAddrLocalhost((http_addr_t *)(addr->ifa_addr)))
164
strlcpy(hostname, "localhost", sizeof(hostname));
165
else
166
httpAddrString((http_addr_t *)(addr->ifa_addr), hostname,
167
sizeof(hostname));
168
}
169
170
/*
171
* Create a new address element...
172
*/
173
174
hostlen = strlen(hostname);
175
if ((temp = calloc(1, sizeof(cupsd_netif_t) + hostlen)) == NULL)
176
{
177
cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdNetIFUpdate: Unable to allocate memory for interface.");
178
break;
179
}
180
181
/*
182
* Copy all of the information...
183
*/
184
185
strlcpy(temp->name, addr->ifa_name, sizeof(temp->name));
186
temp->hostlen = hostlen;
187
memcpy(temp->hostname, hostname, hostlen + 1);
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
226
for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners);
227
lis;
228
lis = (cupsd_listener_t *)cupsArrayNext(Listeners))
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 &
237
temp->mask.ipv4.sin_addr.s_addr) ==
238
(temp->address.ipv4.sin_addr.s_addr &
239
temp->mask.ipv4.sin_addr.s_addr))
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] &
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]) &&
248
(lis->address.ipv6.sin6_addr.s6_addr[1] &
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]) &&
252
(lis->address.ipv6.sin6_addr.s6_addr[2] &
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]) &&
256
(lis->address.ipv6.sin6_addr.s6_addr[3] &
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]))
260
match = 1;
261
#endif /* AF_INET6 */
262
263
if (match)
264
{
265
temp->port = httpAddrPort(&(lis->address));
266
break;
267
}
268
}
269
270
/*
271
* Add it to the array...
272
*/
273
274
cupsArrayAdd(NetIFList, temp);
275
276
cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdNetIFUpdate: \"%s\" = %s:%d",
277
temp->name, temp->hostname, temp->port);
278
}
279
280
freeifaddrs(addrs);
281
}
282
283
284
/*
285
* 'compare_netif()' - Compare two network interfaces.
286
*/
287
288
static int /* O - Result of comparison */
289
compare_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
}
294
295