nat.cc
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:9k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /*    
  2.  * Copyright (c) 1998 Regents of the University of California.
  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.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *      This product includes software developed by the Network Research
  16.  *      Group at Lawrence Berkeley National Laboratory.
  17.  * 4. Neither the name of the University nor of the Laboratory may be used
  18.  *    to endorse or promote products derived from this software without
  19.  *    specific prior written permission.
  20.  *   
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
  31.  * SUCH DAMAGE.
  32.  */  
  33. #ifndef lint
  34. static const char rcsid[] =
  35.     "@(#) $Header: /cvsroot/nsnam/ns-2/emulate/nat.cc,v 1.9 2002/05/22 18:57:10 johnh Exp $";
  36. #endif
  37. #include <stdio.h>
  38. #include <sys/types.h>
  39. #include <netinet/in.h>
  40. #include <netinet/in_systm.h>
  41. #include <netinet/ip.h>
  42. #ifndef __FAVOR_BSD
  43. #define __FAVOR_BSD
  44. #endif
  45. #include <netinet/tcp.h>
  46. #include <arpa/inet.h>
  47. #include "agent.h"
  48. #include "scheduler.h"
  49. #include "packet.h"
  50. #include "ip.h"
  51. #include "emulate/net.h"
  52. #include "emulate/internet.h"
  53. //
  54. // Nat -- a limited-functionality TCP address rewriting
  55. // facility for emulation mode.
  56. // 
  57. class NatAgent : public Agent {
  58. public:
  59. NatAgent() : Agent(PT_LIVE) { }
  60. void recv(Packet*, Handler*);
  61. protected:
  62. virtual void rewrite_addr(ip*) = 0;
  63. u_short addrsum(in_addr*);
  64. u_short addrsum(in_addr*, in_addr*);
  65. void nat(Packet*);
  66. virtual u_short newval() = 0;
  67. virtual u_short oldval(ip*) = 0;
  68. void fixipcksum(ip*, int); // ip only
  69. void fixtcpudpcksum(ip*, int); // tcp,udp/ip
  70. virtual void fixtsum(ip*, int) { }; // any transport
  71. int command(int argc, const char*const* argv);
  72. };
  73. class TCPDestNat : public virtual NatAgent {
  74. protected:
  75. void rewrite_addr(ip*);
  76. void fixtsum(ip* iph, int hlen) {
  77. fixtcpudpcksum(iph, hlen);
  78. }
  79. u_short newval();
  80. u_short oldval(ip*);
  81. int command(int argc, const char*const* argv);
  82. in_addr newdst_;
  83. };
  84. class TCPSrcNat : public virtual NatAgent {
  85. protected:
  86. void rewrite_addr(ip*);
  87. void fixtsum(ip* iph, int hlen) {
  88. fixtcpudpcksum(iph, hlen);
  89. }
  90. u_short newval();
  91. u_short oldval(ip*);
  92. int command(int argc, const char*const* argv);
  93. in_addr newsrc_;
  94. };
  95. class TCPSrcDestNat : public TCPDestNat, public TCPSrcNat {
  96. protected:
  97. void rewrite_addr(ip*);
  98. u_short newval();
  99. u_short oldval(ip*);
  100. void fixtsum(ip* iph, int hlen) {
  101. fixtcpudpcksum(iph, hlen);
  102. }
  103. int command(int argc, const char*const* argv);
  104. };
  105. static class NatTCPSrcAgentClass : public TclClass { 
  106. public:
  107.         NatTCPSrcAgentClass() : TclClass("Agent/NatAgent/TCPSrc") {}
  108.         TclObject* create(int , const char*const*) {
  109.                 return (new TCPSrcNat());
  110.         } 
  111. } class_tcpsrcnat;
  112. static class NatTCPDestAgentClass : public TclClass { 
  113. public:
  114.         NatTCPDestAgentClass() : TclClass("Agent/NatAgent/TCPDest") {}
  115.         TclObject* create(int , const char*const*) {
  116.                 return (new TCPDestNat());
  117.         } 
  118. } class_tcpdstnat;
  119. static class NatTCPSrcDestAgentClass : public TclClass { 
  120. public:
  121.         NatTCPSrcDestAgentClass() : TclClass("Agent/NatAgent/TCPSrcDest") {}
  122.         TclObject* create(int , const char*const*) {
  123.                 return (new TCPSrcDestNat());
  124.         } 
  125. } class_tcpsrcdstnat;
  126. void
  127. NatAgent::recv(Packet *pkt, Handler *)
  128. {
  129. nat(pkt);
  130. // we are merely rewriting an already-existing
  131. // packet (which was destined for us), so be
  132. // sure to rewrite the simulator's notion of the
  133. // address, otherwise we just keep sending to ourselves
  134. // (ouch).
  135. hdr_ip* iph = hdr_ip::access(pkt);
  136. iph->src() = here_;
  137. iph->dst() = dst_;
  138. send(pkt, 0);
  139. }
  140. /*
  141.  * NatAgent base class: fix only IP-layer checksums
  142.  */
  143. void
  144. NatAgent::fixipcksum(ip* iph, int iphlen)
  145. {
  146. // fix IP cksum
  147. iph->ip_sum = 0;
  148. iph->ip_sum = Internet::in_cksum((u_short*) iph, iphlen);
  149. return;
  150. }
  151. /*
  152.  * rewrite packet addresses, calls object-specific rewrite_addr() function
  153.  */
  154. void
  155. NatAgent::nat(Packet* pkt)
  156. {
  157.         hdr_cmn* hc = HDR_CMN(pkt);
  158.         ip* iph = (ip*) pkt->accessdata();
  159. if (pkt->datalen() < hc->size()) {
  160. fprintf(stderr,
  161.     "NatAgent(%s): recvd packet with pkt sz %d but bsize %dn",
  162. name(), hc->size(), pkt->datalen());
  163. return;
  164. }
  165. int iphlen = (((u_char*)iph)[0] & 0x0f) << 2;
  166. fixtcpudpcksum(iph, iphlen); // requires orig header!
  167. rewrite_addr(iph);
  168. fixipcksum(iph, iphlen);
  169. }
  170. /*
  171.  * functions to compute 1's complement sum of 1 and 2 IP addresses
  172.  * (note: only the sum, not the complement of the sum)
  173.  */
  174. u_short
  175. NatAgent::addrsum(in_addr* ia)
  176. {
  177. u_short* p = (u_short*) ia;
  178. u_short sum = 0;
  179. sum += *p++;
  180. sum += *p;
  181. sum = (sum >> 16) + (sum & 0xffff);
  182. sum += (sum >> 16);
  183. return (sum);
  184. }
  185. u_short
  186. NatAgent::addrsum(in_addr* ia1, in_addr* ia2)
  187. {
  188. u_short* p = (u_short*) ia1;
  189. u_short sum = 0;
  190. sum += *p++;
  191. sum += *p;
  192. p = (u_short*) ia2;
  193. sum += *p++;
  194. sum += *p;
  195. sum = (sum >> 16) + (sum & 0xffff);
  196. sum += (sum >> 16);
  197. return (sum);
  198. }
  199. /*
  200.  * incrementally update tcp or udp packet for new addresses:
  201.  * rewrite IP addresses and recompute IP header cksum
  202.  * recompute TCP or UDP pseudoheader checksum
  203.  *
  204.  * note: this code is tricky because of the masking.
  205.  * Please do not modify without careful testing.
  206.  */
  207. void
  208. NatAgent::fixtcpudpcksum(ip* iph, int iphlen)
  209. {
  210. tcphdr* tcph = (tcphdr*)(((u_char*) iph) + iphlen);
  211. u_short sum = tcph->th_sum;
  212. //printf("isum: 0x%xn", sum & 0xffff);
  213. //printf("oval: 0x%x, nval: 0x%xn",
  214. //~oldval(iph) & 0xffff, newval());
  215. u_long nsum;
  216. nsum = ~sum & 0xffff;
  217. nsum += ~oldval(iph) & 0xffff;
  218. nsum += newval();
  219. //printf("nsum2: 0x%xn", nsum);
  220. nsum = (nsum >> 16) + (nsum & 0xffff);
  221. nsum += (nsum >> 16);
  222. sum = ~nsum;
  223. tcph->th_sum = sum & 0xffff;
  224. //printf("fsum: 0x%hxn", tcph->th_sum);
  225. return;
  226. }
  227. void
  228. TCPSrcNat::rewrite_addr(ip* iph)
  229. {
  230. iph->ip_src = newsrc_;
  231. }
  232. u_short
  233. TCPSrcNat::newval()
  234. {
  235. return (addrsum(&newsrc_));
  236. }
  237. u_short
  238. TCPSrcNat::oldval(ip* iph)
  239. {
  240. return (addrsum(&iph->ip_src));
  241. }
  242. u_short
  243. TCPDestNat::newval()
  244. {
  245. return (addrsum(&newdst_));
  246. }
  247. u_short
  248. TCPDestNat::oldval(ip* iph)
  249. {
  250. return (addrsum(&iph->ip_dst));
  251. }
  252. void
  253. TCPDestNat::rewrite_addr(ip* iph)
  254. {
  255. iph->ip_dst = newdst_;
  256. }
  257. void
  258. TCPSrcDestNat::rewrite_addr(ip* iph)
  259. {
  260. TCPSrcNat::rewrite_addr(iph);
  261. TCPDestNat::rewrite_addr(iph);
  262. }
  263. u_short
  264. TCPSrcDestNat::newval()
  265. {
  266. return(addrsum(&newsrc_, &newdst_));
  267. }
  268. u_short
  269. TCPSrcDestNat::oldval(ip* iph)
  270. {
  271. //printf("oldval:%hxn", addrsum(&iph->ip_src, &iph->ip_dst));
  272. return(addrsum(&iph->ip_src, &iph->ip_dst));
  273. }
  274. int
  275. NatAgent::command(int argc, const char*const* argv)
  276. {
  277. return(Agent::command(argc, argv));
  278. }
  279. int
  280. TCPSrcNat::command(int argc, const char*const* argv)
  281. {
  282. // $srcnat source <ipaddr>
  283. if (argc == 3) {
  284. if (strcmp(argv[1], "source") == 0) {
  285. u_long ns;
  286. ns = inet_addr(argv[2]);
  287. newsrc_.s_addr = ns;
  288. return (TCL_OK);
  289. }
  290. }
  291. return (NatAgent::command(argc, argv));
  292. }
  293. int
  294. TCPDestNat::command(int argc, const char*const* argv)
  295. {
  296. // $srcnat destination <ipaddr>
  297. if (argc == 3) {
  298. if (strcmp(argv[1], "destination") == 0) {
  299. u_long nd;
  300. nd = inet_addr(argv[2]);
  301. newdst_.s_addr = nd;
  302. return (TCL_OK);
  303. }
  304. }
  305. return (NatAgent::command(argc, argv));
  306. }
  307. int
  308. TCPSrcDestNat::command(int argc, const char*const* argv)
  309. {
  310. // $srcnat source <ipaddr>
  311. if (argc == 3) {
  312. if (strcmp(argv[1], "source") == 0) {
  313. u_long ns;
  314. ns = inet_addr(argv[2]);
  315. newsrc_.s_addr = ns;
  316. return (TCL_OK);
  317. }
  318. }
  319. // $srcnat destination <ipaddr>
  320. if (argc == 3) {
  321. if (strcmp(argv[1], "destination") == 0) {
  322. u_long nd;
  323. nd = inet_addr(argv[2]);
  324. newdst_.s_addr = nd;
  325. return (TCL_OK);
  326. }
  327. }
  328. return (NatAgent::command(argc, argv));
  329. }