diff -ur --new-file qmail-1.03/Makefile qmail-1.03-moreipme-0.6/Makefile --- qmail-1.03/Makefile Mon Jun 15 06:53:16 1998 +++ qmail-1.03-moreipme-0.6/Makefile Sat May 22 18:38:48 2004 @@ -783,20 +783,31 @@ ipme.o: \ compile ipme.c hassalen.h byte.h ip.h ipalloc.h ip.h gen_alloc.h \ -stralloc.h gen_alloc.h ipme.h ip.h ipalloc.h +stralloc.h gen_alloc.h ipme.h ip.h ipalloc.h readwrite.h ./compile ipme.c ipmeprint: \ -load ipmeprint.o ipme.o ip.o ipalloc.o stralloc.a alloc.a substdio.a \ +load ipmeprint.o ipme.o ip.o ipalloc.o auto_qmail.o open.a getln.a stralloc.a alloc.a substdio.a \ error.a str.a fs.a socket.lib - ./load ipmeprint ipme.o ip.o ipalloc.o stralloc.a alloc.a \ + ./load ipmeprint ipme.o ip.o ipalloc.o auto_qmail.o open.a getln.a stralloc.a alloc.a \ substdio.a error.a str.a fs.a `cat socket.lib` ipmeprint.o: \ compile ipmeprint.c subfd.h substdio.h substdio.h ip.h ipme.h ip.h \ -ipalloc.h ip.h gen_alloc.h exit.h +ipalloc.h ip.h gen_alloc.h exit.h auto_qmail.h ./compile ipmeprint.c +ipmetest: \ +load ipmetest.o ipme.o ip.o ipalloc.o auto_qmail.o open.a getln.a stralloc.a alloc.a substdio.a \ +error.a str.a fs.a env.a socket.lib + ./load ipmetest ipme.o ip.o ipalloc.o auto_qmail.o open.a getln.a stralloc.a alloc.a \ + substdio.a error.a env.a str.a fs.a `cat socket.lib` + +ipmetest.o: \ +compile ipmetest.c subfd.h substdio.h substdio.h ip.h ipme.h ip.h \ +ipalloc.h ip.h gen_alloc.h exit.h auto_qmail.h + ./compile ipmetest.c + it: \ qmail-local qmail-lspawn qmail-getpw qmail-remote qmail-rspawn \ qmail-clean qmail-send qmail-start splogger qmail-queue qmail-inject \ @@ -804,7 +815,7 @@ qmail-pw2u qmail-qread qmail-qstat qmail-tcpto qmail-tcpok \ qmail-pop3d qmail-popup qmail-qmqpc qmail-qmqpd qmail-qmtpd \ qmail-smtpd sendmail tcp-env qmail-newmrh config config-fast dnscname \ -dnsptr dnsip dnsmxip dnsfq hostname ipmeprint qreceipt qsmhook qbiff \ +dnsptr dnsip dnsmxip dnsfq hostname ipmeprint ipmetest qreceipt qsmhook qbiff \ forward preline condredirect bouncesaying except maildirmake \ maildir2mbox maildirwatch qail elq pinq idedit install-big install \ instcheck home home+df proc proc+df binm1 binm1+df binm2 binm2+df \ @@ -1779,7 +1790,7 @@ qmail-qread.c qmail-qstat.sh qmail-queue.c qmail-remote.c \ qmail-rspawn.c qmail-send.c qmail-showctl.c qmail-smtpd.c \ qmail-start.c qmail-tcpok.c qmail-tcpto.c spawn.c dnscname.c dnsfq.c \ -dnsip.c dnsmxip.c dnsptr.c hostname.c ipmeprint.c tcp-env.c \ +dnsip.c dnsmxip.c dnsptr.c hostname.c ipmeprint.c ipmetest.c tcp-env.c \ sendmail.c qreceipt.c qsmhook.c qbiff.c forward.c preline.c predate.c \ except.c bouncesaying.c condredirect.c maildirmake.c maildir2mbox.c \ maildirwatch.c splogger.c qail.sh elq.sh pinq.sh qmail-upq.sh \ diff -ur --new-file qmail-1.03/TARGETS qmail-1.03-moreipme-0.6/TARGETS --- qmail-1.03/TARGETS Mon Jun 15 06:53:16 1998 +++ qmail-1.03-moreipme-0.6/TARGETS Sat May 22 18:38:48 2004 @@ -276,6 +276,8 @@ hostname ipmeprint.o ipmeprint +ipmetest.o +ipmetest qreceipt.o qreceipt qsmhook.o diff -ur --new-file qmail-1.03/ipme.c qmail-1.03-moreipme-0.6/ipme.c --- qmail-1.03/ipme.c Mon Jun 15 06:53:16 1998 +++ qmail-1.03-moreipme-0.6/ipme.c Sat May 22 19:04:25 2004 @@ -14,23 +14,65 @@ #include "ipalloc.h" #include "stralloc.h" #include "ipme.h" +#include "substdio.h" +#include "readwrite.h" static int ipmeok = 0; ipalloc ipme = {0}; +ipalloc ipme_mask = {0}; +ipalloc notipme = {0}; +ipalloc notipme_mask = {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; + return ipme_match(&ipme,&ipme_mask,ip) > ipme_match(¬ipme,¬ipme_mask,ip); } +int ipme_match(ipa, ipa_mask, ip) +struct ipalloc *ipa, *ipa_mask; +struct ip_address *ip; +{ + int i,j; + struct ip_address masked; + int masklen, longest_masklen=-1; + + for(i=0;i < ipa->len;++i) + { + masklen = 0; + for(j=0;j<4;++j) + { + switch(ipa_mask->ix[i].ip.d[j]) + { + case 255: masklen += 8; break; + case 254: masklen += 7; break; + case 252: masklen += 6; break; + case 248: masklen += 5; break; + case 240: masklen += 4; break; + case 224: masklen += 3; break; + case 192: masklen += 2; break; + case 128: masklen += 1; break; + default: masklen += 0; break; + } + if (ipa->ix[i].ip.d[j] != (ip->d[j] & ipa_mask->ix[i].ip.d[j])) + break; + } + if ( (j == 4) && (masklen > longest_masklen) ) + { + longest_masklen = masklen; + } + } + return longest_masklen; +} static stralloc buf = {0}; +#define ipme_init_retclean(ret) { \ + if (moreipme.ix) alloc_free(moreipme.ix); \ + if (moreipme_mask.ix) alloc_free(moreipme_mask.ix); \ + if (buf.s) alloc_free(buf.s); \ + return ret; } + int ipme_init() { struct ifconf ifc; @@ -39,18 +81,45 @@ struct sockaddr_in *sin; int len; int s; - struct ip_mx ix; - + struct ip_mx ix, ix_mask; + ipalloc moreipme = {0}; + ipalloc moreipme_mask = {0}; + int i; + if (ipmeok) return 1; - if (!ipalloc_readyplus(&ipme,0)) return 0; + if (!ipalloc_readyplus(&ipme,0)) ipme_init_retclean(0); + if (!ipalloc_readyplus(&ipme_mask,0)) ipme_init_retclean(0); + if (!ipalloc_readyplus(¬ipme,0)) ipme_init_retclean(0); + if (!ipalloc_readyplus(¬ipme_mask,0)) ipme_init_retclean(0); + if (!ipalloc_readyplus(&moreipme,0)) ipme_init_retclean(0); + if (!ipalloc_readyplus(&moreipme_mask,0)) ipme_init_retclean(0); + ipme.len = 0; - ix.pref = 0; - - if ((s = socket(AF_INET,SOCK_STREAM,0)) == -1) return -1; + ix.pref = ix_mask.pref = 0; + + if (!ipme_readipfile(¬ipme, ¬ipme_mask, "control/notipme")) ipme_init_retclean(0); + + /* 127.0.0.0/255.0.0.0 is the localhost network. Linux will treat + every address in this range as a local interface, even if it + isn't explicitly configured. + */ + byte_copy(&ix.ip,4,"\x7f\0\0\0"); + byte_copy(&ix_mask.ip,4,"\xff\0\0\0"); + if (!ipalloc_append(&ipme,&ix)) ipme_init_retclean(0); + if (!ipalloc_append(&ipme_mask,&ix_mask)) ipme_init_retclean(0); + + /* 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"); + byte_copy(&ix_mask.ip,4,"\xff\xff\xff\xff"); + if (!ipalloc_append(&ipme,&ix)) ipme_init_retclean(0); + if (!ipalloc_append(&ipme_mask,&ix_mask)) ipme_init_retclean(0); + + if ((s = socket(AF_INET,SOCK_STREAM,0)) == -1) ipme_init_retclean(-1); len = 256; for (;;) { - if (!stralloc_ready(&buf,len)) { close(s); return 0; } + if (!stralloc_ready(&buf,len)) { close(s); ipme_init_retclean(0); } buf.len = 0; ifc.ifc_buf = buf.s; ifc.ifc_len = len; @@ -59,7 +128,7 @@ buf.len = ifc.ifc_len; break; } - if (len > 200000) { close(s); return -1; } + if (len > 200000) { close(s); ipme_init_retclean(-1); } len += 100 + (len >> 2); } x = buf.s; @@ -74,7 +143,10 @@ byte_copy(&ix.ip,4,&sin->sin_addr); if (ioctl(s,SIOCGIFFLAGS,x) == 0) if (ifr->ifr_flags & IFF_UP) - if (!ipalloc_append(&ipme,&ix)) { close(s); return 0; } + { + if (!ipalloc_append(&ipme,&ix)) { close(s); ipme_init_retclean(0); } + if (!ipalloc_append(&ipme_mask,&ix_mask)) { close(s); ipme_init_retclean(0); } + } } #else len = sizeof(*ifr); @@ -84,12 +156,60 @@ 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; } + if (!ipalloc_append(&ipme,&ix)) { close(s); ipme_init_retclean(0); } + if (!ipalloc_append(&ipme_mask,&ix_mask)) { close(s); ipme_init_retclean(0); } } #endif x += len; } close(s); + + if (!ipme_readipfile(&moreipme, &moreipme_mask, "control/moreipme")) ipme_init_retclean(0); + for(i = 0;i < moreipme.len;++i) + { + if (!ipalloc_append(&ipme,&moreipme.ix[i])) ipme_init_retclean(0); + if (!ipalloc_append(&ipme_mask,&moreipme_mask.ix[i])) ipme_init_retclean(0); + } ipmeok = 1; - return 1; + ipme_init_retclean(1); } + + +int ipme_readipfile(ipa, ipa_mask, fn) + ipalloc *ipa, *ipa_mask; + char *fn; +{ + int fd = -1; + char inbuf[1024]; + substdio ss; + stralloc l = {0}; + int match; + struct ip_mx ix, ix_mask; + int ret = 1; + int slash = 0; + + 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 (l.s[slash=str_chr(l.s,'/')]!='\0') + { + l.s[slash]='\0'; + if (!ip_scan(l.s+slash+1,&ix_mask.ip)) + continue; + } + else + if (!ip_scan("255.255.255.255",&ix_mask.ip)) { ret = 0; break; } + + if (!ip_scan(l.s, &ix.ip)) continue; + if (!ipalloc_append(ipa,&ix)) { ret = 0; break; } + if (!ipalloc_append(ipa_mask,&ix_mask.ip)) { ret = 0; break; } + } + if (l.s) alloc_free(l.s); + if ( (fd >= 0) && (close(fd) == -1) ) + ret = 0; + } + return ret; +} + diff -ur --new-file qmail-1.03/ipme.h qmail-1.03-moreipme-0.6/ipme.h --- qmail-1.03/ipme.h Mon Jun 15 06:53:16 1998 +++ qmail-1.03-moreipme-0.6/ipme.h Sat May 22 18:38:48 2004 @@ -4,7 +4,7 @@ #include "ip.h" #include "ipalloc.h" -extern ipalloc ipme; +extern ipalloc ipme, ipme_mask, notipme, notipme_mask; extern int ipme_init(); extern int ipme_is(); diff -ur --new-file qmail-1.03/ipmeprint.c qmail-1.03-moreipme-0.6/ipmeprint.c --- qmail-1.03/ipmeprint.c Mon Jun 15 06:53:16 1998 +++ qmail-1.03-moreipme-0.6/ipmeprint.c Sat May 22 18:38:48 2004 @@ -3,12 +3,15 @@ #include "ip.h" #include "ipme.h" #include "exit.h" +#include "auto_qmail.h" char temp[IPFMT]; void main() { - int j; + int j,k; + + chdir(auto_qmail); switch(ipme_init()) { case 0: substdio_putsflush(subfderr,"out of memory\n"); _exit(111); @@ -17,8 +20,18 @@ for (j = 0;j < ipme.len;++j) { substdio_put(subfdout,temp,ip_fmt(temp,&ipme.ix[j].ip)); - substdio_puts(subfdout,"\n"); + substdio_puts(subfdout,"/"); + substdio_put(subfdout,temp,ip_fmt(temp,&ipme_mask.ix[j].ip)); + substdio_puts(subfdout," is me\n"); + } + for (j = 0;j < notipme.len;++j) + { + substdio_put(subfdout,temp,ip_fmt(temp,¬ipme.ix[j].ip)); + substdio_puts(subfdout,"/"); + substdio_put(subfdout,temp,ip_fmt(temp,¬ipme_mask.ix[j].ip)); + substdio_puts(subfdout," is not me\n"); } + substdio_flush(subfdout); _exit(0); } diff -ur --new-file qmail-1.03/ipmetest.c qmail-1.03-moreipme-0.6/ipmetest.c --- qmail-1.03/ipmetest.c Wed Dec 31 19:00:00 1969 +++ qmail-1.03-moreipme-0.6/ipmetest.c Sat May 22 18:38:48 2004 @@ -0,0 +1,38 @@ +#include "subfd.h" +#include "substdio.h" +#include "ip.h" +#include "ipme.h" +#include "exit.h" +#include "auto_qmail.h" +#include "env.h" + +void main(int argc, char *argv[]) +{ + struct ip_address ip; + + if (!env_get("IPMETEST_HERE")) + chdir(auto_qmail); + + if (argc < 2) + { + substdio_puts(subfdout,"invalid usage\n"); + substdio_flush(subfdout); + exit(1); + } + if (!ip_scan(argv[1],&ip)) + { + substdio_puts(subfdout,"invalid IP address\n"); + substdio_flush(subfdout); + exit(1); + } + if (ipme_is(&ip)) + { + substdio_puts(subfdout,"me\n"); + } + else + { + substdio_puts(subfdout,"not me\n"); + } + substdio_flush(subfdout); + exit(0); +} diff -ur --new-file qmail-1.03/qmail-showctl.c qmail-1.03-moreipme-0.6/qmail-showctl.c --- qmail-1.03/qmail-showctl.c Mon Jun 15 06:53:16 1998 +++ qmail-1.03-moreipme-0.6/qmail-showctl.c Sat May 22 18:38:48 2004 @@ -230,6 +230,8 @@ do_str("localiphost",1,"localiphost","Local IP address becomes "); do_lst("locals","Messages for me are delivered locally.","Messages for "," are delivered locally."); do_str("me",0,"undefined! Uh-oh","My name is "); + do_lst("moreipme","No additional IP addresses are me.","IP address "," is me."); + do_lst("notipme","All of my IP addresses are me.","IP address "," is not me."); do_lst("percenthack","The percent hack is not allowed.","The percent hack is allowed for user%host@","."); do_str("plusdomain",1,"plusdomain","Plus domain name is "); do_lst("qmqpservers","No QMQP servers.","QMQP server: ","."); @@ -283,8 +285,10 @@ if (str_equal(d->d_name,"localiphost")) continue; if (str_equal(d->d_name,"locals")) continue; if (str_equal(d->d_name,"me")) continue; + if (str_equal(d->d_name,"moreipme")) continue; if (str_equal(d->d_name,"morercpthosts")) continue; if (str_equal(d->d_name,"morercpthosts.cdb")) continue; + if (str_equal(d->d_name,"notipme")) continue; if (str_equal(d->d_name,"percenthack")) continue; if (str_equal(d->d_name,"plusdomain")) continue; if (str_equal(d->d_name,"qmqpservers")) continue;