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