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/tcptap.cc,v 1.4 2002/09/23 23:25:05 alefiyah Exp $ (ISI)";
00037 #endif
00038
00039 #include "tcptap.h"
00040
00041 static class TCPTapAgentClass : public TclClass {
00042 public:
00043 TCPTapAgentClass() : TclClass("Agent/TCPTap") {}
00044 TclObject* create(int, const char*const*) {
00045 return (new TCPTapAgent());
00046 }
00047 } class_tcptap_agent;
00048
00049
00050
00051 TCPTapAgent::TCPTapAgent() {
00052 adv_window = DEFAULT_ADV_WINDOW;
00053
00054 bzero(&extnode, sizeof(struct sockaddr_in));
00055 extnode.sin_port = DEFAULT_EXT_PORT;
00056 extnode.sin_addr.s_addr = inet_addr(DEFAULT_EXT_ADDR);
00057 extnode.sin_family = AF_INET;
00058
00059 bzero(&nsnode, sizeof(struct sockaddr_in));
00060 nsnode.sin_port = DEFAULT_NS_PORT;
00061 nsnode.sin_addr.s_addr = inet_addr(DEFAULT_NS_ADDR);
00062 nsnode.sin_family = AF_INET;
00063
00064 dropp = 0;
00065 }
00066
00067
00068
00069
00070
00071
00072 int
00073 TCPTapAgent::command(int argc, const char*const* argv)
00074 {
00075 if (argc == 3) {
00076 if (strcmp(argv[1], "nsipaddr") == 0) {
00077 if ((nsnode.sin_addr.s_addr = inet_addr(argv[2]))
00078 == INADDR_NONE) {
00079 printf("Error setting ns ip address");
00080 exit(1);
00081 }
00082 return (TCL_OK);
00083 }
00084
00085
00086 if (strcmp(argv[1], "extipaddr") == 0) {
00087 if ((extnode.sin_addr.s_addr = inet_addr(argv[2]))
00088 == INADDR_NONE) {
00089 printf("Error setting external ip address");
00090 exit(1);
00091 }
00092 return (TCL_OK);
00093 }
00094
00095 if (strcmp(argv[1], "extport") == 0) {
00096 extnode.sin_port = atoi(argv[2]);
00097 return (TCL_OK);
00098 }
00099
00100 if (strcmp(argv[1], "advertised-window") == 0) {
00101 adv_window = atoi(argv[2]);
00102 return (TCL_OK);
00103 }
00104
00105
00106
00107 }
00108 return (TapAgent::command(argc, argv));
00109 }
00110
00111
00112
00113 unsigned short
00114 TCPTapAgent::trans_check(unsigned char proto,
00115 char *packet,
00116 int length,
00117 struct in_addr source_address,
00118 struct in_addr dest_address)
00119 {
00120 char *pseudo_packet;
00121 unsigned short answer;
00122
00123 pseudohdr.protocol = proto;
00124 pseudohdr.length = htons(length);
00125 pseudohdr.place_holder = 0;
00126
00127 pseudohdr.source_address = source_address;
00128 pseudohdr.dest_address = dest_address;
00129
00130 if((pseudo_packet = (char *) malloc(sizeof(pseudohdr) + length)) == NULL) {
00131 perror("malloc");
00132 exit(1);
00133 }
00134
00135 memcpy(pseudo_packet,&pseudohdr,sizeof(pseudohdr));
00136 memcpy((pseudo_packet + sizeof(pseudohdr)),
00137 packet,length);
00138
00139 answer = (unsigned short)in_cksum((unsigned short *)pseudo_packet,
00140 (length + sizeof(pseudohdr)));
00141 free(pseudo_packet);
00142 return answer;
00143 }
00144
00145
00146
00147
00148
00149
00150
00151
00152 unsigned short
00153 TCPTapAgent::in_cksum(unsigned short *addr, int len)
00154 {
00155 register int sum = 0;
00156 u_short answer = 0;
00157 register u_short *w = addr;
00158 register int nleft = len;
00159
00160
00161
00162
00163
00164
00165 while (nleft > 1) {
00166 sum += *w++;
00167 nleft -= 2;
00168 }
00169
00170
00171 if (nleft == 1) {
00172 *(u_char *)(&answer) = *(u_char *)w ;
00173 sum += answer;
00174 }
00175
00176
00177 sum = (sum >> 16) + (sum & 0xffff);
00178 sum += (sum >> 16);
00179 answer = ~sum;
00180 return(answer);
00181
00182 }
00183
00184
00185
00186 void
00187 TCPTapAgent::ip_gen(char *packet, unsigned char protocol,
00188 struct in_addr saddr, struct in_addr daddr,
00189 unsigned short length, unsigned char ttl)
00190 {
00191
00192 struct ip *ipheader;
00193
00194 ipheader = (struct ip *) packet;
00195 bzero((void *) ipheader, IP_HEADER_LEN);
00196
00197 ipheader->ip_hl = (IP_HEADER_LEN / 4);
00198 ipheader->ip_v = IPVERSION;
00199
00200 ipheader->ip_len = length;
00201 ipheader->ip_id = 0;
00202 ipheader->ip_ttl = ttl;
00203 ipheader->ip_p = protocol;
00204
00205 ipheader->ip_src = saddr;
00206 ipheader->ip_dst = daddr;
00207
00208 ipheader->ip_len = ntohs(ipheader->ip_len);
00209 ipheader->ip_off = ntohs(ipheader->ip_off);
00210
00211 ipheader->ip_sum = (unsigned short) in_cksum((unsigned short *) ipheader,
00212 sizeof(struct ip));
00213
00214 }
00215
00216
00217
00218
00219 void
00220 TCPTapAgent::tcp_gen(char *packet, unsigned short sport, unsigned short dport,
00221 Packet *nsp)
00222 {
00223 struct tcphdr *tcpheader;
00224
00225 hdr_tcp* ns_tcphdr = HDR_TCP(nsp);
00226
00227 tcpheader = (struct tcphdr *) packet;
00228 memset((char *)tcpheader, '\0', sizeof(struct tcphdr));
00229
00230 #ifndef LINUX_TCP_HEADER
00231
00232 tcpheader->th_sport = htons(sport);
00233 tcpheader->th_dport = htons(dport);
00234
00235 tcpheader->th_seq = htonl(ns_tcphdr->seqno_);
00236 tcpheader->th_ack = htonl(ns_tcphdr->ackno_);
00237
00238 tcpheader->th_off = (TCP_HEADER_LEN / 4);
00239
00240 tcpheader->th_win = htons(adv_window);
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250 tcpheader->th_flags = 0;
00251 if (ns_tcphdr->tcp_flags_ & TH_FIN)
00252 tcpheader->th_flags |= TH_FIN;
00253 if (ns_tcphdr->tcp_flags_ & TH_SYN)
00254 tcpheader->th_flags |= TH_SYN;
00255 if (ns_tcphdr->tcp_flags_ & TH_RST)
00256 tcpheader->th_flags |= TH_RST;
00257 if (ns_tcphdr->tcp_flags_ & TH_PUSH)
00258 tcpheader->th_flags |= TH_PUSH;
00259 if (ns_tcphdr->tcp_flags_ & TH_ACK)
00260 tcpheader->th_flags |= TH_ACK;
00261 if (ns_tcphdr->tcp_flags_ & TH_URG)
00262 tcpheader->th_flags |= TH_URG;
00263
00264 #else
00265
00266 #define TH_FIN 0x01
00267 #define TH_SYN 0x02
00268 #define TH_RST 0x04
00269 #define TH_PUSH 0x08
00270 #define TH_ACK 0x10
00271 #define TH_URG 0x20
00272
00273 tcpheader->source = htons(sport);
00274 tcpheader->dest = htons(dport);
00275
00276 tcpheader->seq = htonl(ns_tcphdr->seqno_);
00277 tcpheader->ack_seq = htonl(ns_tcphdr->ackno_);
00278
00279 tcpheader->doff = (TCP_HEADER_LEN / 4);
00280 tcpheader->window = htons(adv_window);
00281
00282
00283 if (ns_tcphdr->tcp_flags_ & TH_FIN)
00284 tcpheader->fin= 1;
00285 if (ns_tcphdr->tcp_flags_ & TH_SYN)
00286 tcpheader->syn = 1;
00287 if (ns_tcphdr->tcp_flags_ & TH_RST)
00288 tcpheader->rst =1;
00289 if (ns_tcphdr->tcp_flags_ & TH_PUSH)
00290 tcpheader->psh = 1;
00291 if (ns_tcphdr->tcp_flags_ & TH_ACK)
00292 tcpheader->ack = 1;
00293 if (ns_tcphdr->tcp_flags_ & TH_URG)
00294 tcpheader->urg =1;
00295
00296 #endif
00297
00298
00299 }
00300
00301 void
00302 TCPTapAgent::pkt_handler(void *clientdata, Packet *p, const struct timeval &ts)
00303 {
00304 TCPTapAgent *inst = (TCPTapAgent *)clientdata;
00305 inst->processpkt(p, ts);
00306 }
00307
00308 void
00309 TCPTapAgent::processpkt(Packet *p, const struct timeval &ts)
00310 {
00311 struct ip *ipheader;
00312 struct tcphdr *tcpheader;
00313 unsigned char *buf;
00314
00315
00316 unsigned char ttl;
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329 ipheader = (struct ip *) p->accessdata();
00330 if (in_cksum((unsigned short *) ipheader, (ipheader->ip_hl * 4))) {
00331 fprintf(stderr,
00332 "TCPTapAgent(%s): packet received with invalid IP checksum.\n",
00333 name());
00334 drop(p);
00335 return;
00336 }
00337
00338 ttl = ipheader->ip_ttl;
00339 if (!(--ttl)) {
00340 fprintf(stderr,
00341 "TCPTapAgent(%s): packet received with ttl zero.\n",
00342 name());
00343 drop(p);
00344 return;
00345
00346 }
00347
00348 buf = p->accessdata();
00349 tcpheader = (struct tcphdr *) (buf + (ipheader->ip_hl * 4));
00350
00351 Packet *nspacket = allocpkt();
00352
00353 hdr_ip *ns_iphdr = HDR_IP(nspacket);
00354 ns_iphdr->ttl() = ttl;
00355
00356 hdr_tcp *ns_tcphdr = HDR_TCP(nspacket);
00357 #ifndef LINUX_TCP_HEADER
00358
00359 ns_tcphdr->seqno() = ntohl(tcpheader->th_seq);
00360 ns_tcphdr->ackno() = ntohl(tcpheader->th_ack);
00361 ns_tcphdr->hlen() = (ipheader->ip_hl + tcpheader->th_off) * 4;
00362 ns_tcphdr->ts() = Scheduler::instance().clock();
00363 ns_tcphdr->reason() |= REASON_UNKNOWN;
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373 ns_tcphdr->flags() = 0;
00374 if (tcpheader->th_flags & TH_FIN)
00375 ns_tcphdr->flags() |= TH_FIN;
00376 if (tcpheader->th_flags & TH_SYN)
00377 ns_tcphdr->flags() |= TH_SYN;
00378 if (tcpheader->th_flags & TH_RST)
00379 ns_tcphdr->flags() |= TH_RST;
00380 if (tcpheader->th_flags & TH_PUSH)
00381 ns_tcphdr->flags() |= TH_PUSH;
00382 if (tcpheader->th_flags & TH_ACK)
00383 ns_tcphdr->flags() |= TH_ACK;
00384 if (tcpheader->th_flags & TH_URG)
00385 ns_tcphdr->flags() |= TH_URG;
00386
00387 #else
00388
00389 ns_tcphdr->seqno() = ntohl(tcpheader->seq);
00390 ns_tcphdr->ackno() = ntohl(tcpheader->ack);
00391 ns_tcphdr->hlen() = (ipheader->ip_hl + tcpheader->doff) * 4;
00392 ns_tcphdr->ts() = Scheduler::instance().clock();
00393 ns_tcphdr->reason() |= REASON_UNKNOWN;
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403 #define TH_FIN 0x01
00404 #define TH_SYN 0x02
00405 #define TH_RST 0x04
00406 #define TH_PUSH 0x08
00407 #define TH_ACK 0x10
00408 #define TH_URG 0x20
00409
00410 ns_tcphdr->flags() = 0;
00411
00412 if (tcpheader->fin == 1 )
00413 ns_tcphdr->flags() |= TH_FIN;
00414 if (tcpheader->syn == 1 )
00415 ns_tcphdr->flags() |= TH_SYN;
00416 if (tcpheader->rst == 1 )
00417 ns_tcphdr->flags() |= TH_RST;
00418 if (tcpheader->psh == 1)
00419 ns_tcphdr->flags() |= TH_PUSH;
00420 if (tcpheader->ack == 1)
00421 ns_tcphdr->flags() |= TH_ACK;
00422 if (tcpheader->urg == 1)
00423 ns_tcphdr->flags() |= TH_URG;
00424
00425 #endif
00426
00427
00428 hdr_cmn *ns_cmnhdr = HDR_CMN(nspacket);
00429 ns_cmnhdr->size() = ntohs(ipheader->ip_len);
00430
00431 Packet::free(p);
00432
00433
00434 target_->recv(nspacket);
00435 return;
00436 }
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447 void
00448 TCPTapAgent::recvpkt()
00449 {
00450 if (net_->mode() != O_RDWR && net_->mode() != O_RDONLY) {
00451 fprintf(stderr,
00452 "TCPTapAgent(%s): recvpkt called while in write-only mode!\n",
00453 name());
00454 return;
00455 }
00456
00457 int cc = net_->recv(pkt_handler, this);
00458 if (cc <= 0) {
00459 if (cc < 0) {
00460 perror("recv");
00461 }
00462 return;
00463 }
00464 TDEBUG4("%f: TCPTapAgent(%s): recvpkt, cc:%d\n", now(), name(), cc);
00465
00466
00467
00468 }
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480 int
00481 TCPTapAgent::sendpkt(Packet* p)
00482 {
00483 int byteswritten, datalen;
00484 unsigned char *packet;
00485 unsigned char received_ttl;
00486 int hlength = IP_HEADER_LEN + TCP_HEADER_LEN;
00487 struct tcphdr *tcpheader;
00488
00489 if (net_->mode() != O_RDWR && net_->mode() != O_WRONLY) {
00490 fprintf(stderr,
00491 "TCPTapAgent(%s): sendpkt called while in read-only mode!\n",
00492 name());
00493 return (-1);
00494 }
00495
00496
00497 hdr_cmn* ns_cmnhdr = HDR_CMN(p);
00498 if (net_ == NULL) {
00499 fprintf(stderr,
00500 "TCPTapAgent(%s): sendpkt attempted with NULL net\n",
00501 name());
00502 drop(p);
00503 return (-1);
00504 }
00505
00506 hdr_tcp* ns_tcphdr = HDR_TCP(p);
00507
00508 hdr_ip * ns_iphdr = HDR_IP(p);
00509 received_ttl = ns_iphdr->ttl_;
00510
00511
00512 datalen = ns_cmnhdr->size() - ns_tcphdr->hlen();
00513 packet = (unsigned char *) calloc (1, sizeof(unsigned char) *
00514 (hlength + datalen));
00515 if (packet == NULL) {
00516 fprintf(stderr,
00517 "TCPTapAgent(%s) : Error %d allocating memory.\n", name(), errno);
00518 return (-1);
00519 }
00520
00521
00522
00523 ip_gen((char *)packet, (unsigned char) IPPROTO_TCP,
00524 nsnode.sin_addr, extnode.sin_addr,
00525 hlength + datalen, received_ttl);
00526
00527 tcpheader = (struct tcphdr*) (packet + IP_HEADER_LEN);
00528
00529 tcp_gen((char *)tcpheader, nsnode.sin_port, extnode.sin_port, p);
00530
00531 #ifndef LINUX_TCP_HEADER
00532 tcpheader->th_sum = trans_check(IPPROTO_TCP, (char *) tcpheader,
00533 sizeof(struct tcphdr) + datalen,
00534 nsnode.sin_addr, extnode.sin_addr);
00535 #else
00536 tcpheader->check = trans_check(IPPROTO_TCP, (char *) tcpheader,
00537 sizeof(struct tcphdr) + datalen,
00538 nsnode.sin_addr, extnode.sin_addr);
00539
00540 #endif
00541
00542
00543
00544
00545
00546 byteswritten = net_->send(packet, hlength + datalen);
00547 if (byteswritten < 0) {
00548 fprintf(stderr,"TCPTapAgent(%s): sendpkt (%p, %d): %s\n",
00549 name(), p->accessdata(), ns_cmnhdr->size(), strerror(errno));
00550 Packet::free(p);
00551 free(packet);
00552 return (-1);
00553
00554 }
00555
00556 free(packet);
00557 TDEBUG3("TCPTapAgent(%s): sent packet (sz: %d)\n", name(), byteswritten);
00558 return 0;
00559 }
00560
00561
00562
00563
00564
00565
00566
00567