packet_parser.c

Go to the documentation of this file.
00001 /*
00002  ** Copyright(C) 2003-2006 - INL
00003  ** Written by Eric Leblond <regit@inl.fr>
00004  **            Victor Stinner <haypo@inl.fr>
00005  ** INL http://www.inl.fr/
00006  **
00007  ** $Id: packet_parser.c 4847 2008-06-13 14:48:31Z regit $
00008  **
00009  ** This program is free software; you can redistribute it and/or modify
00010  ** it under the terms of the GNU General Public License as published by
00011  ** the Free Software Foundation, version 3 of the License.
00012  **
00013  ** This program is distributed in the hope that it will be useful,
00014  ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  ** GNU General Public License for more details.
00017  **
00018  ** You should have received a copy of the GNU General Public License
00019  ** along with this program; if not, write to the Free Software
00020  ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00021  */
00022 
00036 #include "packet_parser.h"
00037 
00038 #include <netinet/tcp.h>
00039 #include <netinet/ip.h>
00040 #include <netinet/ip6.h>
00041 #include <netinet/udp.h>
00042 #include <netinet/ip_icmp.h>
00043 #include <netinet/icmp6.h>
00044 
00045 #include <config.h>
00046 
00056 unsigned int get_ip_headers(tracking_t * tracking,
00057                             const unsigned char *dgram,
00058                             unsigned int dgram_size)
00059 {
00060 #ifdef LINUX
00061         struct iphdr *ip = (struct iphdr *) dgram;
00062 #endif
00063 #ifdef FREEBSD
00064         struct ip *ip = (struct ip*) dgram;
00065 #endif
00066         struct ip6_hdr *ip6 = (struct ip6_hdr *) dgram;
00067         unsigned int offset;
00068 
00069         /* check ip headers minimum size */
00070 #ifdef LINUX
00071         if (dgram_size < sizeof(struct iphdr))
00072 #elif defined(FREEBSD)
00073         if (dgram_size < sizeof(struct ip))
00074 #endif
00075                 return 0;
00076 
00077         /* check IP version (should be IPv4) */
00078 #ifdef LINUX
00079         if (ip->version == 4) {
00080                 /* convert IPv4 addresses to IPv6 addresses in format "::ffff:IPv4" */
00081                 uint32_to_ipv6(ip->saddr, &tracking->saddr);
00082                 uint32_to_ipv6(ip->daddr, &tracking->daddr);
00083 
00084                 /* compute offset to next header and copy protocol */
00085                 offset = 4 * ip->ihl;
00086                 tracking->protocol = ip->protocol;
00087 
00088 #ifdef TRACKING_WITH_PAYLOAD
00089                 /* copy payload if any, or fill payload with zero bytes */
00090                 if ((offset + sizeof(tracking->payload)) <= dgram_size)
00091                         memcpy(tracking->payload, dgram + offset,
00092                                sizeof(tracking->payload));
00093                 else
00094                         memset(tracking->payload, 0,
00095                                sizeof(tracking->payload));
00096 #endif /* #ifdef TRACKING_WITH_PAYLOAD */
00097         } else if (ip->version == 6) {
00098 #else
00099         if (ip->ip_v == 4) {
00100                 /* convert IPv4 addresses to IPv6 addresses in format "::ffff:IPv4" */
00101                 uint32_to_ipv6(ip->ip_src.s_addr, &tracking->saddr);
00102                 uint32_to_ipv6(ip->ip_dst.s_addr, &tracking->daddr);
00103 
00104                 /* compute offset to next header and copy protocol */
00105                 offset = 4 * ip->ip_hl;
00106                 tracking->protocol = ip->ip_p;
00107 
00108 #ifdef TRACKING_WITH_PAYLOAD
00109                 /* copy payload if any, or fill payload with zero bytes */
00110                 if ((offset + sizeof(tracking->payload)) <= dgram_size)
00111                         memcpy(tracking->payload, dgram + offset,
00112                                sizeof(tracking->payload));
00113                 else
00114                         memset(tracking->payload, 0,
00115                                sizeof(tracking->payload));
00116 #endif //#ifdef TRACKING_WITH_PAYLOAD
00117         } else if (ip->ip_v == 6) {
00118 #endif
00119 
00120 
00121                 unsigned char found_transport_layer = 0;
00122 #ifdef TRACKING_WITH_PAYLOAD
00123                 unsigned char copy_payload = 1;
00124 #endif
00125                 struct ip6_ext *generic_hdr;
00126                 struct ip6_frag *frag_hdr;
00127 
00128                 /* check buffer underflow */
00129                 if (dgram_size < sizeof(struct ip6_hdr))
00130                         return 0;
00131 
00132                 /* copy ipv6 addresses */
00133                 tracking->saddr = ip6->ip6_src;
00134                 tracking->daddr = ip6->ip6_dst;
00135 
00136                 /* copy protocol */
00137                 tracking->protocol = ip6->ip6_nxt;
00138 
00139                 /* compute offset of next interresting header (udp/tcp/icmp):
00140                  * skip custom ipv6 headers like Hop-by-hop */
00141                 offset = sizeof(struct ip6_hdr);        /* offset=40 */
00142                 found_transport_layer = 0;
00143                 do {
00144                         switch (tracking->protocol) {
00145                         case IPPROTO_HOPOPTS:
00146                         case IPPROTO_ROUTING:
00147                         case IPPROTO_DSTOPTS:
00148                         case IPPROTO_AH:
00149                                 /* we can use generic extension header since we just need
00150                                  * next header and length of this header */
00151                                 generic_hdr =
00152                                     (struct ip6_ext *) (dgram + offset);
00153                                 tracking->protocol = generic_hdr->ip6e_nxt;
00154                                 offset +=
00155                                     (unsigned int) (generic_hdr->
00156                                                     ip6e_len) * 8;
00157                                 break;
00158 
00159                         case IPPROTO_FRAGMENT:
00160                                 frag_hdr =
00161                                     (struct ip6_frag *) (dgram + offset);
00162                                 tracking->protocol = frag_hdr->ip6f_nxt;
00163                                 offset += 8;    /* fragment header has fixed size */
00164                                 break;
00165 
00166                         case IPPROTO_ESP:
00167                         case IPPROTO_NONE:
00168                                 /*
00169                                  * - RFC 2460 asks to ignore payload is last "Next Header"
00170                                  *   is IPPROTO_NONE.
00171                                  * - For ESP, it's not possible to extract any useful
00172                                  *   informations to match ACLs
00173                                  */
00174 #ifdef TRACKING_WITH_PAYLOAD
00175                                 copy_payload = 0;
00176 #endif
00177                                 found_transport_layer = 1;
00178                                 break;
00179 
00180                         default:
00181                                 /* TCP, UDP, ICMP */
00182                                 found_transport_layer = 1;
00183                                 break;
00184                         }
00185                 } while (!found_transport_layer);
00186 
00187 #ifdef TRACKING_WITH_PAYLOAD
00188                 if ((offset + sizeof(tracking->payload)) <= dgram_size
00189                     && copy_payload) {
00190                         memcpy(tracking->payload, dgram + offset,
00191                                sizeof(tracking->payload));
00192                 } else {
00193                         memset(tracking->payload, 0,
00194                                sizeof(tracking->payload));
00195                 }
00196 #endif
00197         } else {
00198                 offset = 0;
00199         }
00200         return offset;
00201 }
00202 
00212 int get_udp_headers(tracking_t * tracking, const unsigned char *dgram,
00213                     unsigned int dgram_size)
00214 {
00215 #ifdef LINUX
00216         struct udphdr *udp = (struct udphdr *) dgram;
00217 
00218         /* check udp headers minimum size */
00219         if (dgram_size < sizeof(struct udphdr))
00220                 return -1;
00221 
00222         tracking->source = ntohs(udp->source);
00223         tracking->dest = ntohs(udp->dest);
00224         tracking->type = 0;
00225         tracking->code = 0;
00226 #else
00227         /* TODO ;) */
00228 #endif
00229         return 0;
00230 }
00231 
00232 
00244 tcp_state_t get_tcp_headers(tracking_t * tracking,
00245                             const unsigned char *dgram,
00246                             unsigned int dgram_size)
00247 {
00248 #ifdef LINUX
00249         struct tcphdr *tcp = (struct tcphdr *) dgram;
00250 
00251         /* check icmp headers minimum size */
00252         if (dgram_size < sizeof(struct tcphdr))
00253                 return TCP_STATE_UNKNOW;
00254 
00255         tracking->source = ntohs(tcp->source);
00256         tracking->dest = ntohs(tcp->dest);
00257         tracking->type = 0;
00258         tracking->code = 0;
00259 
00260         /* test if fin ack or syn */
00261         /* if fin ack return 0 end of connection */
00262         if (tcp->fin || tcp->rst)
00263                 return TCP_STATE_CLOSE;
00264 
00265         /* if syn return 1 */
00266         if (tcp->syn) {
00267                 if (tcp->ack) {
00268                         return TCP_STATE_ESTABLISHED;
00269                 } else {
00270                         return TCP_STATE_OPEN;
00271                 }
00272         }
00273 #else
00274         /* TODO :P */
00275 #endif
00276         return TCP_STATE_UNKNOW;
00277 }
00278 
00288 int get_icmp_headers(tracking_t * tracking, const unsigned char *dgram,
00289                      unsigned int dgram_size)
00290 {
00291 #ifdef LINUX
00292         struct icmphdr *icmp = (struct icmphdr *) dgram;
00293 
00294         /* check udp headers minimum size */
00295         if (dgram_size < sizeof(struct icmphdr))
00296                 return -1;
00297 
00298         tracking->source = 0;
00299         tracking->dest = 0;
00300         tracking->type = icmp->type;
00301         tracking->code = icmp->code;
00302 #else
00303         /* TODO ! */
00304 #endif
00305         return 0;
00306 }
00307 
00317 int get_icmpv6_headers(tracking_t * tracking, const unsigned char *dgram,
00318                        unsigned int dgram_size)
00319 {
00320         struct icmp6_hdr *hdr = (struct icmp6_hdr *) dgram;
00321 
00322         /* check icmp headers minimum size */
00323         if (dgram_size < sizeof(struct icmp6_hdr))
00324                 return -1;
00325 
00326         tracking->source = 0;
00327         tracking->dest = 0;
00328         tracking->type = hdr->icmp6_type;
00329         tracking->code = hdr->icmp6_code;
00330         return 0;
00331 }
00332 

Generated on Sat Nov 22 04:00:37 2008 for NuFW by  doxygen 1.4.7