ipv6: simplify ext hdr parsing and storage

This reduces size of the IPV6ExtHdr structure part of every packet
significantly.

Clean up macro's in the ipv6 header.
pull/2086/head
Victor Julien 10 years ago
parent 64405ae194
commit 68c7fae79f

@ -113,6 +113,14 @@ DecodeIPV6ExtHdrs(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt
char dstopts = 0;
char exthdr_fh_done = 0;
uint8_t ip6_exthdrs_cnt = 0;
IPV6GenOptHdr ip6_exthdrs[IPV6_MAX_OPT];
int hh = 0;
int rh = 0;
int eh = 0;
int ah = 0;
nh = IPV6_GET_NH(p);
plen = len;
@ -161,16 +169,16 @@ DecodeIPV6ExtHdrs(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt
SCReturn;
}
if (p->IPV6_EH_CNT < IPV6_MAX_OPT)
if (ip6_exthdrs_cnt < IPV6_MAX_OPT)
{
p->IPV6_EXTHDRS[p->IPV6_EH_CNT].type = nh;
p->IPV6_EXTHDRS[p->IPV6_EH_CNT].next = *pkt;
p->IPV6_EXTHDRS[p->IPV6_EH_CNT].len = hdrextlen;
p->IPV6_EXTHDRS[p->IPV6_EH_CNT].data = pkt+2;
p->IPV6_EH_CNT++;
ip6_exthdrs[ip6_exthdrs_cnt].type = nh;
ip6_exthdrs[ip6_exthdrs_cnt].next = *pkt;
ip6_exthdrs[ip6_exthdrs_cnt].len = hdrextlen;
ip6_exthdrs[ip6_exthdrs_cnt].data = pkt+2;
ip6_exthdrs_cnt++;
}
if (IPV6_EXTHDR_ISSET_RH(p)) {
if (rh) {
ENGINE_SET_EVENT(p, IPV6_EXTHDR_DUPL_RH);
/* skip past this extension so we can continue parsing the rest
* of the packet */
@ -180,26 +188,14 @@ DecodeIPV6ExtHdrs(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt
break;
}
IPV6_EXTHDR_SET_RH(p, pkt);
/** \todo move into own function and load on demand */
if (IPV6_EXTHDR_RH(p)->ip6rh_type == 0) {
#if 0 // XXX usused and broken, original packet is modified in the memcpy
uint8_t i;
uint8_t n = hdrextlen / 2;
/* because we devide the header len by 2 (as rfc 2460 tells us to)
* we devide the result by 8 and not 16 as the header fields are
* sized */
for (i = 0; i < (n/8) && i < sizeof(IPV6_EXTHDR_RH(p)->ip6rh0_addr)/sizeof(struct in6_addr); ++i) {
/* the address header fields are 16 bytes in size */
/** \todo do this without memcpy since it's expensive */
memcpy(&IPV6_EXTHDR_RH(p)->ip6rh0_addr[i], pkt+(i*16)+8, sizeof(IPV6_EXTHDR_RH(p)->ip6rh0_addr[i]));
}
IPV6_EXTHDR_RH(p)->ip6rh0_num_addrs = i;
#endif
rh = 1;
IPV6_EXTHDR_SET_RH(p);
uint8_t ip6rh_type = *(pkt + 2);
if (ip6rh_type == 0) {
ENGINE_SET_EVENT(p, IPV6_EXTHDR_RH_TYPE_0);
}
p->ip6eh.rh_type = ip6rh_type;
nh = *pkt;
pkt += hdrextlen;
@ -209,9 +205,9 @@ DecodeIPV6ExtHdrs(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt
case IPPROTO_HOPOPTS:
case IPPROTO_DSTOPTS:
{
IPV6OptHAO *hao = NULL;
IPV6OptRA *ra = NULL;
IPV6OptJumbo *jumbo = NULL;
IPV6OptHAO hao_s, *hao = &hao_s;
IPV6OptRA ra_s, *ra = &ra_s;
IPV6OptJumbo jumbo_s, *jumbo = &jumbo_s;
uint16_t optslen = 0;
IPV6_SET_L4PROTO(p,nh);
@ -221,13 +217,13 @@ DecodeIPV6ExtHdrs(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt
SCReturn;
}
if (p->IPV6_EH_CNT < IPV6_MAX_OPT)
if (ip6_exthdrs_cnt < IPV6_MAX_OPT)
{
p->IPV6_EXTHDRS[p->IPV6_EH_CNT].type = nh;
p->IPV6_EXTHDRS[p->IPV6_EH_CNT].next = *pkt;
p->IPV6_EXTHDRS[p->IPV6_EH_CNT].len = hdrextlen;
p->IPV6_EXTHDRS[p->IPV6_EH_CNT].data = pkt+2;
p->IPV6_EH_CNT++;
ip6_exthdrs[ip6_exthdrs_cnt].type = nh;
ip6_exthdrs[ip6_exthdrs_cnt].next = *pkt;
ip6_exthdrs[ip6_exthdrs_cnt].len = hdrextlen;
ip6_exthdrs[ip6_exthdrs_cnt].data = pkt+2;
ip6_exthdrs_cnt++;
}
uint8_t *ptr = pkt + 2; /* +2 to go past nxthdr and len */
@ -235,7 +231,7 @@ DecodeIPV6ExtHdrs(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt
/* point the pointers to right structures
* in Packet. */
if (nh == IPPROTO_HOPOPTS) {
if (IPV6_EXTHDR_ISSET_HH(p)) {
if (hh) {
ENGINE_SET_EVENT(p, IPV6_EXTHDR_DUPL_HH);
/* skip past this extension so we can continue parsing the rest
* of the packet */
@ -245,28 +241,17 @@ DecodeIPV6ExtHdrs(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt
break;
}
IPV6_EXTHDR_SET_HH(p, pkt);
hao = &IPV6_EXTHDR_HH_HAO(p);
ra = &IPV6_EXTHDR_HH_RA(p);
jumbo = &IPV6_EXTHDR_HH_JUMBO(p);
hh = 1;
optslen = ((IPV6_EXTHDR_HH(p)->ip6hh_len+1)<<3)-2;
optslen = ((*(pkt + 1) + 1 ) << 3) - 2;
}
else if (nh == IPPROTO_DSTOPTS)
{
if (dstopts == 0) {
IPV6_EXTHDR_SET_DH1(p, pkt);
hao = &IPV6_EXTHDR_DH1_HAO(p);
ra = &IPV6_EXTHDR_DH1_RA(p);
jumbo = &IPV6_EXTHDR_DH2_JUMBO(p);
optslen = ((IPV6_EXTHDR_DH1(p)->ip6dh_len+1)<<3)-2;
optslen = ((*(pkt + 1) + 1 ) << 3) - 2;
dstopts = 1;
} else if (dstopts == 1) {
IPV6_EXTHDR_SET_DH2(p, pkt);
hao = &IPV6_EXTHDR_DH2_HAO(p);
ra = &IPV6_EXTHDR_DH2_RA(p);
jumbo = &IPV6_EXTHDR_DH2_JUMBO(p);
optslen = ((IPV6_EXTHDR_DH2(p)->ip6dh_len+1)<<3)-2;
optslen = ((*(pkt + 1) + 1 ) << 3) - 2;
dstopts = 2;
} else {
ENGINE_SET_EVENT(p, IPV6_EXTHDR_DUPL_DH);
@ -424,13 +409,13 @@ DecodeIPV6ExtHdrs(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt
/* non fatal, lets try to continue */
}
if(p->IPV6_EH_CNT<IPV6_MAX_OPT)
if(ip6_exthdrs_cnt<IPV6_MAX_OPT)
{
p->IPV6_EXTHDRS[p->IPV6_EH_CNT].type = nh;
p->IPV6_EXTHDRS[p->IPV6_EH_CNT].next = *pkt;
p->IPV6_EXTHDRS[p->IPV6_EH_CNT].len = hdrextlen;
p->IPV6_EXTHDRS[p->IPV6_EH_CNT].data = pkt+2;
p->IPV6_EH_CNT++;
ip6_exthdrs[ip6_exthdrs_cnt].type = nh;
ip6_exthdrs[ip6_exthdrs_cnt].next = *pkt;
ip6_exthdrs[ip6_exthdrs_cnt].len = hdrextlen;
ip6_exthdrs[ip6_exthdrs_cnt].data = pkt+2;
ip6_exthdrs_cnt++;
}
if (IPV6_EXTHDR_ISSET_FH(p)) {
@ -441,14 +426,49 @@ DecodeIPV6ExtHdrs(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt
break;
}
/* set the header ptr first */
IPV6_EXTHDR_SET_FH(p, pkt);
/* set the header flag first */
IPV6_EXTHDR_SET_FH(p);
uint16_t frag_offset = (*(pkt + 2) << 8 | *(pkt + 3)) & 0xFFF8;
int frag_morefrags = (*(pkt + 2) << 8 | *(pkt + 3)) & 0x0001;
p->ip6eh.fh_offset = frag_offset;
p->ip6eh.fh_more_frags_set = frag_morefrags ? TRUE : FALSE;
p->ip6eh.fh_nh = *pkt;
uint32_t fh_id;
memcpy(&fh_id, pkt+4, 4);
p->ip6eh.fh_id = ntohl(fh_id);
SCLogDebug("IPV6 FH: offset %u, mf %s, nh %u, id %u/%x",
p->ip6eh.fh_offset,
p->ip6eh.fh_more_frags_set ? "true" : "false",
p->ip6eh.fh_nh,
p->ip6eh.fh_id, p->ip6eh.fh_id);
// store header offset, data offset
uint16_t frag_hdr_offset = (uint16_t)(pkt - GET_PKT_DATA(p));
uint16_t data_offset = (uint16_t)(frag_hdr_offset + hdrextlen);
uint16_t data_len = plen - hdrextlen;
p->ip6eh.fh_header_offset = frag_hdr_offset;
p->ip6eh.fh_data_offset = data_offset;
p->ip6eh.fh_data_len = data_len;
/* if we have a prev hdr, store the type and offset of it */
if (ip6_exthdrs_cnt > 1) {
p->ip6eh.fh_prev_hdr_offset = frag_hdr_offset - ip6_exthdrs[ip6_exthdrs_cnt - 1].len;
}
SCLogDebug("IPV6 FH: frag_hdr_offset %u, data_offset %u, data_len %u",
p->ip6eh.fh_header_offset, p->ip6eh.fh_data_offset,
p->ip6eh.fh_data_len);
/* if FH has offset 0 and no more fragments are coming, we
* parse this packet further right away, no defrag will be
* needed. It is a useless FH then though, so we do set an
* decoder event. */
if (IPV6_EXTHDR_GET_FH_FLAG(p) == 0 && IPV6_EXTHDR_GET_FH_OFFSET(p) == 0) {
if (frag_morefrags == 0 && frag_offset == 0) {
ENGINE_SET_EVENT(p, IPV6_EXTHDR_USELESS_FH);
nh = *pkt;
@ -470,21 +490,21 @@ DecodeIPV6ExtHdrs(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt
SCReturn;
}
if(p->IPV6_EH_CNT<IPV6_MAX_OPT)
if(ip6_exthdrs_cnt<IPV6_MAX_OPT)
{
p->IPV6_EXTHDRS[p->IPV6_EH_CNT].type = nh;
p->IPV6_EXTHDRS[p->IPV6_EH_CNT].next = IPPROTO_NONE;
p->IPV6_EXTHDRS[p->IPV6_EH_CNT].len = hdrextlen;
p->IPV6_EXTHDRS[p->IPV6_EH_CNT].data = pkt+2;
p->IPV6_EH_CNT++;
ip6_exthdrs[ip6_exthdrs_cnt].type = nh;
ip6_exthdrs[ip6_exthdrs_cnt].next = IPPROTO_NONE;
ip6_exthdrs[ip6_exthdrs_cnt].len = hdrextlen;
ip6_exthdrs[ip6_exthdrs_cnt].data = pkt+2;
ip6_exthdrs_cnt++;
}
if (IPV6_EXTHDR_ISSET_EH(p)) {
if (eh) {
ENGINE_SET_EVENT(p, IPV6_EXTHDR_DUPL_EH);
SCReturn;
}
IPV6_EXTHDR_SET_EH(p, pkt);
eh = 1;
nh = IPPROTO_NONE;
pkt += hdrextlen;
@ -513,16 +533,16 @@ DecodeIPV6ExtHdrs(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt
ENGINE_SET_EVENT(p, IPV6_EXTHDR_AH_RES_NOT_NULL);
}
if(p->IPV6_EH_CNT < IPV6_MAX_OPT)
if(ip6_exthdrs_cnt < IPV6_MAX_OPT)
{
p->IPV6_EXTHDRS[p->IPV6_EH_CNT].type = nh;
p->IPV6_EXTHDRS[p->IPV6_EH_CNT].next = *pkt;
p->IPV6_EXTHDRS[p->IPV6_EH_CNT].len = hdrextlen;
p->IPV6_EXTHDRS[p->IPV6_EH_CNT].data = pkt+2;
p->IPV6_EH_CNT++;
ip6_exthdrs[ip6_exthdrs_cnt].type = nh;
ip6_exthdrs[ip6_exthdrs_cnt].next = *pkt;
ip6_exthdrs[ip6_exthdrs_cnt].len = hdrextlen;
ip6_exthdrs[ip6_exthdrs_cnt].data = pkt+2;
ip6_exthdrs_cnt++;
}
if (IPV6_EXTHDR_ISSET_AH(p)) {
if (ah) {
ENGINE_SET_EVENT(p, IPV6_EXTHDR_DUPL_AH);
nh = *pkt;
pkt += hdrextlen;
@ -530,7 +550,7 @@ DecodeIPV6ExtHdrs(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt
break;
}
IPV6_EXTHDR_SET_AH(p, pkt);
ah = 1;
nh = *pkt;
pkt += hdrextlen;
@ -677,30 +697,6 @@ int DecodeIPV6(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, u
}
}
#ifdef DEBUG
if (IPV6_EXTHDR_ISSET_FH(p)) {
SCLogDebug("IPV6 FRAG - HDRLEN: %" PRIuMAX " NH: %" PRIu32 " OFFSET: %" PRIu32 " ID: %" PRIu32 "",
(uintmax_t)IPV6_EXTHDR_GET_FH_HDRLEN(p), IPV6_EXTHDR_GET_FH_NH(p),
IPV6_EXTHDR_GET_FH_OFFSET(p), IPV6_EXTHDR_GET_FH_ID(p));
}
if (IPV6_EXTHDR_ISSET_RH(p)) {
SCLogDebug("IPV6 ROUTE - HDRLEN: %" PRIu32 " NH: %" PRIu32 " TYPE: %" PRIu32 "",
IPV6_EXTHDR_GET_RH_HDRLEN(p), IPV6_EXTHDR_GET_RH_NH(p),
IPV6_EXTHDR_GET_RH_TYPE(p));
}
if (IPV6_EXTHDR_ISSET_HH(p)) {
SCLogDebug("IPV6 HOPOPT - HDRLEN: %" PRIu32 " NH: %" PRIu32 "",
IPV6_EXTHDR_GET_HH_HDRLEN(p), IPV6_EXTHDR_GET_HH_NH(p));
}
if (IPV6_EXTHDR_ISSET_DH1(p)) {
SCLogDebug("IPV6 DSTOPT1 - HDRLEN: %" PRIu32 " NH: %" PRIu32 "",
IPV6_EXTHDR_GET_DH1_HDRLEN(p), IPV6_EXTHDR_GET_DH1_NH(p));
}
if (IPV6_EXTHDR_ISSET_DH2(p)) {
SCLogDebug("IPV6 DSTOPT2 - HDRLEN: %" PRIu32 " NH: %" PRIu32 "",
IPV6_EXTHDR_GET_DH2_HDRLEN(p), IPV6_EXTHDR_GET_DH2_NH(p));
}
#endif
return TM_ECODE_OK;
}
@ -879,7 +875,6 @@ end:
*/
static int DecodeIPV6RouteTest01 (void)
{
uint8_t raw_pkt1[] = {
0x60, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x2b, 0x40,
0x20, 0x01, 0xaa, 0xaa, 0x00, 0x01, 0x00, 0x00,
@ -893,11 +888,9 @@ static int DecodeIPV6RouteTest01 (void)
0xfa, 0x87, 0x00, 0x00,
};
Packet *p1 = PacketGetFromAlloc();
if (unlikely(p1 == NULL))
return 0;
FAIL_IF(unlikely(p1 == NULL));
ThreadVars tv;
DecodeThreadVars dtv;
int result = 0;
PacketQueue pq;
FlowInitConfig(FLOW_QUIET);
@ -910,22 +903,12 @@ static int DecodeIPV6RouteTest01 (void)
DecodeIPV6(&tv, &dtv, p1, GET_PKT_DATA(p1), GET_PKT_LEN(p1), &pq);
if (!(IPV6_EXTHDR_ISSET_RH(p1))) {
printf("ipv6 routing header not detected: ");
goto end;
}
if (p1->ip6eh.ip6_exthdrs[0].len != 8) {
printf("ipv6 routing length incorrect: ");
goto end;
}
result = 1;
end:
FAIL_IF (!(IPV6_EXTHDR_ISSET_RH(p1)));
FAIL_IF (p1->ip6eh.rh_type != 0);
PACKET_RECYCLE(p1);
SCFree(p1);
FlowShutdown();
return result;
PASS;
}
/**
@ -936,16 +919,15 @@ static int DecodeIPV6HopTest01 (void)
uint8_t raw_pkt1[] = {
0x60,0x00,0x00,0x00,0x00,0x20,0x00,0x01,0xfe,0x80,0x00,0x00,0x00,0x00,0x00,0x00,
0x02,0x0f,0xfe,0xff,0xfe,0x98,0x3d,0x01,0xff,0x02,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x3a,0x00,0x05,0x02,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x3a,0x00,0xff, /* 0xff is a nonsene opt */
0x02,0x00,0x00,0x00,0x00,
0x82,0x00,0x1c,0x6f,0x27,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
Packet *p1 = PacketGetFromAlloc();
if (unlikely(p1 == NULL))
return 0;
FAIL_IF(unlikely(p1 == NULL));
ThreadVars tv;
DecodeThreadVars dtv;
int result = 0;
PacketQueue pq;
FlowInitConfig(FLOW_QUIET);
@ -958,27 +940,12 @@ static int DecodeIPV6HopTest01 (void)
DecodeIPV6(&tv, &dtv, p1, GET_PKT_DATA(p1), GET_PKT_LEN(p1), &pq);
if (!(IPV6_EXTHDR_ISSET_HH(p1))) {
printf("ipv6 routing header not detected: ");
goto end;
}
if (p1->ip6eh.ip6_exthdrs[0].len != 8) {
printf("ipv6 routing length incorrect: ");
goto end;
}
FAIL_IF (!(ENGINE_ISSET_EVENT(p1, IPV6_HOPOPTS_UNKNOWN_OPT)));
if (ENGINE_ISSET_EVENT(p1, IPV6_HOPOPTS_UNKNOWN_OPT)) {
printf("engine event IPV6_HOPOPTS_UNKNOWN_OPT set: ");
goto end;
}
result = 1;
end:
PACKET_RECYCLE(p1);
SCFree(p1);
FlowShutdown();
return result;
PASS;
}
#endif /* UNITTESTS */

@ -109,14 +109,7 @@ typedef struct IPV6Vars_
(p)->ip6h = NULL; \
(p)->ip6vars.ip_opts_len = 0; \
(p)->ip6vars.l4proto = 0; \
(p)->ip6eh.ip6fh = NULL; \
(p)->ip6eh.fh_offset = 0; \
(p)->ip6eh.ip6rh = NULL; \
(p)->ip6eh.ip6eh = NULL; \
(p)->ip6eh.ip6dh1 = NULL; \
(p)->ip6eh.ip6dh2 = NULL; \
(p)->ip6eh.ip6hh = NULL; \
(p)->ip6eh.ip6_exthdrs_cnt = 0; \
memset(&(p)->ip6eh, 0x00, sizeof((p)->ip6eh)); \
} while (0)
/* Fragment header */
@ -128,17 +121,10 @@ typedef struct IPV6FragHdr_
uint32_t ip6fh_ident; /* identification */
} __attribute__((__packed__)) IPV6FragHdr;
#define IPV6_EXTHDR_GET_RAW_FH_NH(p) ((p)->ip6eh.ip6fh->ip6fh_nxt)
#define IPV6_EXTHDR_GET_RAW_FH_HDRLEN(p) sizeof(IPV6FragHdr)
#define IPV6_EXTHDR_GET_RAW_FH_OFFSET(p) (ntohs((p)->ip6eh.ip6fh->ip6fh_offlg) & 0xFFF8)
#define IPV6_EXTHDR_GET_RAW_FH_FLAG(p) (ntohs((p)->ip6eh.ip6fh->ip6fh_offlg) & 0x0001)
#define IPV6_EXTHDR_GET_RAW_FH_ID(p) (ntohl((p)->ip6eh.ip6fh->ip6fh_ident))
#define IPV6_EXTHDR_GET_FH_NH(p) IPV6_EXTHDR_GET_RAW_FH_NH((p))
#define IPV6_EXTHDR_GET_FH_HDRLEN(p) IPV6_EXTHDR_GET_RAW_FH_HDRLEN((p))
#define IPV6_EXTHDR_GET_FH_OFFSET(p) IPV6_EXTHDR_GET_RAW_FH_OFFSET((p))
#define IPV6_EXTHDR_GET_FH_FLAG(p) IPV6_EXTHDR_GET_RAW_FH_FLAG((p))
#define IPV6_EXTHDR_GET_FH_ID(p) IPV6_EXTHDR_GET_RAW_FH_ID((p))
#define IPV6_EXTHDR_GET_FH_NH(p) (p)->ip6eh.fh_nh
#define IPV6_EXTHDR_GET_FH_OFFSET(p) (p)->ip6eh.fh_offset
#define IPV6_EXTHDR_GET_FH_FLAG(p) (p)->ip6eh.fh_more_frags_set
#define IPV6_EXTHDR_GET_FH_ID(p) (p)->ip6eh.fh_id
/* rfc 1826 */
typedef struct IPV6AuthHdr_
@ -164,24 +150,8 @@ typedef struct IPV6RouteHdr_
including first 8 bytes. */
uint8_t ip6rh_type; /* routing type */
uint8_t ip6rh_segsleft; /* segments left */
#if 0
struct in6_addr ip6rh0_addr[23]; /* type 0 addresses */
uint8_t ip6rh0_num_addrs; /* number of actual addresses in the
array/packet. The array is guarranteed
to be filled up to this number. */
#endif
} __attribute__((__packed__)) IPV6RouteHdr;
#define IPV6_EXTHDR_GET_RAW_RH_NH(p) ((p)->ip6eh.ip6rh->ip6rh_nxt)
#define IPV6_EXTHDR_GET_RAW_RH_HDRLEN(p) ((p)->ip6eh.ip6rh->ip6rh_len)
#define IPV6_EXTHDR_GET_RAW_RH_TYPE(p) (ntohs((p)->ip6eh.ip6rh->ip6rh_type))
/* XXX */
#define IPV6_EXTHDR_GET_RH_NH(p) IPV6_EXTHDR_GET_RAW_RH_NH((p))
#define IPV6_EXTHDR_GET_RH_HDRLEN(p) IPV6_EXTHDR_GET_RAW_RH_HDRLEN((p))
#define IPV6_EXTHDR_GET_RH_TYPE(p) IPV6_EXTHDR_GET_RAW_RH_TYPE((p))
/* XXX */
/* Hop-by-Hop header and Destination Options header use options that are
* defined here. */
@ -223,14 +193,6 @@ typedef struct IPV6HopOptsHdr_
including first 8 bytes. */
} __attribute__((__packed__)) IPV6HopOptsHdr;
#define IPV6_EXTHDR_GET_RAW_HH_NH(p) ((p)->ip6eh.ip6hh->ip6hh_nxt)
#define IPV6_EXTHDR_GET_RAW_HH_HDRLEN(p) ((p)->ip6eh.ip6hh->ip6hh_len)
/* XXX */
#define IPV6_EXTHDR_GET_HH_NH(p) IPV6_EXTHDR_GET_RAW_HH_NH((p))
#define IPV6_EXTHDR_GET_HH_HDRLEN(p) IPV6_EXTHDR_GET_RAW_HH_HDRLEN((p))
/* XXX */
typedef struct IPV6DstOptsHdr_
{
uint8_t ip6dh_nxt; /* next header */
@ -238,22 +200,6 @@ typedef struct IPV6DstOptsHdr_
including first 8 bytes. */
} __attribute__((__packed__)) IPV6DstOptsHdr;
#define IPV6_EXTHDR_GET_RAW_DH1_NH(p) ((p)->ip6eh.ip6dh1->ip6dh_nxt)
#define IPV6_EXTHDR_GET_RAW_DH1_HDRLEN(p) ((p)->ip6eh.ip6dh1->ip6dh_len)
/* XXX */
#define IPV6_EXTHDR_GET_DH1_NH(p) IPV6_EXTHDR_GET_RAW_DH1_NH((p))
#define IPV6_EXTHDR_GET_DH1_HDRLEN(p) IPV6_EXTHDR_GET_RAW_DH1_HDRLEN((p))
/* XXX */
#define IPV6_EXTHDR_GET_RAW_DH2_NH(p) ((p)->ip6eh.ip6dh2->ip6dh_nxt)
#define IPV6_EXTHDR_GET_RAW_DH2_HDRLEN(p) ((p)->ip6eh.ip6dh2->ip6dh_len)
/* XXX */
#define IPV6_EXTHDR_GET_DH2_NH(p) IPV6_EXTHDR_GET_RAW_DH2_NH((p))
#define IPV6_EXTHDR_GET_DH2_HDRLEN(p) IPV6_EXTHDR_GET_RAW_DH2_HDRLEN((p))
/* XXX */
typedef struct IPV6GenOptHdr_
{
uint8_t type;
@ -264,69 +210,32 @@ typedef struct IPV6GenOptHdr_
typedef struct IPV6ExtHdrs_
{
const IPV6FragHdr *ip6fh;
_Bool rh_set;
uint8_t rh_type;
_Bool fh_set;
_Bool fh_more_frags_set;
uint8_t fh_nh;
uint8_t fh_prev_nh;
uint16_t fh_prev_hdr_offset;
uint16_t fh_header_offset;
uint16_t fh_data_offset;
uint16_t fh_data_len;
/* In fh_offset we store the offset of this extension into the packet past
* the ipv6 header. We use it in defrag for creating a defragmented packet
* without the frag header */
uint16_t fh_offset;
const IPV6RouteHdr *ip6rh;
const IPV6AuthHdr *ip6ah;
const IPV6EspHdr *ip6eh;
const IPV6DstOptsHdr *ip6dh1;
const IPV6DstOptsHdr *ip6dh2;
const IPV6HopOptsHdr *ip6hh;
/* Hop-By-Hop options */
IPV6OptHAO ip6hh_opt_hao;
IPV6OptRA ip6hh_opt_ra;
IPV6OptJumbo ip6hh_opt_jumbo;
/* Dest Options 1 */
IPV6OptHAO ip6dh1_opt_hao;
IPV6OptRA ip6dh1_opt_ra;
IPV6OptJumbo ip6dh1_opt_jumbo;
/* Dest Options 2 */
IPV6OptHAO ip6dh2_opt_hao;
IPV6OptRA ip6dh2_opt_ra;
IPV6OptJumbo ip6dh2_opt_jumbo;
IPV6GenOptHdr ip6_exthdrs[IPV6_MAX_OPT];
uint8_t ip6_exthdrs_cnt;
uint16_t fh_offset;
uint32_t fh_id;
} IPV6ExtHdrs;
#define IPV6_EXTHDR_FH(p) (p)->ip6eh.ip6fh
#define IPV6_EXTHDR_RH(p) (p)->ip6eh.ip6rh
#define IPV6_EXTHDR_AH(p) (p)->ip6eh.ip6ah
#define IPV6_EXTHDR_EH(p) (p)->ip6eh.ip6eh
#define IPV6_EXTHDR_DH1(p) (p)->ip6eh.ip6dh1
#define IPV6_EXTHDR_DH2(p) (p)->ip6eh.ip6dh2
#define IPV6_EXTHDR_HH(p) (p)->ip6eh.ip6hh
#define IPV6_EXTHDR_HH_HAO(p) (p)->ip6eh.ip6hh_opt_hao
#define IPV6_EXTHDR_DH1_HAO(p) (p)->ip6eh.ip6dh1_opt_hao
#define IPV6_EXTHDR_DH2_HAO(p) (p)->ip6eh.ip6dh2_opt_hao
#define IPV6_EXTHDR_HH_RA(p) (p)->ip6eh.ip6hh_opt_ra
#define IPV6_EXTHDR_DH1_RA(p) (p)->ip6eh.ip6dh1_opt_ra
#define IPV6_EXTHDR_DH2_RA(p) (p)->ip6eh.ip6dh2_opt_ra
#define IPV6_EXTHDR_HH_JUMBO(p) (p)->ip6eh.ip6hh_opt_jumbo
#define IPV6_EXTHDR_DH1_JUMBO(p) (p)->ip6eh.ip6dh1_opt_jumbo
#define IPV6_EXTHDR_DH2_JUMBO(p) (p)->ip6eh.ip6dh2_opt_jumbo
#define IPV6_EXTHDR_SET_FH(p,pkt) IPV6_EXTHDR_FH((p)) = (IPV6FragHdr *)pkt
#define IPV6_EXTHDR_ISSET_FH(p) (IPV6_EXTHDR_FH((p)) != NULL)
#define IPV6_EXTHDR_SET_RH(p,pkt) IPV6_EXTHDR_RH((p)) = (IPV6RouteHdr *)pkt
#define IPV6_EXTHDR_ISSET_RH(p) (IPV6_EXTHDR_RH((p)) != NULL)
#define IPV6_EXTHDR_SET_AH(p,pkt) IPV6_EXTHDR_AH((p)) = (IPV6AuthHdr *)pkt
#define IPV6_EXTHDR_ISSET_AH(p) (IPV6_EXTHDR_AH((p)) != NULL)
#define IPV6_EXTHDR_SET_EH(p,pkt) IPV6_EXTHDR_EH((p)) = (IPV6EspHdr *)pkt
#define IPV6_EXTHDR_ISSET_EH(p) (IPV6_EXTHDR_EH((p)) != NULL)
#define IPV6_EXTHDR_SET_DH1(p,pkt) IPV6_EXTHDR_DH1((p)) = (IPV6DstOptsHdr *)pkt
#define IPV6_EXTHDR_ISSET_DH1(p) (IPV6_EXTHDR_DH1((p)) != NULL)
#define IPV6_EXTHDR_SET_DH2(p,pkt) IPV6_EXTHDR_DH2((p)) = (IPV6DstOptsHdr *)pkt
#define IPV6_EXTHDR_ISSET_DH2(p) (IPV6_EXTHDR_DH2((p)) != NULL)
#define IPV6_EXTHDR_SET_HH(p,pkt) IPV6_EXTHDR_HH((p)) = (IPV6HopOptsHdr *)pkt
#define IPV6_EXTHDR_ISSET_HH(p) (IPV6_EXTHDR_HH((p)) != NULL)
#define IPV6_EXTHDR_SET_FH(p) (p)->ip6eh.fh_set = TRUE
#define IPV6_EXTHDR_ISSET_FH(p) (p)->ip6eh.fh_set
#define IPV6_EXTHDR_SET_RH(p) (p)->ip6eh.rh_set = TRUE
#define IPV6_EXTHDR_ISSET_RH(p) (p)->ip6eh.rh_set
void DecodeIPV6RegisterTests(void);

@ -559,26 +559,27 @@ DefragInsertFrag(ThreadVars *tv, DecodeThreadVars *dtv, DefragTracker *tracker,
else if (tracker->af == AF_INET6) {
more_frags = IPV6_EXTHDR_GET_FH_FLAG(p);
frag_offset = IPV6_EXTHDR_GET_FH_OFFSET(p);
data_offset = (uint8_t *)p->ip6eh.ip6fh + sizeof(IPV6FragHdr) - GET_PKT_DATA(p);
data_len = IPV6_GET_PLEN(p) - (
((uint8_t *)p->ip6eh.ip6fh + sizeof(IPV6FragHdr)) -
((uint8_t *)p->ip6h + sizeof(IPV6Hdr)));
data_offset = p->ip6eh.fh_data_offset;
data_len = p->ip6eh.fh_data_len;
frag_end = frag_offset + data_len;
ip_hdr_offset = (uint8_t *)p->ip6h - GET_PKT_DATA(p);
frag_hdr_offset = (uint8_t *)p->ip6eh.ip6fh - GET_PKT_DATA(p);
frag_hdr_offset = p->ip6eh.fh_header_offset;
SCLogDebug("mf %s frag_offset %u data_offset %u, data_len %u, "
"frag_end %u, ip_hdr_offset %u, frag_hdr_offset %u",
more_frags ? "true" : "false", frag_offset, data_offset,
data_len, frag_end, ip_hdr_offset, frag_hdr_offset);
/* handle unfragmentable exthdrs */
if (ip_hdr_offset + IPV6_HEADER_LEN < frag_hdr_offset) {
SCLogDebug("we have exthdrs before fraghdr %u bytes (%u hdrs total)",
(uint32_t)(frag_hdr_offset - (ip_hdr_offset + IPV6_HEADER_LEN)),
p->ip6eh.ip6_exthdrs_cnt);
SCLogDebug("we have exthdrs before fraghdr %u bytes",
(uint32_t)(frag_hdr_offset - (ip_hdr_offset + IPV6_HEADER_LEN)));
/* get the offset of the 'next' field in exthdr before the FH,
* relative to the buffer start */
int t_offset = (int)((p->ip6eh.ip6_exthdrs[p->ip6eh.ip6_exthdrs_cnt - 2].data - 2) - GET_PKT_DATA(p));
/* store offset and FH 'next' value for updating frag buffer below */
ip6_nh_set_offset = (int)t_offset;
ip6_nh_set_offset = p->ip6eh.fh_prev_hdr_offset;
ip6_nh_set_value = IPV6_EXTHDR_GET_FH_NH(p);
SCLogDebug("offset %d, value %u", ip6_nh_set_offset, ip6_nh_set_value);
}
@ -1109,7 +1110,6 @@ IPV6BuildTestPacket(uint32_t id, uint16_t off, int mf, const char content,
fh->ip6fh_nxt = IPPROTO_ICMP;
fh->ip6fh_ident = htonl(id);
fh->ip6fh_offlg = htons((off << 3) | mf);
p->ip6eh.ip6fh = fh;
pcontent = SCCalloc(1, content_len);
if (unlikely(pcontent == NULL))

@ -87,7 +87,7 @@ int DetectFragOffsetMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet
if (PKT_IS_IPV4(p)) {
frag = IPV4_GET_IPOFFSET(p);
} else if (PKT_IS_IPV6(p)) {
if(IPV6_EXTHDR_FH(p)) {
if (IPV6_EXTHDR_ISSET_FH(p)) {
frag = IPV6_EXTHDR_GET_FH_OFFSET(p);
} else {
return 0;

Loading…
Cancel
Save