Main Page | Modules | Class List | Directories | File List | Class Members | File Members | Related Pages

flow.c

Go to the documentation of this file.
00001 /**
00002  * @file   flow.c
00003  * @author Chris Green <cmg@sourcefire.com>
00004  * @date   Thu May 29 15:38:05 2003
00005  * 
00006  * @brief  FLOW and associated operations
00007  * 
00008  * 
00009  */
00010 
00011 #ifdef HAVE_CONFIG_H
00012 #include "config.h"
00013 #endif
00014 
00015 #include "flow.h"
00016 #include "flow_stat.h"
00017 #include "flow_print.h"
00018 
00019 #include <stdlib.h>
00020 #include <string.h> /* for memcpy */
00021 
00022 int flow_init(FLOW *flow,
00023               char protocol,
00024               u_int32_t init_address,
00025               u_int16_t init_port,
00026               u_int32_t resp_address,
00027               u_int16_t resp_port)
00028 {
00029     if(flow == NULL)
00030     {
00031         return FLOW_ENULL;
00032     }
00033 
00034     flow->key.protocol = protocol;
00035     flow->key.init_address = init_address;
00036     flow->key.init_port = init_port;
00037     flow->key.resp_address = resp_address;
00038     flow->key.resp_port = resp_port;
00039 
00040     if(flowstat_clear(&flow->stats))
00041     {
00042         flow_printf("unable to clear flow stats\n");
00043         return FLOW_EINVALID;
00044     }
00045 
00046     /** have not done anything with the flow->data section yet */
00047     return FLOW_SUCCESS;
00048 }
00049 
00050 /** 
00051  * Calloc a FLOW object of the right type -- this function is not needed
00052  *
00053  * @param family address family
00054  * @param flow paramter to return the actual flow in
00055  * @param size # of bytes allocated for a new flow
00056  * 
00057  * @return 0 on sucess, else failure
00058  */
00059 int flow_alloc(int family, FLOW **flow, int *size)
00060 {
00061     int tmpsize = sizeof(FLOW);   
00062     FLOW *fp;
00063 
00064     if(!flow || !size)
00065     {
00066         return FLOW_ENULL;
00067     }
00068     
00069     fp = (FLOW *) calloc(1,tmpsize);
00070 
00071     if(fp == NULL)
00072     {
00073         *size = 0;
00074         return FLOW_ENOMEM;
00075     }
00076 
00077     *size = tmpsize;
00078     *flow = fp;
00079 
00080     return FLOW_SUCCESS;
00081     
00082 }
00083 
00084 /** 
00085  * Given a packet, generate a key.
00086  *
00087  * @todo ICMP errors on an existing flow
00088  * 
00089  * @param key where to set the key
00090  * @param p Packet to make a key from
00091  * 
00092  * @return FLOW_SUCCESS on success, else failure
00093  */
00094 int flowkey_make(FLOWKEY *key, FLOWPACKET *p)
00095 {
00096     u_int8_t proto;
00097     
00098     if(!key || !p)
00099         return FLOW_ENULL;
00100 
00101     memset(key, 0, sizeof(FLOWKEY));
00102     
00103     /* IPV4 path */
00104     if(IsIPv4Packet(p))
00105     {
00106         proto = GetIPv4Proto(p);
00107         
00108         switch(proto)
00109         {
00110         case IPPROTO_TCP:
00111         case IPPROTO_UDP:
00112             key->init_port = GetIPv4SrcPort(p);
00113             key->resp_port = GetIPv4DstPort(p);
00114         default:
00115             key->protocol = proto;
00116             key->init_address = GetIPv4SrcIp(p);
00117             key->resp_address = GetIPv4DstIp(p);
00118         }
00119 
00120         return FLOW_SUCCESS;
00121     }
00122 
00123     return FLOW_EINVALID;
00124 }
00125 
00126 
00127 /** 
00128  * print out a key to a file stream
00129  * 
00130  * @param key what to print
00131  * 
00132  * @return 0 on sucess
00133  */
00134 int flowkey_print(FLOWKEY *key)
00135 {
00136     flow_printf(" Protocol   : %d", key->protocol);
00137     flow_printf(" InitAddress: %s", inet_ntoa(*(struct in_addr *) &key->init_address));
00138     flow_printf(" InitPort   : %d", key->init_port);
00139     flow_printf(" RespAddress: %s", inet_ntoa(*(struct in_addr *) &key->resp_address));
00140     flow_printf(" RespPort   : %d", key->resp_port);
00141     return 0;
00142 }
00143 
00144 /** 
00145  * Copy into dst from src and normalize the results so that things
00146  * will hash to the same entry no matter what.
00147  *
00148  * This should only be used for SEARCHING as it doesn't store much else.
00149  * 
00150  * @param dst where to copy to
00151  * @param src where to copy from
00152  */
00153 int flowkey_normalize(FLOWKEY *dst, const FLOWKEY *src)
00154 {
00155     
00156     /* normal memcpy */
00157     dst->protocol  = src->protocol;
00158 
00159     if(src->init_address > src->resp_address)
00160     {
00161         dst->resp_port    = src->init_port;
00162         dst->init_port    = src->resp_port;
00163         dst->init_address = src->resp_address;
00164         dst->resp_address = src->init_address;
00165     }
00166     else
00167     {
00168         dst->init_port   = src->init_port;
00169         dst->resp_port   = src->resp_port;
00170         dst->init_address = src->init_address;
00171         dst->resp_address = src->resp_address;
00172     }
00173 
00174     return 0;
00175 }
00176 
00177 /** 
00178  * perform key comparison
00179  * 
00180  * @param s1 pointer to A
00181  * @param s2 pointer to B
00182  * @param n size of each node
00183  * 
00184  * @return 0 if they are equal, else they aren't equal
00185  */
00186 int flowkeycmp_fcn(const void *s1, const void *s2, size_t n)
00187 {
00188     FLOWKEY *a = (FLOWKEY *) s1;
00189     FLOWKEY *b = (FLOWKEY *) s2;
00190 
00191     if(a->init_port != b->init_port)
00192         return -1;
00193 
00194     if(a->init_address != b->init_address)
00195         return -1;
00196 
00197     if(a->resp_address != b->resp_address)
00198         return -1;
00199 
00200     if(a->resp_port != b->resp_port)
00201         return -1;
00202 
00203     if(a->protocol != b->protocol)
00204         return -1;
00205     
00206     return 0;
00207 }
00208 

Generated on Sun May 14 14:51:15 2006 by  doxygen 1.4.2