(Message sendmail:4)
Received: from PACIFIC-CARRIER-ANNEX.MIT.EDU by po7.MIT.EDU (5.61/4.7) id AA11235; Mon, 22 May 95 05:39:04 EDT
Received: from LOLA-GRANOLA.MIT.EDU by MIT.EDU with SMTP
	id AA02789; Mon, 22 May 95 05:39:01 EDT
Received: (from jhawk@localhost) by lola-granola.MIT.EDU (8.6.11/8.6.11) id FAA19808; Mon, 22 May 1995 05:36:55 -0400
Date: Mon, 22 May 1995 05:36:55 -0400
Message-Id: <199505220936.FAA19808@lola-granola.MIT.EDU>
To: sendmail@cs.berkeley.edu
Subject: Support for detecting IP source routes
From: John Hawkinson <jhawk@MIT.EDU>


Just when you thought IPv4 was going to fade away
into non-existance :-).

Attached are patches that detect source routed connections to sendmail
(using getsockopt(,,IP_OPTIONS,)), and record them in the string
returned by getauthinfo().

This uses the format from the Cray/BSD44 telnet, i.e.

	@middle:endpoint

when a packet must be source-routed through middle to get to endpoint.

I've conditionalized compilation on the macro IPSR, which is defined
to 1 in conf.h. I've tested this successfully under IRIX 5.2, 44BSD
(NetBSD -current, specifically), SunOS 4.1.3, and Solaris 2.3. The
wrong things happen under Ultrix 4 and AIX 3.2.5, so I #define IPSR 0
in conf.h for those platforms.  Doubtless some other platforms don't
get it right, either.

I would be nice if these could make it into 8.6.13.

--jhawk@mit.edu					Not wearing my panix.com
  John Hawkinson				hat today...

*** READ_ME	1995/05/22 08:51:00	1.1
--- READ_ME	1995/05/22 09:22:56	1.2
***************
*** 358,363 ****
--- 358,366 ----
  		HP-UX, both of which have a problem in the UDP
  		implementation.  You can define it to be 0 to explicitly
  		turn off IDENT protocol support.
+ IPSR		Define this as 1 to have sendmail detect source routed
+ 		packets and log them in the HELO and Received headers. You
+ 		probably want this, unless it breaks your OS.
  MIME		Include support for MIME-encapsulated error messages.
  LOG		Set this to get syslog(3) support.  Defined by default
  		in conf.h.  You want this if at all possible.
*** conf.h	1995/05/22 09:34:27	1.1
--- conf.h	1995/05/22 09:34:45	1.2
***************
*** 169,174 ****
--- 169,177 ----
  # define HASINITGROUPS	1	/* has initgroups(3) call */
  # define HASUNAME	1	/* use System V uname(2) system call */
  # define HASGETUSERSHELL 0	/* does not have getusershell(3) call */
+ # ifndef IPSR
+ #   define IPSR		0	/* Something is broken with getsockopt() */
+ # endif
  # define FORK		fork	/* no vfork primitive available */
  # undef  SETPROCTITLE		/* setproctitle confuses AIX */
  # define SFS_TYPE	SFS_STATFS	/* use <sys/statfs.h> statfs() impl */
***************
*** 322,327 ****
--- 325,333 ----
  # ifndef IDENTPROTO
  #  define IDENTPROTO	0	/* TCP/IP implementation is broken */
  # endif
+ # ifndef IPSR
+ #  define IPSR		0	/* Broken... */
+ # endif
  #endif
  
  
***************
*** 999,1004 ****
--- 1005,1014 ----
  
  #ifndef IDENTPROTO
  # define IDENTPROTO	1	/* use IDENT proto (RFC 1413) */
+ #endif
+ 
+ #ifdef IPSR
+ # define IPSR		1	/* Detect IP source routing */
  #endif
  
  #ifndef HASGETUSERSHELL
*** daemon.c	1995/05/21 22:36:27	1.1
--- daemon.c	1995/05/22 09:23:28	1.2
***************
*** 53,58 ****
--- 53,64 ----
  # include <resolv.h>
  #endif
  
