]>
git.ipfire.org Git - thirdparty/cups.git/blob - cups/getifaddrs.c
2 * Network interface functions for CUPS.
4 * Copyright © 2007-2010 by Apple Inc.
5 * Copyright © 1997-2006 by Easy Software Products, all rights reserved.
7 * Licensed under Apache License v2.0. See the file "LICENSE" for more
12 * Include necessary headers.
15 #include "http-private.h"
18 #ifndef HAVE_GETIFADDRS
20 * '_cups_getifaddrs()' - Get a list of network interfaces on the system.
23 int /* O - 0 on success, -1 on error */
24 _cups_getifaddrs(struct ifaddrs
**addrs
)/* O - List of interfaces */
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 */
39 * Start with an empty list...
48 * Create a UDP socket to get the interface data...
51 memset (&addr
, 0, sizeof(addr
));
52 if ((sock
= socket(AF_INET
, SOCK_DGRAM
, 0)) < 0)
56 * Try to get the list of interfaces...
59 conf
.ifc_len
= sizeof(buffer
);
60 conf
.ifc_buf
= buffer
;
62 if (ioctl(sock
, SIOCGIFCONF
, &conf
) < 0)
65 * Couldn't get the list of interfaces...
73 * OK, got the list of interfaces, now lets step through the
74 * buffer to pull them out...
77 # ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
78 # define sockaddr_len(a) ((a)->sa_len)
80 # define sockaddr_len(a) (sizeof(struct sockaddr))
81 # endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
83 for (bufptr
= buffer
, bufend
= buffer
+ conf
.ifc_len
;
88 * Get the current interface information...
91 ifp
= (struct ifreq
*)bufptr
;
92 ifpsize
= sizeof(ifp
->ifr_name
) + sockaddr_len(&(ifp
->ifr_addr
));
94 if (ifpsize
< sizeof(struct ifreq
))
95 ifpsize
= sizeof(struct ifreq
);
97 memset(&request
, 0, sizeof(request
));
98 memcpy(request
.ifr_name
, ifp
->ifr_name
, sizeof(ifp
->ifr_name
));
101 * Check the status of the interface...
104 if (ioctl(sock
, SIOCGIFFLAGS
, &request
) < 0)
108 * Allocate memory for a single interface record...
111 if ((temp
= calloc(1, sizeof(struct ifaddrs
))) == NULL
)
114 * Unable to allocate memory...
122 * Add this record to the front of the list and copy the name, flags,
123 * and network address...
126 temp
->ifa_next
= *addrs
;
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
)));
134 * Try to get the netmask for the interface...
137 if (!ioctl(sock
, SIOCGIFNETMASK
, &request
))
140 * Got it, make a copy...
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
));
149 * Then get the broadcast or point-to-point (destination) address,
153 if (temp
->ifa_flags
& IFF_BROADCAST
)
156 * Have a broadcast address, so get it!
159 if (!ioctl(sock
, SIOCGIFBRDADDR
, &request
))
162 * Got it, make a copy...
165 if ((temp
->ifa_broadaddr
=
166 calloc(1, sizeof(request
.ifr_broadaddr
))) != NULL
)
167 memcpy(temp
->ifa_broadaddr
, &(request
.ifr_broadaddr
),
168 sizeof(request
.ifr_broadaddr
));
171 else if (temp
->ifa_flags
& IFF_POINTOPOINT
)
174 * Point-to-point interface; grab the remote address...
177 if (!ioctl(sock
, SIOCGIFDSTADDR
, &request
))
179 temp
->ifa_dstaddr
= malloc(sizeof(request
.ifr_dstaddr
));
180 memcpy(temp
->ifa_dstaddr
, &(request
.ifr_dstaddr
),
181 sizeof(request
.ifr_dstaddr
));
187 * OK, we're done with the socket, close it and return 0...
197 * '_cups_freeifaddrs()' - Free an interface list...
201 _cups_freeifaddrs(struct ifaddrs
*addrs
)/* I - Interface list to free */
203 struct ifaddrs
*next
; /* Next interface in list */
206 while (addrs
!= NULL
)
209 * Make a copy of the next interface pointer...
212 next
= addrs
->ifa_next
;
215 * Free data values as needed...
220 free(addrs
->ifa_name
);
221 addrs
->ifa_name
= NULL
;
226 free(addrs
->ifa_addr
);
227 addrs
->ifa_addr
= NULL
;
230 if (addrs
->ifa_netmask
)
232 free(addrs
->ifa_netmask
);
233 addrs
->ifa_netmask
= NULL
;
236 if (addrs
->ifa_dstaddr
)
238 free(addrs
->ifa_dstaddr
);
239 addrs
->ifa_dstaddr
= NULL
;
243 * Free this node and continue to the next...
251 #endif /* !HAVE_GETIFADDRS */