]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - 6/sys/netinet/libalias/alias.c
Clone Kip's Xen on stable/6 tree so that I can work on improving FreeBSD/amd64
[FreeBSD/FreeBSD.git] / 6 / 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         if (create)
940                 proxy_type =
941                     ProxyCheck(la, pip, &proxy_server_address, &proxy_server_port);
942         else
943                 proxy_type = 0;
944
945         if (proxy_type == 0 && (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY))
946                 return (PKT_ALIAS_OK);
947
948 /* If this is a transparent proxy, save original destination,
949    then alter the destination and adjust checksums */
950         dest_port = tc->th_dport;
951         dest_address = pip->ip_dst;
952         if (proxy_type != 0) {
953                 int accumulate;
954
955                 accumulate = tc->th_dport;
956                 tc->th_dport = proxy_server_port;
957                 accumulate -= tc->th_dport;
958                 accumulate += twowords(&pip->ip_dst);
959                 accumulate -= twowords(&proxy_server_address);
960                 ADJUST_CHECKSUM(accumulate, tc->th_sum);
961
962                 accumulate = twowords(&pip->ip_dst);
963                 pip->ip_dst = proxy_server_address;
964                 accumulate -= twowords(&pip->ip_dst);
965                 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
966         }
967         lnk = FindUdpTcpOut(la, pip->ip_src, pip->ip_dst,
968             tc->th_sport, tc->th_dport,
969             IPPROTO_TCP, create);
970         if (lnk == NULL)
971                 return (PKT_ALIAS_IGNORED);
972         if (lnk != NULL) {
973                 u_short alias_port;
974                 struct in_addr alias_address;
975                 int accumulate;
976
977 /* Save original destination address, if this is a proxy packet.
978    Also modify packet to include destination encoding.  This may
979    change the size of IP header. */
980                 if (proxy_type != 0) {
981                         SetProxyPort(lnk, dest_port);
982                         SetProxyAddress(lnk, dest_address);
983                         ProxyModify(la, lnk, pip, maxpacketsize, proxy_type);
984                         tc = (struct tcphdr *)ip_next(pip);
985                 }
986 /* Get alias address and port */
987                 alias_port = GetAliasPort(lnk);
988                 alias_address = GetAliasAddress(lnk);
989
990 /* Monitor TCP connection state */
991                 TcpMonitorOut(pip, lnk);
992
993 /* Special processing for IP encoding protocols */
994                 if (ntohs(tc->th_dport) == FTP_CONTROL_PORT_NUMBER
995                     || ntohs(tc->th_sport) == FTP_CONTROL_PORT_NUMBER)
996                         AliasHandleFtpOut(la, pip, lnk, maxpacketsize);
997                 else if (ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_1
998                     || ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_2)
999                         AliasHandleIrcOut(la, pip, lnk, maxpacketsize);
1000                 else if (ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_1
1001                             || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_1
1002                             || ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_2
1003                     || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_2)
1004                         AliasHandleRtspOut(la, pip, lnk, maxpacketsize);
1005                 else if (ntohs(tc->th_dport) == PPTP_CONTROL_PORT_NUMBER
1006                     || ntohs(tc->th_sport) == PPTP_CONTROL_PORT_NUMBER)
1007                         AliasHandlePptpOut(la, pip, lnk);
1008                 else if (la->skinnyPort != 0 && (ntohs(tc->th_sport) == la->skinnyPort
1009                     || ntohs(tc->th_dport) == la->skinnyPort))
1010                         AliasHandleSkinny(la, pip, lnk);
1011
1012 /* Adjust TCP checksum since source port is being aliased */
1013 /* and source address is being altered                    */
1014                 accumulate = tc->th_sport;
1015                 tc->th_sport = alias_port;
1016                 accumulate -= tc->th_sport;
1017                 accumulate += twowords(&pip->ip_src);
1018                 accumulate -= twowords(&alias_address);
1019
1020 /* Modify sequence number if necessary */
1021                 if (GetAckModified(lnk) == 1) {
1022                         int delta;
1023
1024                         delta = GetDeltaSeqOut(pip, lnk);
1025                         if (delta != 0) {
1026                                 accumulate += twowords(&tc->th_seq);
1027                                 tc->th_seq = htonl(ntohl(tc->th_seq) + delta);
1028                                 accumulate -= twowords(&tc->th_seq);
1029                         }
1030                 }
1031                 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1032
1033 /* Change source address */
1034                 accumulate = twowords(&pip->ip_src);
1035                 pip->ip_src = alias_address;
1036                 accumulate -= twowords(&pip->ip_src);
1037                 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
1038
1039                 return (PKT_ALIAS_OK);
1040         }
1041         return (PKT_ALIAS_IGNORED);
1042 }
1043
1044
1045
1046
1047 /* Fragment Handling
1048
1049     FragmentIn()
1050     FragmentOut()
1051
1052 The packet aliasing module has a limited ability for handling IP
1053 fragments.  If the ICMP, TCP or UDP header is in the first fragment
1054 received, then the ID number of the IP packet is saved, and other
1055 fragments are identified according to their ID number and IP address
1056 they were sent from.  Pointers to unresolved fragments can also be
1057 saved and recalled when a header fragment is seen.
1058 */
1059
1060 /* Local prototypes */
1061 static int      FragmentIn(struct libalias *, struct ip *);
1062 static int      FragmentOut(struct libalias *, struct ip *);
1063
1064
1065 static int
1066 FragmentIn(struct libalias *la, struct ip *pip)
1067 {
1068         struct alias_link *lnk;
1069
1070         lnk = FindFragmentIn2(la, pip->ip_src, pip->ip_dst, pip->ip_id);
1071         if (lnk != NULL) {
1072                 struct in_addr original_address;
1073
1074                 GetFragmentAddr(lnk, &original_address);
1075                 DifferentialChecksum(&pip->ip_sum,
1076                     &original_address, &pip->ip_dst, 2);
1077                 pip->ip_dst = original_address;
1078
1079                 return (PKT_ALIAS_OK);
1080         }
1081         return (PKT_ALIAS_UNRESOLVED_FRAGMENT);
1082 }
1083
1084
1085 static int
1086 FragmentOut(struct libalias *la, struct ip *pip)
1087 {
1088         struct in_addr alias_address;
1089
1090         alias_address = FindAliasAddress(la, pip->ip_src);
1091         DifferentialChecksum(&pip->ip_sum,
1092             &alias_address, &pip->ip_src, 2);
1093         pip->ip_src = alias_address;
1094
1095         return (PKT_ALIAS_OK);
1096 }
1097
1098
1099
1100
1101
1102
1103 /* Outside World Access
1104
1105         PacketAliasSaveFragment()
1106         PacketAliasGetFragment()
1107         PacketAliasFragmentIn()
1108         PacketAliasIn()
1109         PacketAliasOut()
1110         PacketUnaliasOut()
1111
1112 (prototypes in alias.h)
1113 */
1114
1115
1116 int
1117 LibAliasSaveFragment(struct libalias *la, char *ptr)
1118 {
1119         int iresult;
1120         struct alias_link *lnk;
1121         struct ip *pip;
1122
1123         pip = (struct ip *)ptr;
1124         lnk = AddFragmentPtrLink(la, pip->ip_src, pip->ip_id);
1125         iresult = PKT_ALIAS_ERROR;
1126         if (lnk != NULL) {
1127                 SetFragmentPtr(lnk, ptr);
1128                 iresult = PKT_ALIAS_OK;
1129         }
1130         return (iresult);
1131 }
1132
1133
1134 char           *
1135 LibAliasGetFragment(struct libalias *la, char *ptr)
1136 {
1137         struct alias_link *lnk;
1138         char *fptr;
1139         struct ip *pip;
1140
1141         pip = (struct ip *)ptr;
1142         lnk = FindFragmentPtr(la, pip->ip_src, pip->ip_id);
1143         if (lnk != NULL) {
1144                 GetFragmentPtr(lnk, &fptr);
1145                 SetFragmentPtr(lnk, NULL);
1146                 SetExpire(lnk, 0);      /* Deletes link */
1147
1148                 return (fptr);
1149         } else {
1150                 return (NULL);
1151         }
1152 }
1153
1154
1155 void
1156 LibAliasFragmentIn(struct libalias *la, char *ptr,      /* Points to correctly
1157                                                          * de-aliased header
1158                                                          * fragment */
1159     char *ptr_fragment          /* Points to fragment which must be
1160                                  * de-aliased   */
1161 )
1162 {
1163         struct ip *pip;
1164         struct ip *fpip;
1165
1166         (void)la;
1167         pip = (struct ip *)ptr;
1168         fpip = (struct ip *)ptr_fragment;
1169
1170         DifferentialChecksum(&fpip->ip_sum,
1171             &pip->ip_dst, &fpip->ip_dst, 2);
1172         fpip->ip_dst = pip->ip_dst;
1173 }
1174
1175
1176 int
1177 LibAliasIn(struct libalias *la, char *ptr, int maxpacketsize)
1178 {
1179         struct in_addr alias_addr;
1180         struct ip *pip;
1181         int iresult;
1182
1183         if (la->packetAliasMode & PKT_ALIAS_REVERSE) {
1184                 la->packetAliasMode &= ~PKT_ALIAS_REVERSE;
1185                 iresult = LibAliasOut(la, ptr, maxpacketsize);
1186                 la->packetAliasMode |= PKT_ALIAS_REVERSE;
1187                 return (iresult);
1188         }
1189         HouseKeeping(la);
1190         ClearCheckNewLink(la);
1191         pip = (struct ip *)ptr;
1192         alias_addr = pip->ip_dst;
1193
1194         /* Defense against mangled packets */
1195         if (ntohs(pip->ip_len) > maxpacketsize
1196             || (pip->ip_hl << 2) > maxpacketsize)
1197                 return (PKT_ALIAS_IGNORED);
1198
1199         iresult = PKT_ALIAS_IGNORED;
1200         if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) {
1201                 switch (pip->ip_p) {
1202                 case IPPROTO_ICMP:
1203                         iresult = IcmpAliasIn(la, pip);
1204                         break;
1205                 case IPPROTO_UDP:
1206                         iresult = UdpAliasIn(la, pip);
1207                         break;
1208                 case IPPROTO_TCP:
1209                         iresult = TcpAliasIn(la, pip);
1210                         break;
1211                 case IPPROTO_GRE:
1212                         if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY ||
1213                             AliasHandlePptpGreIn(la, pip) == 0)
1214                                 iresult = PKT_ALIAS_OK;
1215                         else
1216                                 iresult = ProtoAliasIn(la, pip);
1217                         break;
1218                 default:
1219                         iresult = ProtoAliasIn(la, pip);
1220                         break;
1221                 }
1222
1223                 if (ntohs(pip->ip_off) & IP_MF) {
1224                         struct alias_link *lnk;
1225
1226                         lnk = FindFragmentIn1(la, pip->ip_src, alias_addr, pip->ip_id);
1227                         if (lnk != NULL) {
1228                                 iresult = PKT_ALIAS_FOUND_HEADER_FRAGMENT;
1229                                 SetFragmentAddr(lnk, pip->ip_dst);
1230                         } else {
1231                                 iresult = PKT_ALIAS_ERROR;
1232                         }
1233                 }
1234         } else {
1235                 iresult = FragmentIn(la, pip);
1236         }
1237
1238         return (iresult);
1239 }
1240
1241
1242
1243 /* Unregistered address ranges */
1244
1245 /* 10.0.0.0   ->   10.255.255.255 */
1246 #define UNREG_ADDR_A_LOWER 0x0a000000
1247 #define UNREG_ADDR_A_UPPER 0x0affffff
1248
1249 /* 172.16.0.0  ->  172.31.255.255 */
1250 #define UNREG_ADDR_B_LOWER 0xac100000
1251 #define UNREG_ADDR_B_UPPER 0xac1fffff
1252
1253 /* 192.168.0.0 -> 192.168.255.255 */
1254 #define UNREG_ADDR_C_LOWER 0xc0a80000
1255 #define UNREG_ADDR_C_UPPER 0xc0a8ffff
1256
1257 int
1258 LibAliasOut(struct libalias *la, char *ptr,     /* valid IP packet */
1259     int maxpacketsize           /* How much the packet data may grow (FTP
1260                                  * and IRC inline changes) */
1261 )
1262 {
1263         return (LibAliasOutTry(la, ptr, maxpacketsize, 1));
1264 }
1265
1266 int
1267 LibAliasOutTry(struct libalias *la, char *ptr,  /* valid IP packet */
1268     int maxpacketsize,          /* How much the packet data may grow (FTP
1269                                  * and IRC inline changes) */
1270     int create                  /* Create new entries ? */
1271 )
1272 {
1273         int iresult;
1274         struct in_addr addr_save;
1275         struct ip *pip;
1276
1277         if (la->packetAliasMode & PKT_ALIAS_REVERSE) {
1278                 la->packetAliasMode &= ~PKT_ALIAS_REVERSE;
1279                 iresult = LibAliasIn(la, ptr, maxpacketsize);
1280                 la->packetAliasMode |= PKT_ALIAS_REVERSE;
1281                 return (iresult);
1282         }
1283         HouseKeeping(la);
1284         ClearCheckNewLink(la);
1285         pip = (struct ip *)ptr;
1286
1287         /* Defense against mangled packets */
1288         if (ntohs(pip->ip_len) > maxpacketsize
1289             || (pip->ip_hl << 2) > maxpacketsize)
1290                 return (PKT_ALIAS_IGNORED);
1291
1292         addr_save = GetDefaultAliasAddress(la);
1293         if (la->packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY) {
1294                 u_long addr;
1295                 int iclass;
1296
1297                 iclass = 0;
1298                 addr = ntohl(pip->ip_src.s_addr);
1299                 if (addr >= UNREG_ADDR_C_LOWER && addr <= UNREG_ADDR_C_UPPER)
1300                         iclass = 3;
1301                 else if (addr >= UNREG_ADDR_B_LOWER && addr <= UNREG_ADDR_B_UPPER)
1302                         iclass = 2;
1303                 else if (addr >= UNREG_ADDR_A_LOWER && addr <= UNREG_ADDR_A_UPPER)
1304                         iclass = 1;
1305
1306                 if (iclass == 0) {
1307                         SetDefaultAliasAddress(la, pip->ip_src);
1308                 }
1309         } else if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY) {
1310                 SetDefaultAliasAddress(la, pip->ip_src);
1311         }
1312         iresult = PKT_ALIAS_IGNORED;
1313         if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) {
1314                 switch (pip->ip_p) {
1315                 case IPPROTO_ICMP:
1316                         iresult = IcmpAliasOut(la, pip, create);
1317                         break;
1318                 case IPPROTO_UDP:
1319                         iresult = UdpAliasOut(la, pip, create);
1320                         break;
1321                         case IPPROTO_TCP:
1322                         iresult = TcpAliasOut(la, pip, maxpacketsize, create);
1323                         break;
1324                 case IPPROTO_GRE:
1325                         if (AliasHandlePptpGreOut(la, pip) == 0)
1326                                 iresult = PKT_ALIAS_OK;
1327                         else
1328                                 iresult = ProtoAliasOut(la, pip, create);
1329                         break;
1330                 default:
1331                         iresult = ProtoAliasOut(la, pip, create);
1332                         break;
1333                 }
1334         } else {
1335                 iresult = FragmentOut(la, pip);
1336         }
1337
1338         SetDefaultAliasAddress(la, addr_save);
1339         return (iresult);
1340 }
1341
1342 int
1343 LibAliasUnaliasOut(struct libalias *la, char *ptr,      /* valid IP packet */
1344     int maxpacketsize           /* for error checking */
1345 )
1346 {
1347         struct ip *pip;
1348         struct icmp *ic;
1349         struct udphdr *ud;
1350         struct tcphdr *tc;
1351         struct alias_link *lnk;
1352         int iresult = PKT_ALIAS_IGNORED;
1353
1354         pip = (struct ip *)ptr;
1355
1356         /* Defense against mangled packets */
1357         if (ntohs(pip->ip_len) > maxpacketsize
1358             || (pip->ip_hl << 2) > maxpacketsize)
1359                 return (iresult);
1360
1361         ud = (struct udphdr *)ip_next(pip);
1362         tc = (struct tcphdr *)ip_next(pip);
1363         ic = (struct icmp *)ip_next(pip);
1364
1365         /* Find a link */
1366         if (pip->ip_p == IPPROTO_UDP)
1367                 lnk = FindUdpTcpIn(la, pip->ip_dst, pip->ip_src,
1368                     ud->uh_dport, ud->uh_sport,
1369                     IPPROTO_UDP, 0);
1370         else if (pip->ip_p == IPPROTO_TCP)
1371                 lnk = FindUdpTcpIn(la, pip->ip_dst, pip->ip_src,
1372                     tc->th_dport, tc->th_sport,
1373                     IPPROTO_TCP, 0);
1374         else if (pip->ip_p == IPPROTO_ICMP)
1375                 lnk = FindIcmpIn(la, pip->ip_dst, pip->ip_src, ic->icmp_id, 0);
1376         else
1377                 lnk = NULL;
1378
1379         /* Change it from an aliased packet to an unaliased packet */
1380         if (lnk != NULL) {
1381                 if (pip->ip_p == IPPROTO_UDP || pip->ip_p == IPPROTO_TCP) {
1382                         int accumulate;
1383                         struct in_addr original_address;
1384                         u_short original_port;
1385
1386                         original_address = GetOriginalAddress(lnk);
1387                         original_port = GetOriginalPort(lnk);
1388
1389                         /* Adjust TCP/UDP checksum */
1390                         accumulate = twowords(&pip->ip_src);
1391                         accumulate -= twowords(&original_address);
1392
1393                         if (pip->ip_p == IPPROTO_UDP) {
1394                                 accumulate += ud->uh_sport;
1395                                 accumulate -= original_port;
1396                                 ADJUST_CHECKSUM(accumulate, ud->uh_sum);
1397                         } else {
1398                                 accumulate += tc->th_sport;
1399                                 accumulate -= original_port;
1400                                 ADJUST_CHECKSUM(accumulate, tc->th_sum);
1401                         }
1402
1403                         /* Adjust IP checksum */
1404                         DifferentialChecksum(&pip->ip_sum,
1405                             &original_address, &pip->ip_src, 2);
1406
1407                         /* Un-alias source address and port number */
1408                         pip->ip_src = original_address;
1409                         if (pip->ip_p == IPPROTO_UDP)
1410                                 ud->uh_sport = original_port;
1411                         else
1412                                 tc->th_sport = original_port;
1413
1414                         iresult = PKT_ALIAS_OK;
1415
1416                 } else if (pip->ip_p == IPPROTO_ICMP) {
1417
1418                         int accumulate;
1419                         struct in_addr original_address;
1420                         u_short original_id;
1421
1422                         original_address = GetOriginalAddress(lnk);
1423                         original_id = GetOriginalPort(lnk);
1424
1425                         /* Adjust ICMP checksum */
1426                         accumulate = twowords(&pip->ip_src);
1427                         accumulate -= twowords(&original_address);
1428                         accumulate += ic->icmp_id;
1429                         accumulate -= original_id;
1430                         ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
1431
1432                         /* Adjust IP checksum */
1433                         DifferentialChecksum(&pip->ip_sum,
1434                             &original_address, &pip->ip_src, 2);
1435
1436                         /* Un-alias source address and port number */
1437                         pip->ip_src = original_address;
1438                         ic->icmp_id = original_id;
1439
1440                         iresult = PKT_ALIAS_OK;
1441                 }
1442         }
1443         return (iresult);
1444
1445 }