ifiter_ioctl.c revision 9c3531d72aeaad6c5f01efe6a1c82023e1379e4d
f6b909274159da7aaad8463c90f15018136cf6cbTinderbox User * Copyright (C) 1999, 2000 Internet Software Consortium.
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * Permission to use, copy, modify, and distribute this software for any
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * purpose with or without fee is hereby granted, provided that the above
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * copyright notice and this permission notice appear in all copies.
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley/* $Id: ifiter_ioctl.c,v 1.11 2000/06/22 21:58:37 tale Exp $ */
9297259c7abecc78470fdeca173c101137e4b5bbMark Andrews * Obtain the list of network interfaces using the SIOCGLIFCONF ioctl.
9297259c7abecc78470fdeca173c101137e4b5bbMark Andrews * See netintro(4).
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley#define VALID_IFITER(t) ((t) != NULL && (t)->magic == IFITER_MAGIC)
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley SIOCGLIFCONF data */
6af51ff1a30dd977c4fc6c342a0661bb4f6501a5Bob Halley isc_interface_t current; /* Current interface data. */
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * Size of buffer for SIOCGLIFCONF, in bytes. We assume no sane system
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * will have more than a megabyte of interface configuration data.
6af51ff1a30dd977c4fc6c342a0661bb4f6501a5Bob Halleyisc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) {
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * Create an unbound datagram socket to do the SIOCGLIFADDR ioctl on.
bfa633fc0e5dea8f65676c5393993ba7053a9899Andreas Gustafsson if ((iter->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
bfa633fc0e5dea8f65676c5393993ba7053a9899Andreas Gustafsson "making interface scan socket: %s",
e605e98f3e4be079f545b26bb53ba02a6d04b0b6Andreas Gustafsson * Get the interface configuration, allocating more memory if
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * necessary.
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley memset(&iter->ifc.lifc_len, 0, sizeof(iter->ifc.lifc_len));
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * Ignore the HP/UX warning about "interger overflow during
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * conversion. It comes from its own macro definition,
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * and is really hard to shut up.
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley if (ioctl(iter->socket, SIOCGLIFCONF, (char *)&iter->ifc)
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley "get interface configuration: %s",
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * EINVAL. Retry with a bigger buffer.
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * The ioctl succeeded.
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * Some OS's just return what will fit rather
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * than set EINVAL if the buffer is too small
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * to fit all the interfaces in. If
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * ifc.lifc_len is too near to the end of the
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * buffer we will grow it just in case and
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley if (iter->ifc.lifc_len + 2 * sizeof(struct lifreq)
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley "get interface configuration: "
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley "maximum buffer size exceeded");
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff * A newly created iterator has an undefined position
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * until isc_interfaceiter_first() is called.
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * Get information about the current interface to iter->current.
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * If successful, return ISC_R_SUCCESS.
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * If the interface has an unsupported address family, or if
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * some operation on it fails, return ISC_R_IGNORE to make
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * the higher-level iterator code ignore it.
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley REQUIRE (iter->pos < (unsigned int) iter->ifc.lifc_len);
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley ifrp = (struct lifreq *)((char *) iter->ifc.lifc_req + iter->pos);
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley memset(&iter->current, 0, sizeof(iter->current));
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley INSIST(sizeof(lifreq.lifr_name) <= sizeof(iter->current.name));
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley memcpy(iter->current.name, lifreq.lifr_name, sizeof(lifreq.lifr_name));
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * Get interface flags.
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * Ignore the HP/UX warning about "interger overflow during
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * conversion. It comes from its own macro definition,
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * and is really hard to shut up.
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley if (ioctl(iter->socket, SIOCGLIFFLAGS, (char *) &lifreq) < 0) {
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley "%s: getting interface flags: %s",
4e21e54a0394d0f87798620a95c1f675c0b0d09cMichael Graff if ((lifreq.lifr_flags & IFF_POINTOPOINT) != 0)
558ab0f6a8046499bfe3e39ea4789036313b72b3Michael Graff iter->current.flags |= INTERFACE_F_POINTTOPOINT;
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * If the interface is point-to-point, get the destination address.
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) {
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * Ignore the HP/UX warning about "interger overflow during
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * conversion. It comes from its own macro definition,
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * and is really hard to shut up.
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley if (ioctl(iter->socket, SIOCGLIFDSTADDR, (char *)&lifreq)
95b41befcb9e75df2b451ceeb9f8812ccedcc25fAndreas Gustafsson "%s: getting destination address: %s",
7cbfebb762d0d9ba77699e2c15530278e0e4980eAndreas Gustafsson get_addr(family, &iter->current.dstaddress,
7cbfebb762d0d9ba77699e2c15530278e0e4980eAndreas Gustafsson (struct sockaddr *)&lifreq.lifr_dstaddr);
7cbfebb762d0d9ba77699e2c15530278e0e4980eAndreas Gustafsson * Get the network mask.
7cbfebb762d0d9ba77699e2c15530278e0e4980eAndreas Gustafsson * Ignore the HP/UX warning about "interger overflow during
7cbfebb762d0d9ba77699e2c15530278e0e4980eAndreas Gustafsson * conversion. It comes from its own macro definition,
7cbfebb762d0d9ba77699e2c15530278e0e4980eAndreas Gustafsson * and is really hard to shut up.
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence if (ioctl(iter->socket, SIOCGLIFNETMASK, (char *)&lifreq)
7cbfebb762d0d9ba77699e2c15530278e0e4980eAndreas Gustafsson "%s: getting netmask: %s",
95b41befcb9e75df2b451ceeb9f8812ccedcc25fAndreas Gustafsson * Netmask already zeroed.
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff for (i = 0 ; i < lifreq.lifr_addrlen; i += 8) {
7cbfebb762d0d9ba77699e2c15530278e0e4980eAndreas Gustafsson iter->current.netmask.type.in6.s6_addr[i/8] =
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * Step the iterator to the next interface. Unlike
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * isc_interfaceiter_next(), this may leave the iterator
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley * positioned on an interface that will ultimately
de4ef688d73a449d4c1218adbb35a4f70a71e672Brian Wellington * be ignored. Return ISC_R_NOMORE if there are no more
de4ef688d73a449d4c1218adbb35a4f70a71e672Brian Wellington * interfaces, otherwise ISC_R_SUCCESS.
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley REQUIRE (iter->pos < (unsigned int) iter->ifc.lifc_len);
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley ifrp = (struct lifreq *)((char *) iter->ifc.lifc_req + iter->pos);
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence if (ifrp->lifr_addr.sa_len > sizeof(struct sockaddr))
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley iter->pos += sizeof(ifrp->lifr_name) + ifrp->lifr_addr.sa_len;
99a9539ccde4a3769fd890bdae5bcce3a3492fbaBob Halley if (iter->pos >= (unsigned int) iter->ifc.lifc_len)