+ #if IPSR
+ # include <netinet/in_systm.h>
+ # include <netinet/ip.h>
+ # include <netinet/ip_var.h>
+ #endif
+ 
  /*
  **  DAEMON.C -- routines to use when running as a daemon.
  **
***************
*** 998,1003 ****
--- 1004,1015 ----
  	int nleft;
  	char ibuf[MAXNAME + 1];
  #endif
+ #if IPSR
+ 	struct ipoption ipopt;
+ 	int ipoptlen, j;
+ 	char *q, *r;
+ 	struct in_addr addr;
+ #endif
  	static char hbuf[MAXNAME * 2 + 2];
  	extern char *hostnamebyanyaddr();
  	extern char RealUserName[];			/* main.c */
***************
*** 1136,1142 ****
  	i = strlen(hbuf);
  	hbuf[i++] = '@';
  	strcpy(&hbuf[i], RealHostName == NULL ? "localhost" : RealHostName);
! 	goto finish;
  
  closeident:
  	(void) close(s);
--- 1148,1154 ----
  	i = strlen(hbuf);
  	hbuf[i++] = '@';
  	strcpy(&hbuf[i], RealHostName == NULL ? "localhost" : RealHostName);
! 	goto postident;
  
  closeident:
  	(void) close(s);
***************
*** 1153,1164 ****
  	}
  	(void) strcpy(hbuf, RealHostName);
  
! finish:
  	if (RealHostName != NULL && RealHostName[0] != '[')
  	{
  		p = &hbuf[strlen(hbuf)];
  		(void) sprintf(p, " [%s]", anynet_ntoa(&RealHostAddr));
  	}
  	if (tTd(9, 1))
  		printf("getauthinfo: %s\n", hbuf);
  	return hbuf;
--- 1165,1226 ----
  	}
  	(void) strcpy(hbuf, RealHostName);
  
! postident:
! #if IPSR
! /*
!  * p - pointer within ipopt_list structure.
!  * q - pointer within ls/ss rr route data
!  * r - pointer to hbuf
!  *
!  * Format of output is (connection was from site a through b through c to d):
!  *
!  *	loose:      @site-c@site-b:site-a
!  *	strict:	   !@site-c@site-b:site-a
!  */
! 	if (RealHostAddr.sa.sa_family == AF_INET) {
! 	  if (getsockopt(fd, IPPROTO_IP, IP_OPTIONS, (char*)&ipopt,
! 			 (ipoptlen=sizeof(ipopt), &ipoptlen)) < 0)
! 	    syserr("Can't get IP options");
! 	  if (ipoptlen != 0) {
! 	    for (p=(char*)&ipopt.ipopt_list;
! 		 p != NULL && (p < (char*)(&ipopt+ipoptlen));
! 		 )
! 	      switch (*p) {
! 	      case (char)IPOPT_EOL: 
! 		p=NULL; continue;
! 	      case (char)IPOPT_NOP:
! 		p++; continue;
! 	      case (char)IPOPT_SSRR:
! 	      case (char)IPOPT_LSRR:
! 		r = &hbuf[strlen(hbuf)];
! 		r += sprintf(r, " [%s@%s",
! 			     (*p == (char)IPOPT_SSRR)?"!":"",
! 			     inet_ntoa(ipopt.ipopt_dst));
! 		j = (*++p)/sizeof(struct in_addr) -1;	/* p is now length */
! 		q = p+2;      /* q skips length and router pointer to data */
! 		for ( ; j>=0 ; j--) {
! 		  memcpy(&addr, q, sizeof(addr));
! 		  r += sprintf(r, "%c%s", j?'@':':', inet_ntoa(addr));
! 		  q+=sizeof(struct in_addr); 
! 		}
! 		p+=*p;
! 		continue;
! 	      default:
! 		p+=*(p+1); /* Increment by option length */
! 		continue;
! 	      }
! 	    strcat(hbuf,"]");
! 	    goto postipsr;
! 	  }
! 	}
! #endif
! noipsr:
  	if (RealHostName != NULL && RealHostName[0] != '[')
  	{
  		p = &hbuf[strlen(hbuf)];
  		(void) sprintf(p, " [%s]", anynet_ntoa(&RealHostAddr));
  	}
+ postipsr:
  	if (tTd(9, 1))
  		printf("getauthinfo: %s\n", hbuf);
  	return hbuf;
