xref: /aosp_15_r20/external/libcups/cups/getifaddrs.c (revision 5e7646d21f1134fb0638875d812ef646c12ab91e)
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