--- ipme.c.orig 1998-06-15 +++ ipme.c 2007-03-21 --- .././qmail-1.03/ipme.c Mon Jun 15 12:53:16 1998 +++ ../qmail-1.03.2418/ipme.c Mon Nov 22 21:55:35 2004 @@ -14,6 +14,10 @@ #include "ipalloc.h" #include "stralloc.h" #include "ipme.h" +#include "substdio.h" +#include "readwrite.h" + +#define MOREIPME static int ipmeok = 0; ipalloc ipme = {0}; @@ -31,6 +35,14 @@ 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; @@ -40,17 +52,48 @@ 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 (;;) { - if (!stralloc_ready(&buf,len)) { close(s); return 0; } +#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; @@ -59,7 +102,11 @@ 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; @@ -74,7 +121,11 @@ 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); @@ -84,12 +135,64 @@ if (ifr->ifr_addr.sa_family == AF_INET) { sin = (struct sockaddr_in *) &ifr->ifr_addr; byte_copy(&ix.ip,4,&sin->sin_addr); - if (!ipalloc_append(&ipme,&ix)) { close(s); return 0; } +#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 }