nat.cc

Go to the documentation of this file.
00001 /*    
00002  * Copyright (c) 1998 Regents of the University of California.
00003  * All rights reserved.
00004  *    
00005  * Redistribution and use in source and binary forms, with or without 
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. All advertising materials mentioning features or use of this software
00014  *    must display the following acknowledgement:
00015  *      This product includes software developed by the Network Research
00016  *      Group at Lawrence Berkeley National Laboratory.
00017  * 4. Neither the name of the University nor of the Laboratory may be used
00018  *    to endorse or promote products derived from this software without
00019  *    specific prior written permission.
00020  *   
00021  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00022  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00023  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00024  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00025  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00026  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00027  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
00028  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
00029  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00030  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
00031  * SUCH DAMAGE.
00032  */  
00033 
00034 #ifndef lint
00035 static const char rcsid[] =
00036     "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/emulate/nat.cc,v 1.9 2002/05/22 18:57:10 johnh Exp $";
00037 #endif
00038 
00039 #include <stdio.h>
00040 #include <sys/types.h>
00041 #include <netinet/in.h>
00042 #include <netinet/in_systm.h>
00043 #include <netinet/ip.h>
00044 
00045 #ifndef __FAVOR_BSD
00046 #define __FAVOR_BSD
00047 #endif
00048 #include <netinet/tcp.h>
00049 #include <arpa/inet.h>
00050 
00051 #include "agent.h"
00052 #include "scheduler.h"
00053 #include "packet.h"
00054 #include "ip.h"
00055 #include "emulate/net.h"
00056 #include "emulate/internet.h"
00057 
00058 //
00059 // Nat -- a limited-functionality TCP address rewriting
00060 // facility for emulation mode.
00061 // 
00062 
00063 class NatAgent : public Agent {
00064 public:
00065     NatAgent() : Agent(PT_LIVE) { }
00066     void recv(Packet*, Handler*);
00067 protected:
00068     virtual void    rewrite_addr(ip*) = 0;
00069     u_short     addrsum(in_addr*);
00070     u_short     addrsum(in_addr*, in_addr*);
00071     void    nat(Packet*);
00072     virtual u_short newval() = 0;
00073     virtual u_short oldval(ip*) = 0;
00074 
00075     void    fixipcksum(ip*, int);       // ip only
00076     void    fixtcpudpcksum(ip*, int);   // tcp,udp/ip
00077     virtual void    fixtsum(ip*, int) { };  // any transport
00078 
00079     int command(int argc, const char*const* argv);
00080 };
00081 
00082 class TCPDestNat : public virtual NatAgent {
00083 protected:
00084     void    rewrite_addr(ip*);
00085     void    fixtsum(ip* iph, int hlen) {
00086         fixtcpudpcksum(iph, hlen);
00087     }
00088     u_short newval();
00089     u_short oldval(ip*);
00090     int command(int argc, const char*const* argv);
00091     in_addr newdst_;
00092 };
00093 
00094 class TCPSrcNat : public virtual NatAgent {
00095 protected:
00096     void    rewrite_addr(ip*);
00097     void    fixtsum(ip* iph, int hlen) {
00098         fixtcpudpcksum(iph, hlen);
00099     }
00100     u_short newval();
00101     u_short oldval(ip*);
00102     int command(int argc, const char*const* argv);
00103     in_addr newsrc_;
00104 };
00105 
00106 class TCPSrcDestNat : public TCPDestNat, public TCPSrcNat {
00107 protected:
00108     void    rewrite_addr(ip*);
00109     u_short newval();
00110     u_short oldval(ip*);
00111     void    fixtsum(ip* iph, int hlen) {
00112         fixtcpudpcksum(iph, hlen);
00113     }
00114     int command(int argc, const char*const* argv);
00115 };
00116 
00117 static class NatTCPSrcAgentClass : public TclClass { 
00118 public:
00119         NatTCPSrcAgentClass() : TclClass("Agent/NatAgent/TCPSrc") {}
00120         TclObject* create(int , const char*const*) {
00121                 return (new TCPSrcNat());
00122         } 
00123 } class_tcpsrcnat;
00124 
00125 static class NatTCPDestAgentClass : public TclClass { 
00126 public:
00127         NatTCPDestAgentClass() : TclClass("Agent/NatAgent/TCPDest") {}
00128         TclObject* create(int , const char*const*) {
00129                 return (new TCPDestNat());
00130         } 
00131 } class_tcpdstnat;
00132 
00133 static class NatTCPSrcDestAgentClass : public TclClass { 
00134 public:
00135         NatTCPSrcDestAgentClass() : TclClass("Agent/NatAgent/TCPSrcDest") {}
00136         TclObject* create(int , const char*const*) {
00137                 return (new TCPSrcDestNat());
00138         } 
00139 } class_tcpsrcdstnat;
00140 
00141 void
00142 NatAgent::recv(Packet *pkt, Handler *)
00143 {
00144     nat(pkt);
00145     // we are merely rewriting an already-existing
00146     // packet (which was destined for us), so be
00147     // sure to rewrite the simulator's notion of the
00148     // address, otherwise we just keep sending to ourselves
00149     // (ouch).
00150     hdr_ip* iph = hdr_ip::access(pkt);
00151     iph->src() = here_;
00152     iph->dst() = dst_;
00153     send(pkt, 0);
00154 }
00155 
00156 /*
00157  * NatAgent base class: fix only IP-layer checksums
00158  */
00159 
00160 void
00161 NatAgent::fixipcksum(ip* iph, int iphlen)
00162 {
00163     // fix IP cksum
00164     iph->ip_sum = 0;
00165     iph->ip_sum = Internet::in_cksum((u_short*) iph, iphlen);
00166     return;
00167 }
00168 
00169 /*
00170  * rewrite packet addresses, calls object-specific rewrite_addr() function
00171  */
00172 
00173 void
00174 NatAgent::nat(Packet* pkt)
00175 {
00176         hdr_cmn* hc = HDR_CMN(pkt);
00177         ip* iph = (ip*) pkt->accessdata();
00178     if (pkt->datalen() < hc->size()) {
00179         fprintf(stderr,
00180             "NatAgent(%s): recvd packet with pkt sz %d but bsize %d\n",
00181             name(), hc->size(), pkt->datalen());
00182         return;
00183     }
00184     int iphlen = (((u_char*)iph)[0] & 0x0f) << 2;
00185     fixtcpudpcksum(iph, iphlen);    // requires orig header!
00186     rewrite_addr(iph);
00187     fixipcksum(iph, iphlen);
00188 }
00189 
00190 /*
00191  * functions to compute 1's complement sum of 1 and 2 IP addresses
00192  * (note: only the sum, not the complement of the sum)
00193  */
00194 u_short
00195 NatAgent::addrsum(in_addr* ia)
00196 {
00197     u_short* p = (u_short*) ia;
00198     u_short sum = 0;
00199 
00200     sum += *p++;
00201     sum += *p;
00202     sum = (sum >> 16) + (sum & 0xffff);
00203     sum += (sum >> 16);
00204     return (sum);
00205 }
00206 
00207 u_short
00208 NatAgent::addrsum(in_addr* ia1, in_addr* ia2)
00209 {
00210     u_short* p = (u_short*) ia1;
00211     u_short sum = 0;
00212 
00213     sum += *p++;
00214     sum += *p;
00215 
00216     p = (u_short*) ia2;
00217     sum += *p++;
00218     sum += *p;
00219     sum = (sum >> 16) + (sum & 0xffff);
00220     sum += (sum >> 16);
00221     return (sum);
00222 }
00223 
00224 /*
00225  * incrementally update tcp or udp packet for new addresses:
00226  *  rewrite IP addresses and recompute IP header cksum
00227  *  recompute TCP or UDP pseudoheader checksum
00228  *
00229  * note: this code is tricky because of the masking.
00230  * Please do not modify without careful testing.
00231  */
00232 void
00233 NatAgent::fixtcpudpcksum(ip* iph, int iphlen)
00234 {
00235     tcphdr* tcph = (tcphdr*)(((u_char*) iph) + iphlen);
00236     u_short sum = tcph->th_sum;
00237 //printf("isum: 0x%x\n", sum & 0xffff);
00238 //printf("oval: 0x%x, nval: 0x%x\n",
00239 //~oldval(iph) & 0xffff, newval());
00240     u_long nsum;
00241     nsum = ~sum & 0xffff;
00242     nsum += ~oldval(iph) & 0xffff;
00243     nsum += newval();
00244 //printf("nsum2: 0x%x\n", nsum);
00245     nsum = (nsum >> 16) + (nsum & 0xffff);
00246     nsum += (nsum >> 16);
00247     sum = ~nsum;
00248     tcph->th_sum = sum & 0xffff;
00249 //printf("fsum: 0x%hx\n", tcph->th_sum);
00250     return;
00251 }
00252 
00253 
00254 void
00255 TCPSrcNat::rewrite_addr(ip* iph)
00256 {
00257     iph->ip_src = newsrc_;
00258 }
00259 
00260 u_short
00261 TCPSrcNat::newval()
00262 {
00263     return (addrsum(&newsrc_));
00264 }
00265 
00266 u_short
00267 TCPSrcNat::oldval(ip* iph)
00268 {
00269     return (addrsum(&iph->ip_src));
00270 }
00271 
00272 u_short
00273 TCPDestNat::newval()
00274 {
00275     return (addrsum(&newdst_));
00276 }
00277 
00278 u_short
00279 TCPDestNat::oldval(ip* iph)
00280 {
00281     return (addrsum(&iph->ip_dst));
00282 }
00283 
00284 void
00285 TCPDestNat::rewrite_addr(ip* iph)
00286 {
00287     iph->ip_dst = newdst_;
00288 }
00289 
00290 void
00291 TCPSrcDestNat::rewrite_addr(ip* iph)
00292 {
00293     TCPSrcNat::rewrite_addr(iph);
00294     TCPDestNat::rewrite_addr(iph);
00295 }
00296 
00297 u_short
00298 TCPSrcDestNat::newval()
00299 {
00300     return(addrsum(&newsrc_, &newdst_));
00301 }
00302 
00303 u_short
00304 TCPSrcDestNat::oldval(ip* iph)
00305 {
00306 //printf("oldval:%hx\n", addrsum(&iph->ip_src, &iph->ip_dst));
00307     return(addrsum(&iph->ip_src, &iph->ip_dst));
00308 }
00309 
00310 int
00311 NatAgent::command(int argc, const char*const* argv)
00312 {
00313     return(Agent::command(argc, argv));
00314 }
00315 
00316 int
00317 TCPSrcNat::command(int argc, const char*const* argv)
00318 {
00319     // $srcnat source <ipaddr>
00320     if (argc == 3) {
00321         if (strcmp(argv[1], "source") == 0) {
00322             u_long ns;
00323             ns = inet_addr(argv[2]);
00324             newsrc_.s_addr = ns;
00325             return (TCL_OK);
00326         }
00327     }
00328 
00329     return (NatAgent::command(argc, argv));
00330 }
00331 
00332 int
00333 TCPDestNat::command(int argc, const char*const* argv)
00334 {
00335     // $srcnat destination <ipaddr>
00336     if (argc == 3) {
00337         if (strcmp(argv[1], "destination") == 0) {
00338             u_long nd;
00339             nd = inet_addr(argv[2]);
00340             newdst_.s_addr = nd;
00341             return (TCL_OK);
00342         }
00343     }
00344     return (NatAgent::command(argc, argv));
00345 }
00346 
00347 int
00348 TCPSrcDestNat::command(int argc, const char*const* argv)
00349 {
00350     // $srcnat source <ipaddr>
00351     if (argc == 3) {
00352         if (strcmp(argv[1], "source") == 0) {
00353             u_long ns;
00354             ns = inet_addr(argv[2]);
00355             newsrc_.s_addr = ns;
00356             return (TCL_OK);
00357         }
00358     }
00359 
00360     // $srcnat destination <ipaddr>
00361     if (argc == 3) {
00362         if (strcmp(argv[1], "destination") == 0) {
00363             u_long nd;
00364             nd = inet_addr(argv[2]);
00365             newdst_.s_addr = nd;
00366             return (TCL_OK);
00367         }
00368     }
00369 
00370     return (NatAgent::command(argc, argv));
00371 }

Generated on Tue Mar 6 16:47:47 2007 for ns2 Network Simulator 2.29 by  doxygen 1.4.6