You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
suricata/src/decode.h

320 lines
8.7 KiB
C

/* Copyright (c) 2008 Victor Julien <victor@inliniac.net> */
#ifndef __DECODE_H__
#define __DECODE_H__
//#define IPQ
#define NFQ
//#define IPFW
//#define PCAP
//#define DEBUG
#define DBG_PERF
//#define DBG_THREADS
#define COUNTERS
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include "threadvars.h"
#ifdef NFQ
#include "source-nfq.h"
#endif /* NFQ */
#include "decode-ethernet.h"
#include "decode-ipv4.h"
#include "decode-ipv6.h"
#include "decode-icmpv4.h"
#include "decode-icmpv6.h"
#include "decode-tcp.h"
#include "decode-http.h"
/* Address */
typedef struct _Address
{
char family;
union {
u_int32_t address_un_data32[4]; /* type-specific field */
u_int16_t address_un_data16[8]; /* type-specific field */
u_int8_t address_un_data8[16]; /* type-specific field */
} address;
} Address;
#define addr_data32 address.address_un_data32
#define addr_data16 address.address_un_data16
#define addr_data8 address.address_un_data8
/* Set the IPv4 addressesinto the Addrs of the Packet.
* Make sure p->ip4h is initialized and validated.
*
* We set the rest of the struct to 0 so we can
* prevent using memset. */
#define SET_IPV4_SRC_ADDR(p,a) { \
(a)->family = AF_INET; \
(a)->addr_data32[0] = (u_int32_t)(p)->ip4h->ip_src.s_addr; \
(a)->addr_data32[1] = 0; \
(a)->addr_data32[2] = 0; \
(a)->addr_data32[3] = 0; \
}
#define SET_IPV4_DST_ADDR(p,a) { \
(a)->family = AF_INET; \
(a)->addr_data32[0] = (u_int32_t)(p)->ip4h->ip_dst.s_addr; \
(a)->addr_data32[1] = 0; \
(a)->addr_data32[2] = 0; \
(a)->addr_data32[3] = 0; \
}
/* Set the IPv6 addressesinto the Addrs of the Packet.
* Make sure p->ip6h is initialized and validated. */
#define SET_IPV6_SRC_ADDR(p,a) { \
(a)->family = AF_INET6; \
(a)->addr_data32[0] = (p)->ip6h->ip6_src[0]; \
(a)->addr_data32[1] = (p)->ip6h->ip6_src[1]; \
(a)->addr_data32[2] = (p)->ip6h->ip6_src[2]; \
(a)->addr_data32[3] = (p)->ip6h->ip6_src[3]; \
}
#define SET_IPV6_DST_ADDR(p,a) { \
(a)->family = AF_INET6; \
(a)->addr_data32[0] = (p)->ip6h->ip6_dst[0]; \
(a)->addr_data32[1] = (p)->ip6h->ip6_dst[1]; \
(a)->addr_data32[2] = (p)->ip6h->ip6_dst[2]; \
(a)->addr_data32[3] = (p)->ip6h->ip6_dst[3]; \
}
/* Set the TCP ports into the Ports of the Packet.
* Make sure p->tcph is initialized and validated. */
#define SET_TCP_SRC_PORT(pkt,prt) { \
SET_PORT(TCP_GET_SRC_PORT((pkt)), *prt); \
}
#define SET_TCP_DST_PORT(pkt,prt) { \
SET_PORT(TCP_GET_DST_PORT((pkt)), *prt); \
}
#define GET_IPV4_SRC_ADDR_U32(p) ((p)->src.addr_data32[0])
#define GET_IPV4_DST_ADDR_U32(p) ((p)->dst.addr_data32[0])
#define GET_IPV4_SRC_ADDR_PTR(p) ((p)->src.addr_data32)
#define GET_IPV4_DST_ADDR_PTR(p) ((p)->dst.addr_data32)
#define GET_IPV6_SRC_ADDR(p) ((p)->src.addr_data32)
#define GET_IPV6_DST_ADDR(p) ((p)->dst.addr_data32)
#define GET_TCP_SRC_PORT(p) ((p)->sp)
#define GET_TCP_DST_PORT(p) ((p)->dp)
/* Port is just a u_int16_t */
typedef u_int16_t Port;
#define SET_PORT(v, p) ((p) = (v))
#define CMP_ADDR(a1,a2) \
(((a1)->addr_data32[3] == (a2)->addr_data32[3] && \
(a1)->addr_data32[2] == (a2)->addr_data32[2] && \
(a1)->addr_data32[1] == (a2)->addr_data32[1] && \
(a1)->addr_data32[0] == (a2)->addr_data32[0]))
#define CMP_PORT(p1,p2) \
((p1 == p2))
#define PKT_IS_IPV4(p) (((p)->ip4h != NULL))
#define PKT_IS_IPV6(p) (((p)->ip6h != NULL))
/* structure to store the sids/gids/etc the detection engine
* found in this packet */
typedef struct _PacketAlert {
u_int8_t gid;
u_int32_t sid;
u_int8_t rev;
u_int8_t class;
u_int8_t prio;
char *msg;
} PacketAlert;
#define PACKET_ALERT_MAX 256
typedef struct _PacketAlerts {
u_int16_t cnt;
PacketAlert alerts[PACKET_ALERT_MAX];
} PacketAlerts;
#define HTTP_URI_MAXCNT 8
#define HTTP_URI_MAXLEN 1024
typedef struct _HttpUri {
/* the raw uri for the packet as set by pcre */
u_int8_t *raw[HTTP_URI_MAXCNT];
u_int16_t raw_size[HTTP_URI_MAXCNT];
/* normalized uri */
u_int8_t norm[HTTP_URI_MAXCNT][HTTP_URI_MAXLEN];
u_int16_t norm_size[HTTP_URI_MAXCNT];
u_int8_t cnt;
} HttpUri;
typedef struct _Packet
{
/* Addresses, Ports and protocol
* these are on top so we can use
* the Packet as a hash key */
Address src;
Address dst;
Port sp;
Port dp;
u_int8_t proto;
struct timeval ts;
/* program flow */
int pickup_q_id;
int verdict_q_id;
/* ready to set verdict counter, only set in root */
u_int8_t rtv_cnt;
/* tunnel packet ref count */
u_int8_t tpr_cnt;
pthread_mutex_t mutex_rtv_cnt;
/* tunnel XXX convert to bitfield*/
int tunnel_pkt;
/* nfq stuff */
#ifdef NFQ
NFQPacketVars nfq_v;
#endif /* NFQ */
/* tunnel stuff */
u_int8_t tunnel_proto;
/* storage */
u_int8_t pkt[65536];
u_int16_t pktlen;
/* flow */
struct _Flow *flow;
u_int8_t flowflags;
/* header pointers */
EthernetHdr *ethh;
IPV4Hdr *ip4h;
IPV4Vars ip4vars;
IPV4Cache ip4c;
IPV6Hdr *ip6h;
IPV6Vars ip6vars;
IPV6Cache ip6c;
IPV6ExtHdrs ip6eh;
ICMPV4Hdr *icmpv4h;
ICMPV6Hdr *icmpv6h;
TCPHdr *tcph;
TCPVars tcpvars;
u_int8_t *tcp_payload;
u_int16_t tcp_payload_len;
/* decoder events: review how many events we have */
u_int8_t events[65535/8];
HttpUri http_uri;
PacketAlerts alerts;
/* IPS action to take */
int action;
/* double linked list ptrs */
struct _Packet *next;
struct _Packet *prev;
/* tunnel/encapsulation handling */
struct _Packet *root; /* in case of tunnel this is a ptr
* to the 'real' packet, the one we
* need to set the verdict on --
* It should always point to the lowest
* packet in a encapsulated packet */
} Packet;
/* clear key vars so we don't need to call the expensive
* memset or bzero
*/
#define CLEAR_PACKET(p) { \
if ((p)->tcph != NULL) { \
CLEAR_TCP_PACKET((p)); \
} \
(p)->ethh = NULL; \
(p)->ip4h = NULL; \
(p)->ip6h = NULL; \
(p)->action = 0; \
(p)->pktlen = 0; \
(p)->tunnel_pkt = 0; \
(p)->rtv_cnt = 0; \
(p)->tpr_cnt = 0; \
(p)->root = NULL; \
(p)->proto = 0; \
(p)->sp = 0; \
(p)->dp = 0; \
(p)->flow = NULL; \
(p)->flowflags = 0; \
(p)->alerts.cnt = 0; \
(p)->http_uri.cnt = 0; \
}
#define ACTION_ACCEPT 0
#define ACTION_DROP 1
#define ACTION_REJECT 2
/* macro's for setting the action
* handle the case of a root packet
* for tunnels */
#define ACCEPT_PACKET(p) ((p)->root ? ((p)->root->action = ACTION_ACCEPT) : ((p)->action = ACTION_ACCEPT))
#define DROP_PACKET(p) ((p)->root ? ((p)->root->action = ACTION_DROP) : ((p)->action = ACTION_DROP))
#define REJECT_PACKET(p) ((p)->root ? ((p)->root->action = ACTION_REJECT) : ((p)->action = ACTION_REJECT))
#define INCR_PKT_RTV(p) \
{ \
mutex_lock((p)->root ? &(p)->root->mutex_rtv_cnt : &(p)->mutex_rtv_cnt); \
((p)->root ? (p)->root->rtv_cnt++ : (p)->rtv_cnt++); \
mutex_unlock((p)->root ? &(p)->root->mutex_rtv_cnt : &(p)->mutex_rtv_cnt); \
}
#define INCR_PKT_TPR(p) \
{ \
mutex_lock((p)->root ? &(p)->root->mutex_rtv_cnt : &(p)->mutex_rtv_cnt); \
((p)->root ? (p)->root->tpr_cnt++ : (p)->tpr_cnt++); \
mutex_unlock((p)->root ? &(p)->root->mutex_rtv_cnt : &(p)->mutex_rtv_cnt); \
}
#define PKT_RTV(p) ((p)->root ? (p)->root->rtv_cnt : (p)->rtv_cnt)
#define PKT_TPR(p) ((p)->root ? (p)->root->tpr_cnt : (p)->tpr_cnt)
#define IS_TUNNEL_ROOT_PKT(p) (((p)->root == NULL && (p)->tunnel_pkt == 1))
#define IS_TUNNEL_PKT(p) (((p)->tunnel_pkt == 1))
#define SET_TUNNEL_PKT(p) ((p)->tunnel_pkt = 1)
#define IS_IPV4_PKT(p) ((p)->ip4h ? 1 : 0)
#define IS_IPV6_PKT(p) ((p)->ip6h ? 1 : 0)
/* decoder functions */
void DecodeTunnel(ThreadVars *, Packet *, u_int8_t *, u_int16_t);
void DecodeIPV4(ThreadVars *, Packet *, u_int8_t *, u_int16_t);
void DecodeIPV6(ThreadVars *, Packet *, u_int8_t *, u_int16_t);
void DecodeICMPV4(ThreadVars *, Packet *, u_int8_t *, u_int16_t);
void DecodeICMPV6(ThreadVars *, Packet *, u_int8_t *, u_int16_t);
void DecodeTCP(ThreadVars *, Packet *, u_int8_t *, u_int16_t);
void DecodeHTTP(ThreadVars *, Packet *, u_int8_t *, u_int16_t);
Packet *SetupPkt (void);
void SetupTunnelPkt(ThreadVars *, Packet *, u_int8_t *, u_int16_t, u_int8_t);
#define DECODER_SET_EVENT(p, e) ((p)->events[(e/8)] |= (1<<(e%8)))
#define DECODER_ISSET_EVENT(p, e) ((p)->events[(e/8)] & (1<<(e%8)))
#endif /* __DECODE_H__ */