Azinix

pktTfc.c

Go to the documentation of this file.
00001 /** \file pktTfc.c
00002 
00003 \brief Routines for creating packets.
00004 
00005 */
00006 
00007 #include "pkt.h"
00008 
00009 /*---------------------------------------------------------------------------*/
00010 /* Constant declarations                                                     */
00011 /*---------------------------------------------------------------------------*/
00012 
00013 /**AutomaticStart*************************************************************/
00014 
00015 /*---------------------------------------------------------------------------*/
00016 /* Static function prototypes                                                */
00017 /*---------------------------------------------------------------------------*/
00018 
00019 static void assembleUdpPkt (Pkt_UdpHdr_t * result, u_int16_t srcPort,
00020                 u_int16_t destPort, u_int16_t checkSum,
00021                 util_byte_array_t * payload);
00022 static void assembleTcpPkt (Pkt_TcpHdr_t * result, u_int16_t srcPort,
00023                 u_int16_t destPort, u_int32_t seqNum,
00024                 u_int32_t ackNum,
00025                 Pkt_TcpResDoffFlags_t resDoffFlags,
00026                 u_int16_t advWindow, u_int16_t checkSum,
00027                 u_int16_t urgPtr, util_byte_array_t * payload);
00028 static void assembleIpPkt (Pkt_IpHdr_t * pkt, u_int8_t ihl, u_int8_t version,
00029                u_int8_t TOS, u_int16_t length, u_int16_t id,
00030                Pkt_IpFlags_t ipFlags, st_table * ipOptions,
00031                u_int8_t TTL, u_int8_t protocol,
00032                u_int16_t checksum, u_int32_t sourceIp,
00033                u_int32_t destIp, util_byte_array_t * payload);
00034 static int computeOptionsLength (st_table * ipoptions);
00035 
00036 /**AutomaticEnd***************************************************************/
00037 
00038 /** \brief  Create an ICMP packet
00039   
00040 \sa Pkt_CreateTcpPkt
00041 */
00042 
00043 util_byte_array_t *
00044 Pkt_CreateIcmpPkt (array_t * typeArray,
00045            array_t * codeArray, array_t * idArray, array_t * seqArray)
00046 {
00047   Pkt_IcmpHdr_t *pkt;
00048 
00049   u_int8_t type;
00050   u_int8_t code;
00051   u_int16_t checkSum;
00052 
00053   u_int16_t id;
00054   u_int16_t seq;
00055 
00056   float direct = 1.0;
00057 
00058   int index;
00059   if ((typeArray != NIL (array_t)) && (array_n (typeArray) != 0)
00060       && (util_unit_rand () < direct))
00061     {
00062       index = util_rand_int () % array_n (typeArray);
00063       type = array_fetch (u_int8_t, typeArray, index);
00064     }
00065   else
00066     {
00067       type = (u_int8_t) util_rand_int ();
00068     }
00069   if ((codeArray != NIL (array_t)) && (array_n (codeArray) != 0)
00070       && (util_unit_rand () < direct))
00071     {
00072       index = util_rand_int () % array_n (codeArray);
00073       code = array_fetch (u_int8_t, codeArray, index);
00074     }
00075   else
00076     {
00077       code = (u_int8_t) util_rand_int ();
00078     }
00079   if ((idArray != NIL (array_t)) && (array_n (idArray) != 0)
00080       && (util_unit_rand () < direct))
00081     {
00082       index = util_rand_int () % array_n (idArray);
00083       id = array_fetch (u_int8_t, idArray, index);
00084     }
00085   else
00086     {
00087       id = (u_int8_t) util_rand_int ();
00088     }
00089   if ((seqArray != NIL (array_t)) && (array_n (seqArray) != 0)
00090       && (util_unit_rand () < direct))
00091     {
00092       index = util_rand_int () % array_n (seqArray);
00093       seq = array_fetch (u_int8_t, seqArray, index);
00094     }
00095   else
00096     {
00097       seq = (u_int8_t) util_rand_int ();
00098     }
00099 
00100   pkt = (Pkt_IcmpHdr_t *) malloc (sizeof (Pkt_IcmpHdr_t));
00101   pkt->type = type;
00102   pkt->code = code;
00103   pkt->checksum = 0;
00104   (*pkt).un.echo.id = id;
00105   (*pkt).un.echo.sequence = seq;
00106 
00107   util_byte_array_t *result =
00108     (util_byte_array_t *) malloc (sizeof (util_byte_array_t));
00109   result->bytes = (char *) pkt;
00110   result->length = sizeof (Pkt_IcmpHdr_t);
00111 
00112   return result;
00113 }
00114 
00115 
00116 /**
00117   \brief  Create a UDP packet
00118   
00119 User defines the "interesting" source and dest ports, 
00120 and byteStrings to be inserted in the packet.  
00121 
00122   \sa Pkt_CreateTcpPkt
00123 */
00124 
00125 util_byte_array_t *
00126 Pkt_CreateUdpPkt (array_t * srcPorts,
00127           array_t * destPorts, array_t * sizes, array_t * byteStrings)
00128 {
00129   Pkt_UdpHdr_t *pkt;
00130 
00131   u_int16_t srcPort;
00132   u_int16_t destPort;
00133   u_int16_t checkSum;
00134 
00135   u_int16_t payloadLength;
00136 
00137   util_byte_array_t *payload;
00138 
00139   float direct = 1.0;
00140 
00141   int index;
00142   if ((srcPorts != NIL (array_t)) && (array_n (srcPorts) != 0)
00143       && (util_unit_rand () < direct))
00144     {
00145       index = util_rand_int () % array_n (srcPorts);
00146       srcPort = array_fetch (u_int16_t, srcPorts, index);
00147     }
00148   else
00149     {
00150       srcPort = (u_int16_t) util_rand_int ();
00151     }
00152   if ((destPorts != NIL (array_t)) && (array_n (destPorts) != 0)
00153       && (util_unit_rand () < direct))
00154     {
00155       index = util_rand_int () % array_n (destPorts);
00156       destPort = array_fetch (u_int16_t, destPorts, index);
00157     }
00158   else
00159     {
00160       destPort = (u_int16_t) util_rand_int ();
00161     }
00162 
00163   bool useTargetStrings = false;
00164   int targetStringIndex = -1;
00165   if ((sizes != NIL (array_t)) && (array_n (sizes) != 0)
00166       && (util_unit_rand () < direct))
00167     {
00168       useTargetStrings = true;
00169       targetStringIndex = util_rand_int () % array_n (byteStrings);
00170       int sizesIndex = util_rand_int () % array_n (sizes);
00171       payloadLength = array_fetch (int, sizes, sizesIndex);
00172     }
00173   else
00174     {
00175       /// \todo the calculation above assumes no IP options - this is not a big deal
00176       /// because it's in random pkt gen mode, not going to be used
00177       /// outside of a test environment
00178       payloadLength = (util_rand_int () % (1500 - sizeof (Pkt_TcpHdr_t)
00179                        - sizeof (Pkt_IpHdr_t)
00180                        - sizeof (Pkt_EthernetHdr_t)));
00181     }
00182   payload = util_byte_array_create (NIL (char), payloadLength);
00183 
00184   int i;
00185   // cannot use the random result we got from malloc
00186   // because it fails purify checks
00187   // srand(0);
00188   for (i = 0; (i < payloadLength); i++)
00189     {
00190       payload->bytes[i] = (unsigned char) (rand ());
00191     }
00192   if (useTargetStrings == true)
00193     {
00194       util_byte_array_t *aByteString =
00195     array_fetch (util_byte_array_t *, byteStrings, targetStringIndex);
00196       // for testing other systems
00197       int offset = 0;
00198       if ( payloadLength != 0 ) {
00199         int offset = MAX( 0, ( (rand () % payloadLength) - aByteString->length) - 1 );
00200       }
00201       offset = (offset < 0) ? 0 : offset;
00202       for (i = 0; i < aByteString->length; i++)
00203     {
00204       payload->bytes[offset + i] = aByteString->bytes[i];
00205     }
00206     }
00207 
00208   pkt = (Pkt_UdpHdr_t *) malloc (payloadLength + sizeof (Pkt_UdpHdr_t));
00209   assembleUdpPkt (pkt, srcPort, destPort, checkSum, payload);
00210 
00211   util_byte_array_t *result =
00212     (util_byte_array_t *) malloc (sizeof (util_byte_array_t));
00213   result->bytes = (char *) pkt;
00214   result->length = payloadLength + sizeof (Pkt_UdpHdr_t);
00215 
00216   util_byte_array_free (payload);
00217 
00218   return result;
00219 }
00220 
00221 
00222 /**
00223   * \brief  Create a TCP packet
00224   * 
00225   * User defines
00226   * the "interesting" source and dest ports, seq numbers, ack numbers, sizes,
00227   * and byteStrings to be inserted in the packet.  If any of these arrays
00228   * are empty, we take the corresponding field to be un-constrained.
00229   *     Otherwise, the field takes a value with equal likelihood from the correp
00230   *     array.  (The array can be of length 1, which is useful for directed testing.)
00231   * 
00232   * User also define flags to be set by a st_table containing strings
00233   * "fin", "syn", "rst", "psh", "ack", "urg", "ece", "cwr" - default is 
00234   * set with prob 0.5.  If the st_table is NIL, flags are set at random.
00235   * 
00236   * Since there is no length field in the tcp header, we return a 
00237   * util_byte_array_t *, with the bytes entry being the actual packet,
00238   * and the length entry being the length of the packet.
00239   */
00240 
00241 util_byte_array_t *
00242 Pkt_CreateTcpPkt (array_t * srcPorts,
00243           array_t * destPorts,
00244           array_t * seqNums,
00245           array_t * ackNums,
00246           st_table * flags, array_t * sizes, array_t * byteStrings)
00247 {
00248   Pkt_TcpHdr_t *pkt;
00249 
00250   u_int16_t srcPort;
00251   u_int16_t destPort;
00252   u_int32_t seqNum;
00253   u_int32_t ackNum;
00254 
00255   Pkt_TcpResDoffFlags_t resDoffFlags;
00256 
00257   u_int16_t advWindow;
00258   u_int16_t checkSum;
00259   u_int16_t urgPtr;
00260 
00261   u_int16_t payloadLength;
00262 
00263   util_byte_array_t *payload;
00264 
00265   float direct = 1.0;
00266 
00267   int index;
00268   if ((srcPorts != NIL (array_t)) && (array_n (srcPorts) != 0)
00269       && (util_unit_rand () < direct))
00270     {
00271       index = util_rand_int () % array_n (srcPorts);
00272       srcPort = array_fetch (u_int16_t, srcPorts, index);
00273     }
00274   else
00275     {
00276       srcPort = (u_int16_t) util_rand_int ();
00277     }
00278   if ((destPorts != NIL (array_t)) && (array_n (destPorts) != 0)
00279       && (util_unit_rand () < direct))
00280     {
00281       index = util_rand_int () % array_n (destPorts);
00282       destPort = array_fetch (u_int16_t, destPorts, index);
00283     }
00284   else
00285     {
00286       destPort = (u_int16_t) util_rand_int ();
00287     }
00288   if ((seqNums != NIL (array_t)) && (array_n (seqNums) != 0)
00289       && (util_unit_rand () < direct))
00290     {
00291       index = util_rand_int () % array_n (seqNums);
00292       seqNum = array_fetch (u_int32_t, seqNums, index);
00293     }
00294   else
00295     {
00296       seqNum = (u_int32_t) util_rand_int ();
00297     }
00298   if ((ackNums != NIL (array_t)) && (array_n (ackNums) != 0)
00299       && (util_unit_rand () < direct))
00300     {
00301       index = util_rand_int () % array_n (ackNums);
00302       ackNum = array_fetch (u_int32_t, ackNums, index);
00303     }
00304   else
00305     {
00306       ackNum = (u_int32_t) util_rand_int ();
00307     }
00308 
00309   resDoffFlags.res1 = 0;    /// \todo reserved bits, see if this needs flexibility
00310   resDoffFlags.doff = 5;    /// \todo no options for now, see if this needs flexibility
00311 
00312   int val;
00313   resDoffFlags.fin = Hash_Lookup (flags, "F", (char **) &val) ? val
00314     : 0;
00315   resDoffFlags.syn = Hash_Lookup (flags, "S", (char **) &val) ? val
00316     : 0;
00317   resDoffFlags.rst = Hash_Lookup (flags, "R", (char **) &val) ? val
00318     :0;
00319   resDoffFlags.psh = Hash_Lookup (flags, "P", (char **) &val) ? val
00320     : 0;
00321   resDoffFlags.ack = Hash_Lookup (flags, "A", (char **) &val) ? val
00322     : 0;
00323   resDoffFlags.urg = Hash_Lookup (flags, "U", (char **) &val) ? val
00324     : 0;
00325   resDoffFlags.ece = Hash_Lookup (flags, "E", (char **) &val) ? val
00326     : 0;
00327   resDoffFlags.cwr = Hash_Lookup (flags, "C", (char **) &val) ? val
00328     : 0;
00329 
00330   /// \todo see if we need the flexibility to set these
00331   advWindow = 0;
00332   checkSum = 0;
00333   urgPtr = 0;
00334 
00335   bool useTargetStrings = false;
00336   int targetStringIndex = -1;
00337   if ((sizes != NIL (array_t)) && (array_n (sizes) != 0)
00338       && (util_unit_rand () < direct))
00339     {
00340       useTargetStrings = true;
00341       targetStringIndex = util_rand_int () % array_n (byteStrings);
00342       int sizesIndex = util_rand_int () % array_n (sizes);
00343       payloadLength = array_fetch (int, sizes, sizesIndex);
00344     }
00345   else
00346     {
00347       payloadLength = (util_rand_int () % (1500 - sizeof (Pkt_TcpHdr_t)
00348                        - sizeof (Pkt_IpHdr_t)
00349                        - sizeof (Pkt_EthernetHdr_t)));
00350     }
00351   payload = util_byte_array_create (NIL (char), payloadLength);
00352 
00353   int i;
00354   // cannot use the random result we got from malloc
00355   // because it fails purify checks
00356   // srand(0);
00357   for (i = 0; (i < payloadLength); i++)
00358     {
00359       payload->bytes[i] = (unsigned char) (rand ());
00360     }
00361   if (useTargetStrings == true)
00362     {
00363       util_byte_array_t *aByteString =
00364     array_fetch (util_byte_array_t *, byteStrings, targetStringIndex);
00365       // for testing other systems
00366       // int offset = 0;
00367       int offset =
00368     (payloadLength ==
00369      0) ? 0 : (rand () % payloadLength) - aByteString->length;
00370       offset = (offset < 0) ? 0 : offset;
00371       // protect from user specifing size:4; content:"adnan"
00372       for (i = 0; i < MIN (aByteString->length, payload->length); i++)
00373     {
00374       payload->bytes[offset + i] = aByteString->bytes[i];
00375     }
00376     }
00377 
00378   pkt = (Pkt_TcpHdr_t *) malloc (payloadLength + sizeof (Pkt_TcpHdr_t));
00379   assembleTcpPkt (pkt,
00380           srcPort,
00381           destPort,
00382           seqNum,
00383           ackNum, resDoffFlags, advWindow, checkSum, urgPtr, payload);
00384 
00385 
00386   util_byte_array_t *result =
00387     (util_byte_array_t *) malloc (sizeof (util_byte_array_t));
00388   result->bytes = (char *) pkt;
00389   result->length = payloadLength + sizeof (Pkt_TcpHdr_t);
00390 
00391   util_byte_array_free (payload);
00392 
00393   return result;
00394 }
00395 
00396 
00397 /**
00398   * \brief  Assemble all the given arguments to create a udp pkt.
00399   * It is assumed there is enough space pointed to by result.
00400   */
00401 
00402 static void
00403 assembleUdpPkt (Pkt_UdpHdr_t * result,
00404         u_int16_t srcPort,
00405         u_int16_t destPort,
00406         u_int16_t checkSum, util_byte_array_t * payload)
00407 {
00408   result->srcPort = srcPort;
00409   result->destPort = destPort;
00410 
00411   memcpy (((char *) result) + sizeof (Pkt_UdpHdr_t), payload->bytes,
00412       payload->length);
00413 
00414   result->checkSum = checkSum;
00415   result->length = payload->length + sizeof (Pkt_UdpHdr_t);
00416 }
00417 
00418 
00419 /**
00420   * \brief  Assemble all the given arguments to create a tcp pkt.
00421   *
00422   * It is assumed there is enough space pointed to by result
00423   */
00424 
00425 static void
00426 assembleTcpPkt (Pkt_TcpHdr_t * result,
00427         u_int16_t srcPort,
00428         u_int16_t destPort,
00429         u_int32_t seqNum,
00430         u_int32_t ackNum,
00431         Pkt_TcpResDoffFlags_t resDoffFlags,
00432         u_int16_t advWindow,
00433         u_int16_t checkSum,
00434         u_int16_t urgPtr, util_byte_array_t * payload)
00435 {
00436   assert (resDoffFlags.doff >= 5);  // hdr length, multiples 4 bytes -> min is 5
00437   result->srcPort = srcPort;
00438   result->destPort = destPort;
00439 
00440   result->seqNum = seqNum;
00441   result->ackNum = ackNum;
00442 
00443   result->res1 = resDoffFlags.res1;
00444   result->doff = resDoffFlags.doff;
00445 
00446   result->fin = resDoffFlags.fin;
00447   result->syn = resDoffFlags.syn;
00448   result->rst = resDoffFlags.rst;
00449   result->psh = resDoffFlags.psh;
00450   result->ack = resDoffFlags.ack;
00451   result->urg = resDoffFlags.urg;
00452   result->ece = resDoffFlags.ece;
00453   result->cwr = resDoffFlags.cwr;
00454 
00455   result->advWindow = advWindow;
00456   result->checkSum = checkSum;
00457   result->urgPtr = urgPtr;
00458 
00459   memcpy (((char *) result) + (result->doff) * 4, payload->bytes,
00460       payload->length);
00461 
00462 }
00463 
00464 
00465 /**
00466   * \brief  Create a IP packet
00467   * 
00468   * User defines the "interesting" source and dest IP addresses.
00469   * If any of these arrays are empty, we take the corresponding field 
00470   * to be unconstrained.  
00471   *
00472   * Payload is constructed by calling function, which is responsible for freeing it.
00473   */
00474 
00475 util_byte_array_t *
00476 Pkt_CreateIpPkt (array_t * srcIps,
00477          array_t * destIps,
00478          st_table * ipFlagsTable,
00479          array_t * offsets,
00480          array_t * ids,
00481          st_table * ipOptions,
00482          array_t * ttls,
00483          util_byte_array_t * l4Payload, int l4Protocol)
00484 {
00485   int optionsLength = computeOptionsLength (ipOptions);
00486   u_int8_t ihl;
00487   if ((optionsLength % 4) == 0)
00488     {
00489       ihl = 5 + (optionsLength / 4);
00490     }
00491   else
00492     {
00493       ihl = 5 + 1 + (optionsLength / 4);
00494     }
00495   u_int8_t version = 4;     // IPv4 only
00496   u_int8_t TOS = 0;     // not checked in the rules, using 0 
00497   u_int16_t checksum = 0;   // not checked in the rules, using 0
00498 
00499   u_int32_t srcIp;
00500   u_int32_t destIp;
00501 
00502   u_int16_t length;
00503 
00504   u_int16_t offset;     // will be converted to a 13 bit quantity
00505   u_int16_t id;
00506   u_int8_t ttl = 1;
00507   u_int8_t prot;
00508 
00509   Pkt_IpFlags_t ipFlags;
00510   /// \todo make direct user settable
00511   float direct = 1.0;
00512   int index;
00513   if ((srcIps != NIL (array_t)) && (array_n (srcIps) != 0)
00514       && (util_unit_rand () < direct))
00515     {
00516       index = util_rand_int () % array_n (srcIps);
00517       srcIp = array_fetch (u_int32_t, srcIps, index);
00518     }
00519   else
00520     {
00521       srcIp = (u_int32_t) util_rand_int ();
00522     }
00523   if ((destIps != NIL (array_t)) && (array_n (destIps) != 0)
00524       && (util_unit_rand () < direct))
00525     {
00526       index = util_rand_int () % array_n (destIps);
00527       destIp = array_fetch (u_int32_t, destIps, index);
00528     }
00529   else
00530     {
00531       destIp = (u_int32_t) util_rand_int ();
00532     }
00533 
00534   length =
00535     l4Payload->length + sizeof (Pkt_IpHdr_t) +
00536     computeOptionsLength (ipOptions);
00537 
00538   if ((offsets != NIL (array_t)) && (array_n (offsets) != 0)
00539       && (util_unit_rand () < direct))
00540     {
00541       index = util_rand_int () % array_n (offsets);
00542       offset = array_fetch (int, offsets, index);
00543     }
00544   else
00545     {
00546       offset = util_rand_int () % (2 << 13);
00547     }
00548 
00549   if ((ids != NIL (array_t)) && (array_n (ids) != 0)
00550       && (util_unit_rand () < direct))
00551     {
00552       id = util_rand_int () % array_n (ids);
00553       id = array_fetch (int, ids, index);
00554     }
00555   else
00556     {
00557       id = util_rand_int () % (2 << 16);
00558     }
00559 
00560   if ((ttls != NIL (array_t)) && (array_n (ttls) != 0)
00561       && (util_unit_rand () < direct))
00562     {
00563       index = util_rand_int () % array_n (ttls);
00564       ttl = array_fetch (u_int8_t, ttls, index);
00565     }
00566   else
00567     {
00568       ttl = util_rand_int () % (2 << 8);
00569     }
00570   ipFlags.offset = offset;
00571 
00572   int val;
00573   ipFlags.RB = Hash_Lookup (ipFlagsTable, (char *) "RB", (char **) &val) ? val :
00574     0;
00575   ipFlags.DF = Hash_Lookup (ipFlagsTable, (char *) "DF", (char **) &val) ? val :
00576     0;
00577   ipFlags.MF = Hash_Lookup (ipFlagsTable, (char *) "MF", (char **) &val) ? val :
00578     0;
00579 
00580   prot = l4Protocol;
00581 
00582   util_byte_array_t *result =
00583     (util_byte_array_t *) malloc (sizeof (util_byte_array_t));
00584   result->bytes = (char *) malloc (length);
00585   result->length = length;
00586   assembleIpPkt ((Pkt_IpHdr_t *) result->bytes,
00587          ihl,
00588          version,
00589          TOS,
00590          length,
00591          id,
00592          ipFlags,
00593          ipOptions, ttl, prot, checksum, srcIp, destIp, l4Payload);
00594 
00595   return result;
00596 }
00597 
00598 
00599 /**
00600   * \brief Create Ethernet packet with given params
00601   */
00602 
00603 Pkt_EthernetHdr_t *
00604 Pkt_CreateEthPkt (char *srcMac,
00605           char *destMac,
00606           util_byte_array_t * l3Payload, u_int16_t l3Protocol)
00607 {
00608   char *result = (char *) malloc (sizeof (Pkt_EthernetHdr_t) + l3Payload->length);
00609   memcpy (result, srcMac, 6);
00610   memcpy (result + 6, destMac, 6);
00611 
00612   *((u_int16_t *) (result + 12)) = l3Protocol;
00613   memcpy (result + sizeof (Pkt_EthernetHdr_t), l3Payload->bytes,
00614       l3Payload->length);
00615 
00616   return (Pkt_EthernetHdr_t *) result;
00617 }
00618 
00619 
00620 /**
00621   * \brief  Assemble an IP pkt out of the given components
00622   * 
00623   * \todo todo Add ip options
00624   */
00625 
00626 static void
00627 assembleIpPkt (Pkt_IpHdr_t * pkt,
00628            u_int8_t ihl,
00629            u_int8_t version,
00630            u_int8_t TOS,
00631            u_int16_t length,
00632            u_int16_t id,
00633            Pkt_IpFlags_t ipFlags,
00634            st_table * ipOptions,
00635            u_int8_t TTL,
00636            u_int8_t protocol,
00637            u_int16_t checksum,
00638            u_int32_t sourceIp,
00639            u_int32_t destIp, util_byte_array_t * payload)
00640 {
00641   pkt->ihl = ihl;
00642   pkt->version = version;
00643   pkt->TOS = TOS;
00644   pkt->length = length;
00645   pkt->id = id;
00646   pkt->RB = ipFlags.RB;
00647   pkt->DF = ipFlags.DF;
00648   pkt->MF = ipFlags.MF;
00649   pkt->offset = ipFlags.offset;
00650   pkt->TTL = TTL;
00651   pkt->protocol = protocol;
00652   pkt->checksum = checksum;
00653   pkt->sourceIp = sourceIp;
00654   pkt->destIp = destIp;
00655 
00656   int optionsLength = computeOptionsLength (ipOptions);
00657   char *optionsPtr = ((char *) pkt) + sizeof (Pkt_IpHdr_t);
00658   char *option;
00659   Hash_ForEachItemNew (ipOptions, (char **) &option, NIL (char * ))
00660   {
00661     if (util_strequal (option, "eol"))
00662       {
00663     *(u_int8_t *) optionsPtr = (u_int8_t) 0;
00664     optionsPtr += 1;
00665       }
00666     else if (util_strequal (option, "nop"))
00667       {
00668     *(u_int8_t *) optionsPtr = (u_int8_t) 1;
00669     optionsPtr += 1;
00670       }
00671     else if (util_strequal (option, "rr"))
00672       {
00673     *(u_int8_t *) optionsPtr = (u_int8_t) 7;
00674     optionsPtr += 1;
00675     *(u_int8_t *) optionsPtr = (u_int8_t) 4;    // length field
00676     optionsPtr += 3;
00677       }
00678     else if (util_strequal (option, "ts"))
00679       {
00680     *(u_int8_t *) optionsPtr = (u_int8_t) 68;
00681     optionsPtr += 1;
00682     *(u_int8_t *) optionsPtr = (u_int8_t) 4;    // length field
00683     optionsPtr += 3;
00684       }
00685     else if (util_strequal (option, "sec"))
00686       {
00687     *(u_int8_t *) optionsPtr = (u_int8_t) 130;
00688     optionsPtr += 1;
00689     *(u_int8_t *) optionsPtr = (u_int8_t) 4;    // length field
00690     optionsPtr += 3;
00691       }
00692     else if (util_strequal (option, "lsrr"))
00693       {
00694     *(u_int8_t *) optionsPtr = (u_int8_t) 131;
00695     optionsPtr += 1;
00696     *(u_int8_t *) optionsPtr = (u_int8_t) 4;    // length field
00697     optionsPtr += 3;
00698       }
00699     else if (util_strequal (option, "ssrr"))
00700       {
00701     *(u_int8_t *) optionsPtr = (u_int8_t) 137;
00702     optionsPtr += 1;
00703     *(u_int8_t *) optionsPtr = (u_int8_t) 4;    // length field
00704     optionsPtr += 3;
00705       }
00706     else if (util_strequal (option, "satid"))
00707       {
00708     *(u_int8_t *) optionsPtr = (u_int8_t) 136;
00709     optionsPtr += 1;
00710     *(u_int8_t *) optionsPtr = (u_int8_t) 4;    // length field
00711     optionsPtr += 3;
00712       }
00713   }
00714 
00715   char *pktPayload = Pkt_IpExtractPayload (pkt);
00716   // pad the 0-3 remaining bytes with eop
00717   while (optionsPtr != pktPayload)
00718     {
00719       *(u_int8_t *) optionsPtr = (u_int8_t) 0;
00720       optionsPtr++;
00721     }
00722 
00723   int headerLength = ihl * 4;
00724   memcpy (pktPayload, payload->bytes, length - headerLength);
00725 }
00726 
00727 
00728 /**
00729   * \brief  Create a random ethernet packet
00730   * 
00731   * For other systems, use Pkt_NetworkByteOrder_c for packet
00732   * For narya, use Pkt_HostByteOrder_c for packet
00733   * 
00734   * numSeeds is the number of packets that the routine
00735   * uses for seeding the array.
00736   */
00737 
00738 Pkt_EthernetHdr_t *
00739 Pkt_CreateRandEthPkt (array_t * tmpArray)
00740 {
00741   static int index = 0;
00742 
00743   Pkt_EthernetHdr_t *result =
00744     array_fetch (Pkt_EthernetHdr_t *, tmpArray, index);
00745   index = (index + 1) % array_n (tmpArray);
00746 
00747   return result;
00748 }
00749 
00750 
00751 /** \brief  Create a random ethernet packet; only tcp for now.  */
00752 
00753 array_t *
00754 Pkt_SeedRandEthPktArray (Pkt_ByteOrder_t byteOrder,
00755              int numSeeds, Pkt_TfcMode_t * tfcMode)
00756 {
00757   array_t *interestingSourcePorts = array_alloc (u_int16_t, 0);
00758   array_t *interestingDestPorts = array_alloc (u_int16_t, 0);
00759   array_t *interestingSeqNumbers = array_alloc (u_int32_t, 0);
00760   array_t *interestingAckNumbers = array_alloc (u_int32_t, 0);
00761   st_table *tcpFlags = Hash_InitTable ( ( int(*)() ) strcmp, ( int(*)() ) st_strhash);
00762   array_t *sizes = array_alloc (int, 0);
00763   array_t *byteStrings = array_alloc (util_byte_array_t *, 0);
00764 
00765   // 21 = ftp
00766   array_insert_last (u_int16_t, interestingSourcePorts, (u_int16_t) 21);
00767 
00768   array_insert_last (u_int16_t, interestingDestPorts, (u_int16_t) 80);
00769 
00770   array_insert_last (u_int32_t, interestingSeqNumbers, 101058054);
00771 
00772   array_insert_last (u_int32_t, interestingAckNumbers, 0);
00773 
00774   // if ack is present in tcpFlags, corresp value is used, else set randomly
00775   // same for other flags
00776   Hash_Insert (tcpFlags, "fin", 0);
00777   Hash_Insert (tcpFlags, "syn", 0);
00778   Hash_Insert (tcpFlags, "rst", 0);
00779   Hash_Insert (tcpFlags, "psh", 0);
00780   Hash_Insert (tcpFlags, "ack", 0);
00781   Hash_Insert (tcpFlags, "urg", 0);
00782   Hash_Insert (tcpFlags, "ece", 0);
00783   Hash_Insert (tcpFlags, "cwr", 0);
00784 
00785   // sizes is the size of the payload of the encapsulated tcp packet
00786   // array_insert_last( int, sizes, 1446 );
00787   array_insert_last (int, sizes, tfcMode->size);
00788 
00789   util_byte_array_t *testByteString1 = util_byte_array_create ("foobar", 6);
00790   array_insert_last (util_byte_array_t *, byteStrings, testByteString1);
00791   util_byte_array_t *testByteString2 = util_byte_array_create ("adnan!", 6);
00792   array_insert_last (util_byte_array_t *, byteStrings, testByteString2);
00793 
00794   array_t *srcIps = array_alloc (u_int32_t, 0);
00795   array_t *destIps = array_alloc (u_int32_t, 0);
00796   st_table *ipFlags = Hash_InitTable ( ( int(*)() ) strcmp, ( int(*)() ) st_strhash);
00797   st_table *ipOptions = Hash_InitTable ( ( int(*)() ) strcmp, ( int(*)() ) st_strhash);
00798   array_t *offsets = array_alloc (u_int16_t, 0);
00799   array_t *ids = array_alloc (u_int16_t, 0);
00800   array_t *ttls = array_alloc (u_int8_t, 0);
00801   array_t *protocols = array_alloc (u_int8_t, 0);
00802 
00803   array_insert_last (u_int32_t, srcIps, (u_int32_t) 3232235876);
00804   array_insert_last (u_int32_t, destIps, 3232235786);
00805 
00806   // all ip flags are set to 0
00807   Hash_Insert (ipFlags, "RB", (char *) 0);
00808   Hash_Insert (ipFlags, "DF", (char *) 0);
00809   Hash_Insert (ipFlags, "MF", (char *) 0);
00810 
00811   array_insert_last (u_int16_t, offsets, 0);
00812   array_insert_last (u_int16_t, ids, 0);
00813   array_insert_last (u_int8_t, ttls, 255);
00814   array_insert_last (u_int8_t, protocols, 6);
00815 
00816   array_t *pktArray = array_alloc (Pkt_EthernetHdr_t *, 0);
00817   int i;
00818   for (i = 0; i < numSeeds; i++)
00819     {
00820       util_byte_array_t *l4Packet =
00821     Pkt_CreateTcpPkt (interestingSourcePorts, interestingDestPorts,
00822               interestingSeqNumbers, interestingAckNumbers,
00823               tcpFlags, sizes, byteStrings);
00824 
00825       util_byte_array_t *l3Packet =
00826     Pkt_CreateIpPkt (srcIps, destIps, ipFlags, offsets, ids, ipOptions,
00827              ttls, l4Packet, Pkt_L4ProtTcp_c);
00828 
00829       assert (l3Packet->length <= 1500);
00830       assert (l3Packet->length >= 20);
00831 
00832       char *srcMac = tfcMode->srcMac;
00833       char *destMac = tfcMode->destMac;
00834 
00835       Pkt_EthernetHdr_t *result =
00836     Pkt_CreateEthPkt (srcMac, destMac, l3Packet, Pkt_L3ProtIp_c);
00837 
00838       memcpy ((char *) result + sizeof (Pkt_EthernetHdr_t), l3Packet->bytes,
00839           l3Packet->length);
00840       free (l3Packet);
00841       if (byteOrder == Pkt_NetworkByteOrder_c)
00842     {
00843       Pkt_HTON (result);
00844     }
00845       array_insert_last (Pkt_EthernetHdr_t *, pktArray, result);
00846     }
00847 
00848   return pktArray;
00849 }
00850 
00851 
00852 /**
00853   * \brief  Take an ethernet packet and convert it to network order.
00854   *
00855   * \todo make this work with other protocols, currently only support ip-tcp
00856   */
00857 
00858 void
00859 Pkt_HTON (Pkt_EthernetHdr_t * anEth)
00860 {
00861   if (anEth->type != Pkt_L3ProtIp_c)
00862     {
00863       return;
00864     }
00865   Pkt_IpHdr_t *anIp = Pkt_EthernetExtractIp (anEth);
00866 
00867   /// \todo figure out why
00868   /// for some reason, it seems the translation should not
00869   /// touch the ethernet type
00870   /// anEth->type = htons( anEth->type );
00871 
00872   anIp->length = htons (anIp->length);
00873   anIp->id = htons (anIp->id);
00874 
00875   u_int16_t *RDMoffsetPtr = ((u_int16_t *) ((char *) anIp + 6));
00876   *RDMoffsetPtr = htons (*RDMoffsetPtr);
00877 
00878   anIp->checksum = htons (anIp->checksum);
00879 
00880   anIp->sourceIp = htonl (anIp->sourceIp);
00881   anIp->destIp = htonl (anIp->destIp);
00882 
00883   if (anIp->protocol != Pkt_L4ProtTcp_c)
00884     {
00885       return;
00886     }
00887   Pkt_TcpHdr_t *aTcp = Pkt_IpExtractTcp (anIp);
00888 
00889   aTcp->srcPort = htons (aTcp->srcPort);
00890   aTcp->destPort = htons (aTcp->destPort);
00891 
00892   aTcp->seqNum = htonl (aTcp->seqNum);
00893   aTcp->ackNum = htonl (aTcp->ackNum);
00894 
00895   u_int16_t *resdoffPtr USE = ((u_int16_t *) ((char *) aTcp + 12));
00896   /// \todo
00897   ///other systems seems to think that the reserved 4 bits and the offset 4 bits
00898   ///are a single byte (see decode.h), and the flags are another byte.
00899   ///this contradicts /usr/include/linux/tcp.h, where the two are a single
00900   ///u_int16_t.  i've turned off the htons to conform with other systems
00901   ///*resdoffPtr = htons( *resdoffPtr );
00902 
00903   aTcp->advWindow = htons (aTcp->advWindow);
00904   aTcp->checkSum = htons (aTcp->checkSum);
00905   aTcp->urgPtr = htons (aTcp->urgPtr);
00906 
00907   return;
00908 }
00909 
00910 
00911 /**
00912   * \brief  Take an ethernet packet and convert it to host order.
00913   *
00914   * \todo need to support other protocols beyond just tcp and ip
00915   */
00916 
00917 void
00918 Pkt_NTOH (Pkt_EthernetHdr_t * anEth)
00919 {
00920   /// \todo seems ethernet type field is not
00921   /// tranlated to network order, vice versa
00922   /// anEth->type = ntohs( anEth->type );
00923 
00924   if (anEth->type != Pkt_L3ProtIp_c)
00925     {
00926       return;
00927     }
00928 
00929   // layer 3 
00930   Pkt_IpHdr_t *anIp = Pkt_EthernetExtractIp (anEth);
00931   anIp->length = ntohs (anIp->length);
00932   anIp->id = ntohs (anIp->id);
00933 
00934   u_int16_t *RDMoffsetPtr = ((u_int16_t *) ((char *) anIp + 6));
00935   *RDMoffsetPtr = ntohs (*RDMoffsetPtr);
00936 
00937   anIp->checksum = ntohs (anIp->checksum);
00938 
00939   anIp->sourceIp = ntohl (anIp->sourceIp);
00940   anIp->destIp = ntohl (anIp->destIp);
00941 
00942   if (anIp->protocol != Pkt_L4ProtTcp_c)
00943     {
00944       return;
00945     }
00946 
00947   // layer 4
00948   Pkt_TcpHdr_t *aTcp = Pkt_IpExtractTcp (anIp);
00949   aTcp->srcPort = ntohs (aTcp->srcPort);
00950   aTcp->destPort = ntohs (aTcp->destPort);
00951   aTcp->seqNum = ntohl (aTcp->seqNum);
00952   aTcp->ackNum = ntohl (aTcp->ackNum);
00953 
00954   u_int16_t *resdoffPtr USE = ((u_int16_t *) ((char *) aTcp + 12));
00955   /// \todo
00956   /// other systems seems to think that the reserved 4 bits and the offset 4 bits
00957   /// are a single byte (see decode.h), and the flags are another byte.
00958   /// this contradicts /usr/include/linux/tcp.h, where the two are a single
00959   /// u_int16_t.  i've turned off the htons to conform with other systems
00960   /// *resdoffPtr = htons( *resdoffPtr );
00961 
00962   aTcp->advWindow = ntohs (aTcp->advWindow);
00963   aTcp->checkSum = ntohs (aTcp->checkSum);
00964   aTcp->urgPtr = ntohs (aTcp->urgPtr);
00965 
00966   return;
00967 }
00968 
00969 
00970 /** \brief Compute the length of the ip options we are supposed to set */
00971 
00972 static int
00973 computeOptionsLength (st_table * ipoptions)
00974 {
00975   int result = 0;
00976 
00977   char *option;
00978   Hash_ForEachItemNew (ipoptions, (char **) &option, NIL (char *))
00979   {
00980     if (util_strequal (option, "eol") || util_strequal (option, "nop"))
00981       {
00982     result += 1;
00983       }
00984     else
00985       {
00986     result += 4;        // not taking variable lenght options now
00987       }
00988   }
00989   return result;
00990 }