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