Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Compound Members | File Members

iptap.cc

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 1997, 1998 The 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 MASH Research
00016  *      Group at the University of California, Berkeley.
00017  * 4. Neither the name of the University nor of the Research Group 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/iptap.cc,v 1.3 2002/09/23 23:25:05 alefiyah Exp $ (ISI)";
00037 #endif
00038 
00039 #include "iptap.h"
00040 
00041 
00042 static class IPTapAgentClass : public TclClass {
00043  public:
00044         IPTapAgentClass() : TclClass("Agent/IPTap") {}
00045         TclObject* create(int, const char*const*) {
00046                 return (new IPTapAgent());
00047         }
00048 } class_iptap_agent;
00049 
00050 
00051 IPTapAgent::IPTapAgent() 
00052 {
00053   int i = 0;
00054   index = 0;
00055   for (; i < MAX_PACKETS ; i++) {
00056     ident[i] = -1;
00057     offset[i] = -1;
00058   }
00059 
00060 }
00061 
00062 
00063 /*
00064  * Checking for duplicate packets.  Need to do this, if running
00065  * emulation on a machine with one interface.  We simply store
00066  * a list of IP identification fields of the packets that we see.
00067  * When we see a new packet, we check this list to see if the packet
00068  * is coming to this interface again (because when writing out the packet
00069  * using a raw socket, the bpf will pick it up again.)
00070  */
00071 int
00072 IPTapAgent::isDuplicate(unsigned short id, unsigned short off) 
00073 {
00074   int i = 0;
00075   for( ; i < MAX_PACKETS; i++){
00076     if ((ident[i] == id) && (offset[i] == off)) {
00077       return 1;
00078     }
00079   }
00080   ident[index % MAX_PACKETS] = id;
00081   offset[index % MAX_PACKETS] = off;
00082   index++;
00083   return 0;
00084 }
00085 
00086 
00087 
00088 /*
00089  * Taken from the raw-sock program
00090  */
00091 unsigned short 
00092 IPTapAgent::in_cksum(unsigned short *addr, int len)
00093 {
00094   register int sum = 0;
00095   u_short answer = 0;
00096   register u_short *w = addr;
00097   register int nleft = len;
00098   
00099   /*
00100    * Our algorithm is simple, using a 32 bit accumulator (sum), we add
00101    * sequential 16 bit words to it, and at the end, fold back all the
00102    * carry bits from the top 16 bits into the lower 16 bits.
00103    */
00104   while (nleft > 1)  {
00105     sum += *w++;
00106     nleft -= 2;
00107   }
00108   
00109   /* mop up an odd byte, if necessary */
00110   if (nleft == 1) {
00111     *(u_char *)(&answer) = *(u_char *)w ;
00112     sum += answer;
00113   }
00114   
00115   /* add back carry outs from top 16 bits to low 16 bits */
00116   sum = (sum >> 16) + (sum & 0xffff);     /* add hi 16 to low 16 */
00117   sum += (sum >> 16);                     /* add carry */
00118   answer = ~sum;                          /* truncate to 16 bits */
00119   return(answer);
00120   
00121 }
00122 
00123 void
00124 IPTapAgent::pkt_handler(void *clientdata, Packet *p, const struct timeval &ts)
00125 {
00126   IPTapAgent *inst = (IPTapAgent *)clientdata;
00127   inst->processpkt(p, ts);
00128 }
00129 
00130 void
00131 IPTapAgent::processpkt(Packet *p, const struct timeval &ts)
00132 {
00133   struct ip *ipheader;
00134   struct tcphdr *tcpheader;
00135   unsigned char *buf;
00136   
00137   /* Ip header information from the grabbed packet. */
00138   int iphlen;  
00139   unsigned short datagramlen;
00140   unsigned char ttl;
00141   
00142   /* TCP header info from the grabbed packet. */
00143   unsigned char tcphlen;
00144   
00145   /* 
00146      At this point, all I have to do is to grab the ttl value 
00147      from the received packet and put it in p's ttl field after
00148      decrementing it. It's ok, if we don't recalculate the checksum
00149      of the actual packet, because we'll do it at the end anyways.
00150   */
00151 
00152   ipheader = (struct ip *) p->accessdata();
00153   buf = p->accessdata();
00154   iphlen = ipheader->ip_hl * 4;
00155   ttl = ipheader->ip_ttl;
00156   if (!(--ttl)) {
00157     fprintf(stderr,
00158             "IPTapAgent(%s) : received ttl zero.\n",
00159             name());
00160     Packet::free(p);
00161     return;
00162   }
00163 
00164    /* Removed test for isDuplicate on 08/19/02 
00165     * Recommend adding ether dst or adding not ether src instead 
00166     * since at high packet rates the test cannot keep up and results 
00167     * in losing packets */
00168   /* Discard if duplicate. */
00169   /* if (isDuplicate(ntohs(ipheader->ip_id), ntohs(ipheader->ip_off))) {
00170     Packet::free(p);
00171     return;
00172     } */ 
00173   
00174   datagramlen = ntohs(ipheader->ip_len);
00175 
00176   /* Put all the info in the ns headers. */
00177   hdr_cmn *ch = HDR_CMN(p);
00178   ch->size() = datagramlen;
00179 
00180   hdr_ip *ih = HDR_IP(p);
00181   ih->ttl() = ttl;
00182 
00183   // inject into simulator
00184   target_->recv(p);
00185   return;
00186 }
00187 
00188 /*
00189  * ns scheduler calls TapAgent::dispatch which calls recvpkt.
00190  * 
00191  * recvpkt then calls the network (net_) to receive as many packets
00192  * as there are from the packet capture facility.
00193  * For every packet received through the callback, it populates the ns packet
00194  * ttl value and inject it into the simulator by calling target_->recv
00195  * 
00196  */
00197 void
00198 IPTapAgent::recvpkt()
00199 {
00200   if (net_->mode() != O_RDWR && net_->mode() != O_RDONLY) {
00201     fprintf(stderr,
00202             "IPTapAgent(%s): recvpkt called while in write-only mode!\n",
00203             name());
00204     return;
00205   }
00206   
00207   int cc = net_->recv(pkt_handler, this);
00208   if (cc <= 0) {
00209     if (cc < 0) {
00210       perror("recv");
00211     }
00212     return;
00213   }
00214   TDEBUG4("%f: IPTapAgent(%s): recvpkt, cc:%d\n", now(), name(), cc);
00215 
00216   // nothing to do coz pkt_handler would have called processpkt()
00217   // that would have injected packets into the simulator
00218 
00219 }
00220 
00221 
00222 
00223 
00224 /*
00225  * simulator schedules TapAgent::recv which calls sendpkt
00226  *
00227  * Grabs a ns packet, converts it into real packet 
00228  * and injects onto the network using net_->send
00229  */
00230 int
00231 IPTapAgent::sendpkt(Packet* p)
00232 {
00233   int byteswritten;
00234   unsigned char *packet;
00235   unsigned char received_ttl;
00236   unsigned short dglen;
00237   struct ip *ipheader;
00238 
00239   if (net_->mode() != O_RDWR && net_->mode() != O_WRONLY) {
00240     fprintf(stderr,
00241             "IPTapAgent(%s): sendpkt called while in read-only mode!\n",
00242             name());
00243     return (-1);
00244   }
00245   
00246   // send packet into the live network
00247   hdr_cmn* hc = HDR_CMN(p);
00248   if (net_ == NULL) {
00249     fprintf(stderr,
00250             "IPTapAgent(%s): sendpkt attempted with NULL net\n",
00251             name());
00252     drop(p);
00253     return (-1);
00254   }
00255   
00256   /*
00257     At this point, we should grab the ttl field from the ns
00258     packet, put it in the IP header of the actual packet,
00259     recalculate the checksum and send the packet on it's
00260     way (hoping that anything else in the packet hasn't got
00261     corrupted.
00262   */
00263 
00264   /* Grab the info from the ns packet. */
00265   hdr_ip  *ih = HDR_IP(p);
00266   received_ttl = ih->ttl_;
00267   if (!received_ttl) {
00268     /* Should drop the packet if ttl is zero. */
00269     fprintf(stderr,
00270             "IPTapAgent(%s): received packet ttl zero.\n",
00271             name());
00272     drop(p);
00273     return(-1);
00274   }
00275 
00276 
00277   /* Modify the original packet with the new info. */
00278   packet = p->accessdata();
00279   ipheader = (struct ip *) packet;
00280   ipheader->ip_ttl = received_ttl;
00281   ipheader->ip_sum = 0;
00282   ipheader->ip_sum = (unsigned short) in_cksum((unsigned short *) ipheader,
00283                                                 sizeof(struct ip));
00284 
00285   if (net_->send(p->accessdata(), hc->size()) < 0) {
00286     fprintf(stderr,
00287             "IPTapAgent(%s): sendpkt (%p, %d): %s\n",
00288             name(), p->accessdata(), hc->size(), strerror(errno));
00289     Packet::free(p);
00290     return (-1);
00291     
00292   }
00293   Packet::free(p);
00294   TDEBUG3("IPTapAgent(%s): sent packet (sz: %d)\n",
00295           name(), hc->size());
00296   return 0;
00297 }
00298 
00299 

Generated on Tue Apr 20 12:14:20 2004 for NS2.26SourcesOriginal by doxygen 1.3.3