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