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 * $OpenBSD: alias.c,v 1.19 2002/06/15 08:01:59 brian 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/types.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
141
142
143 /* TCP Handling Routines
144
145 TcpMonitorIn() -- These routines monitor TCP connections, and
146 TcpMonitorOut() delete a link when a connection is closed.
147
148 These routines look for SYN, FIN and RST flags to determine when TCP
149 connections open and close. When a TCP connection closes, the data
150 structure containing packet aliasing information is deleted after
151 a timeout period.
152 */
153
154 /* Local prototypes */
155 static void TcpMonitorIn(struct ip *, struct alias_link *);
156
157 static void TcpMonitorOut(struct ip *, struct alias_link *);
158
159
160 static void
TcpMonitorIn(struct ip * pip,struct alias_link * link)161 TcpMonitorIn(struct ip *pip, struct alias_link *link)
162 {
163 struct tcphdr *tc;
164
165 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
166
167 switch (GetStateIn(link))
168 {
169 case ALIAS_TCP_STATE_NOT_CONNECTED:
170 if (tc->th_flags & TH_RST)
171 SetStateIn(link, ALIAS_TCP_STATE_DISCONNECTED);
172 else if (tc->th_flags & TH_SYN)
173 SetStateIn(link, ALIAS_TCP_STATE_CONNECTED);
174 break;
175 case ALIAS_TCP_STATE_CONNECTED:
176 if (tc->th_flags & (TH_FIN | TH_RST))
177 SetStateIn(link, ALIAS_TCP_STATE_DISCONNECTED);
178 break;
179 }
180 }
181
182 static void
TcpMonitorOut(struct ip * pip,struct alias_link * link)183 TcpMonitorOut(struct ip *pip, struct alias_link *link)
184 {
185 struct tcphdr *tc;
186
187 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
188
189 switch (GetStateOut(link))
190 {
191 case ALIAS_TCP_STATE_NOT_CONNECTED:
192 if (tc->th_flags & TH_RST)
193 SetStateOut(link, ALIAS_TCP_STATE_DISCONNECTED);
194 else if (tc->th_flags & TH_SYN)
195 SetStateOut(link, ALIAS_TCP_STATE_CONNECTED);
196 break;
197 case ALIAS_TCP_STATE_CONNECTED:
198 if (tc->th_flags & (TH_FIN | TH_RST))
199 SetStateOut(link, ALIAS_TCP_STATE_DISCONNECTED);
200 break;
201 }
202 }
203
204
205
206
207
208 /* Protocol Specific Packet Aliasing Routines
209
210 IcmpAliasIn(), IcmpAliasIn1(), IcmpAliasIn2()
211 IcmpAliasOut(), IcmpAliasOut1(), IcmpAliasOut2()
212 ProtoAliasIn(), ProtoAliasOut()
213 UdpAliasIn(), UdpAliasOut()
214 TcpAliasIn(), TcpAliasOut()
215
216 These routines handle protocol specific details of packet aliasing.
217 One may observe a certain amount of repetitive arithmetic in these
218 functions, the purpose of which is to compute a revised checksum
219 without actually summing over the entire data packet, which could be
220 unnecessarily time consuming.
221
222 The purpose of the packet aliasing routines is to replace the source
223 address of the outgoing packet and then correctly put it back for
224 any incoming packets. For TCP and UDP, ports are also re-mapped.
225
226 For ICMP echo/timestamp requests and replies, the following scheme
227 is used: the ID number is replaced by an alias for the outgoing
228 packet.
229
230 ICMP error messages are handled by looking at the IP fragment
231 in the data section of the message.
232
233 For TCP and UDP protocols, a port number is chosen for an outgoing
234 packet, and then incoming packets are identified by IP address and
235 port numbers. For TCP packets, there is additional logic in the event
236 that sequence and ACK numbers have been altered (as in the case for
237 FTP data port commands).
238
239 The port numbers used by the packet aliasing module are not true
240 ports in the Unix sense. No sockets are actually bound to ports.
241 They are more correctly thought of as placeholders.
242
243 All packets go through the aliasing mechanism, whether they come from
244 the gateway machine or other machines on a local area network.
245 */
246
247
248 /* Local prototypes */
249 static int IcmpAliasIn1(struct ip *);
250 static int IcmpAliasIn2(struct ip *);
251 static int IcmpAliasIn (struct ip *);
252
253 static int IcmpAliasOut1(struct ip *);
254 static int IcmpAliasOut2(struct ip *);
255 static int IcmpAliasOut (struct ip *);
256
257 static int ProtoAliasIn(struct ip *);
258 static int ProtoAliasOut(struct ip *);
259
260 static int UdpAliasOut(struct ip *);
261 static int UdpAliasIn (struct ip *);
262
263 static int TcpAliasOut(struct ip *, int);
264 static int TcpAliasIn (struct ip *);
265
266
267 static int
IcmpAliasIn1(struct ip * pip)268 IcmpAliasIn1(struct ip *pip)
269 {
270 /*
271 De-alias incoming echo and timestamp replies.
272 Alias incoming echo and timestamp requests.
273 */
274 struct alias_link *link;
275 struct icmp *ic;
276
277 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
278
279 /* Get source address from ICMP data field and restore original data */
280 link = FindIcmpIn(pip->ip_src, pip->ip_dst, ic->icmp_id, 1);
281 if (link != NULL)
282 {
283 u_short original_id;
284 int accumulate;
285
286 original_id = GetOriginalPort(link);
287
288 /* Adjust ICMP checksum */
289 accumulate = ic->icmp_id;
290 accumulate -= original_id;
291 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
292
293 /* Put original sequence number back in */
294 ic->icmp_id = original_id;
295
296 /* Put original address back into IP header */
297 {
298 struct in_addr original_address;
299
300 original_address = GetOriginalAddress(link);
301 DifferentialChecksum(&pip->ip_sum,
302 (u_short *) &original_address,
303 (u_short *) &pip->ip_dst,
304 2);
305 pip->ip_dst = original_address;
306 }
307
308 return(PKT_ALIAS_OK);
309 }
310 return(PKT_ALIAS_IGNORED);
311 }
312
313 static int
IcmpAliasIn2(struct ip * pip)314 IcmpAliasIn2(struct ip *pip)
315 {
316 /*
317 Alias incoming ICMP error messages containing
318 IP header and first 64 bits of datagram.
319 */
320 struct ip *ip;
321 struct icmp *ic, *ic2;
322 struct udphdr *ud;
323 struct tcphdr *tc;
324 struct alias_link *link;
325
326 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
327 ip = &ic->icmp_ip;
328
329 ud = (struct udphdr *) ((char *) ip + (ip->ip_hl <<2));
330 tc = (struct tcphdr *) ud;
331 ic2 = (struct icmp *) ud;
332
333 if (ip->ip_p == IPPROTO_UDP)
334 link = FindUdpTcpIn(ip->ip_dst, ip->ip_src,
335 ud->uh_dport, ud->uh_sport,
336 IPPROTO_UDP, 0);
337 else if (ip->ip_p == IPPROTO_TCP)
338 link = FindUdpTcpIn(ip->ip_dst, ip->ip_src,
339 tc->th_dport, tc->th_sport,
340 IPPROTO_TCP, 0);
341 else if (ip->ip_p == IPPROTO_ICMP) {
342 if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP)
343 link = FindIcmpIn(ip->ip_dst, ip->ip_src, ic2->icmp_id, 0);
344 else
345 link = NULL;
346 } else
347 link = NULL;
348
349 if (link != NULL)
350 {
351 if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP)
352 {
353 u_short *sptr;
354 int accumulate;
355 struct in_addr original_address;
356 u_short original_port;
357
358 original_address = GetOriginalAddress(link);
359 original_port = GetOriginalPort(link);
360
361 /* Adjust ICMP checksum */
362 sptr = (u_short *) &(ip->ip_src);
363 accumulate = *sptr++;
364 accumulate += *sptr;
365 sptr = (u_short *) &original_address;
366 accumulate -= *sptr++;
367 accumulate -= *sptr;
368 accumulate += ud->uh_sport;
369 accumulate -= original_port;
370 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
371
372 /* Un-alias address in IP header */
373 DifferentialChecksum(&pip->ip_sum,
374 (u_short *) &original_address,
375 (u_short *) &pip->ip_dst,
376 2);
377 pip->ip_dst = original_address;
378
379 /* Un-alias address and port number of original IP packet
380 fragment contained in ICMP data section */
381 ip->ip_src = original_address;
382 ud->uh_sport = original_port;
383 }
384 else if (ip->ip_p == IPPROTO_ICMP)
385 {
386 u_short *sptr;
387 int accumulate;
388 struct in_addr original_address;
389 u_short original_id;
390
391 original_address = GetOriginalAddress(link);
392 original_id = GetOriginalPort(link);
393
394 /* Adjust ICMP checksum */
395 sptr = (u_short *) &(ip->ip_src);
396 accumulate = *sptr++;
397 accumulate += *sptr;
398 sptr = (u_short *) &original_address;
399 accumulate -= *sptr++;
400 accumulate -= *sptr;
401 accumulate += ic2->icmp_id;
402 accumulate -= original_id;
403 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
404
405 /* Un-alias address in IP header */
406 DifferentialChecksum(&pip->ip_sum,
407 (u_short *) &original_address,
408 (u_short *) &pip->ip_dst,
409 2);
410 pip->ip_dst = original_address;
411
412 /* Un-alias address of original IP packet and sequence number of
413 embedded ICMP datagram */
414 ip->ip_src = original_address;
415 ic2->icmp_id = original_id;
416 }
417 return(PKT_ALIAS_OK);
418 }
419 return(PKT_ALIAS_IGNORED);
420 }
421
422
423 static int
IcmpAliasIn(struct ip * pip)424 IcmpAliasIn(struct ip *pip)
425 {
426 int iresult;
427 struct icmp *ic;
428
429 /* Return if proxy-only mode is enabled */
430 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
431 return PKT_ALIAS_OK;
432
433 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
434
435 iresult = PKT_ALIAS_IGNORED;
436 switch (ic->icmp_type)
437 {
438 case ICMP_ECHOREPLY:
439 case ICMP_TSTAMPREPLY:
440 if (ic->icmp_code == 0)
441 {
442 iresult = IcmpAliasIn1(pip);
443 }
444 break;
445 case ICMP_UNREACH:
446 case ICMP_SOURCEQUENCH:
447 case ICMP_TIMXCEED:
448 case ICMP_PARAMPROB:
449 iresult = IcmpAliasIn2(pip);
450 break;
451 case ICMP_ECHO:
452 case ICMP_TSTAMP:
453 iresult = IcmpAliasIn1(pip);
454 break;
455 }
456 return(iresult);
457 }
458
459
460 static int
IcmpAliasOut1(struct ip * pip)461 IcmpAliasOut1(struct ip *pip)
462 {
463 /*
464 Alias outgoing echo and timestamp requests.
465 De-alias outgoing echo and timestamp replies.
466 */
467 struct alias_link *link;
468 struct icmp *ic;
469
470 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
471
472 /* Save overwritten data for when echo packet returns */
473 link = FindIcmpOut(pip->ip_src, pip->ip_dst, ic->icmp_id, 1);
474 if (link != NULL)
475 {
476 u_short alias_id;
477 int accumulate;
478
479 alias_id = GetAliasPort(link);
480
481 /* Since data field is being modified, adjust ICMP checksum */
482 accumulate = ic->icmp_id;
483 accumulate -= alias_id;
484 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
485
486 /* Alias sequence number */
487 ic->icmp_id = alias_id;
488
489 /* Change source address */
490 {
491 struct in_addr alias_address;
492
493 alias_address = GetAliasAddress(link);
494 DifferentialChecksum(&pip->ip_sum,
495 (u_short *) &alias_address,
496 (u_short *) &pip->ip_src,
497 2);
498 pip->ip_src = alias_address;
499 }
500
501 return(PKT_ALIAS_OK);
502 }
503 return(PKT_ALIAS_IGNORED);
504 }
505
506
507 static int
IcmpAliasOut2(struct ip * pip)508 IcmpAliasOut2(struct ip *pip)
509 {
510 /*
511 Alias outgoing ICMP error messages containing
512 IP header and first 64 bits of datagram.
513 */
514 struct ip *ip;
515 struct icmp *ic, *ic2;
516 struct udphdr *ud;
517 struct tcphdr *tc;
518 struct alias_link *link;
519
520 ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
521 ip = &ic->icmp_ip;
522
523 ud = (struct udphdr *) ((char *) ip + (ip->ip_hl <<2));
524 tc = (struct tcphdr *) ud;
525 ic2 = (struct icmp *) ud;
526
527 if (ip->ip_p == IPPROTO_UDP)
528 link = FindUdpTcpOut(ip->ip_dst, ip->ip_src,
529 ud->uh_dport, ud->uh_sport,
530 IPPROTO_UDP, 0);
531 else if (ip->ip_p == IPPROTO_TCP)
532 link = FindUdpTcpOut(ip->ip_dst, ip->ip_src,
533 tc->th_dport, tc->th_sport,
534 IPPROTO_TCP, 0);
535 else if (ip->ip_p == IPPROTO_ICMP) {
536 if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP)
537 link = FindIcmpOut(ip->ip_dst, ip->ip_src, ic2->icmp_id, 0);
538 else
539 link = NULL;
540 } else
541 link = NULL;
542
543 if (link != NULL)
544 {
545 if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP)
546 {
547 u_short *sptr;
548 int accumulate;
549 struct in_addr alias_address;
550 u_short alias_port;
551
552 alias_address = GetAliasAddress(link);
553 alias_port = GetAliasPort(link);
554
555 /* Adjust ICMP checksum */
556 sptr = (u_short *) &(ip->ip_dst);
557 accumulate = *sptr++;
558 accumulate += *sptr;
559 sptr = (u_short *) &alias_address;
560 accumulate -= *sptr++;
561 accumulate -= *sptr;
562 accumulate += ud->uh_dport;
563 accumulate -= alias_port;
564 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
565
566 /*
567 * Alias address in IP header if it comes from the host
568 * the original TCP/UDP packet was destined for.
569 */
570 if (pip->ip_src.s_addr == ip->ip_dst.s_addr) {
571 DifferentialChecksum(&pip->ip_sum,
572 (u_short *) &alias_address,
573 (u_short *) &pip->ip_src,
574 2);
575 pip->ip_src = alias_address;
576 }
577
578 /* Alias address and port number of original IP packet
579 fragment contained in ICMP data section */
580 ip->ip_dst = alias_address;
581 ud->uh_dport = alias_port;
582 }
583 else if (ip->ip_p == IPPROTO_ICMP)
584 {
585 u_short *sptr;
586 int accumulate;
587 struct in_addr alias_address;
588 u_short alias_id;
589
590 alias_address = GetAliasAddress(link);
591 alias_id = GetAliasPort(link);
592
593 /* Adjust ICMP checksum */
594 sptr = (u_short *) &(ip->ip_dst);
595 accumulate = *sptr++;
596 accumulate += *sptr;
597 sptr = (u_short *) &alias_address;
598 accumulate -= *sptr++;
599 accumulate -= *sptr;
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 u_short *sptr;
755 int r = 0;
756
757 alias_address = GetAliasAddress(link);
758 original_address = GetOriginalAddress(link);
759 alias_port = ud->uh_dport;
760 ud->uh_dport = GetOriginalPort(link);
761
762 /* Special processing for IP encoding protocols */
763 if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER)
764 AliasHandleCUSeeMeIn(pip, original_address);
765 /* If NETBIOS Datagram, It should be alias address in UDP Data, too */
766 else if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER
767 || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER)
768 r = AliasHandleUdpNbt(pip, link, &original_address, ud->uh_dport);
769 else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER
770 || ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER)
771 r = AliasHandleUdpNbtNS(pip, link, &alias_address, &alias_port,
772 &original_address, &ud->uh_dport);
773
774 /* If UDP checksum is not zero, then adjust since destination port */
775 /* is being unaliased and destination address is being altered. */
776 if (ud->uh_sum != 0)
777 {
778 accumulate = alias_port;
779 accumulate -= ud->uh_dport;
780 sptr = (u_short *) &alias_address;
781 accumulate += *sptr++;
782 accumulate += *sptr;
783 sptr = (u_short *) &original_address;
784 accumulate -= *sptr++;
785 accumulate -= *sptr;
786 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
787 }
788
789 /* Restore original IP address */
790 DifferentialChecksum(&pip->ip_sum,
791 (u_short *) &original_address,
792 (u_short *) &pip->ip_dst,
793 2);
794 pip->ip_dst = original_address;
795
796 /*
797 * If we cannot figure out the packet, ignore it.
798 */
799 if (r < 0)
800 return(PKT_ALIAS_IGNORED);
801 else
802 return(PKT_ALIAS_OK);
803 }
804 return(PKT_ALIAS_IGNORED);
805 }
806
807 static int
UdpAliasOut(struct ip * pip)808 UdpAliasOut(struct ip *pip)
809 {
810 struct udphdr *ud;
811 struct alias_link *link;
812
813 /* Return if proxy-only mode is enabled */
814 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
815 return PKT_ALIAS_OK;
816
817 ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
818
819 link = FindUdpTcpOut(pip->ip_src, pip->ip_dst,
820 ud->uh_sport, ud->uh_dport,
821 IPPROTO_UDP, 1);
822 if (link != NULL)
823 {
824 u_short alias_port;
825 struct in_addr alias_address;
826
827 alias_address = GetAliasAddress(link);
828 alias_port = GetAliasPort(link);
829
830 /* Special processing for IP encoding protocols */
831 if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER)
832 AliasHandleCUSeeMeOut(pip, link);
833 /* If NETBIOS Datagram, It should be alias address in UDP Data, too */
834 else if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER
835 || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER)
836 AliasHandleUdpNbt(pip, link, &alias_address, alias_port);
837 else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER
838 || ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER)
839 AliasHandleUdpNbtNS(pip, link, &pip->ip_src, &ud->uh_sport,
840 &alias_address, &alias_port);
841 /*
842 * We don't know in advance what TID the TFTP server will choose,
843 * so we create a wilcard link (destination port is unspecified)
844 * that will match any TID from a given destination.
845 */
846 else if (ntohs(ud->uh_dport) == TFTP_PORT_NUMBER)
847 FindRtspOut(pip->ip_src, pip->ip_dst,
848 ud->uh_sport, alias_port, IPPROTO_UDP);
849
850 /* If UDP checksum is not zero, adjust since source port is */
851 /* being aliased and source address is being altered */
852 if (ud->uh_sum != 0)
853 {
854 int accumulate;
855 u_short *sptr;
856
857 accumulate = ud->uh_sport;
858 accumulate -= alias_port;
859 sptr = (u_short *) &(pip->ip_src);
860 accumulate += *sptr++;
861 accumulate += *sptr;
862 sptr = (u_short *) &alias_address;
863 accumulate -= *sptr++;
864 accumulate -= *sptr;
865 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
866 }
867
868 /* Put alias port in UDP header */
869 ud->uh_sport = alias_port;
870
871 /* Change source address */
872 DifferentialChecksum(&pip->ip_sum,
873 (u_short *) &alias_address,
874 (u_short *) &pip->ip_src,
875 2);
876 pip->ip_src = alias_address;
877
878 return(PKT_ALIAS_OK);
879 }
880 return(PKT_ALIAS_IGNORED);
881 }
882
883
884
885 static int
TcpAliasIn(struct ip * pip)886 TcpAliasIn(struct ip *pip)
887 {
888 struct tcphdr *tc;
889 struct alias_link *link;
890
891 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
892
893 link = FindUdpTcpIn(pip->ip_src, pip->ip_dst,
894 tc->th_sport, tc->th_dport,
895 IPPROTO_TCP,
896 !(packetAliasMode & PKT_ALIAS_PROXY_ONLY));
897 if (link != NULL)
898 {
899 struct in_addr alias_address;
900 struct in_addr original_address;
901 struct in_addr proxy_address;
902 u_short alias_port;
903 u_short proxy_port;
904 int accumulate;
905 u_short *sptr;
906
907 /* Special processing for IP encoding protocols */
908 if (ntohs(tc->th_dport) == PPTP_CONTROL_PORT_NUMBER
909 || ntohs(tc->th_sport) == PPTP_CONTROL_PORT_NUMBER)
910 AliasHandlePptpIn(pip, link);
911
912 alias_address = GetAliasAddress(link);
913 original_address = GetOriginalAddress(link);
914 proxy_address = GetProxyAddress(link);
915 alias_port = tc->th_dport;
916 tc->th_dport = GetOriginalPort(link);
917 proxy_port = GetProxyPort(link);
918
919 /* Adjust TCP checksum since destination port is being unaliased */
920 /* and destination port is being altered. */
921 accumulate = alias_port;
922 accumulate -= tc->th_dport;
923 sptr = (u_short *) &alias_address;
924 accumulate += *sptr++;
925 accumulate += *sptr;
926 sptr = (u_short *) &original_address;
927 accumulate -= *sptr++;
928 accumulate -= *sptr;
929
930 /* If this is a proxy, then modify the TCP source port and
931 checksum accumulation */
932 if (proxy_port != 0)
933 {
934 accumulate += tc->th_sport;
935 tc->th_sport = proxy_port;
936 accumulate -= tc->th_sport;
937
938 sptr = (u_short *) &pip->ip_src;
939 accumulate += *sptr++;
940 accumulate += *sptr;
941 sptr = (u_short *) &proxy_address;
942 accumulate -= *sptr++;
943 accumulate -= *sptr;
944 }
945
946 /* See if ACK number needs to be modified */
947 if (GetAckModified(link) == 1)
948 {
949 int delta;
950
951 delta = GetDeltaAckIn(pip, link);
952 if (delta != 0)
953 {
954 sptr = (u_short *) &tc->th_ack;
955 accumulate += *sptr++;
956 accumulate += *sptr;
957 tc->th_ack = htonl(ntohl(tc->th_ack) - delta);
958 sptr = (u_short *) &tc->th_ack;
959 accumulate -= *sptr++;
960 accumulate -= *sptr;
961 }
962 }
963
964 ADJUST_CHECKSUM(accumulate, tc->th_sum);
965
966 /* Restore original IP address */
967 sptr = (u_short *) &pip->ip_dst;
968 accumulate = *sptr++;
969 accumulate += *sptr;
970 pip->ip_dst = original_address;
971 sptr = (u_short *) &pip->ip_dst;
972 accumulate -= *sptr++;
973 accumulate -= *sptr;
974
975 /* If this is a transparent proxy packet, then modify the source
976 address */
977 if (proxy_address.s_addr != 0)
978 {
979 sptr = (u_short *) &pip->ip_src;
980 accumulate += *sptr++;
981 accumulate += *sptr;
982 pip->ip_src = proxy_address;
983 sptr = (u_short *) &pip->ip_src;
984 accumulate -= *sptr++;
985 accumulate -= *sptr;
986 }
987
988 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
989
990 /* Monitor TCP connection state */
991 TcpMonitorIn(pip, link);
992
993 return(PKT_ALIAS_OK);
994 }
995 return(PKT_ALIAS_IGNORED);
996 }
997
998 static int
TcpAliasOut(struct ip * pip,int maxpacketsize)999 TcpAliasOut(struct ip *pip, int maxpacketsize)
1000 {
1001 int proxy_type;
1002 u_short dest_port;
1003 u_short proxy_server_port;
1004 struct in_addr dest_address;
1005 struct in_addr proxy_server_address;
1006 struct tcphdr *tc;
1007 struct alias_link *link;
1008
1009 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
1010
1011 proxy_type = ProxyCheck(pip, &proxy_server_address, &proxy_server_port);
1012
1013 if (proxy_type == 0 && (packetAliasMode & PKT_ALIAS_PROXY_ONLY))
1014 return PKT_ALIAS_OK;
1015
1016 /* If this is a transparent proxy, save original destination,
1017 then alter the destination and adjust checksums */
1018 dest_port = tc->th_dport;
1019 dest_address = pip->ip_dst;
1020 if (proxy_type != 0)
1021 {
1022 int accumulate;
1023 u_short *sptr;
1024
1025 accumulate = tc->th_dport;
1026 tc->th_dport = proxy_server_port;
1027 accumulate -= tc->th_dport;
1028
1029 sptr = (u_short *) &(pip->ip_dst);
1030 accumulate += *sptr++;
1031 accumulate += *sptr;
1032 sptr = (u_short *) &proxy_server_address;
1033 accumulate -= *sptr++;
1034 accumulate -= *sptr;
1035
1036 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1037
1038 sptr = (u_short *) &(pip->ip_dst);
1039 accumulate = *sptr++;
1040 accumulate += *sptr;
1041 pip->ip_dst = proxy_server_address;
1042 sptr = (u_short *) &(pip->ip_dst);
1043 accumulate -= *sptr++;
1044 accumulate -= *sptr;
1045
1046 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
1047 }
1048
1049 link = FindUdpTcpOut(pip->ip_src, pip->ip_dst,
1050 tc->th_sport, tc->th_dport,
1051 IPPROTO_TCP, 1);
1052 if (link !=NULL)
1053 {
1054 u_short alias_port;
1055 struct in_addr alias_address;
1056 int accumulate;
1057 u_short *sptr;
1058
1059 /* Save original destination address, if this is a proxy packet.
1060 Also modify packet to include destination encoding. This may
1061 change the size of IP header. */
1062 if (proxy_type != 0)
1063 {
1064 SetProxyPort(link, dest_port);
1065 SetProxyAddress(link, dest_address);
1066 ProxyModify(link, pip, maxpacketsize, proxy_type);
1067 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
1068 }
1069
1070 /* Get alias address and port */
1071 alias_port = GetAliasPort(link);
1072 alias_address = GetAliasAddress(link);
1073
1074 /* Monitor TCP connection state */
1075 TcpMonitorOut(pip, link);
1076
1077 /* Special processing for IP encoding protocols */
1078 if (ntohs(tc->th_dport) == FTP_CONTROL_PORT_NUMBER
1079 || ntohs(tc->th_sport) == FTP_CONTROL_PORT_NUMBER)
1080 AliasHandleFtpOut(pip, link, maxpacketsize);
1081 else if (ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_1
1082 || ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_2)
1083 AliasHandleIrcOut(pip, link, maxpacketsize);
1084 else if (ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_1
1085 || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_1
1086 || ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_2
1087 || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_2)
1088 AliasHandleRtspOut(pip, link, maxpacketsize);
1089 else if (ntohs(tc->th_dport) == PPTP_CONTROL_PORT_NUMBER
1090 || ntohs(tc->th_sport) == PPTP_CONTROL_PORT_NUMBER)
1091 AliasHandlePptpOut(pip, link);
1092
1093 /* Adjust TCP checksum since source port is being aliased */
1094 /* and source address is being altered */
1095 accumulate = tc->th_sport;
1096 tc->th_sport = alias_port;
1097 accumulate -= tc->th_sport;
1098
1099 sptr = (u_short *) &(pip->ip_src);
1100 accumulate += *sptr++;
1101 accumulate += *sptr;
1102 sptr = (u_short *) &alias_address;
1103 accumulate -= *sptr++;
1104 accumulate -= *sptr;
1105
1106 /* Modify sequence number if necessary */
1107 if (GetAckModified(link) == 1)
1108 {
1109 int delta;
1110
1111 delta = GetDeltaSeqOut(pip, link);
1112 if (delta != 0)
1113 {
1114 sptr = (u_short *) &tc->th_seq;
1115 accumulate += *sptr++;
1116 accumulate += *sptr;
1117 tc->th_seq = htonl(ntohl(tc->th_seq) + delta);
1118 sptr = (u_short *) &tc->th_seq;
1119 accumulate -= *sptr++;
1120 accumulate -= *sptr;
1121 }
1122 }
1123
1124 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1125
1126 /* Change source address */
1127 sptr = (u_short *) &(pip->ip_src);
1128 accumulate = *sptr++;
1129 accumulate += *sptr;
1130 pip->ip_src = alias_address;
1131 sptr = (u_short *) &(pip->ip_src);
1132 accumulate -= *sptr++;
1133 accumulate -= *sptr;
1134
1135 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
1136
1137 return(PKT_ALIAS_OK);
1138 }
1139 return(PKT_ALIAS_IGNORED);
1140 }
1141
1142
1143
1144
1145 /* Fragment Handling
1146
1147 FragmentIn()
1148 FragmentOut()
1149
1150 The packet aliasing module has a limited ability for handling IP
1151 fragments. If the ICMP, TCP or UDP header is in the first fragment
1152 received, then the ID number of the IP packet is saved, and other
1153 fragments are identified according to their ID number and IP address
1154 they were sent from. Pointers to unresolved fragments can also be
1155 saved and recalled when a header fragment is seen.
1156 */
1157
1158 /* Local prototypes */
1159 static int FragmentIn(struct ip *);
1160 static int FragmentOut(struct ip *);
1161
1162
1163 static int
FragmentIn(struct ip * pip)1164 FragmentIn(struct ip *pip)
1165 {
1166 struct alias_link *link;
1167
1168 link = FindFragmentIn2(pip->ip_src, pip->ip_dst, pip->ip_id);
1169 if (link != NULL)
1170 {
1171 struct in_addr original_address;
1172
1173 GetFragmentAddr(link, &original_address);
1174 DifferentialChecksum(&pip->ip_sum,
1175 (u_short *) &original_address,
1176 (u_short *) &pip->ip_dst,
1177 2);
1178 pip->ip_dst = original_address;
1179
1180 return(PKT_ALIAS_OK);
1181 }
1182 return(PKT_ALIAS_UNRESOLVED_FRAGMENT);
1183 }
1184
1185
1186 static int
FragmentOut(struct ip * pip)1187 FragmentOut(struct ip *pip)
1188 {
1189 struct in_addr alias_address;
1190
1191 alias_address = FindAliasAddress(pip->ip_src);
1192 DifferentialChecksum(&pip->ip_sum,
1193 (u_short *) &alias_address,
1194 (u_short *) &pip->ip_src,
1195 2);
1196 pip->ip_src = alias_address;
1197
1198 return(PKT_ALIAS_OK);
1199 }
1200
1201
1202
1203
1204
1205
1206 /* Outside World Access
1207
1208 PacketAliasSaveFragment()
1209 PacketAliasGetFragment()
1210 PacketAliasFragmentIn()
1211 PacketAliasIn()
1212 PacketAliasOut()
1213 PacketUnaliasOut()
1214
1215 (prototypes in alias.h)
1216 */
1217
1218
1219 int
PacketAliasSaveFragment(char * ptr)1220 PacketAliasSaveFragment(char *ptr)
1221 {
1222 int iresult;
1223 struct alias_link *link;
1224 struct ip *pip;
1225
1226 pip = (struct ip *) ptr;
1227 link = AddFragmentPtrLink(pip->ip_src, pip->ip_id);
1228 iresult = PKT_ALIAS_ERROR;
1229 if (link != NULL)
1230 {
1231 SetFragmentPtr(link, ptr);
1232 iresult = PKT_ALIAS_OK;
1233 }
1234 return(iresult);
1235 }
1236
1237
1238 char *
PacketAliasGetFragment(char * ptr)1239 PacketAliasGetFragment(char *ptr)
1240 {
1241 struct alias_link *link;
1242 char *fptr;
1243 struct ip *pip;
1244
1245 pip = (struct ip *) ptr;
1246 link = FindFragmentPtr(pip->ip_src, pip->ip_id);
1247 if (link != NULL)
1248 {
1249 GetFragmentPtr(link, &fptr);
1250 SetFragmentPtr(link, NULL);
1251 SetExpire(link, 0); /* Deletes link */
1252
1253 return(fptr);
1254 }
1255 else
1256 {
1257 return(NULL);
1258 }
1259 }
1260
1261
1262 void
PacketAliasFragmentIn(char * ptr,char * ptr_fragment)1263 PacketAliasFragmentIn(char *ptr, /* Points to correctly de-aliased
1264 header fragment */
1265 char *ptr_fragment /* Points to fragment which must
1266 be de-aliased */
1267 )
1268 {
1269 struct ip *pip;
1270 struct ip *fpip;
1271
1272 pip = (struct ip *) ptr;
1273 fpip = (struct ip *) ptr_fragment;
1274
1275 DifferentialChecksum(&fpip->ip_sum,
1276 (u_short *) &pip->ip_dst,
1277 (u_short *) &fpip->ip_dst,
1278 2);
1279 fpip->ip_dst = pip->ip_dst;
1280 }
1281
1282
1283 int
PacketAliasIn(char * ptr,int maxpacketsize)1284 PacketAliasIn(char *ptr, int maxpacketsize)
1285 {
1286 struct in_addr alias_addr;
1287 struct ip *pip;
1288 int iresult;
1289
1290 if (packetAliasMode & PKT_ALIAS_REVERSE) {
1291 packetAliasMode &= ~PKT_ALIAS_REVERSE;
1292 iresult = PacketAliasOut(ptr, maxpacketsize);
1293 packetAliasMode |= PKT_ALIAS_REVERSE;
1294 return iresult;
1295 }
1296
1297 HouseKeeping();
1298 ClearCheckNewLink();
1299 pip = (struct ip *) ptr;
1300 alias_addr = pip->ip_dst;
1301
1302 /* Defense against mangled packets */
1303 if (ntohs(pip->ip_len) > maxpacketsize
1304 || (pip->ip_hl<<2) > maxpacketsize)
1305 return PKT_ALIAS_IGNORED;
1306
1307 iresult = PKT_ALIAS_IGNORED;
1308 if ( (ntohs(pip->ip_off) & IP_OFFMASK) == 0 )
1309 {
1310 switch (pip->ip_p)
1311 {
1312 case IPPROTO_ICMP:
1313 iresult = IcmpAliasIn(pip);
1314 break;
1315 case IPPROTO_UDP:
1316 iresult = UdpAliasIn(pip);
1317 break;
1318 case IPPROTO_TCP:
1319 iresult = TcpAliasIn(pip);
1320 break;
1321 case IPPROTO_GRE:
1322 if (packetAliasMode & PKT_ALIAS_PROXY_ONLY ||
1323 AliasHandlePptpGreIn(pip) == 0)
1324 iresult = PKT_ALIAS_OK;
1325 else
1326 iresult = ProtoAliasIn(pip);
1327 break;
1328 default:
1329 iresult = ProtoAliasIn(pip);
1330 break;
1331 }
1332
1333 if (ntohs(pip->ip_off) & IP_MF)
1334 {
1335 struct alias_link *link;
1336
1337 link = FindFragmentIn1(pip->ip_src, alias_addr, pip->ip_id);
1338 if (link != NULL)
1339 {
1340 iresult = PKT_ALIAS_FOUND_HEADER_FRAGMENT;
1341 SetFragmentAddr(link, pip->ip_dst);
1342 }
1343 else
1344 {
1345 iresult = PKT_ALIAS_ERROR;
1346 }
1347 }
1348 }
1349 else
1350 {
1351 iresult = FragmentIn(pip);
1352 }
1353
1354 return(iresult);
1355 }
1356
1357
1358
1359 /* Unregistered address ranges */
1360
1361 /* 10.0.0.0 -> 10.255.255.255 */
1362 #define UNREG_ADDR_A_LOWER 0x0a000000
1363 #define UNREG_ADDR_A_UPPER 0x0affffff
1364
1365 /* 172.16.0.0 -> 172.31.255.255 */
1366 #define UNREG_ADDR_B_LOWER 0xac100000
1367 #define UNREG_ADDR_B_UPPER 0xac1fffff
1368
1369 /* 192.168.0.0 -> 192.168.255.255 */
1370 #define UNREG_ADDR_C_LOWER 0xc0a80000
1371 #define UNREG_ADDR_C_UPPER 0xc0a8ffff
1372
1373 int
PacketAliasOut(char * ptr,int maxpacketsize)1374 PacketAliasOut(char *ptr, /* valid IP packet */
1375 int maxpacketsize /* How much the packet data may grow
1376 (FTP and IRC inline changes) */
1377 )
1378 {
1379 int iresult;
1380 struct in_addr addr_save;
1381 struct ip *pip;
1382
1383 if (packetAliasMode & PKT_ALIAS_REVERSE) {
1384 packetAliasMode &= ~PKT_ALIAS_REVERSE;
1385 iresult = PacketAliasIn(ptr, maxpacketsize);
1386 packetAliasMode |= PKT_ALIAS_REVERSE;
1387 return iresult;
1388 }
1389
1390 HouseKeeping();
1391 ClearCheckNewLink();
1392 pip = (struct ip *) ptr;
1393
1394 /* Defense against mangled packets */
1395 if (ntohs(pip->ip_len) > maxpacketsize
1396 || (pip->ip_hl<<2) > maxpacketsize)
1397 return PKT_ALIAS_IGNORED;
1398
1399 addr_save = GetDefaultAliasAddress();
1400 if (packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY)
1401 {
1402 u_long addr;
1403 int iclass;
1404
1405 iclass = 0;
1406 addr = ntohl(pip->ip_src.s_addr);
1407 if (addr >= UNREG_ADDR_C_LOWER && addr <= UNREG_ADDR_C_UPPER)
1408 iclass = 3;
1409 else if (addr >= UNREG_ADDR_B_LOWER && addr <= UNREG_ADDR_B_UPPER)
1410 iclass = 2;
1411 else if (addr >= UNREG_ADDR_A_LOWER && addr <= UNREG_ADDR_A_UPPER)
1412 iclass = 1;
1413
1414 if (iclass == 0)
1415 {
1416 SetDefaultAliasAddress(pip->ip_src);
1417 }
1418 }
1419
1420 iresult = PKT_ALIAS_IGNORED;
1421 if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0)
1422 {
1423 switch (pip->ip_p)
1424 {
1425 case IPPROTO_ICMP:
1426 iresult = IcmpAliasOut(pip);
1427 break;
1428 case IPPROTO_UDP:
1429 iresult = UdpAliasOut(pip);
1430 break;
1431 case IPPROTO_TCP:
1432 iresult = TcpAliasOut(pip, maxpacketsize);
1433 break;
1434 case IPPROTO_GRE:
1435 if (AliasHandlePptpGreOut(pip) == 0)
1436 iresult = PKT_ALIAS_OK;
1437 else
1438 iresult = ProtoAliasOut(pip);
1439 break;
1440 default:
1441 iresult = ProtoAliasOut(pip);
1442 break;
1443 }
1444 }
1445 else
1446 {
1447 iresult = FragmentOut(pip);
1448 }
1449
1450 SetDefaultAliasAddress(addr_save);
1451 return(iresult);
1452 }
1453
1454 int
PacketUnaliasOut(char * ptr,int maxpacketsize)1455 PacketUnaliasOut(char *ptr, /* valid IP packet */
1456 int maxpacketsize /* for error checking */
1457 )
1458 {
1459 struct ip *pip;
1460 struct icmp *ic;
1461 struct udphdr *ud;
1462 struct tcphdr *tc;
1463 struct alias_link *link;
1464 int iresult = PKT_ALIAS_IGNORED;
1465
1466 pip = (struct ip *) ptr;
1467
1468 /* Defense against mangled packets */
1469 if (ntohs(pip->ip_len) > maxpacketsize
1470 || (pip->ip_hl<<2) > maxpacketsize)
1471 return(iresult);
1472
1473 ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
1474 tc = (struct tcphdr *) ud;
1475 ic = (struct icmp *) ud;
1476
1477 /* Find a link */
1478 if (pip->ip_p == IPPROTO_UDP)
1479 link = FindUdpTcpIn(pip->ip_dst, pip->ip_src,
1480 ud->uh_dport, ud->uh_sport,
1481 IPPROTO_UDP, 0);
1482 else if (pip->ip_p == IPPROTO_TCP)
1483 link = FindUdpTcpIn(pip->ip_dst, pip->ip_src,
1484 tc->th_dport, tc->th_sport,
1485 IPPROTO_TCP, 0);
1486 else if (pip->ip_p == IPPROTO_ICMP)
1487 link = FindIcmpIn(pip->ip_dst, pip->ip_src, ic->icmp_id, 0);
1488 else
1489 link = NULL;
1490
1491 /* Change it from an aliased packet to an unaliased packet */
1492 if (link != NULL)
1493 {
1494 if (pip->ip_p == IPPROTO_UDP || pip->ip_p == IPPROTO_TCP)
1495 {
1496 u_short *sptr;
1497 int accumulate;
1498 struct in_addr original_address;
1499 u_short original_port;
1500
1501 original_address = GetOriginalAddress(link);
1502 original_port = GetOriginalPort(link);
1503
1504 /* Adjust TCP/UDP checksum */
1505 sptr = (u_short *) &(pip->ip_src);
1506 accumulate = *sptr++;
1507 accumulate += *sptr;
1508 sptr = (u_short *) &original_address;
1509 accumulate -= *sptr++;
1510 accumulate -= *sptr;
1511
1512 if (pip->ip_p == IPPROTO_UDP) {
1513 accumulate += ud->uh_sport;
1514 accumulate -= original_port;
1515 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
1516 } else {
1517 accumulate += tc->th_sport;
1518 accumulate -= original_port;
1519 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1520 }
1521
1522 /* Adjust IP checksum */
1523 DifferentialChecksum(&pip->ip_sum,
1524 (u_short *) &original_address,
1525 (u_short *) &pip->ip_src,
1526 2);
1527
1528 /* Un-alias source address and port number */
1529 pip->ip_src = original_address;
1530 if (pip->ip_p == IPPROTO_UDP)
1531 ud->uh_sport = original_port;
1532 else
1533 tc->th_sport = original_port;
1534
1535 iresult = PKT_ALIAS_OK;
1536
1537 } else if (pip->ip_p == IPPROTO_ICMP) {
1538
1539 u_short *sptr;
1540 int accumulate;
1541 struct in_addr original_address;
1542 u_short original_id;
1543
1544 original_address = GetOriginalAddress(link);
1545 original_id = GetOriginalPort(link);
1546
1547 /* Adjust ICMP checksum */
1548 sptr = (u_short *) &(pip->ip_src);
1549 accumulate = *sptr++;
1550 accumulate += *sptr;
1551 sptr = (u_short *) &original_address;
1552 accumulate -= *sptr++;
1553 accumulate -= *sptr;
1554 accumulate += ic->icmp_id;
1555 accumulate -= original_id;
1556 ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
1557
1558 /* Adjust IP checksum */
1559 DifferentialChecksum(&pip->ip_sum,
1560 (u_short *) &original_address,
1561 (u_short *) &pip->ip_src,
1562 2);
1563
1564 /* Un-alias source address and port number */
1565 pip->ip_src = original_address;
1566 ic->icmp_id = original_id;
1567
1568 iresult = PKT_ALIAS_OK;
1569 }
1570 }
1571 return(iresult);
1572
1573 }
1574