1*5e7646d2SAndroid Build Coastguard Worker /*
2*5e7646d2SAndroid Build Coastguard Worker * Network interface functions for CUPS.
3*5e7646d2SAndroid Build Coastguard Worker *
4*5e7646d2SAndroid Build Coastguard Worker * Copyright © 2007-2018 by Apple Inc.
5*5e7646d2SAndroid Build Coastguard Worker * Copyright © 1997-2006 by Easy Software Products, all rights reserved.
6*5e7646d2SAndroid Build Coastguard Worker *
7*5e7646d2SAndroid Build Coastguard Worker * Licensed under Apache License v2.0. See the file "LICENSE" for more
8*5e7646d2SAndroid Build Coastguard Worker * information.
9*5e7646d2SAndroid Build Coastguard Worker */
10*5e7646d2SAndroid Build Coastguard Worker
11*5e7646d2SAndroid Build Coastguard Worker /*
12*5e7646d2SAndroid Build Coastguard Worker * Include necessary headers.
13*5e7646d2SAndroid Build Coastguard Worker */
14*5e7646d2SAndroid Build Coastguard Worker
15*5e7646d2SAndroid Build Coastguard Worker #include "getifaddrs-internal.h"
16*5e7646d2SAndroid Build Coastguard Worker
17*5e7646d2SAndroid Build Coastguard Worker
18*5e7646d2SAndroid Build Coastguard Worker #ifndef HAVE_GETIFADDRS
19*5e7646d2SAndroid Build Coastguard Worker /*
20*5e7646d2SAndroid Build Coastguard Worker * '_cups_getifaddrs()' - Get a list of network interfaces on the system.
21*5e7646d2SAndroid Build Coastguard Worker */
22*5e7646d2SAndroid Build Coastguard Worker
23*5e7646d2SAndroid Build Coastguard Worker int /* O - 0 on success, -1 on error */
_cups_getifaddrs(struct ifaddrs ** addrs)24*5e7646d2SAndroid Build Coastguard Worker _cups_getifaddrs(struct ifaddrs **addrs)/* O - List of interfaces */
25*5e7646d2SAndroid Build Coastguard Worker {
26*5e7646d2SAndroid Build Coastguard Worker int sock; /* Socket */
27*5e7646d2SAndroid Build Coastguard Worker char buffer[65536], /* Buffer for address info */
28*5e7646d2SAndroid Build Coastguard Worker *bufptr, /* Pointer into buffer */
29*5e7646d2SAndroid Build Coastguard Worker *bufend; /* End of buffer */
30*5e7646d2SAndroid Build Coastguard Worker struct ifconf conf; /* Interface configurations */
31*5e7646d2SAndroid Build Coastguard Worker struct sockaddr addr; /* Address data */
32*5e7646d2SAndroid Build Coastguard Worker struct ifreq *ifp; /* Interface data */
33*5e7646d2SAndroid Build Coastguard Worker int ifpsize; /* Size of interface data */
34*5e7646d2SAndroid Build Coastguard Worker struct ifaddrs *temp; /* Pointer to current interface */
35*5e7646d2SAndroid Build Coastguard Worker struct ifreq request; /* Interface request */
36*5e7646d2SAndroid Build Coastguard Worker
37*5e7646d2SAndroid Build Coastguard Worker
38*5e7646d2SAndroid Build Coastguard Worker /*
39*5e7646d2SAndroid Build Coastguard Worker * Start with an empty list...
40*5e7646d2SAndroid Build Coastguard Worker */
41*5e7646d2SAndroid Build Coastguard Worker
42*5e7646d2SAndroid Build Coastguard Worker if (addrs == NULL)
43*5e7646d2SAndroid Build Coastguard Worker return (-1);
44*5e7646d2SAndroid Build Coastguard Worker
45*5e7646d2SAndroid Build Coastguard Worker *addrs = NULL;
46*5e7646d2SAndroid Build Coastguard Worker
47*5e7646d2SAndroid Build Coastguard Worker /*
48*5e7646d2SAndroid Build Coastguard Worker * Create a UDP socket to get the interface data...
49*5e7646d2SAndroid Build Coastguard Worker */
50*5e7646d2SAndroid Build Coastguard Worker
51*5e7646d2SAndroid Build Coastguard Worker memset (&addr, 0, sizeof(addr));
52*5e7646d2SAndroid Build Coastguard Worker if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
53*5e7646d2SAndroid Build Coastguard Worker return (-1);
54*5e7646d2SAndroid Build Coastguard Worker
55*5e7646d2SAndroid Build Coastguard Worker /*
56*5e7646d2SAndroid Build Coastguard Worker * Try to get the list of interfaces...
57*5e7646d2SAndroid Build Coastguard Worker */
58*5e7646d2SAndroid Build Coastguard Worker
59*5e7646d2SAndroid Build Coastguard Worker conf.ifc_len = sizeof(buffer);
60*5e7646d2SAndroid Build Coastguard Worker conf.ifc_buf = buffer;
61*5e7646d2SAndroid Build Coastguard Worker
62*5e7646d2SAndroid Build Coastguard Worker if (ioctl(sock, SIOCGIFCONF, &conf) < 0)
63*5e7646d2SAndroid Build Coastguard Worker {
64*5e7646d2SAndroid Build Coastguard Worker /*
65*5e7646d2SAndroid Build Coastguard Worker * Couldn't get the list of interfaces...
66*5e7646d2SAndroid Build Coastguard Worker */
67*5e7646d2SAndroid Build Coastguard Worker
68*5e7646d2SAndroid Build Coastguard Worker close(sock);
69*5e7646d2SAndroid Build Coastguard Worker return (-1);
70*5e7646d2SAndroid Build Coastguard Worker }
71*5e7646d2SAndroid Build Coastguard Worker
72*5e7646d2SAndroid Build Coastguard Worker /*
73*5e7646d2SAndroid Build Coastguard Worker * OK, got the list of interfaces, now lets step through the
74*5e7646d2SAndroid Build Coastguard Worker * buffer to pull them out...
75*5e7646d2SAndroid Build Coastguard Worker */
76*5e7646d2SAndroid Build Coastguard Worker
77*5e7646d2SAndroid Build Coastguard Worker # ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
78*5e7646d2SAndroid Build Coastguard Worker # define sockaddr_len(a) ((a)->sa_len)
79*5e7646d2SAndroid Build Coastguard Worker # else
80*5e7646d2SAndroid Build Coastguard Worker # define sockaddr_len(a) (sizeof(struct sockaddr))
81*5e7646d2SAndroid Build Coastguard Worker # endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
82*5e7646d2SAndroid Build Coastguard Worker
83*5e7646d2SAndroid Build Coastguard Worker for (bufptr = buffer, bufend = buffer + conf.ifc_len;
84*5e7646d2SAndroid Build Coastguard Worker bufptr < bufend;
85*5e7646d2SAndroid Build Coastguard Worker bufptr += ifpsize)
86*5e7646d2SAndroid Build Coastguard Worker {
87*5e7646d2SAndroid Build Coastguard Worker /*
88*5e7646d2SAndroid Build Coastguard Worker * Get the current interface information...
89*5e7646d2SAndroid Build Coastguard Worker */
90*5e7646d2SAndroid Build Coastguard Worker
91*5e7646d2SAndroid Build Coastguard Worker ifp = (struct ifreq *)bufptr;
92*5e7646d2SAndroid Build Coastguard Worker ifpsize = sizeof(ifp->ifr_name) + sockaddr_len(&(ifp->ifr_addr));
93*5e7646d2SAndroid Build Coastguard Worker
94*5e7646d2SAndroid Build Coastguard Worker if (ifpsize < sizeof(struct ifreq))
95*5e7646d2SAndroid Build Coastguard Worker ifpsize = sizeof(struct ifreq);
96*5e7646d2SAndroid Build Coastguard Worker
97*5e7646d2SAndroid Build Coastguard Worker memset(&request, 0, sizeof(request));
98*5e7646d2SAndroid Build Coastguard Worker memcpy(request.ifr_name, ifp->ifr_name, sizeof(ifp->ifr_name));
99*5e7646d2SAndroid Build Coastguard Worker
100*5e7646d2SAndroid Build Coastguard Worker /*
101*5e7646d2SAndroid Build Coastguard Worker * Check the status of the interface...
102*5e7646d2SAndroid Build Coastguard Worker */
103*5e7646d2SAndroid Build Coastguard Worker
104*5e7646d2SAndroid Build Coastguard Worker if (ioctl(sock, SIOCGIFFLAGS, &request) < 0)
105*5e7646d2SAndroid Build Coastguard Worker continue;
106*5e7646d2SAndroid Build Coastguard Worker
107*5e7646d2SAndroid Build Coastguard Worker /*
108*5e7646d2SAndroid Build Coastguard Worker * Allocate memory for a single interface record...
109*5e7646d2SAndroid Build Coastguard Worker */
110*5e7646d2SAndroid Build Coastguard Worker
111*5e7646d2SAndroid Build Coastguard Worker if ((temp = calloc(1, sizeof(struct ifaddrs))) == NULL)
112*5e7646d2SAndroid Build Coastguard Worker {
113*5e7646d2SAndroid Build Coastguard Worker /*
114*5e7646d2SAndroid Build Coastguard Worker * Unable to allocate memory...
115*5e7646d2SAndroid Build Coastguard Worker */
116*5e7646d2SAndroid Build Coastguard Worker
117*5e7646d2SAndroid Build Coastguard Worker close(sock);
118*5e7646d2SAndroid Build Coastguard Worker return (-1);
119*5e7646d2SAndroid Build Coastguard Worker }
120*5e7646d2SAndroid Build Coastguard Worker
121*5e7646d2SAndroid Build Coastguard Worker /*
122*5e7646d2SAndroid Build Coastguard Worker * Add this record to the front of the list and copy the name, flags,
123*5e7646d2SAndroid Build Coastguard Worker * and network address...
124*5e7646d2SAndroid Build Coastguard Worker */
125*5e7646d2SAndroid Build Coastguard Worker
126*5e7646d2SAndroid Build Coastguard Worker temp->ifa_next = *addrs;
127*5e7646d2SAndroid Build Coastguard Worker *addrs = temp;
128*5e7646d2SAndroid Build Coastguard Worker temp->ifa_name = strdup(ifp->ifr_name);
129*5e7646d2SAndroid Build Coastguard Worker temp->ifa_flags = request.ifr_flags;
130*5e7646d2SAndroid Build Coastguard Worker if ((temp->ifa_addr = calloc(1, sockaddr_len(&(ifp->ifr_addr)))) != NULL)
131*5e7646d2SAndroid Build Coastguard Worker memcpy(temp->ifa_addr, &(ifp->ifr_addr), sockaddr_len(&(ifp->ifr_addr)));
132*5e7646d2SAndroid Build Coastguard Worker
133*5e7646d2SAndroid Build Coastguard Worker /*
134*5e7646d2SAndroid Build Coastguard Worker * Try to get the netmask for the interface...
135*5e7646d2SAndroid Build Coastguard Worker */
136*5e7646d2SAndroid Build Coastguard Worker
137*5e7646d2SAndroid Build Coastguard Worker if (!ioctl(sock, SIOCGIFNETMASK, &request))
138*5e7646d2SAndroid Build Coastguard Worker {
139*5e7646d2SAndroid Build Coastguard Worker /*
140*5e7646d2SAndroid Build Coastguard Worker * Got it, make a copy...
141*5e7646d2SAndroid Build Coastguard Worker */
142*5e7646d2SAndroid Build Coastguard Worker
143*5e7646d2SAndroid Build Coastguard Worker if ((temp->ifa_netmask = calloc(1, sizeof(request.ifr_netmask))) != NULL)
144*5e7646d2SAndroid Build Coastguard Worker memcpy(temp->ifa_netmask, &(request.ifr_netmask),
145*5e7646d2SAndroid Build Coastguard Worker sizeof(request.ifr_netmask));
146*5e7646d2SAndroid Build Coastguard Worker }
147*5e7646d2SAndroid Build Coastguard Worker
148*5e7646d2SAndroid Build Coastguard Worker /*
149*5e7646d2SAndroid Build Coastguard Worker * Then get the broadcast or point-to-point (destination) address,
150*5e7646d2SAndroid Build Coastguard Worker * if applicable...
151*5e7646d2SAndroid Build Coastguard Worker */
152*5e7646d2SAndroid Build Coastguard Worker
153*5e7646d2SAndroid Build Coastguard Worker if (temp->ifa_flags & IFF_BROADCAST)
154*5e7646d2SAndroid Build Coastguard Worker {
155*5e7646d2SAndroid Build Coastguard Worker /*
156*5e7646d2SAndroid Build Coastguard Worker * Have a broadcast address, so get it!
157*5e7646d2SAndroid Build Coastguard Worker */
158*5e7646d2SAndroid Build Coastguard Worker
159*5e7646d2SAndroid Build Coastguard Worker if (!ioctl(sock, SIOCGIFBRDADDR, &request))
160*5e7646d2SAndroid Build Coastguard Worker {
161*5e7646d2SAndroid Build Coastguard Worker /*
162*5e7646d2SAndroid Build Coastguard Worker * Got it, make a copy...
163*5e7646d2SAndroid Build Coastguard Worker */
164*5e7646d2SAndroid Build Coastguard Worker
165*5e7646d2SAndroid Build Coastguard Worker if ((temp->ifa_broadaddr =
166*5e7646d2SAndroid Build Coastguard Worker calloc(1, sizeof(request.ifr_broadaddr))) != NULL)
167*5e7646d2SAndroid Build Coastguard Worker memcpy(temp->ifa_broadaddr, &(request.ifr_broadaddr),
168*5e7646d2SAndroid Build Coastguard Worker sizeof(request.ifr_broadaddr));
169*5e7646d2SAndroid Build Coastguard Worker }
170*5e7646d2SAndroid Build Coastguard Worker }
171*5e7646d2SAndroid Build Coastguard Worker else if (temp->ifa_flags & IFF_POINTOPOINT)
172*5e7646d2SAndroid Build Coastguard Worker {
173*5e7646d2SAndroid Build Coastguard Worker /*
174*5e7646d2SAndroid Build Coastguard Worker * Point-to-point interface; grab the remote address...
175*5e7646d2SAndroid Build Coastguard Worker */
176*5e7646d2SAndroid Build Coastguard Worker
177*5e7646d2SAndroid Build Coastguard Worker if (!ioctl(sock, SIOCGIFDSTADDR, &request))
178*5e7646d2SAndroid Build Coastguard Worker {
179*5e7646d2SAndroid Build Coastguard Worker temp->ifa_dstaddr = malloc(sizeof(request.ifr_dstaddr));
180*5e7646d2SAndroid Build Coastguard Worker memcpy(temp->ifa_dstaddr, &(request.ifr_dstaddr),
181*5e7646d2SAndroid Build Coastguard Worker sizeof(request.ifr_dstaddr));
182*5e7646d2SAndroid Build Coastguard Worker }
183*5e7646d2SAndroid Build Coastguard Worker }
184*5e7646d2SAndroid Build Coastguard Worker }
185*5e7646d2SAndroid Build Coastguard Worker
186*5e7646d2SAndroid Build Coastguard Worker /*
187*5e7646d2SAndroid Build Coastguard Worker * OK, we're done with the socket, close it and return 0...
188*5e7646d2SAndroid Build Coastguard Worker */
189*5e7646d2SAndroid Build Coastguard Worker
190*5e7646d2SAndroid Build Coastguard Worker close(sock);
191*5e7646d2SAndroid Build Coastguard Worker
192*5e7646d2SAndroid Build Coastguard Worker return (0);
193*5e7646d2SAndroid Build Coastguard Worker }
194*5e7646d2SAndroid Build Coastguard Worker
195*5e7646d2SAndroid Build Coastguard Worker
196*5e7646d2SAndroid Build Coastguard Worker /*
197*5e7646d2SAndroid Build Coastguard Worker * '_cups_freeifaddrs()' - Free an interface list...
198*5e7646d2SAndroid Build Coastguard Worker */
199*5e7646d2SAndroid Build Coastguard Worker
200*5e7646d2SAndroid Build Coastguard Worker void
_cups_freeifaddrs(struct ifaddrs * addrs)201*5e7646d2SAndroid Build Coastguard Worker _cups_freeifaddrs(struct ifaddrs *addrs)/* I - Interface list to free */
202*5e7646d2SAndroid Build Coastguard Worker {
203*5e7646d2SAndroid Build Coastguard Worker struct ifaddrs *next; /* Next interface in list */
204*5e7646d2SAndroid Build Coastguard Worker
205*5e7646d2SAndroid Build Coastguard Worker
206*5e7646d2SAndroid Build Coastguard Worker while (addrs != NULL)
207*5e7646d2SAndroid Build Coastguard Worker {
208*5e7646d2SAndroid Build Coastguard Worker /*
209*5e7646d2SAndroid Build Coastguard Worker * Make a copy of the next interface pointer...
210*5e7646d2SAndroid Build Coastguard Worker */
211*5e7646d2SAndroid Build Coastguard Worker
212*5e7646d2SAndroid Build Coastguard Worker next = addrs->ifa_next;
213*5e7646d2SAndroid Build Coastguard Worker
214*5e7646d2SAndroid Build Coastguard Worker /*
215*5e7646d2SAndroid Build Coastguard Worker * Free data values as needed...
216*5e7646d2SAndroid Build Coastguard Worker */
217*5e7646d2SAndroid Build Coastguard Worker
218*5e7646d2SAndroid Build Coastguard Worker if (addrs->ifa_name)
219*5e7646d2SAndroid Build Coastguard Worker {
220*5e7646d2SAndroid Build Coastguard Worker free(addrs->ifa_name);
221*5e7646d2SAndroid Build Coastguard Worker addrs->ifa_name = NULL;
222*5e7646d2SAndroid Build Coastguard Worker }
223*5e7646d2SAndroid Build Coastguard Worker
224*5e7646d2SAndroid Build Coastguard Worker if (addrs->ifa_addr)
225*5e7646d2SAndroid Build Coastguard Worker {
226*5e7646d2SAndroid Build Coastguard Worker free(addrs->ifa_addr);
227*5e7646d2SAndroid Build Coastguard Worker addrs->ifa_addr = NULL;
228*5e7646d2SAndroid Build Coastguard Worker }
229*5e7646d2SAndroid Build Coastguard Worker
230*5e7646d2SAndroid Build Coastguard Worker if (addrs->ifa_netmask)
231*5e7646d2SAndroid Build Coastguard Worker {
232*5e7646d2SAndroid Build Coastguard Worker free(addrs->ifa_netmask);
233*5e7646d2SAndroid Build Coastguard Worker addrs->ifa_netmask = NULL;
234*5e7646d2SAndroid Build Coastguard Worker }
235*5e7646d2SAndroid Build Coastguard Worker
236*5e7646d2SAndroid Build Coastguard Worker if (addrs->ifa_dstaddr)
237*5e7646d2SAndroid Build Coastguard Worker {
238*5e7646d2SAndroid Build Coastguard Worker free(addrs->ifa_dstaddr);
239*5e7646d2SAndroid Build Coastguard Worker addrs->ifa_dstaddr = NULL;
240*5e7646d2SAndroid Build Coastguard Worker }
241*5e7646d2SAndroid Build Coastguard Worker
242*5e7646d2SAndroid Build Coastguard Worker /*
243*5e7646d2SAndroid Build Coastguard Worker * Free this node and continue to the next...
244*5e7646d2SAndroid Build Coastguard Worker */
245*5e7646d2SAndroid Build Coastguard Worker
246*5e7646d2SAndroid Build Coastguard Worker free(addrs);
247*5e7646d2SAndroid Build Coastguard Worker
248*5e7646d2SAndroid Build Coastguard Worker addrs = next;
249*5e7646d2SAndroid Build Coastguard Worker }
250*5e7646d2SAndroid Build Coastguard Worker }
251*5e7646d2SAndroid Build Coastguard Worker #endif /* !HAVE_GETIFADDRS */
252