| 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 | } |