#include #include #include #include #include #include #include #ifndef SIOCGIFCONF /* whatever works */ #include #endif #include "hassalen.h" #include "byte.h" #include "ip.h" #include "ipalloc.h" #include "stralloc.h" #include "ipme.h" #include "substdio.h" #include "readwrite.h" /* #define MOREIPME */ static int ipmeok = 0; ipalloc ipme = {0}; int ipme_is(ip) struct ip_address *ip; { int i; if (ipme_init() != 1) return -1; for (i = 0;i < ipme.len;++i) if (byte_equal(&ipme.ix[i].ip,4,ip)) return 1; return 0; } static stralloc buf = {0}; #ifdef MOREIPME #define ipme_init_retclean(ret) { \ if (notipme.ix) alloc_free(notipme.ix); \ if (moreipme.ix) alloc_free(moreipme.ix); \ if (buf.s) alloc_free(buf.s); \ return ret; } #endif int ipme_init() { struct ifconf ifc; char *x; struct ifreq *ifr; struct sockaddr_in *sin; int len; int s; struct ip_mx ix; #ifdef MOREIPME ipalloc notipme = {0}; ipalloc moreipme = {0}; int i; if (ipmeok) return 1; if (!ipalloc_readyplus(&ipme,0)) ipme_init_retclean(0); if (!ipalloc_readyplus(¬ipme,0)) ipme_init_retclean(0); if (!ipalloc_readyplus(&moreipme,0)) ipme_init_retclean(0); #else if (ipmeok) return 1; if (!ipalloc_readyplus(&ipme,0)) return 0; #endif ipme.len = 0; ix.pref = 0; #ifdef MOREIPME if (!ipme_readipfile(¬ipme, "control/notipme")) ipme_init_retclean(0); #endif /* 0.0.0.0 is a special address which always refers to * "this host, this network", according to RFC 1122, Sec. 3.2.1.3a. */ byte_copy(&ix.ip,4,"\0\0\0\0"); #ifdef MOREIPME if ((s = socket(AF_INET,SOCK_STREAM,0)) == -1) ipme_init_retclean(-1); if (!ipme_append_unless(&ix,¬ipme)) ipme_init_retclean(0); #else if (!ipalloc_append(&ipme,&ix)) { return 0; } if ((s = socket(AF_INET,SOCK_STREAM,0)) == -1) return -1; #endif len = 256; for (;;) { #ifdef MOREIPME if (!stralloc_ready(&buf,len)) { close(s); ipme_init_retclean(0); } #else if (!stralloc_ready(&buf,len)) { close(s); return 0; } #endif buf.len = 0; ifc.ifc_buf = buf.s; ifc.ifc_len = len; if (ioctl(s,SIOCGIFCONF,&ifc) >= 0) /* > is for System V */ if (ifc.ifc_len + sizeof(*ifr) + 64 < len) { /* what a stupid interface */ buf.len = ifc.ifc_len; break; } #ifdef MOREIPME if (len > 200000) { close(s); ipme_init_retclean(-1); } #else if (len > 200000) { close(s); return -1; } #endif len += 100 + (len >> 2); } x = buf.s; while (x < buf.s + buf.len) { ifr = (struct ifreq *) x; #ifdef HASSALEN len = sizeof(ifr->ifr_name) + ifr->ifr_addr.sa_len; if (len < sizeof(*ifr)) len = sizeof(*ifr); if (ifr->ifr_addr.sa_family == AF_INET) { sin = (struct sockaddr_in *) &ifr->ifr_addr; byte_copy(&ix.ip,4,&sin->sin_addr); if (ioctl(s,SIOCGIFFLAGS,x) == 0) if (ifr->ifr_flags & IFF_UP) #ifdef MOREIPME if (!ipme_append_unless(&ix,¬ipme)) { close(s); ipme_init_retclean(0); } #else if (!ipalloc_append(&ipme,&ix)) { close(s); return 0; } #endif } #else len = sizeof(*ifr); if (ioctl(s,SIOCGIFFLAGS,x) == 0) if (ifr->ifr_flags & IFF_UP) if (ioctl(s,SIOCGIFADDR,x) == 0) if (ifr->ifr_addr.sa_family == AF_INET) { sin = (struct sockaddr_in *) &ifr->ifr_addr; byte_copy(&ix.ip,4,&sin->sin_addr); #ifdef MOREIPME if (!ipme_append_unless(&ix,¬ipme)) { close(s); ipme_init_retclean(0); } #else if (!ipalloc_append(&ipme,&ix)) { close(s); return 0; } #endif } #endif x += len; } close(s); #ifdef MOREIPME if (!ipme_readipfile(&moreipme, "control/moreipme")) ipme_init_retclean(0); for(i = 0;i < moreipme.len;++i) if (!ipme_append_unless(&moreipme.ix[i],¬ipme)) ipme_init_retclean(0); ipmeok = 1; ipme_init_retclean(1); } int ipme_readipfile(ipa, fn) ipalloc *ipa; char *fn; { int fd = -1; char inbuf[1024]; substdio ss; stralloc l = {0}; int match; struct ip_mx ix; int ret = 1; if ( (fd = open_read(fn)) != -1) { substdio_fdbuf(&ss, read, fd, inbuf, sizeof(inbuf)); while ( (getln(&ss,&l,&match,'\n') != -1) && (match || l.len) ) { l.len--; if (!stralloc_0(&l)) { ret = 0; break; } if (!ip_scan(l.s, &ix.ip)) continue; if (!ipalloc_append(ipa,&ix)) { ret = 0; break; } } if (l.s) alloc_free(l.s); if ( (fd >= 0) && (close(fd) == -1) ) ret = 0; } return ret; } int ipme_append_unless(ix, notip) struct ip_mx *ix; struct ipalloc *notip; { int i; for (i = 0;i < notip->len;++i) if (byte_equal(¬ip->ix[i].ip,4,&ix->ip)) return 1; return ipalloc_append(&ipme, ix); #else ipmeok = 1; return 1; #endif }