Lloyd Zusman <[EMAIL PROTECTED]> writes:

> [ ... ]
>
> And as for this patch itself, remember that it consists solely of
> putting a unique "id" field into the "Received" header.  This is a minor
> change, and it mirrors what some other MTA's already do.  Even if we
> don't end up using this to facilitate the methodology that I outlined in
> my Modest Proposal, it still is a useful feature in and of itself.

This patch is attached.  It's for courier-0.44.2.20040207.  It adds an
"id" field to the "Received" header, as in the 3rd line of this example:

  Received: from speed.spamwall.net ([::ffff:66.55.26.26])
    (TLS: TLSv1/SSLv3,256bits,AES256-SHA)
    id 2LYK%swpAQCyOStAlKYKAGP4qUs
    by asfast.net with esmtp; Thu, 12 Feb 2004 03:30:41 -0500

The majority of the code in this patch is for the algorithm for
generating the ID.  The insertion of the ID itself takes just 2-3 lines
of code.

I have not yet completed the data store module that will make use of
this ID to implement my Modest Proposal.  Once I complete and test this
code, I will post it, along with the results of benchmarks that I will
run, comparing it to the rejection/re-insertion methodology.

*** courier/submit.C.orig	Mon Dec 15 20:51:29 2003
--- courier/submit.C	Thu Feb 12 07:34:41 2004
***************
*** 12,17 ****
--- 12,18 ----
  #include	"rfc2045/rfc2045charset.h"
  #include	"rfc1035/rfc1035.h"
  #include	"rfc1035/rfc1035mxlist.h"
+ #include	"rfc2045/rfc2045.h"
  #include	"numlib/numlib.h"
  #include	"dbobj.h"
  #include	"afx.h"
***************
*** 35,41 ****
--- 36,52 ----
  #if	HAVE_UNISTD_H
  #include	<unistd.h>
  #endif
+ #if	TIME_WITH_SYS_TIME
+ #include 	<sys/time.h>
  #include	<time.h>
+ #else
+ #if	HAVE_SYS_TIME_H
+ #include	<sys/time.h>
+ #else
+ #include	<time.h>
+ #endif
+ #endif
+ #include	<netdb.h>
  
  #define	TIMEOUT	1800
  
***************
*** 935,940 ****
--- 946,1076 ----
  static void getrcpt(struct rw_info *rwi);
  static void rcpttoerr(int, const char *, struct rw_info *);
  
+ struct unique_id_buffer
+ {
+ 	struct in_addr ip;
+ 	int pid;
+ 	struct timeval calltime;
+ 	unsigned int counter;
+ };
+ #define UNIQUE_BUFFER_SIZE (sizeof (unique_id_buffer))
+ 
+ static int write_unique_bytes(const char *p, size_t l, void *vp)
+ {
+ char **cp = (char **) vp;
+ 
+ 	while (l > 0)
+ 	{
+ 		switch (*p)
+ 		{
+ 		case '\r':
+ 		case '\n':
+ 		case '=':
+ 			p++;
+ 			l--;
+ 			continue;
+ 		case '/':
+ 			*p++;
+ 			**cp = '@';
+ 			break;
+ 		case '+':
+ 			*p++;
+ 			**cp = '%';
+ 			break;
+ 		default:
+ 			**cp = *p++;
+ 			break;
+ 		}
+ 		++*cp;
+ 		l--;
+ 	}
+ 
+ 	return 0;
+ }
+ 
+ union ul_byte_overlay {
+ 	unsigned long ul;
+ 	struct {
+ 		unsigned char b[4];
+ 	} uc;
+ };
+ 
+ static unsigned long reverse_bytes(unsigned long item)
+ {
+ union ul_byte_overlay inp;
+ union ul_byte_overlay out;
+ 
+ 	inp.ul = item;
+ 	for (int i = 0; i < 4; i++) {
+ 		out.uc.b[i] = inp.uc.b[3 - i];
+ 	}
+ 	return (out.ul);
+ }
+ 
+ static char* unique_id()
+ {
+ static char result[ (UNIQUE_BUFFER_SIZE + 3) / 3 * 4 + 1 ];
+ static struct unique_id_buffer unique_id_buff = { 0 };
+ 
+ char* rp = result;
+ struct rfc2045_encode_info encodeInfo;
+ 
+ 	if (unique_id_buff.pid == 0)
+ 	{
+ char hostbuff[256];
+ struct hostent* he;
+ 
+ 		// First call only.
+ 		unique_id_buff.pid = getpid();
+ 		gethostname(hostbuff, sizeof (hostbuff) - 1);
+ 		he = gethostbyname(hostbuff);
+ 		if (he == NULL)
+ 		{
+ 			memset((char*) &unique_id_buff.ip, 0xff, 
+ 			       sizeof (unique_id_buff.ip));
+ 		}
+ 		else
+ 		{
+ 			struct in_addr hin;
+ 			if (he->h_addrtype != AF_INET || 
+ 			    he->h_length < (int) sizeof (hin))
+ 			{
+ 				memset((char*) &unique_id_buff.ip, 0xff, 
+ 				       sizeof (unique_id_buff.ip));
+ 			}
+ 			else
+ 			{
+ 				memcpy((char*) &hin, he->h_addr_list[0], 
+ 				       sizeof (hin));
+ 				memcpy((char*) &unique_id_buff.ip, 
+ 				       (char*) &(hin.s_addr),
+ 				       sizeof (unique_id_buff.ip));
+ 			}
+ 		}
+ 		srandomdev();
+ 		unique_id_buff.counter = (unsigned long) random();
+ 	}
+ 
+ 	gettimeofday(&unique_id_buff.calltime, NULL);
+ 
+ 	rfc2045_encode_start(&encodeInfo, "base64", &write_unique_bytes, &rp);
+ 	rfc2045_encode(&encodeInfo, (char*) &unique_id_buff, 
+ 		       UNIQUE_BUFFER_SIZE);
+ 	rfc2045_encode_end(&encodeInfo);
+ 	*rp = 0;
+ 
+ 	// It doesn't matter if the following increment overflows,
+ 	// because that will only be a problem if this routine is called
+ 	// 2**32 times within a single microsecond. By the time systems
+ 	// are fast enough for this to happen, we should refactor this
+ 	// routine.
+ 
+ 	unique_id_buff.counter = 
+ 		reverse_bytes(reverse_bytes(unique_id_buff.counter) + 1);
+ 
+ 	return (result);
+ }
+ 
  static void getrcpts(struct rw_info *rwi)
  {
  struct mailfrominfo *mf=(struct mailfrominfo *)rwi->udata;
***************
*** 1087,1092 ****
--- 1223,1232 ----
  		line += identinfo;
  		line += ')';
  	}
+ 
+ 	// Now, always insert a unique ID
+ 	line += "\n  id ";
+ 	line += unique_id();
  
  	line += "\n  by ";
  	line += config_me();

-- 
 Lloyd Zusman
 [EMAIL PROTECTED]

Reply via email to