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