xref: /dragonfly/lib/libalias/alias_irc.c (revision 86d7f5d3)
1*86d7f5d3SJohn Marino /*-
2*86d7f5d3SJohn Marino  * Copyright (c) 2001 Charles Mott <cm@linktel.net>
3*86d7f5d3SJohn Marino  * All rights reserved.
4*86d7f5d3SJohn Marino  *
5*86d7f5d3SJohn Marino  * Redistribution and use in source and binary forms, with or without
6*86d7f5d3SJohn Marino  * modification, are permitted provided that the following conditions
7*86d7f5d3SJohn Marino  * are met:
8*86d7f5d3SJohn Marino  * 1. Redistributions of source code must retain the above copyright
9*86d7f5d3SJohn Marino  *    notice, this list of conditions and the following disclaimer.
10*86d7f5d3SJohn Marino  * 2. Redistributions in binary form must reproduce the above copyright
11*86d7f5d3SJohn Marino  *    notice, this list of conditions and the following disclaimer in the
12*86d7f5d3SJohn Marino  *    documentation and/or other materials provided with the distribution.
13*86d7f5d3SJohn Marino  *
14*86d7f5d3SJohn Marino  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15*86d7f5d3SJohn Marino  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16*86d7f5d3SJohn Marino  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17*86d7f5d3SJohn Marino  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18*86d7f5d3SJohn Marino  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19*86d7f5d3SJohn Marino  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20*86d7f5d3SJohn Marino  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21*86d7f5d3SJohn Marino  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22*86d7f5d3SJohn Marino  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23*86d7f5d3SJohn Marino  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24*86d7f5d3SJohn Marino  * SUCH DAMAGE.
25*86d7f5d3SJohn Marino  *
26*86d7f5d3SJohn Marino  * $FreeBSD: src/lib/libalias/alias_irc.c,v 1.5.2.5 2001/11/03 11:34:33 brian Exp $
27*86d7f5d3SJohn Marino  * $DragonFly: src/lib/libalias/alias_irc.c,v 1.3 2004/08/20 00:08:17 joerg Exp $
28*86d7f5d3SJohn Marino  */
29*86d7f5d3SJohn Marino 
30*86d7f5d3SJohn Marino /* Alias_irc.c intercepts packages contain IRC CTCP commands, and
31*86d7f5d3SJohn Marino 	changes DCC commands to export a port on the aliasing host instead
32*86d7f5d3SJohn Marino 	of an aliased host.
33*86d7f5d3SJohn Marino 
34*86d7f5d3SJohn Marino     For this routine to work, the DCC command must fit entirely into a
35*86d7f5d3SJohn Marino     single TCP packet.  This will usually happen, but is not
36*86d7f5d3SJohn Marino     guaranteed.
37*86d7f5d3SJohn Marino 
38*86d7f5d3SJohn Marino 	 The interception is likely to change the length of the packet.
39*86d7f5d3SJohn Marino 	 The handling of this is copied more-or-less verbatim from
40*86d7f5d3SJohn Marino 	 ftp_alias.c
41*86d7f5d3SJohn Marino 
42*86d7f5d3SJohn Marino 	 Initial version: Eivind Eklund <perhaps@yes.no> (ee) 97-01-29
43*86d7f5d3SJohn Marino 
44*86d7f5d3SJohn Marino          Version 2.1:  May, 1997 (cjm)
45*86d7f5d3SJohn Marino              Very minor changes to conform with
46*86d7f5d3SJohn Marino              local/global/function naming conventions
47*86d7f5d3SJohn Marino              withing the packet alising module.
48*86d7f5d3SJohn Marino */
49*86d7f5d3SJohn Marino 
50*86d7f5d3SJohn Marino /* Includes */
51*86d7f5d3SJohn Marino #include <sys/param.h>
52*86d7f5d3SJohn Marino #include <ctype.h>
53*86d7f5d3SJohn Marino #include <stdio.h>
54*86d7f5d3SJohn Marino #include <string.h>
55*86d7f5d3SJohn Marino #include <netinet/in_systm.h>
56*86d7f5d3SJohn Marino #include <netinet/in.h>
57*86d7f5d3SJohn Marino #include <netinet/ip.h>
58*86d7f5d3SJohn Marino #include <netinet/tcp.h>
59*86d7f5d3SJohn Marino #include <limits.h>
60*86d7f5d3SJohn Marino 
61*86d7f5d3SJohn Marino #include "alias_local.h"
62*86d7f5d3SJohn Marino 
63*86d7f5d3SJohn Marino /* Local defines */
64*86d7f5d3SJohn Marino #define DBprintf(a)
65*86d7f5d3SJohn Marino 
66*86d7f5d3SJohn Marino 
67*86d7f5d3SJohn Marino void
AliasHandleIrcOut(struct ip * pip,struct alias_link * link,int maxsize)68*86d7f5d3SJohn Marino AliasHandleIrcOut(struct ip *pip, /* IP packet to examine */
69*86d7f5d3SJohn Marino 				 struct alias_link *link,		  /* Which link are we on? */
70*86d7f5d3SJohn Marino 				 int maxsize		  /* Maximum size of IP packet including headers */
71*86d7f5d3SJohn Marino 				 )
72*86d7f5d3SJohn Marino {
73*86d7f5d3SJohn Marino     int hlen, tlen, dlen;
74*86d7f5d3SJohn Marino     struct in_addr true_addr;
75*86d7f5d3SJohn Marino     u_short true_port;
76*86d7f5d3SJohn Marino     char *sptr;
77*86d7f5d3SJohn Marino     struct tcphdr *tc;
78*86d7f5d3SJohn Marino 	 int i;							  /* Iterator through the source */
79*86d7f5d3SJohn Marino 
80*86d7f5d3SJohn Marino /* Calculate data length of TCP packet */
81*86d7f5d3SJohn Marino     tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
82*86d7f5d3SJohn Marino     hlen = (pip->ip_hl + tc->th_off) << 2;
83*86d7f5d3SJohn Marino     tlen = ntohs(pip->ip_len);
84*86d7f5d3SJohn Marino     dlen = tlen - hlen;
85*86d7f5d3SJohn Marino 
86*86d7f5d3SJohn Marino 	 /* Return if data length is too short - assume an entire PRIVMSG in each packet. */
87*86d7f5d3SJohn Marino     if (dlen<sizeof(":A!a@n.n PRIVMSG A :aDCC 1 1a")-1)
88*86d7f5d3SJohn Marino         return;
89*86d7f5d3SJohn Marino 
90*86d7f5d3SJohn Marino /* Place string pointer at beginning of data */
91*86d7f5d3SJohn Marino     sptr = (char *) pip;
92*86d7f5d3SJohn Marino     sptr += hlen;
93*86d7f5d3SJohn Marino 	 maxsize -= hlen;				  /* We're interested in maximum size of data, not packet */
94*86d7f5d3SJohn Marino 
95*86d7f5d3SJohn Marino 	 /* Search for a CTCP command [Note 1] */
96*86d7f5d3SJohn Marino 	 for(	i=0; i<dlen; i++ ) {
97*86d7f5d3SJohn Marino 		 if(sptr[i]=='\001')
98*86d7f5d3SJohn Marino 			 goto lFOUND_CTCP;
99*86d7f5d3SJohn Marino 	 }
100*86d7f5d3SJohn Marino 	 return;					  /* No CTCP commands in  */
101*86d7f5d3SJohn Marino 	 /* Handle CTCP commands - the buffer may have to be copied */
102*86d7f5d3SJohn Marino lFOUND_CTCP:
103*86d7f5d3SJohn Marino 	 {
104*86d7f5d3SJohn Marino 		 char newpacket[65536];	  /* Estimate of maximum packet size :) */
105*86d7f5d3SJohn Marino 		 int  copyat = i;			  /* Same */
106*86d7f5d3SJohn Marino 		 int  iCopy = 0;			  /* How much data have we written to copy-back string? */
107*86d7f5d3SJohn Marino 		 unsigned long org_addr;  /* Original IP address */
108*86d7f5d3SJohn Marino 		 unsigned short org_port; /* Original source port address */
109*86d7f5d3SJohn Marino 	 lCTCP_START:
110*86d7f5d3SJohn Marino 		 if( i >= dlen || iCopy >= sizeof(newpacket) )
111*86d7f5d3SJohn Marino 			 goto lPACKET_DONE;
112*86d7f5d3SJohn Marino 		 newpacket[iCopy++] = sptr[i++];	/* Copy the CTCP start character */
113*86d7f5d3SJohn Marino 		 /* Start of a CTCP */
114*86d7f5d3SJohn Marino 		 if( i+4 >= dlen )		  /* Too short for DCC */
115*86d7f5d3SJohn Marino 			 goto lBAD_CTCP;
116*86d7f5d3SJohn Marino 		 if( sptr[i+0] != 'D' )
117*86d7f5d3SJohn Marino 			 goto lBAD_CTCP;
118*86d7f5d3SJohn Marino 		 if( sptr[i+1] != 'C' )
119*86d7f5d3SJohn Marino 			 goto lBAD_CTCP;
120*86d7f5d3SJohn Marino 		 if( sptr[i+2] != 'C' )
121*86d7f5d3SJohn Marino 			 goto lBAD_CTCP;
122*86d7f5d3SJohn Marino 		 if( sptr[i+3] != ' ' )
123*86d7f5d3SJohn Marino 			 goto lBAD_CTCP;
124*86d7f5d3SJohn Marino 		 /* We have a DCC command - handle it! */
125*86d7f5d3SJohn Marino 		 i+= 4;						  /* Skip "DCC " */
126*86d7f5d3SJohn Marino 		 if( iCopy+4 > sizeof(newpacket) )
127*86d7f5d3SJohn Marino 			 goto lPACKET_DONE;
128*86d7f5d3SJohn Marino 		 newpacket[iCopy++] = 'D';
129*86d7f5d3SJohn Marino 		 newpacket[iCopy++] = 'C';
130*86d7f5d3SJohn Marino 		 newpacket[iCopy++] = 'C';
131*86d7f5d3SJohn Marino 		 newpacket[iCopy++] = ' ';
132*86d7f5d3SJohn Marino 
133*86d7f5d3SJohn Marino 		 DBprintf(("Found DCC\n"));
134*86d7f5d3SJohn Marino 		 /* Skip any extra spaces (should not occur according to
135*86d7f5d3SJohn Marino           protocol, but DCC breaks CTCP protocol anyway */
136*86d7f5d3SJohn Marino 		 while(sptr[i] == ' ') {
137*86d7f5d3SJohn Marino 			 if( ++i >= dlen) {
138*86d7f5d3SJohn Marino 				 DBprintf(("DCC packet terminated in just spaces\n"));
139*86d7f5d3SJohn Marino 				 goto lPACKET_DONE;
140*86d7f5d3SJohn Marino 			 }
141*86d7f5d3SJohn Marino 		 }
142*86d7f5d3SJohn Marino 
143*86d7f5d3SJohn Marino 		 DBprintf(("Transferring command...\n"));
144*86d7f5d3SJohn Marino 		 while(sptr[i] != ' ') {
145*86d7f5d3SJohn Marino 			 newpacket[iCopy++] = sptr[i];
146*86d7f5d3SJohn Marino 			 if( ++i >= dlen || iCopy >= sizeof(newpacket) ) {
147*86d7f5d3SJohn Marino 				 DBprintf(("DCC packet terminated during command\n"));
148*86d7f5d3SJohn Marino 				 goto lPACKET_DONE;
149*86d7f5d3SJohn Marino 			 }
150*86d7f5d3SJohn Marino 		 }
151*86d7f5d3SJohn Marino 		 /* Copy _one_ space */
152*86d7f5d3SJohn Marino 		 if( i+1 < dlen && iCopy < sizeof(newpacket) )
153*86d7f5d3SJohn Marino 			 newpacket[iCopy++] = sptr[i++];
154*86d7f5d3SJohn Marino 
155*86d7f5d3SJohn Marino 		 DBprintf(("Done command - removing spaces\n"));
156*86d7f5d3SJohn Marino 		 /* Skip any extra spaces (should not occur according to
157*86d7f5d3SJohn Marino           protocol, but DCC breaks CTCP protocol anyway */
158*86d7f5d3SJohn Marino 		 while(sptr[i] == ' ') {
159*86d7f5d3SJohn Marino 			 if( ++i >= dlen ) {
160*86d7f5d3SJohn Marino 				 DBprintf(("DCC packet terminated in just spaces (post-command)\n"));
161*86d7f5d3SJohn Marino 				 goto lPACKET_DONE;
162*86d7f5d3SJohn Marino 			 }
163*86d7f5d3SJohn Marino 		 }
164*86d7f5d3SJohn Marino 
165*86d7f5d3SJohn Marino 		 DBprintf(("Transferring filename...\n"));
166*86d7f5d3SJohn Marino 		 while(sptr[i] != ' ') {
167*86d7f5d3SJohn Marino 			 newpacket[iCopy++] = sptr[i];
168*86d7f5d3SJohn Marino 			 if( ++i >= dlen || iCopy >= sizeof(newpacket) ) {
169*86d7f5d3SJohn Marino 				 DBprintf(("DCC packet terminated during filename\n"));
170*86d7f5d3SJohn Marino 				 goto lPACKET_DONE;
171*86d7f5d3SJohn Marino 			 }
172*86d7f5d3SJohn Marino 		 }
173*86d7f5d3SJohn Marino 		 /* Copy _one_ space */
174*86d7f5d3SJohn Marino 		 if( i+1 < dlen && iCopy < sizeof(newpacket) )
175*86d7f5d3SJohn Marino 			 newpacket[iCopy++] = sptr[i++];
176*86d7f5d3SJohn Marino 
177*86d7f5d3SJohn Marino 		 DBprintf(("Done filename - removing spaces\n"));
178*86d7f5d3SJohn Marino 		 /* Skip any extra spaces (should not occur according to
179*86d7f5d3SJohn Marino           protocol, but DCC breaks CTCP protocol anyway */
180*86d7f5d3SJohn Marino 		 while(sptr[i] == ' ') {
181*86d7f5d3SJohn Marino 			 if( ++i >= dlen ) {
182*86d7f5d3SJohn Marino 				 DBprintf(("DCC packet terminated in just spaces (post-filename)\n"));
183*86d7f5d3SJohn Marino 				 goto lPACKET_DONE;
184*86d7f5d3SJohn Marino 			 }
185*86d7f5d3SJohn Marino 		 }
186*86d7f5d3SJohn Marino 
187*86d7f5d3SJohn Marino 		 DBprintf(("Fetching IP address\n"));
188*86d7f5d3SJohn Marino 		 /* Fetch IP address */
189*86d7f5d3SJohn Marino 		 org_addr = 0;
190*86d7f5d3SJohn Marino 		 while(i<dlen && isdigit(sptr[i])) {
191*86d7f5d3SJohn Marino 			 if( org_addr > ULONG_MAX/10UL )	{ /* Terminate on overflow */
192*86d7f5d3SJohn Marino 				 DBprintf(("DCC Address overflow (org_addr == 0x%08lx, next char %c\n", org_addr, sptr[i]));
193*86d7f5d3SJohn Marino 				 goto lBAD_CTCP;
194*86d7f5d3SJohn Marino 			 }
195*86d7f5d3SJohn Marino 			 org_addr *= 10;
196*86d7f5d3SJohn Marino 			 org_addr += sptr[i++]-'0';
197*86d7f5d3SJohn Marino 		 }
198*86d7f5d3SJohn Marino 		 DBprintf(("Skipping space\n"));
199*86d7f5d3SJohn Marino 		 if( i+1 >= dlen || sptr[i] != ' ' ) {
200*86d7f5d3SJohn Marino 			 DBprintf(("Overflow (%d >= %d) or bad character (%02x) terminating IP address\n", i+1, dlen, sptr[i]));
201*86d7f5d3SJohn Marino 			 goto lBAD_CTCP;
202*86d7f5d3SJohn Marino 		 }
203*86d7f5d3SJohn Marino 		 /* Skip any extra spaces (should not occur according to
204*86d7f5d3SJohn Marino           protocol, but DCC breaks CTCP protocol anyway, so we might
205*86d7f5d3SJohn Marino           as well play it safe */
206*86d7f5d3SJohn Marino 		 while(sptr[i] == ' ') {
207*86d7f5d3SJohn Marino 			 if( ++i >= dlen ) {
208*86d7f5d3SJohn Marino 				 DBprintf(("Packet failure - space overflow.\n"));
209*86d7f5d3SJohn Marino 				 goto lPACKET_DONE;
210*86d7f5d3SJohn Marino 			 }
211*86d7f5d3SJohn Marino 		 }
212*86d7f5d3SJohn Marino 		 DBprintf(("Fetching port number\n"));
213*86d7f5d3SJohn Marino 		 /* Fetch source port */
214*86d7f5d3SJohn Marino 		 org_port = 0;
215*86d7f5d3SJohn Marino 		 while(i<dlen && isdigit(sptr[i])) {
216*86d7f5d3SJohn Marino 			 if( org_port > 6554 )	{ /* Terminate on overflow (65536/10 rounded up*/
217*86d7f5d3SJohn Marino 				 DBprintf(("DCC: port number overflow\n"));
218*86d7f5d3SJohn Marino 				 goto lBAD_CTCP;
219*86d7f5d3SJohn Marino 			 }
220*86d7f5d3SJohn Marino 			 org_port *= 10;
221*86d7f5d3SJohn Marino 			 org_port += sptr[i++]-'0';
222*86d7f5d3SJohn Marino 		 }
223*86d7f5d3SJohn Marino 		 /* Skip illegal addresses (or early termination) */
224*86d7f5d3SJohn Marino 		 if( i >= dlen || (sptr[i] != '\001' && sptr[i] != ' ') ) {
225*86d7f5d3SJohn Marino 			 DBprintf(("Bad port termination\n"));
226*86d7f5d3SJohn Marino 			 goto lBAD_CTCP;
227*86d7f5d3SJohn Marino 		 }
228*86d7f5d3SJohn Marino 		 DBprintf(("Got IP %lu and port %u\n", org_addr, (unsigned)org_port));
229*86d7f5d3SJohn Marino 
230*86d7f5d3SJohn Marino 		 /* We've got the address and port - now alias it */
231*86d7f5d3SJohn Marino 		 {
232*86d7f5d3SJohn Marino 			 struct alias_link *dcc_link;
233*86d7f5d3SJohn Marino 			 struct in_addr destaddr;
234*86d7f5d3SJohn Marino 
235*86d7f5d3SJohn Marino 
236*86d7f5d3SJohn Marino 			 true_port = htons(org_port);
237*86d7f5d3SJohn Marino 			 true_addr.s_addr = htonl(org_addr);
238*86d7f5d3SJohn Marino 			 destaddr.s_addr = 0;
239*86d7f5d3SJohn Marino 
240*86d7f5d3SJohn Marino 			 /* Sanity/Security checking */
241*86d7f5d3SJohn Marino 			 if (!org_addr || !org_port ||
242*86d7f5d3SJohn Marino 			     pip->ip_src.s_addr != true_addr.s_addr ||
243*86d7f5d3SJohn Marino 			     org_port < IPPORT_RESERVED)
244*86d7f5d3SJohn Marino 				 goto lBAD_CTCP;
245*86d7f5d3SJohn Marino 
246*86d7f5d3SJohn Marino 			 /* Steal the FTP_DATA_PORT - it doesn't really matter, and this
247*86d7f5d3SJohn Marino 				 would probably allow it through at least _some_
248*86d7f5d3SJohn Marino 				 firewalls. */
249*86d7f5d3SJohn Marino 			 dcc_link = FindUdpTcpOut(true_addr, destaddr,
250*86d7f5d3SJohn Marino 						  true_port, 0,
251*86d7f5d3SJohn Marino 						  IPPROTO_TCP, 1);
252*86d7f5d3SJohn Marino 			 DBprintf(("Got a DCC link\n"));
253*86d7f5d3SJohn Marino 			 if ( dcc_link ) {
254*86d7f5d3SJohn Marino 				 struct in_addr alias_address;	/* Address from aliasing */
255*86d7f5d3SJohn Marino 				 u_short alias_port;	/* Port given by aliasing */
256*86d7f5d3SJohn Marino 
257*86d7f5d3SJohn Marino #ifndef NO_FW_PUNCH
258*86d7f5d3SJohn Marino 				 /* Generate firewall hole as appropriate */
259*86d7f5d3SJohn Marino 				 PunchFWHole(dcc_link);
260*86d7f5d3SJohn Marino #endif
261*86d7f5d3SJohn Marino 
262*86d7f5d3SJohn Marino 				 alias_address = GetAliasAddress(link);
263*86d7f5d3SJohn Marino 				 iCopy += snprintf(&newpacket[iCopy],
264*86d7f5d3SJohn Marino 										 sizeof(newpacket)-iCopy,
265*86d7f5d3SJohn Marino 										 "%lu ", (u_long)htonl(alias_address.s_addr));
266*86d7f5d3SJohn Marino 				 if( iCopy >= sizeof(newpacket) ) { /* Truncated/fit exactly - bad news */
267*86d7f5d3SJohn Marino 					 DBprintf(("DCC constructed packet overflow.\n"));
268*86d7f5d3SJohn Marino 					 goto lBAD_CTCP;
269*86d7f5d3SJohn Marino 				 }
270*86d7f5d3SJohn Marino 				 alias_port = GetAliasPort(dcc_link);
271*86d7f5d3SJohn Marino 				 iCopy += snprintf(&newpacket[iCopy],
272*86d7f5d3SJohn Marino 										 sizeof(newpacket)-iCopy,
273*86d7f5d3SJohn Marino 										 "%u", htons(alias_port) );
274*86d7f5d3SJohn Marino 				 /* Done - truncated cases will be taken care of by lBAD_CTCP */
275*86d7f5d3SJohn Marino 				 DBprintf(("Aliased IP %lu and port %u\n", alias_address.s_addr, (unsigned)alias_port));
276*86d7f5d3SJohn Marino 			 }
277*86d7f5d3SJohn Marino 		 }
278*86d7f5d3SJohn Marino 		 /* An uninteresting CTCP - state entered right after '\001' has
279*86d7f5d3SJohn Marino           been pushed.  Also used to copy the rest of a DCC, after IP
280*86d7f5d3SJohn Marino           address and port has been handled */
281*86d7f5d3SJohn Marino 	 lBAD_CTCP:
282*86d7f5d3SJohn Marino 		 for(; i<dlen && iCopy<sizeof(newpacket); i++,iCopy++) {
283*86d7f5d3SJohn Marino 			 newpacket[iCopy] = sptr[i]; /* Copy CTCP unchanged */
284*86d7f5d3SJohn Marino 			 if(sptr[i] == '\001') {
285*86d7f5d3SJohn Marino 				 goto lNORMAL_TEXT;
286*86d7f5d3SJohn Marino 			 }
287*86d7f5d3SJohn Marino 		 }
288*86d7f5d3SJohn Marino 		 goto lPACKET_DONE;
289*86d7f5d3SJohn Marino 		 /* Normal text */
290*86d7f5d3SJohn Marino 	 lNORMAL_TEXT:
291*86d7f5d3SJohn Marino 		 for(; i<dlen && iCopy<sizeof(newpacket); i++,iCopy++) {
292*86d7f5d3SJohn Marino 			 newpacket[iCopy] = sptr[i]; /* Copy CTCP unchanged */
293*86d7f5d3SJohn Marino 			 if(sptr[i] == '\001') {
294*86d7f5d3SJohn Marino 				 goto lCTCP_START;
295*86d7f5d3SJohn Marino 			 }
296*86d7f5d3SJohn Marino 		 }
297*86d7f5d3SJohn Marino 		 /* Handle the end of a packet */
298*86d7f5d3SJohn Marino 	 lPACKET_DONE:
299*86d7f5d3SJohn Marino 		 iCopy = iCopy > maxsize-copyat ? maxsize-copyat : iCopy;
300*86d7f5d3SJohn Marino 		 memcpy(sptr+copyat, newpacket, iCopy);
301*86d7f5d3SJohn Marino 
302*86d7f5d3SJohn Marino /* Save information regarding modified seq and ack numbers */
303*86d7f5d3SJohn Marino         {
304*86d7f5d3SJohn Marino             int delta;
305*86d7f5d3SJohn Marino 
306*86d7f5d3SJohn Marino             SetAckModified(link);
307*86d7f5d3SJohn Marino             delta = GetDeltaSeqOut(pip, link);
308*86d7f5d3SJohn Marino             AddSeq(pip, link, delta+copyat+iCopy-dlen);
309*86d7f5d3SJohn Marino         }
310*86d7f5d3SJohn Marino 
311*86d7f5d3SJohn Marino 		  /* Revise IP header */
312*86d7f5d3SJohn Marino         {
313*86d7f5d3SJohn Marino 			  u_short new_len;
314*86d7f5d3SJohn Marino 
315*86d7f5d3SJohn Marino 			  new_len = htons(hlen + iCopy + copyat);
316*86d7f5d3SJohn Marino 			  DifferentialChecksum(&pip->ip_sum,
317*86d7f5d3SJohn Marino 										  &new_len,
318*86d7f5d3SJohn Marino 										  &pip->ip_len,
319*86d7f5d3SJohn Marino 										  1);
320*86d7f5d3SJohn Marino 			  pip->ip_len = new_len;
321*86d7f5d3SJohn Marino         }
322*86d7f5d3SJohn Marino 
323*86d7f5d3SJohn Marino 		  /* Compute TCP checksum for revised packet */
324*86d7f5d3SJohn Marino         tc->th_sum = 0;
325*86d7f5d3SJohn Marino         tc->th_sum = TcpChecksum(pip);
326*86d7f5d3SJohn Marino 		  return;
327*86d7f5d3SJohn Marino 	 }
328*86d7f5d3SJohn Marino }
329*86d7f5d3SJohn Marino 
330*86d7f5d3SJohn Marino /* Notes:
331*86d7f5d3SJohn Marino 	[Note 1]
332*86d7f5d3SJohn Marino 	The initial search will most often fail; it could be replaced with a 32-bit specific search.
333*86d7f5d3SJohn Marino 	Such a search would be done for 32-bit unsigned value V:
334*86d7f5d3SJohn Marino 	V ^= 0x01010101;				  (Search is for null bytes)
335*86d7f5d3SJohn Marino 	if( ((V-0x01010101)^V) & 0x80808080 ) {
336*86d7f5d3SJohn Marino      (found a null bytes which was a 01 byte)
337*86d7f5d3SJohn Marino 	}
338*86d7f5d3SJohn Marino    To assert that the processor is 32-bits, do
339*86d7f5d3SJohn Marino    extern int ircdccar[32];        (32 bits)
340*86d7f5d3SJohn Marino    extern int ircdccar[CHAR_BIT*sizeof(unsigned int)];
341*86d7f5d3SJohn Marino    which will generate a type-error on all but 32-bit machines.
342*86d7f5d3SJohn Marino 
343*86d7f5d3SJohn Marino 	[Note 2] This routine really ought to be replaced with one that
344*86d7f5d3SJohn Marino 	creates a transparent proxy on the aliasing host, to allow arbitary
345*86d7f5d3SJohn Marino 	changes in the TCP stream.  This should not be too difficult given
346*86d7f5d3SJohn Marino 	this base;  I (ee) will try to do this some time later.
347*86d7f5d3SJohn Marino 	*/
348