spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, int invert)
{
int r=0;
- DEBUGP("esp spi_match:%c 0x%x <= 0x%x <= 0x%x",invert? '!':' ',
- min,spi,max);
+ DEBUGP("esp spi_match:%c 0x%x <= 0x%x <= 0x%x",invert? '!':' ',
+ min,spi,max);
r=(spi >= min && spi <= max) ^ invert;
DEBUGP(" result %s\n",r? "PASS\n" : "FAILED\n");
return r;
const struct net_device *out,
const void *matchinfo,
int offset,
- const void *protohdr,
- u_int16_t datalen,
+ unsigned int protoff,
int *hotdrop)
{
- struct ip_esp_hdr *esp = NULL;
+ struct ip_esp_hdr _esp, *eh = NULL;
const struct ip6t_esp *espinfo = matchinfo;
unsigned int temp;
int len;
len = skb->len - ptr;
temp = 0;
- while (ip6t_ext_hdr(nexthdr)) {
- struct ipv6_opt_hdr *hdr;
- int hdrlen;
+ while (ip6t_ext_hdr(nexthdr)) {
+ struct ipv6_opt_hdr _hdr, *hp;
+ int hdrlen;
DEBUGP("ipv6_esp header iteration \n");
/* Is there enough space for the next ext header? */
- if (len < (int)sizeof(struct ipv6_opt_hdr))
- return 0;
+ if (len < sizeof(struct ipv6_opt_hdr))
+ return 0;
/* No more exthdr -> evaluate */
- if (nexthdr == NEXTHDR_NONE) {
+ if (nexthdr == NEXTHDR_NONE)
break;
- }
/* ESP -> evaluate */
- if (nexthdr == NEXTHDR_ESP) {
+ if (nexthdr == NEXTHDR_ESP) {
temp |= MASK_ESP;
break;
}
- hdr=(struct ipv6_opt_hdr *)skb->data+ptr;
+ hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
+ BUG_ON(hp == NULL);
/* Calculate the header length */
- if (nexthdr == NEXTHDR_FRAGMENT) {
- hdrlen = 8;
- } else if (nexthdr == NEXTHDR_AUTH)
- hdrlen = (hdr->hdrlen+2)<<2;
- else
- hdrlen = ipv6_optlen(hdr);
+ if (nexthdr == NEXTHDR_FRAGMENT)
+ hdrlen = 8;
+ else if (nexthdr == NEXTHDR_AUTH)
+ hdrlen = (hp->hdrlen+2)<<2;
+ else
+ hdrlen = ipv6_optlen(hp);
/* set the flag */
- switch (nexthdr){
- case NEXTHDR_HOP:
- case NEXTHDR_ROUTING:
- case NEXTHDR_FRAGMENT:
- case NEXTHDR_AUTH:
- case NEXTHDR_DEST:
- break;
- default:
- DEBUGP("ipv6_esp match: unknown nextheader %u\n",nexthdr);
- return 0;
- break;
+ switch (nexthdr) {
+ case NEXTHDR_HOP:
+ case NEXTHDR_ROUTING:
+ case NEXTHDR_FRAGMENT:
+ case NEXTHDR_AUTH:
+ case NEXTHDR_DEST:
+ break;
+ default:
+ DEBUGP("ipv6_esp match: unknown nextheader %u\n",nexthdr);
+ return 0;
}
- nexthdr = hdr->nexthdr;
- len -= hdrlen;
- ptr += hdrlen;
- if ( ptr > skb->len ) {
+ nexthdr = hp->nexthdr;
+ len -= hdrlen;
+ ptr += hdrlen;
+ if (ptr > skb->len) {
DEBUGP("ipv6_esp: new pointer too large! \n");
break;
}
- }
+ }
/* ESP header not found */
- if ( temp != MASK_ESP ) return 0;
+ if (temp != MASK_ESP)
+ return 0;
- if (len < (int)sizeof(struct ip_esp_hdr)){
- *hotdrop = 1;
- return 0;
- }
+ if (len < sizeof(struct ip_esp_hdr)) {
+ *hotdrop = 1;
+ return 0;
+ }
- esp = (struct ip_esp_hdr *) (skb->data + ptr);
+ eh = skb_header_pointer(skb, ptr, sizeof(_esp), &_esp);
+ BUG_ON(eh == NULL);
- DEBUGP("IPv6 ESP SPI %u %08X\n", ntohl(esp->spi), ntohl(esp->spi));
+ DEBUGP("IPv6 ESP SPI %u %08X\n", ntohl(eh->spi), ntohl(eh->spi));
- return (esp != NULL)
+ return (eh != NULL)
&& spi_match(espinfo->spis[0], espinfo->spis[1],
- ntohl(esp->spi),
+ ntohl(eh->spi),
!!(espinfo->invflags & IP6T_ESP_INV_SPI));
}
espinfo->invflags);
return 0;
}
-
return 1;
}