00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
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
00060
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);
00076 void fixtcpudpcksum(ip*, int);
00077 virtual void fixtsum(ip*, int) { };
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
00146
00147
00148
00149
00150 hdr_ip* iph = hdr_ip::access(pkt);
00151 iph->src() = here_;
00152 iph->dst() = dst_;
00153 send(pkt, 0);
00154 }
00155
00156
00157
00158
00159
00160 void
00161 NatAgent::fixipcksum(ip* iph, int iphlen)
00162 {
00163
00164 iph->ip_sum = 0;
00165 iph->ip_sum = Internet::in_cksum((u_short*) iph, iphlen);
00166 return;
00167 }
00168
00169
00170
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);
00186 rewrite_addr(iph);
00187 fixipcksum(iph, iphlen);
00188 }
00189
00190
00191
00192
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
00226
00227
00228
00229
00230
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
00238
00239
00240 u_long nsum;
00241 nsum = ~sum & 0xffff;
00242 nsum += ~oldval(iph) & 0xffff;
00243 nsum += newval();
00244
00245 nsum = (nsum >> 16) + (nsum & 0xffff);
00246 nsum += (nsum >> 16);
00247 sum = ~nsum;
00248 tcph->th_sum = sum & 0xffff;
00249
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
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
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
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
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
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 }