ipme.c
changeset 0 068428edee47
equal deleted inserted replaced
-1:000000000000 0:068428edee47
       
     1 #include <sys/types.h>
       
     2 #include <sys/param.h>
       
     3 #include <sys/time.h>
       
     4 #include <sys/ioctl.h>
       
     5 #include <sys/socket.h>
       
     6 #include <net/if.h>
       
     7 #include <netinet/in.h>
       
     8 #ifndef SIOCGIFCONF /* whatever works */
       
     9 #include <sys/sockio.h>
       
    10 #endif
       
    11 #include "hassalen.h"
       
    12 #include "byte.h"
       
    13 #include "ip.h"
       
    14 #include "ipalloc.h"
       
    15 #include "stralloc.h"
       
    16 #include "ipme.h"
       
    17 
       
    18 static int ipmeok = 0;
       
    19 ipalloc ipme = {0};
       
    20 
       
    21 int ipme_is(ip)
       
    22 struct ip_address *ip;
       
    23 {
       
    24   int i;
       
    25   if (ipme_init() != 1) return -1;
       
    26   for (i = 0;i < ipme.len;++i)
       
    27     if (byte_equal(&ipme.ix[i].ip,4,ip))
       
    28       return 1;
       
    29   return 0;
       
    30 }
       
    31 
       
    32 static stralloc buf = {0};
       
    33 
       
    34 int ipme_init()
       
    35 {
       
    36   struct ifconf ifc;
       
    37   char *x;
       
    38   struct ifreq *ifr;
       
    39   struct sockaddr_in *sin;
       
    40   int len;
       
    41   int s;
       
    42   struct ip_mx ix;
       
    43  
       
    44   if (ipmeok) return 1;
       
    45   if (!ipalloc_readyplus(&ipme,0)) return 0;
       
    46   ipme.len = 0;
       
    47   ix.pref = 0;
       
    48  
       
    49   if ((s = socket(AF_INET,SOCK_STREAM,0)) == -1) return -1;
       
    50  
       
    51   len = 256;
       
    52   for (;;) {
       
    53     if (!stralloc_ready(&buf,len)) { close(s); return 0; }
       
    54     buf.len = 0;
       
    55     ifc.ifc_buf = buf.s;
       
    56     ifc.ifc_len = len;
       
    57     if (ioctl(s,SIOCGIFCONF,&ifc) >= 0) /* > is for System V */
       
    58       if (ifc.ifc_len + sizeof(*ifr) + 64 < len) { /* what a stupid interface */
       
    59         buf.len = ifc.ifc_len;
       
    60         break;
       
    61       }
       
    62     if (len > 200000) { close(s); return -1; }
       
    63     len += 100 + (len >> 2);
       
    64   }
       
    65   x = buf.s;
       
    66   while (x < buf.s + buf.len) {
       
    67     ifr = (struct ifreq *) x;
       
    68 #ifdef HASSALEN
       
    69     len = sizeof(ifr->ifr_name) + ifr->ifr_addr.sa_len;
       
    70     if (len < sizeof(*ifr))
       
    71       len = sizeof(*ifr);
       
    72     if (ifr->ifr_addr.sa_family == AF_INET) {
       
    73       sin = (struct sockaddr_in *) &ifr->ifr_addr;
       
    74       byte_copy(&ix.ip,4,&sin->sin_addr);
       
    75       if (ioctl(s,SIOCGIFFLAGS,x) == 0)
       
    76         if (ifr->ifr_flags & IFF_UP)
       
    77           if (!ipalloc_append(&ipme,&ix)) { close(s); return 0; }
       
    78     }
       
    79 #else
       
    80     len = sizeof(*ifr);
       
    81     if (ioctl(s,SIOCGIFFLAGS,x) == 0)
       
    82       if (ifr->ifr_flags & IFF_UP)
       
    83         if (ioctl(s,SIOCGIFADDR,x) == 0)
       
    84 	  if (ifr->ifr_addr.sa_family == AF_INET) {
       
    85 	    sin = (struct sockaddr_in *) &ifr->ifr_addr;
       
    86 	    byte_copy(&ix.ip,4,&sin->sin_addr);
       
    87 	    if (!ipalloc_append(&ipme,&ix)) { close(s); return 0; }
       
    88 	  }
       
    89 #endif
       
    90     x += len;
       
    91   }
       
    92   close(s);
       
    93   ipmeok = 1;
       
    94   return 1;
       
    95 }