Back to index

glibc  2.9
ifreq.c
Go to the documentation of this file.
00001 /* Copyright (C) 1999,2002,2003,2004,2005,2006 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003    Contributed by Andreas Jaeger <aj@suse.de>.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #include "ifreq.h"
00021 #include <kernel-features.h>
00022 
00023 /* Variable to signal whether SIOCGIFCONF is not available.  */
00024 #if __ASSUME_SIOCGIFNAME == 0 || 1
00025 static int old_siocgifconf;
00026 #else
00027 # define old_siocgifconf 0
00028 #endif
00029 
00030 
00031 void
00032 __ifreq (struct ifreq **ifreqs, int *num_ifs, int sockfd)
00033 {
00034   int fd = sockfd;
00035   struct ifconf ifc;
00036   int rq_len;
00037   int nifs;
00038 # define RQ_IFS      4
00039 
00040   if (fd < 0)
00041     fd = __opensock ();
00042   if (fd < 0)
00043     {
00044       *num_ifs = 0;
00045       *ifreqs = NULL;
00046       return;
00047     }
00048 
00049   ifc.ifc_buf = NULL;
00050 
00051   /* We may be able to get the needed buffer size directly, rather than
00052      guessing.  */
00053   if (! old_siocgifconf)
00054     {
00055       ifc.ifc_buf = NULL;
00056       ifc.ifc_len = 0;
00057       if (__ioctl (fd, SIOCGIFCONF, &ifc) < 0 || ifc.ifc_len == 0)
00058        {
00059 # if __ASSUME_SIOCGIFNAME == 0
00060          old_siocgifconf = 1;
00061 # endif
00062          rq_len = RQ_IFS * sizeof (struct ifreq);
00063        }
00064       else
00065        rq_len = ifc.ifc_len;
00066     }
00067   else
00068     rq_len = RQ_IFS * sizeof (struct ifreq);
00069 
00070   /* Read all the interfaces out of the kernel.  */
00071   while (1)
00072     {
00073       ifc.ifc_len = rq_len;
00074       void *newp = realloc (ifc.ifc_buf, ifc.ifc_len);
00075       if (newp == NULL
00076          || (ifc.ifc_buf = newp, __ioctl (fd, SIOCGIFCONF, &ifc)) < 0)
00077        {
00078          free (ifc.ifc_buf);
00079 
00080          if (fd != sockfd)
00081            __close (fd);
00082 
00083          *num_ifs = 0;
00084          *ifreqs = NULL;
00085          return;
00086        }
00087 
00088       if (!old_siocgifconf || ifc.ifc_len < rq_len)
00089        break;
00090 
00091       rq_len *= 2;
00092     }
00093 
00094   nifs = ifc.ifc_len / sizeof (struct ifreq);
00095 
00096   if (fd != sockfd)
00097     __close (fd);
00098 
00099   *num_ifs = nifs;
00100   *ifreqs = realloc (ifc.ifc_buf, nifs * sizeof (struct ifreq));
00101 }