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/arp.cc,v 1.8 2000/11/09 17:42:23 haoboy Exp $";
00037 #endif
00038
00039 #include "object.h"
00040 #include "packet.h"
00041
00042 #include <sys/types.h>
00043 #include <sys/param.h>
00044 #include <sys/socket.h>
00045 #include <sys/ioctl.h>
00046 #include <netinet/in.h>
00047 #include <netinet/in_systm.h>
00048 #include <netinet/ip.h>
00049 #include <net/if.h>
00050 #include <net/ethernet.h>
00051 #include <net/if_arp.h>
00052 #include <netinet/if_ether.h>
00053 #include <arpa/inet.h>
00054 #include <memory.h>
00055 #include <stdio.h>
00056 #include <errno.h>
00057
00058 #include "emulate/net.h"
00059 #include "emulate/ether.h"
00060 #include "emulate/internet.h"
00061
00062
00063 #ifndef ether_aton
00064 extern "C" {
00065 ether_addr* ether_aton(const char *);
00066 }
00067 #endif
00068
00069
00070
00071
00072
00073
00074
00075 class ArpAgent : public NsObject, public IOHandler {
00076 public:
00077 ArpAgent();
00078 ~ArpAgent();
00079
00080 protected:
00081 struct acache_entry {
00082 in_addr ip;
00083 ether_addr ether;
00084 char code;
00085 };
00086
00087 char icode(const char*);
00088 acache_entry* find(in_addr&);
00089 void insert(in_addr&, ether_addr&, char code);
00090 void dispatch(int);
00091 int sendreq(in_addr&);
00092 int sendresp(ether_addr&, in_addr&, ether_addr&);
00093 int resolve(const char* host, char*& result, int sendreq);
00094
00095 void doreq(ether_arp*);
00096 void doreply(ether_arp*);
00097
00098 void recv(Packet*, Handler*) { abort(); }
00099
00100 int command(int, const char*const*);
00101
00102 Network* net_;
00103 ether_header eh_template_;
00104 ether_arp ea_template_;
00105 ether_addr my_ether_;
00106 in_addr my_ip_;
00107 int base_size_;
00108 u_char* rcv_buf_;
00109 acache_entry* acache_;
00110 int nacache_;
00111 int cur_;
00112 int pending_;
00113 };
00114
00115 static class ArpAgentClass : public TclClass {
00116 public:
00117 ArpAgentClass() : TclClass("ArpAgent") {}
00118 TclObject* create(int , const char*const*) {
00119 return (new ArpAgent());
00120 }
00121 } class_arpagent;
00122
00123 ArpAgent::ArpAgent() : net_(NULL), pending_(0)
00124 {
00125
00126 eh_template_.ether_dhost[0] = 0xff;
00127 eh_template_.ether_dhost[1] = 0xff;
00128 eh_template_.ether_dhost[2] = 0xff;
00129 eh_template_.ether_dhost[3] = 0xff;
00130 eh_template_.ether_dhost[4] = 0xff;
00131 eh_template_.ether_dhost[5] = 0xff;
00132
00133 memcpy(&eh_template_.ether_shost, &my_ether_, ETHER_ADDR_LEN);
00134
00135 eh_template_.ether_type = htons(ETHERTYPE_ARP);
00136
00137 ea_template_.ea_hdr.ar_hrd = htons(ARPHRD_ETHER);
00138 ea_template_.ea_hdr.ar_pro = htons(ETHERTYPE_IP);
00139 ea_template_.ea_hdr.ar_hln = ETHER_ADDR_LEN;
00140 ea_template_.ea_hdr.ar_pln = 4;
00141 ea_template_.ea_hdr.ar_op = htons(ARPOP_REQUEST);
00142 memcpy(&ea_template_.arp_sha, &my_ether_, ETHER_ADDR_LEN);
00143 memset(&ea_template_.arp_spa, 0, 4);
00144 memset(&ea_template_.arp_tha, 0, ETHER_ADDR_LEN);
00145 memset(&ea_template_.arp_tpa, 0, 4);
00146 base_size_ = sizeof(eh_template_) + sizeof(ea_template_);
00147 rcv_buf_ = new u_char[base_size_];
00148
00149 bind("cachesize_", &nacache_);
00150 acache_ = new acache_entry[nacache_];
00151 memset(acache_, 0, nacache_*sizeof(acache_entry));
00152 cur_ = nacache_;
00153 }
00154
00155 ArpAgent::~ArpAgent()
00156 {
00157 delete[] rcv_buf_;
00158 delete[] acache_;
00159 }
00160
00161 ArpAgent::acache_entry*
00162 ArpAgent::find(in_addr& target)
00163 {
00164 int n = nacache_;
00165 acache_entry* ae = &acache_[n-1];
00166 while (--n >= 0) {
00167 if (ae->ip.s_addr == target.s_addr) {
00168 return (ae);
00169 }
00170 --ae;
00171 }
00172 return (NULL);
00173 }
00174
00175 char
00176 ArpAgent::icode(const char *how)
00177 {
00178 if (strcmp(how, "publish") == 0)
00179 return 'P';
00180
00181 return 'D';
00182 }
00183
00184 void
00185 ArpAgent::insert(in_addr& target, ether_addr& eaddr, char code)
00186 {
00187 acache_entry* ae;
00188 if (--cur_ < 0)
00189 cur_ = nacache_ - 1;
00190
00191 ae = &acache_[cur_];
00192 ae->ip = target;
00193 ae->ether = eaddr;
00194 ae->code = code;
00195
00196
00197 return;
00198 }
00199
00200 int
00201 ArpAgent::sendreq(in_addr& target)
00202 {
00203 int pktsz = sizeof(eh_template_) + sizeof(ea_template_);
00204 if (pktsz < 64)
00205 pktsz = 64;
00206 u_char* buf = new u_char[pktsz];
00207 memset(buf, 0, pktsz);
00208
00209 ether_header* eh = (ether_header*) buf;
00210 ether_arp* ea = (ether_arp*) (buf + sizeof(eh_template_));
00211 *eh = eh_template_;
00212 *ea = ea_template_;
00213 memcpy(ea->arp_tpa, &target, sizeof(target));
00214
00215 if (net_->send(buf, pktsz) < 0) {
00216 fprintf(stderr,
00217 "ArpAgent(%s): sendpkt (%p, %d): %s\n",
00218 name(), buf, pktsz, strerror(errno));
00219 return (-1);
00220 }
00221 delete[] buf;
00222 return (0);
00223 }
00224
00225
00226
00227
00228
00229
00230
00231 int
00232 ArpAgent::sendresp(ether_addr& dest, in_addr& tip, ether_addr& tea)
00233 {
00234 int pktsz = sizeof(eh_template_) + sizeof(ea_template_);
00235 if (pktsz < 64)
00236 pktsz = 64;
00237 u_char* buf = new u_char[pktsz];
00238 memset(buf, 0, pktsz);
00239
00240 ether_header* eh = (ether_header*) buf;
00241 ether_arp* ea = (ether_arp*) (buf + sizeof(eh_template_));
00242
00243
00244
00245 *eh = eh_template_;
00246 memcpy(eh->ether_dhost, &dest, ETHER_ADDR_LEN);
00247
00248
00249 *ea = ea_template_;
00250 ea->ea_hdr.ar_op = htons(ARPOP_REPLY);
00251
00252
00253 memcpy(ea->arp_tpa, ea->arp_spa, sizeof(in_addr));
00254 memcpy(ea->arp_tha, ea->arp_sha, sizeof(in_addr));
00255
00256 memcpy(ea->arp_sha, &tea, ETHER_ADDR_LEN);
00257 memcpy(ea->arp_spa, &tip, ETHER_ADDR_LEN);
00258
00259 if (net_->send(buf, pktsz) < 0) {
00260 fprintf(stderr,
00261 "ArpAgent(%s): sendpkt (%p, %d): %s\n",
00262 name(), buf, pktsz, strerror(errno));
00263 return (-1);
00264 }
00265 delete[] buf;
00266 return (0);
00267 }
00268
00269
00270
00271
00272
00273
00274 void
00275 ArpAgent::dispatch(int)
00276 {
00277 double ts;
00278 sockaddr sa;
00279 int cc = net_->recv(rcv_buf_, base_size_, sa, ts);
00280 if (cc < int(base_size_ - sizeof(ether_header))) {
00281 if (cc == 0)
00282 return;
00283 fprintf(stderr,
00284 "ArpAgent(%s): recv small pkt (%d) [base sz:%d]: %s\n",
00285 name(), cc, base_size_, strerror(errno));
00286 return;
00287 }
00288 ether_arp* ea = (ether_arp*) rcv_buf_;
00289 int op = ntohs(ea->ea_hdr.ar_op);
00290
00291
00292 switch (op) {
00293 case ARPOP_REPLY:
00294 doreply(ea);
00295 break;
00296 case ARPOP_REQUEST:
00297 doreq(ea);
00298 break;
00299 default:
00300 fprintf(stderr,
00301 "ArpAgent(%s): cannot interpret ARP op %d\n",
00302 name(), op);
00303 return;
00304 }
00305 return;
00306 }
00307
00308
00309
00310
00311 void
00312 ArpAgent::doreply(ether_arp* ea)
00313 {
00314
00315
00316
00317
00318
00319 in_addr t;
00320 ether_addr e;
00321 memcpy(&t, ea->arp_spa, 4);
00322 memcpy(&e, ea->arp_sha, ETHER_ADDR_LEN);
00323 insert(t, e, 'D');
00324 return;
00325 }
00326
00327
00328
00329
00330
00331 void
00332 ArpAgent::doreq(ether_arp* ea)
00333 {
00334 in_addr t;
00335 memcpy(&t, ea->arp_tpa, 4);
00336
00337 acache_entry *ae;
00338 if ((ae = find(t)) == NULL) {
00339
00340
00341 return;
00342 }
00343
00344 if (ae->code == 'P') {
00345
00346 ether_addr dst;
00347 memcpy(&dst, ea->arp_sha, ETHER_ADDR_LEN);
00348 sendresp(dst, t, ae->ether);
00349 }
00350 return;
00351 }
00352
00353
00354 int
00355 ArpAgent::command(int argc, const char*const* argv)
00356 {
00357 Tcl& tcl = Tcl::instance();
00358 if (argc == 2) {
00359 if (strcmp(argv[1], "network") == 0) {
00360 if (net_ == NULL)
00361 tcl.result("");
00362 else
00363 tcl.result(net_->name());
00364 return (TCL_OK);
00365 }
00366 } else if (argc == 3) {
00367 if (strcmp(argv[1], "network") == 0) {
00368 net_ = (Network *)TclObject::lookup(argv[2]);
00369 if (net_ != 0) {
00370 link(net_->rchannel(), TCL_READABLE);
00371 return (TCL_OK);
00372 } else {
00373 fprintf(stderr,
00374 "ArpAgent(%s): unknown network %s\n",
00375 name(), argv[2]);
00376 return (TCL_ERROR);
00377 }
00378 return(TCL_OK);
00379 }
00380 if (strcmp(argv[1], "myether") == 0) {
00381 my_ether_ = *(::ether_aton((char*)argv[2]));
00382 memcpy(&eh_template_.ether_shost, &my_ether_,
00383 ETHER_ADDR_LEN);
00384 memcpy(&ea_template_.arp_sha,
00385 &my_ether_, ETHER_ADDR_LEN);
00386 return (TCL_OK);
00387 }
00388 if (strcmp(argv[1], "myip") == 0) {
00389 u_long a = inet_addr(argv[2]);
00390 if (a == 0)
00391 return (TCL_ERROR);
00392 in_addr ia;
00393 ia.s_addr = a;
00394 my_ip_ = ia;
00395 memcpy(&ea_template_.arp_spa,
00396 &my_ip_, 4);
00397 return (TCL_OK);
00398 }
00399 if (strcmp(argv[1], "lookup") == 0) {
00400 char *p = NULL;
00401 if (resolve(argv[2], p, 0) < 0)
00402 return (TCL_ERROR);
00403 if (p)
00404 tcl.result(p);
00405 return (TCL_OK);
00406 }
00407 if (strcmp(argv[1], "resolve") == 0) {
00408 char *p = NULL;
00409 if (resolve(argv[2], p, 1) < 0)
00410 return (TCL_ERROR);
00411 if (p)
00412 tcl.resultf("%s", p);
00413 return (TCL_OK);
00414 }
00415 } else if (argc == 5) {
00416
00417 if (strcmp(argv[1], "insert") == 0) {
00418 u_long a = inet_addr(argv[2]);
00419 if (a == 0)
00420 return (TCL_ERROR);
00421 in_addr ia;
00422 ia.s_addr = a;
00423 ether_addr ea = *(::ether_aton((char*)argv[3]));
00424 insert(ia, ea, icode(argv[4]));
00425 return (TCL_OK);
00426 }
00427 }
00428
00429 return (NsObject::command(argc, argv));
00430 }
00431
00432 int
00433 ArpAgent::resolve(const char* host, char*& result, int doreq)
00434 {
00435 u_long a = inet_addr(host);
00436 in_addr ia;
00437 ia.s_addr = a;
00438 acache_entry* ae;
00439 if ((ae = find(ia)) == NULL) {
00440 result = NULL;
00441 if (doreq)
00442 return(sendreq(ia));
00443 return (0);
00444 }
00445 result = Ethernet::etheraddr_string((u_char*) &ae->ether);
00446 return (1);
00447 }