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