1 /* -*- mode: c; tab-width: 8; c-basic-indent: 4; -*- */
2
3 /*-
4 * Copyright (c) 2001 Charles Mott <cm@linktel.net>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 * $FreeBSD: src/lib/libalias/alias.c,v 1.16.2.11 2002/07/25 12:31:37 ru Exp $
29 */
30
31 /*
32 Alias.c provides supervisory control for the functions of the
33 packet aliasing software. It consists of routines to monitor
34 TCP connection state, protocol-specific aliasing routines,
35 fragment handling and the following outside world functional
36 interfaces: SaveFragmentPtr, GetFragmentPtr, FragmentAliasIn,
37 PacketAliasIn and PacketAliasOut.
38
39 The other C program files are briefly described. The data
40 structure framework which holds information needed to translate
41 packets is encapsulated in alias_db.c. Data is accessed by
42 function calls, so other segments of the program need not know
43 about the underlying data structures. Alias_ftp.c contains
44 special code for modifying the ftp PORT command used to establish
45 data connections, while alias_irc.c does the same for IRC
46 DCC. Alias_util.c contains a few utility routines.
47
48 Version 1.0 August, 1996 (cjm)
49
50 Version 1.1 August 20, 1996 (cjm)
51 PPP host accepts incoming connections for ports 0 to 1023.
52 (Gary Roberts pointed out the need to handle incoming
53 connections.)
54
55 Version 1.2 September 7, 1996 (cjm)
56 Fragment handling error in alias_db.c corrected.
57 (Tom Torrance helped fix this problem.)
58
59 Version 1.4 September 16, 1996 (cjm)
60 - A more generalized method for handling incoming
61 connections, without the 0-1023 restriction, is
62 implemented in alias_db.c
63 - Improved ICMP support in alias.c. Traceroute
64 packet streams can now be correctly aliased.
65 - TCP connection closing logic simplified in
66 alias.c and now allows for additional 1 minute
67 "grace period" after FIN or RST is observed.
68
69 Version 1.5 September 17, 1996 (cjm)
70 Corrected error in handling incoming UDP packets with 0 checksum.
71 (Tom Torrance helped fix this problem.)
72
73 Version 1.6 September 18, 1996 (cjm)
74 Simplified ICMP aliasing scheme. Should now support
75 traceroute from Win95 as well as FreeBSD.
76
77 Version 1.7 January 9, 1997 (cjm)
78 - Out-of-order fragment handling.
79 - IP checksum error fixed for ftp transfers
80 from aliasing host.
81 - Integer return codes added to all
82 aliasing/de-aliasing functions.
83 - Some obsolete comments cleaned up.
84 - Differential checksum computations for
85 IP header (TCP, UDP and ICMP were already
86 differential).
87
88 Version 2.1 May 1997 (cjm)
89 - Added support for outgoing ICMP error
90 messages.
91 - Added two functions PacketAliasIn2()
92 and PacketAliasOut2() for dynamic address
93 control (e.g. round-robin allocation of
94 incoming packets).
95
96 Version 2.2 July 1997 (cjm)
97 - Rationalized API function names to begin
98 with "PacketAlias..."
99 - Eliminated PacketAliasIn2() and
100 PacketAliasOut2() as poorly conceived.
101
102 Version 2.3 Dec 1998 (dillon)
103 - Major bounds checking additions, see FreeBSD/CVS
104
105 Version 3.1 May, 2000 (salander)
106 - Added hooks to handle PPTP.
107
108 Version 3.2 July, 2000 (salander and satoh)
109 - Added PacketUnaliasOut routine.
110 - Added hooks to handle RTSP/RTP.
111
112 See HISTORY file for additional revisions.
113 */
114
115 #include <sys/param.h>
116
117 #include <netinet/in_systm.h>
118 #include <netinet/in.h>
119 #include <netinet/ip.h>
120 #include <netinet/ip_icmp.h>
121 #include <netinet/tcp.h>
122 #include <netinet/udp.h>
123
124 #include <stdio.h>
125
126 #include "alias_local.h"
127 #include "alias.h"
128
129 #define NETBIOS_NS_PORT_NUMBER 137
130 #define NETBIOS_DGM_PORT_NUMBER 138
131 #define FTP_CONTROL_PORT_NUMBER 21
132 #define IRC_CONTROL_PORT_NUMBER_1 6667
133 #define IRC_CONTROL_PORT_NUMBER_2 6668
134 #define CUSEEME_PORT_NUMBER 7648
135 #define RTSP_CONTROL_PORT_NUMBER_1 554
136 #define RTSP_CONTROL_PORT_NUMBER_2 7070
137 #define TFTP_PORT_NUMBER 69
138 #define PPTP_CONTROL_PORT_NUMBER 1723
139
140 static __inline int
twowords(void * p)141 twowords(void *p)
142 {
143 uint8_t *c = p;
144
145 #if BYTE_ORDER == LITTLE_ENDIAN
146 uint16_t s1 = ((uint16_t)c[1] << 8) + (uint16_t)c[0];
147 uint16_t s2 = ((uint16_t)c[3] << 8) + (uint16_t)c[2];
148 #else
149 uint16_t s1 = ((uint16_t)c[0] << 8) + (uint16_t)c[1];
150 uint16_t s2 = ((uint16_t)c[2] << 8) + (uint16_t)c[3];
151 #endif
152 return (s1 + s2);
153 }
154
155 /* TCP Handling Routines
156
157 TcpMonitorIn() -- These routines monitor TCP connections, and
158 TcpMonitorOut() delete a link when a connection is closed.
159
160 These routines look for SYN, FIN and RST flags to determine when TCP
161 connections open and close. When a TCP connection closes, the data
162 structure containing packet aliasing information is deleted after
163 a timeout period.
164 */
165
166 /* Local prototypes */
167 static void TcpMonitorIn(struct ip *, struct alias_link *);
168
169 static void TcpMonitorOut(struct ip *, struct alias_link *);
170
171
172 static void
TcpMonitorIn(struct ip * pip,struct alias_link * link)173 TcpMonitorIn(struct ip *pip, struct alias_link *link)
174 {
175 struct tcphdr *tc;
176
177 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
178
179 switch (GetStateIn(link))
180 {
181 case ALIAS_TCP_STATE_NOT_CONNECTED:
182 if (tc->th_flags & TH_RST)
183 SetStateIn(link, ALIAS_TCP_STATE_DISCONNECTED);
184 else if (tc->th_flags & TH_SYN)
185 SetStateIn(link, ALIAS_TCP_STATE_CONNECTED);
186 break;
187 case ALIAS_TCP_STATE_CONNECTED:
188 if (tc->th_flags & (TH_FIN | TH_RST))
189 SetStateIn(link, ALIAS_TCP_STATE_DISCONNECTED);
190 break;
191 }
192 }
193
194 static void
TcpMonitorOut(struct ip * pip,struct alias_link * link)195 TcpMonitorOut(struct ip *pip, struct alias_link *link)
196 {
197 struct tcphdr *tc;
198
199 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
200
201 switch (GetStateOut(link))
202 {
203 case ALIAS_TCP_STATE_NOT_CONNECTED:
204 if (tc->th_flags & TH_RST)
205 SetStateOut(link, ALIAS_TCP_STATE_DISCONNECTED);
206 else if (tc->th_flags & TH_SYN)
207 SetStateOut(link, ALIAS_TCP_STATE_CONNECTED);
208 break;
209 case ALIAS_TCP_STATE_CONNECTED:
210 if (tc->th_flags & (TH_FIN | TH_RST))
211 SetStateOut(link, ALIAS_TCP_STATE_DISCONNECTED);
212 break;
213 }
214 }
215
216
217
218
219
220 /* Protocol Specific Packet Aliasing Routines
221
222 IcmpAliasIn(), IcmpAliasIn1(), IcmpAliasIn2()
223 IcmpAliasOut(), IcmpAliasOut1(), IcmpAliasOut2()
224 ProtoAliasIn(), ProtoAliasOut()
225 UdpAliasIn(), UdpAliasOut()
226 TcpAliasIn(), TcpAliasOut()
227
228 These routines handle protocol specific details of packet aliasing.
229 One may observe a certain amount of repetitive arithmetic in these
230 functions, the purpose of which is to compute a revised checksum
231 without actually summing over the entire data packet, which could be
232 unnecessarily time consuming.
233
234 The purpose of the packet aliasing routines is to replace the source
235 address of the outgoing packet and then correctly put it back for
236 any incoming packets. For TCP and UDP, ports are also re-mapped.
237
238 For ICMP echo/timestamp requests and replies, the following scheme
239 is used: the ID number is replaced by an alias for the outgoing
240 packet.
241
242 ICMP error messages are handled by looking at the IP fragment
243 in the data section of the message.
244
245 For TCP and UDP protocols, a port number is chosen for an outgoing
246 packet, and then incoming packets are identified by IP address and
247 port numbers. For TCP packets, there is additional logic in the event
248 that sequence and ACK numbers have been altered (as in the case for
249 FTP data port commands).
250
251 The port numbers used by the packet aliasing module are not true
252 ports in the Unix sense. No sockets are actually bound to ports.
253 They are more correctly thought of as placeholders.
254
255 All packets go through the aliasing mechanism, whether they come from
256 the gateway machine or other machines on a local area network.
257 */
258
259
260 /* Local prototypes */
261 static int IcmpAliasIn1(struct ip *);
262 static int IcmpAliasIn2(struct ip *);
263 static int IcmpAliasIn (struct ip *);
264
265 static int IcmpAliasOut1(struct ip *);
266 static int IcmpAliasOut2(struct ip *);
267 static int IcmpAliasOut (struct ip *);
268
269 static int ProtoAliasIn(struct ip *);
270 static int ProtoAliasOut(struct ip *);
271
272 static int UdpAliasOut(struct ip *);
273 static int UdpAliasIn (struct ip *);
274
275 static int TcpAliasOut(struct ip *, int);
276 static int TcpAliasIn (struct ip *);
277
278
279 static int
IcmpAliasIn1(struct ip * pip)280 IcmpAliasIn1(struct ip *pip)
281 {
282 /*
283 De-alias incoming echo and timestamp replies.
284 Alias incoming echo and timestamp requests.
285 */
286 struct alias_link *link;
287 struct icmp *ic;
288
289 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
290
291 /* Get source address from ICMP data field and restore original data */
292 link = FindIcmpIn(pip->ip_src, pip->ip_dst, ic->icmp_id, 1);
293 if (link != NULL)
294 {
295 u_short original_id;
296 int accumulate;
297
298 original_id = GetOriginalPort(link);
299
300 /* Adjust ICMP checksum */
301 accumulate = ic->icmp_id;
302 accumulate -= original_id;
303 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
304
305 /* Put original sequence number back in */
306 ic->icmp_id = original_id;
307
308 /* Put original address back into IP header */
309 {
310 struct in_addr original_address;
311
312 original_address = GetOriginalAddress(link);
313 DifferentialChecksum(&pip->ip_sum,
314 (u_short *) &original_address,
315 (u_short *) &pip->ip_dst,
316 2);
317 pip->ip_dst = original_address;
318 }
319
320 return(PKT_ALIAS_OK);
321 }
322 return(PKT_ALIAS_IGNORED);
323 }
324
325 static int
IcmpAliasIn2(struct ip * pip)326 IcmpAliasIn2(struct ip *pip)
327 {
328 /*
329 Alias incoming ICMP error messages containing
330 IP header and first 64 bits of datagram.
331 */
332 struct ip *ip;
333 struct icmp *ic, *ic2;
334 struct udphdr *ud;
335 struct tcphdr *tc;
336 struct alias_link *link;
337
338 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
339 ip = &ic->icmp_ip;
340
341 ud = (struct udphdr *) ((char *) ip + (ip->ip_hl <<2));
342 tc = (struct tcphdr *) ud;
343 ic2 = (struct icmp *) ud;
344
345 if (ip->ip_p == IPPROTO_UDP)
346 link = FindUdpTcpIn(ip->ip_dst, ip->ip_src,
347 ud->uh_dport, ud->uh_sport,
348 IPPROTO_UDP, 0);
349 else if (ip->ip_p == IPPROTO_TCP)
350 link = FindUdpTcpIn(ip->ip_dst, ip->ip_src,
351 tc->th_dport, tc->th_sport,
352 IPPROTO_TCP, 0);
353 else if (ip->ip_p == IPPROTO_ICMP) {
354 if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP)
355 link = FindIcmpIn(ip->ip_dst, ip->ip_src, ic2->icmp_id, 0);
356 else
357 link = NULL;
358 } else
359 link = NULL;
360
361 if (link != NULL)
362 {
363 if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP)
364 {
365 int accumulate, accumulate2;
366 struct in_addr original_address;
367 u_short original_port;
368
369 original_address = GetOriginalAddress(link);
370 original_port = GetOriginalPort(link);
371
372 /* Adjust ICMP checksum */
373 accumulate = twowords(&ip->ip_src);
374 accumulate -= twowords(&original_address);
375 accumulate += ud->uh_sport;
376 accumulate -= original_port;
377 accumulate2 = accumulate;
378 accumulate2 += ip->ip_sum;
379 ADJUST_CHECKSUM(accumulate, ip->ip_sum);
380 accumulate2 -= ip->ip_sum;
381 ADJUST_CHECKSUM(accumulate2, ic->icmp_cksum);
382
383 /* Un-alias address in IP header */
384 DifferentialChecksum(&pip->ip_sum,
385 (u_short *) &original_address,
386 (u_short *) &pip->ip_dst,
387 2);
388 pip->ip_dst = original_address;
389
390 /* Un-alias address and port number of original IP packet
391 fragment contained in ICMP data section */
392 ip->ip_src = original_address;
393 ud->uh_sport = original_port;
394 }
395 else if (ip->ip_p == IPPROTO_ICMP)
396 {
397 int accumulate, accumulate2;
398 struct in_addr original_address;
399 u_short original_id;
400
401 original_address = GetOriginalAddress(link);
402 original_id = GetOriginalPort(link);
403
404 /* Adjust ICMP checksum */
405 accumulate = twowords(&ip->ip_src);
406 accumulate -= twowords(&original_address);
407 accumulate += ic2->icmp_id;
408 accumulate -= original_id;
409 accumulate2 = accumulate;
410 accumulate2 += ip->ip_sum;
411 ADJUST_CHECKSUM(accumulate, ip->ip_sum);
412 accumulate2 -= ip->ip_sum;
413 ADJUST_CHECKSUM(accumulate2, ic->icmp_cksum);
414
415 /* Un-alias address in IP header */
416 DifferentialChecksum(&pip->ip_sum,
417 (u_short *) &original_address,
418 (u_short *) &pip->ip_dst,
419 2);
420 pip->ip_dst = original_address;
421
422 /* Un-alias address of original IP packet and sequence number of
423 embedded ICMP datagram */
424 ip->ip_src = original_address;
425 ic2->icmp_id = original_id;
426 }
427 return(PKT_ALIAS_OK);
428 }
429 return(PKT_ALIAS_IGNORED);
430 }
431
432
433 static int
IcmpAliasIn(struct ip * pip)434 IcmpAliasIn(struct ip *pip)
435 {
436 int iresult;
437 struct icmp *ic;
438
439 /* Return if proxy-only mode is enabled */
440 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
441 return PKT_ALIAS_OK;
442
443 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
444
445 iresult = PKT_ALIAS_IGNORED;
446 switch (ic->icmp_type)
447 {
448 case ICMP_ECHOREPLY:
449 case ICMP_TSTAMPREPLY:
450 if (ic->icmp_code == 0)
451 {
452 iresult = IcmpAliasIn1(pip);
453 }
454 break;
455 case ICMP_UNREACH:
456 case ICMP_SOURCEQUENCH:
457 case ICMP_TIMXCEED:
458 case ICMP_PARAMPROB:
459 iresult = IcmpAliasIn2(pip);
460 break;
461 case ICMP_ECHO:
462 case ICMP_TSTAMP:
463 iresult = IcmpAliasIn1(pip);
464 break;
465 }
466 return(iresult);
467 }
468
469
470 static int
IcmpAliasOut1(struct ip * pip)471 IcmpAliasOut1(struct ip *pip)
472 {
473 /*
474 Alias outgoing echo and timestamp requests.
475 De-alias outgoing echo and timestamp replies.
476 */
477 struct alias_link *link;
478 struct icmp *ic;
479
480 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
481
482 /* Save overwritten data for when echo packet returns */
483 link = FindIcmpOut(pip->ip_src, pip->ip_dst, ic->icmp_id, 1);
484 if (link != NULL)
485 {
486 u_short alias_id;
487 int accumulate;
488
489 alias_id = GetAliasPort(link);
490
491 /* Since data field is being modified, adjust ICMP checksum */
492 accumulate = ic->icmp_id;
493 accumulate -= alias_id;
494 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
495
496 /* Alias sequence number */
497 ic->icmp_id = alias_id;
498
499 /* Change source address */
500 {
501 struct in_addr alias_address;
502
503 alias_address = GetAliasAddress(link);
504 DifferentialChecksum(&pip->ip_sum,
505 (u_short *) &alias_address,
506 (u_short *) &pip->ip_src,
507 2);
508 pip->ip_src = alias_address;
509 }
510
511 return(PKT_ALIAS_OK);
512 }
513 return(PKT_ALIAS_IGNORED);
514 }
515
516
517 static int
IcmpAliasOut2(struct ip * pip)518 IcmpAliasOut2(struct ip *pip)
519 {
520 /*
521 Alias outgoing ICMP error messages containing
522 IP header and first 64 bits of datagram.
523 */
524 struct ip *ip;
525 struct icmp *ic, *ic2;
526 struct udphdr *ud;
527 struct tcphdr *tc;
528 struct alias_link *link;
529
530 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
531 ip = &ic->icmp_ip;
532
533 ud = (struct udphdr *) ((char *) ip + (ip->ip_hl <<2));
534 tc = (struct tcphdr *) ud;
535 ic2 = (struct icmp *) ud;
536
537 if (ip->ip_p == IPPROTO_UDP)
538 link = FindUdpTcpOut(ip->ip_dst, ip->ip_src,
539 ud->uh_dport, ud->uh_sport,
540 IPPROTO_UDP, 0);
541 else if (ip->ip_p == IPPROTO_TCP)
542 link = FindUdpTcpOut(ip->ip_dst, ip->ip_src,
543 tc->th_dport, tc->th_sport,
544 IPPROTO_TCP, 0);
545 else if (ip->ip_p == IPPROTO_ICMP) {
546 if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP)
547 link = FindIcmpOut(ip->ip_dst, ip->ip_src, ic2->icmp_id, 0);
548 else
549 link = NULL;
550 } else
551 link = NULL;
552
553 if (link != NULL)
554 {
555 if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP)
556 {
557 int accumulate;
558 struct in_addr alias_address;
559 u_short alias_port;
560
561 alias_address = GetAliasAddress(link);
562 alias_port = GetAliasPort(link);
563
564 /* Adjust ICMP checksum */
565 accumulate = twowords(&ip->ip_dst);
566 accumulate -= twowords(&alias_address);
567 accumulate += ud->uh_dport;
568 accumulate -= alias_port;
569 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
570
571 /*
572 * Alias address in IP header if it comes from the host
573 * the original TCP/UDP packet was destined for.
574 */
575 if (pip->ip_src.s_addr == ip->ip_dst.s_addr) {
576 DifferentialChecksum(&pip->ip_sum,
577 (u_short *) &alias_address,
578 (u_short *) &pip->ip_src,
579 2);
580 pip->ip_src = alias_address;
581 }
582
583 /* Alias address and port number of original IP packet
584 fragment contained in ICMP data section */
585 ip->ip_dst = alias_address;
586 ud->uh_dport = alias_port;
587 }
588 else if (ip->ip_p == IPPROTO_ICMP)
589 {
590 int accumulate;
591 struct in_addr alias_address;
592 u_short alias_id;
593
594 alias_address = GetAliasAddress(link);
595 alias_id = GetAliasPort(link);
596
597 /* Adjust ICMP checksum */
598 accumulate = twowords(&ip->ip_dst);
599 accumulate -= twowords(&alias_address);
600 accumulate += ic2->icmp_id;
601 accumulate -= alias_id;
602 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
603
604 /*
605 * Alias address in IP header if it comes from the host
606 * the original ICMP message was destined for.
607 */
608 if (pip->ip_src.s_addr == ip->ip_dst.s_addr) {
609 DifferentialChecksum(&pip->ip_sum,
610 (u_short *) &alias_address,
611 (u_short *) &pip->ip_src,
612 2);
613 pip->ip_src = alias_address;
614 }
615
616 /* Alias address of original IP packet and sequence number of
617 embedded ICMP datagram */
618 ip->ip_dst = alias_address;
619 ic2->icmp_id = alias_id;
620 }
621 return(PKT_ALIAS_OK);
622 }
623 return(PKT_ALIAS_IGNORED);
624 }
625
626
627 static int
IcmpAliasOut(struct ip * pip)628 IcmpAliasOut(struct ip *pip)
629 {
630 int iresult;
631 struct icmp *ic;
632
633 /* Return if proxy-only mode is enabled */
634 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
635 return PKT_ALIAS_OK;
636
637 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
638
639 iresult = PKT_ALIAS_IGNORED;
640 switch (ic->icmp_type)
641 {
642 case ICMP_ECHO:
643 case ICMP_TSTAMP:
644 if (ic->icmp_code == 0)
645 {
646 iresult = IcmpAliasOut1(pip);
647 }
648 break;
649 case ICMP_UNREACH:
650 case ICMP_SOURCEQUENCH:
651 case ICMP_TIMXCEED:
652 case ICMP_PARAMPROB:
653 iresult = IcmpAliasOut2(pip);
654 break;
655 case ICMP_ECHOREPLY:
656 case ICMP_TSTAMPREPLY:
657 iresult = IcmpAliasOut1(pip);
658 }
659 return(iresult);
660 }
661
662
663
664 static int
ProtoAliasIn(struct ip * pip)665 ProtoAliasIn(struct ip *pip)
666 {
667 /*
668 Handle incoming IP packets. The
669 only thing which is done in this case is to alias
670 the dest IP address of the packet to our inside
671 machine.
672 */
673 struct alias_link *link;
674
675 /* Return if proxy-only mode is enabled */
676 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
677 return PKT_ALIAS_OK;
678
679 link = FindProtoIn(pip->ip_src, pip->ip_dst, pip->ip_p);
680 if (link != NULL)
681 {
682 struct in_addr original_address;
683
684 original_address = GetOriginalAddress(link);
685
686 /* Restore original IP address */
687 DifferentialChecksum(&pip->ip_sum,
688 (u_short *) &original_address,
689 (u_short *) &pip->ip_dst,
690 2);
691 pip->ip_dst = original_address;
692
693 return(PKT_ALIAS_OK);
694 }
695 return(PKT_ALIAS_IGNORED);
696 }
697
698
699 static int
ProtoAliasOut(struct ip * pip)700 ProtoAliasOut(struct ip *pip)
701 {
702 /*
703 Handle outgoing IP packets. The
704 only thing which is done in this case is to alias
705 the source IP address of the packet.
706 */
707 struct alias_link *link;
708
709 /* Return if proxy-only mode is enabled */
710 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
711 return PKT_ALIAS_OK;
712
713 link = FindProtoOut(pip->ip_src, pip->ip_dst, pip->ip_p);
714 if (link != NULL)
715 {
716 struct in_addr alias_address;
717
718 alias_address = GetAliasAddress(link);
719
720 /* Change source address */
721 DifferentialChecksum(&pip->ip_sum,
722 (u_short *) &alias_address,
723 (u_short *) &pip->ip_src,
724 2);
725 pip->ip_src = alias_address;
726
727 return(PKT_ALIAS_OK);
728 }
729 return(PKT_ALIAS_IGNORED);
730 }
731
732
733 static int
UdpAliasIn(struct ip * pip)734 UdpAliasIn(struct ip *pip)
735 {
736 struct udphdr *ud;
737 struct alias_link *link;
738
739 /* Return if proxy-only mode is enabled */
740 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
741 return PKT_ALIAS_OK;
742
743 ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
744
745 link = FindUdpTcpIn(pip->ip_src, pip->ip_dst,
746 ud->uh_sport, ud->uh_dport,
747 IPPROTO_UDP, 1);
748 if (link != NULL)
749 {
750 struct in_addr alias_address;
751 struct in_addr original_address;
752 u_short alias_port;
753 int accumulate;
754 int r = 0;
755
756 alias_address = GetAliasAddress(link);
757 original_address = GetOriginalAddress(link);
758 alias_port = ud->uh_dport;
759 ud->uh_dport = GetOriginalPort(link);
760
761 /* Special processing for IP encoding protocols */
762 if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER)
763 AliasHandleCUSeeMeIn(pip, original_address);
764 /* If NETBIOS Datagram, It should be alias address in UDP Data, too */
765 else if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER
766 || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER)
767 r = AliasHandleUdpNbt(pip, link, &original_address, ud->uh_dport);
768 else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER
769 || ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER)
770 r = AliasHandleUdpNbtNS(pip, link, &alias_address, &alias_port,
771 &original_address, &ud->uh_dport);
772
773 /* If UDP checksum is not zero, then adjust since destination port */
774 /* is being unaliased and destination address is being altered. */
775 if (ud->uh_sum != 0)
776 {
777 accumulate = alias_port;
778 accumulate -= ud->uh_dport;
779 accumulate += twowords(&alias_address);
780 accumulate -= twowords(&original_address);
781 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
782 }
783
784 /* Restore original IP address */
785 DifferentialChecksum(&pip->ip_sum,
786 (u_short *) &original_address,
787 (u_short *) &pip->ip_dst,
788 2);
789 pip->ip_dst = original_address;
790
791 /*
792 * If we cannot figure out the packet, ignore it.
793 */
794 if (r < 0)
795 return(PKT_ALIAS_IGNORED);
796 else
797 return(PKT_ALIAS_OK);
798 }
799 return(PKT_ALIAS_IGNORED);
800 }
801
802 static int
UdpAliasOut(struct ip * pip)803 UdpAliasOut(struct ip *pip)
804 {
805 struct udphdr *ud;
806 struct alias_link *link;
807
808 /* Return if proxy-only mode is enabled */
809 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
810 return PKT_ALIAS_OK;
811
812 ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
813
814 link = FindUdpTcpOut(pip->ip_src, pip->ip_dst,
815 ud->uh_sport, ud->uh_dport,
816 IPPROTO_UDP, 1);
817 if (link != NULL)
818 {
819 u_short alias_port;
820 struct in_addr alias_address;
821
822 alias_address = GetAliasAddress(link);
823 alias_port = GetAliasPort(link);
824
825 /* Special processing for IP encoding protocols */
826 if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER)
827 AliasHandleCUSeeMeOut(pip, link);
828 /* If NETBIOS Datagram, It should be alias address in UDP Data, too */
829 else if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER
830 || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER)
831 AliasHandleUdpNbt(pip, link, &alias_address, alias_port);
832 else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER
833 || ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER)
834 AliasHandleUdpNbtNS(pip, link, &pip->ip_src, &ud->uh_sport,
835 &alias_address, &alias_port);
836 /*
837 * We don't know in advance what TID the TFTP server will choose,
838 * so we create a wilcard link (destination port is unspecified)
839 * that will match any TID from a given destination.
840 */
841 else if (ntohs(ud->uh_dport) == TFTP_PORT_NUMBER)
842 FindRtspOut(pip->ip_src, pip->ip_dst,
843 ud->uh_sport, alias_port, IPPROTO_UDP);
844
845 /* If UDP checksum is not zero, adjust since source port is */
846 /* being aliased and source address is being altered */
847 if (ud->uh_sum != 0)
848 {
849 int accumulate;
850
851 accumulate = ud->uh_sport;
852 accumulate -= alias_port;
853 accumulate += twowords(&pip->ip_src);
854 accumulate -= twowords(&alias_address);
855 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
856 }
857
858 /* Put alias port in UDP header */
859 ud->uh_sport = alias_port;
860
861 /* Change source address */
862 DifferentialChecksum(&pip->ip_sum,
863 (u_short *) &alias_address,
864 (u_short *) &pip->ip_src,
865 2);
866 pip->ip_src = alias_address;
867
868 return(PKT_ALIAS_OK);
869 }
870 return(PKT_ALIAS_IGNORED);
871 }
872
873
874
875 static int
TcpAliasIn(struct ip * pip)876 TcpAliasIn(struct ip *pip)
877 {
878 struct tcphdr *tc;
879 struct alias_link *link;
880
881 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
882
883 link = FindUdpTcpIn(pip->ip_src, pip->ip_dst,
884 tc->th_sport, tc->th_dport,
885 IPPROTO_TCP,
886 !(packetAliasMode & PKT_ALIAS_PROXY_ONLY));
887 if (link != NULL)
888 {
889 struct in_addr alias_address;
890 struct in_addr original_address;
891 struct in_addr proxy_address;
892 u_short alias_port;
893 u_short proxy_port;
894 int accumulate;
895
896 /* Special processing for IP encoding protocols */
897 if (ntohs(tc->th_dport) == PPTP_CONTROL_PORT_NUMBER
898 || ntohs(tc->th_sport) == PPTP_CONTROL_PORT_NUMBER)
899 AliasHandlePptpIn(pip, link);
900
901 alias_address = GetAliasAddress(link);
902 original_address = GetOriginalAddress(link);
903 proxy_address = GetProxyAddress(link);
904 alias_port = tc->th_dport;
905 tc->th_dport = GetOriginalPort(link);
906 proxy_port = GetProxyPort(link);
907
908 /* Adjust TCP checksum since destination port is being unaliased */
909 /* and destination port is being altered. */
910 accumulate = alias_port;
911 accumulate -= tc->th_dport;
912 accumulate += twowords(&alias_address);
913 accumulate -= twowords(&original_address);
914
915 /* If this is a proxy, then modify the TCP source port and
916 checksum accumulation */
917 if (proxy_port != 0)
918 {
919 accumulate += tc->th_sport;
920 tc->th_sport = proxy_port;
921 accumulate -= tc->th_sport;
922 accumulate += twowords(&pip->ip_src);
923 accumulate -= twowords(&proxy_address);
924 }
925
926 /* See if ACK number needs to be modified */
927 if (GetAckModified(link) == 1)
928 {
929 int delta;
930
931 delta = GetDeltaAckIn(pip, link);
932 if (delta != 0)
933 {
934 accumulate += twowords(&tc->th_ack);
935 tc->th_ack = htonl(ntohl(tc->th_ack) - delta);
936 accumulate -= twowords(&tc->th_ack);
937 }
938 }
939
940 ADJUST_CHECKSUM(accumulate, tc->th_sum);
941
942 /* Restore original IP address */
943 accumulate = twowords(&pip->ip_dst);
944 pip->ip_dst = original_address;
945 accumulate -= twowords(&pip->ip_dst);
946
947 /* If this is a transparent proxy packet, then modify the source
948 address */
949 if (proxy_address.s_addr != 0)
950 {
951 accumulate += twowords(&pip->ip_src);
952 pip->ip_src = proxy_address;
953 accumulate -= twowords(&pip->ip_src);
954 }
955
956 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
957
958 /* Monitor TCP connection state */
959 TcpMonitorIn(pip, link);
960
961 return(PKT_ALIAS_OK);
962 }
963 return(PKT_ALIAS_IGNORED);
964 }
965
966 static int
TcpAliasOut(struct ip * pip,int maxpacketsize)967 TcpAliasOut(struct ip *pip, int maxpacketsize)
968 {
969 int proxy_type;
970 u_short dest_port;
971 u_short proxy_server_port;
972 struct in_addr dest_address;
973 struct in_addr proxy_server_address;
974 struct tcphdr *tc;
975 struct alias_link *link;
976
977 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
978
979 proxy_type = ProxyCheck(pip, &proxy_server_address, &proxy_server_port);
980
981 if (proxy_type == 0 && (packetAliasMode & PKT_ALIAS_PROXY_ONLY))
982 return PKT_ALIAS_OK;
983
984 /* If this is a transparent proxy, save original destination,
985 then alter the destination and adjust checksums */
986 dest_port = tc->th_dport;
987 dest_address = pip->ip_dst;
988 if (proxy_type != 0)
989 {
990 int accumulate;
991
992 accumulate = tc->th_dport;
993 tc->th_dport = proxy_server_port;
994 accumulate -= tc->th_dport;
995 accumulate += twowords(&pip->ip_dst);
996 accumulate -= twowords(&proxy_server_address);
997 ADJUST_CHECKSUM(accumulate, tc->th_sum);
998
999 accumulate = twowords(&pip->ip_dst);
1000 pip->ip_dst = proxy_server_address;
1001 accumulate -= twowords(&pip->ip_dst);
1002 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
1003 }
1004
1005 link = FindUdpTcpOut(pip->ip_src, pip->ip_dst,
1006 tc->th_sport, tc->th_dport,
1007 IPPROTO_TCP, 1);
1008 if (link !=NULL)
1009 {
1010 u_short alias_port;
1011 struct in_addr alias_address;
1012 int accumulate;
1013
1014 /* Save original destination address, if this is a proxy packet.
1015 Also modify packet to include destination encoding. This may
1016 change the size of IP header. */
1017 if (proxy_type != 0)
1018 {
1019 SetProxyPort(link, dest_port);
1020 SetProxyAddress(link, dest_address);
1021 ProxyModify(link, pip, maxpacketsize, proxy_type);
1022 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
1023 }
1024
1025 /* Get alias address and port */
1026 alias_port = GetAliasPort(link);
1027 alias_address = GetAliasAddress(link);
1028
1029 /* Monitor TCP connection state */
1030 TcpMonitorOut(pip, link);
1031
1032 /* Special processing for IP encoding protocols */
1033 if (ntohs(tc->th_dport) == FTP_CONTROL_PORT_NUMBER
1034 || ntohs(tc->th_sport) == FTP_CONTROL_PORT_NUMBER)
1035 AliasHandleFtpOut(pip, link, maxpacketsize);
1036 else if (ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_1
1037 || ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_2)
1038 AliasHandleIrcOut(pip, link, maxpacketsize);
1039 else if (ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_1
1040 || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_1
1041 || ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_2
1042 || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_2)
1043 AliasHandleRtspOut(pip, link, maxpacketsize);
1044 else if (ntohs(tc->th_dport) == PPTP_CONTROL_PORT_NUMBER
1045 || ntohs(tc->th_sport) == PPTP_CONTROL_PORT_NUMBER)
1046 AliasHandlePptpOut(pip, link);
1047
1048 /* Adjust TCP checksum since source port is being aliased */
1049 /* and source address is being altered */
1050 accumulate = tc->th_sport;
1051 tc->th_sport = alias_port;
1052 accumulate -= tc->th_sport;
1053 accumulate += twowords(&pip->ip_src);
1054 accumulate -= twowords(&alias_address);
1055
1056 /* Modify sequence number if necessary */
1057 if (GetAckModified(link) == 1)
1058 {
1059 int delta;
1060
1061 delta = GetDeltaSeqOut(pip, link);
1062 if (delta != 0)
1063 {
1064 accumulate += twowords(&tc->th_seq);
1065 tc->th_seq = htonl(ntohl(tc->th_seq) + delta);
1066 accumulate -= twowords(&tc->th_seq);
1067 }
1068 }
1069
1070 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1071
1072 /* Change source address */
1073 accumulate = twowords(&pip->ip_src);
1074 pip->ip_src = alias_address;
1075 accumulate -= twowords(&pip->ip_src);
1076 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
1077
1078 return(PKT_ALIAS_OK);
1079 }
1080 return(PKT_ALIAS_IGNORED);
1081 }
1082
1083
1084
1085
1086 /* Fragment Handling
1087
1088 FragmentIn()
1089 FragmentOut()
1090
1091 The packet aliasing module has a limited ability for handling IP
1092 fragments. If the ICMP, TCP or UDP header is in the first fragment
1093 received, then the ID number of the IP packet is saved, and other
1094 fragments are identified according to their ID number and IP address
1095 they were sent from. Pointers to unresolved fragments can also be
1096 saved and recalled when a header fragment is seen.
1097 */
1098
1099 /* Local prototypes */
1100 static int FragmentIn(struct ip *);
1101 static int FragmentOut(struct ip *);
1102
1103
1104 static int
FragmentIn(struct ip * pip)1105 FragmentIn(struct ip *pip)
1106 {
1107 struct alias_link *link;
1108
1109 link = FindFragmentIn2(pip->ip_src, pip->ip_dst, pip->ip_id);
1110 if (link != NULL)
1111 {
1112 struct in_addr original_address;
1113
1114 GetFragmentAddr(link, &original_address);
1115 DifferentialChecksum(&pip->ip_sum,
1116 (u_short *) &original_address,
1117 (u_short *) &pip->ip_dst,
1118 2);
1119 pip->ip_dst = original_address;
1120
1121 return(PKT_ALIAS_OK);
1122 }
1123 return(PKT_ALIAS_UNRESOLVED_FRAGMENT);
1124 }
1125
1126
1127 static int
FragmentOut(struct ip * pip)1128 FragmentOut(struct ip *pip)
1129 {
1130 struct in_addr alias_address;
1131
1132 alias_address = FindAliasAddress(pip->ip_src);
1133 DifferentialChecksum(&pip->ip_sum,
1134 (u_short *) &alias_address,
1135 (u_short *) &pip->ip_src,
1136 2);
1137 pip->ip_src = alias_address;
1138
1139 return(PKT_ALIAS_OK);
1140 }
1141
1142
1143
1144
1145
1146
1147 /* Outside World Access
1148
1149 PacketAliasSaveFragment()
1150 PacketAliasGetFragment()
1151 PacketAliasFragmentIn()
1152 PacketAliasIn()
1153 PacketAliasOut()
1154 PacketUnaliasOut()
1155
1156 (prototypes in alias.h)
1157 */
1158
1159
1160 int
PacketAliasSaveFragment(char * ptr)1161 PacketAliasSaveFragment(char *ptr)
1162 {
1163 int iresult;
1164 struct alias_link *link;
1165 struct ip *pip;
1166
1167 pip = (struct ip *) ptr;
1168 link = AddFragmentPtrLink(pip->ip_src, pip->ip_id);
1169 iresult = PKT_ALIAS_ERROR;
1170 if (link != NULL)
1171 {
1172 SetFragmentPtr(link, ptr);
1173 iresult = PKT_ALIAS_OK;
1174 }
1175 return(iresult);
1176 }
1177
1178
1179 char *
PacketAliasGetFragment(char * ptr)1180 PacketAliasGetFragment(char *ptr)
1181 {
1182 struct alias_link *link;
1183 char *fptr;
1184 struct ip *pip;
1185
1186 pip = (struct ip *) ptr;
1187 link = FindFragmentPtr(pip->ip_src, pip->ip_id);
1188 if (link != NULL)
1189 {
1190 GetFragmentPtr(link, &fptr);
1191 SetFragmentPtr(link, NULL);
1192 SetExpire(link, 0); /* Deletes link */
1193
1194 return(fptr);
1195 }
1196 else
1197 {
1198 return(NULL);
1199 }
1200 }
1201
1202
1203 void
PacketAliasFragmentIn(char * ptr,char * ptr_fragment)1204 PacketAliasFragmentIn(char *ptr, /* Points to correctly de-aliased
1205 header fragment */
1206 char *ptr_fragment /* Points to fragment which must
1207 be de-aliased */
1208 )
1209 {
1210 struct ip *pip;
1211 struct ip *fpip;
1212
1213 pip = (struct ip *) ptr;
1214 fpip = (struct ip *) ptr_fragment;
1215
1216 DifferentialChecksum(&fpip->ip_sum,
1217 (u_short *) &pip->ip_dst,
1218 (u_short *) &fpip->ip_dst,
1219 2);
1220 fpip->ip_dst = pip->ip_dst;
1221 }
1222
1223
1224 int
PacketAliasIn(char * ptr,int maxpacketsize)1225 PacketAliasIn(char *ptr, int maxpacketsize)
1226 {
1227 struct in_addr alias_addr;
1228 struct ip *pip;
1229 int iresult;
1230
1231 if (packetAliasMode & PKT_ALIAS_REVERSE) {
1232 packetAliasMode &= ~PKT_ALIAS_REVERSE;
1233 iresult = PacketAliasOut(ptr, maxpacketsize);
1234 packetAliasMode |= PKT_ALIAS_REVERSE;
1235 return iresult;
1236 }
1237
1238 HouseKeeping();
1239 ClearCheckNewLink();
1240 pip = (struct ip *) ptr;
1241 alias_addr = pip->ip_dst;
1242
1243 /* Defense against mangled packets */
1244 if (ntohs(pip->ip_len) > maxpacketsize
1245 || (pip->ip_hl<<2) > maxpacketsize)
1246 return PKT_ALIAS_IGNORED;
1247
1248 iresult = PKT_ALIAS_IGNORED;
1249 if ( (ntohs(pip->ip_off) & IP_OFFMASK) == 0 )
1250 {
1251 switch (pip->ip_p)
1252 {
1253 case IPPROTO_ICMP:
1254 iresult = IcmpAliasIn(pip);
1255 break;
1256 case IPPROTO_UDP:
1257 iresult = UdpAliasIn(pip);
1258 break;
1259 case IPPROTO_TCP:
1260 iresult = TcpAliasIn(pip);
1261 break;
1262 case IPPROTO_GRE:
1263 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY ||
1264 AliasHandlePptpGreIn(pip) == 0)
1265 iresult = PKT_ALIAS_OK;
1266 else
1267 iresult = ProtoAliasIn(pip);
1268 break;
1269 default:
1270 iresult = ProtoAliasIn(pip);
1271 break;
1272 }
1273
1274 if (ntohs(pip->ip_off) & IP_MF)
1275 {
1276 struct alias_link *link;
1277
1278 link = FindFragmentIn1(pip->ip_src, alias_addr, pip->ip_id);
1279 if (link != NULL)
1280 {
1281 iresult = PKT_ALIAS_FOUND_HEADER_FRAGMENT;
1282 SetFragmentAddr(link, pip->ip_dst);
1283 }
1284 else
1285 {
1286 iresult = PKT_ALIAS_ERROR;
1287 }
1288 }
1289 }
1290 else
1291 {
1292 iresult = FragmentIn(pip);
1293 }
1294
1295 return(iresult);
1296 }
1297
1298
1299
1300 /* Unregistered address ranges */
1301
1302 /* 10.0.0.0 -> 10.255.255.255 */
1303 #define UNREG_ADDR_A_LOWER 0x0a000000
1304 #define UNREG_ADDR_A_UPPER 0x0affffff
1305
1306 /* 172.16.0.0 -> 172.31.255.255 */
1307 #define UNREG_ADDR_B_LOWER 0xac100000
1308 #define UNREG_ADDR_B_UPPER 0xac1fffff
1309
1310 /* 192.168.0.0 -> 192.168.255.255 */
1311 #define UNREG_ADDR_C_LOWER 0xc0a80000
1312 #define UNREG_ADDR_C_UPPER 0xc0a8ffff
1313
1314 int
PacketAliasOut(char * ptr,int maxpacketsize)1315 PacketAliasOut(char *ptr, /* valid IP packet */
1316 int maxpacketsize /* How much the packet data may grow
1317 (FTP and IRC inline changes) */
1318 )
1319 {
1320 int iresult;
1321 struct in_addr addr_save;
1322 struct ip *pip;
1323
1324 if (packetAliasMode & PKT_ALIAS_REVERSE) {
1325 packetAliasMode &= ~PKT_ALIAS_REVERSE;
1326 iresult = PacketAliasIn(ptr, maxpacketsize);
1327 packetAliasMode |= PKT_ALIAS_REVERSE;
1328 return iresult;
1329 }
1330
1331 HouseKeeping();
1332 ClearCheckNewLink();
1333 pip = (struct ip *) ptr;
1334
1335 /* Defense against mangled packets */
1336 if (ntohs(pip->ip_len) > maxpacketsize
1337 || (pip->ip_hl<<2) > maxpacketsize)
1338 return PKT_ALIAS_IGNORED;
1339
1340 addr_save = GetDefaultAliasAddress();
1341 if (packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY)
1342 {
1343 u_long addr;
1344 int iclass;
1345
1346 iclass = 0;
1347 addr = ntohl(pip->ip_src.s_addr);
1348 if (addr >= UNREG_ADDR_C_LOWER && addr <= UNREG_ADDR_C_UPPER)
1349 iclass = 3;
1350 else if (addr >= UNREG_ADDR_B_LOWER && addr <= UNREG_ADDR_B_UPPER)
1351 iclass = 2;
1352 else if (addr >= UNREG_ADDR_A_LOWER && addr <= UNREG_ADDR_A_UPPER)
1353 iclass = 1;
1354
1355 if (iclass == 0)
1356 {
1357 SetDefaultAliasAddress(pip->ip_src);
1358 }
1359 }
1360
1361 iresult = PKT_ALIAS_IGNORED;
1362 if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0)
1363 {
1364 switch (pip->ip_p)
1365 {
1366 case IPPROTO_ICMP:
1367 iresult = IcmpAliasOut(pip);
1368 break;
1369 case IPPROTO_UDP:
1370 iresult = UdpAliasOut(pip);
1371 break;
1372 case IPPROTO_TCP:
1373 iresult = TcpAliasOut(pip, maxpacketsize);
1374 break;
1375 case IPPROTO_GRE:
1376 if (AliasHandlePptpGreOut(pip) == 0)
1377 iresult = PKT_ALIAS_OK;
1378 else
1379 iresult = ProtoAliasOut(pip);
1380 break;
1381 default:
1382 iresult = ProtoAliasOut(pip);
1383 break;
1384 }
1385 }
1386 else
1387 {
1388 iresult = FragmentOut(pip);
1389 }
1390
1391 SetDefaultAliasAddress(addr_save);
1392 return(iresult);
1393 }
1394
1395 int
PacketUnaliasOut(char * ptr,int maxpacketsize)1396 PacketUnaliasOut(char *ptr, /* valid IP packet */
1397 int maxpacketsize /* for error checking */
1398 )
1399 {
1400 struct ip *pip;
1401 struct icmp *ic;
1402 struct udphdr *ud;
1403 struct tcphdr *tc;
1404 struct alias_link *link;
1405 int iresult = PKT_ALIAS_IGNORED;
1406
1407 pip = (struct ip *) ptr;
1408
1409 /* Defense against mangled packets */
1410 if (ntohs(pip->ip_len) > maxpacketsize
1411 || (pip->ip_hl<<2) > maxpacketsize)
1412 return(iresult);
1413
1414 ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
1415 tc = (struct tcphdr *) ud;
1416 ic = (struct icmp *) ud;
1417
1418 /* Find a link */
1419 if (pip->ip_p == IPPROTO_UDP)
1420 link = FindUdpTcpIn(pip->ip_dst, pip->ip_src,
1421 ud->uh_dport, ud->uh_sport,
1422 IPPROTO_UDP, 0);
1423 else if (pip->ip_p == IPPROTO_TCP)
1424 link = FindUdpTcpIn(pip->ip_dst, pip->ip_src,
1425 tc->th_dport, tc->th_sport,
1426 IPPROTO_TCP, 0);
1427 else if (pip->ip_p == IPPROTO_ICMP)
1428 link = FindIcmpIn(pip->ip_dst, pip->ip_src, ic->icmp_id, 0);
1429 else
1430 link = NULL;
1431
1432 /* Change it from an aliased packet to an unaliased packet */
1433 if (link != NULL)
1434 {
1435 if (pip->ip_p == IPPROTO_UDP || pip->ip_p == IPPROTO_TCP)
1436 {
1437 int accumulate;
1438 struct in_addr original_address;
1439 u_short original_port;
1440
1441 original_address = GetOriginalAddress(link);
1442 original_port = GetOriginalPort(link);
1443
1444 /* Adjust TCP/UDP checksum */
1445 accumulate = twowords(&pip->ip_src);
1446 accumulate -= twowords(&original_address);
1447
1448 if (pip->ip_p == IPPROTO_UDP) {
1449 accumulate += ud->uh_sport;
1450 accumulate -= original_port;
1451 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
1452 } else {
1453 accumulate += tc->th_sport;
1454 accumulate -= original_port;
1455 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1456 }
1457
1458 /* Adjust IP checksum */
1459 DifferentialChecksum(&pip->ip_sum,
1460 (u_short *) &original_address,
1461 (u_short *) &pip->ip_src,
1462 2);
1463
1464 /* Un-alias source address and port number */
1465 pip->ip_src = original_address;
1466 if (pip->ip_p == IPPROTO_UDP)
1467 ud->uh_sport = original_port;
1468 else
1469 tc->th_sport = original_port;
1470
1471 iresult = PKT_ALIAS_OK;
1472
1473 } else if (pip->ip_p == IPPROTO_ICMP) {
1474
1475 int accumulate;
1476 struct in_addr original_address;
1477 u_short original_id;
1478
1479 original_address = GetOriginalAddress(link);
1480 original_id = GetOriginalPort(link);
1481
1482 /* Adjust ICMP checksum */
1483 accumulate = twowords(&pip->ip_src);
1484 accumulate -= twowords(&original_address);
1485 accumulate += ic->icmp_id;
1486 accumulate -= original_id;
1487 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
1488
1489 /* Adjust IP checksum */
1490 DifferentialChecksum(&pip->ip_sum,
1491 (u_short *) &original_address,
1492 (u_short *) &pip->ip_src,
1493 2);
1494
1495 /* Un-alias source address and port number */
1496 pip->ip_src = original_address;
1497 ic->icmp_id = original_id;
1498
1499 iresult = PKT_ALIAS_OK;
1500 }
1501 }
1502 return(iresult);
1503
1504 }
1505