2005-04-17 02:20:36 +04:00
/*
* IPv6 library code , needed by static components when full IPv6 support is
* not configured or static .
*/
# include <net/ipv6.h>
2007-02-09 17:24:49 +03:00
/*
2005-04-17 02:20:36 +04:00
* find out if nexthdr is a well - known extension header or a protocol
*/
int ipv6_ext_hdr ( u8 nexthdr )
{
2007-02-09 17:24:49 +03:00
/*
2005-04-17 02:20:36 +04:00
* find out if nexthdr is an extension header or a protocol
*/
return ( ( nexthdr = = NEXTHDR_HOP ) | |
( nexthdr = = NEXTHDR_ROUTING ) | |
( nexthdr = = NEXTHDR_FRAGMENT ) | |
( nexthdr = = NEXTHDR_AUTH ) | |
( nexthdr = = NEXTHDR_NONE ) | |
( nexthdr = = NEXTHDR_DEST ) ) ;
}
/*
* Skip any extension headers . This is used by the ICMP module .
*
* Note that strictly speaking this conflicts with RFC 2460 4.0 :
2007-02-09 17:24:49 +03:00
* . . . The contents and semantics of each extension header determine whether
2005-04-17 02:20:36 +04:00
* or not to proceed to the next header . Therefore , extension headers must
* be processed strictly in the order they appear in the packet ; a
* receiver must not , for example , scan through a packet looking for a
* particular kind of extension header and process that header prior to
* processing all preceding ones .
2007-02-09 17:24:49 +03:00
*
2005-04-17 02:20:36 +04:00
* We do exactly this . This is a protocol bug . We can ' t decide after a
2007-02-09 17:24:49 +03:00
* seeing an unknown discard - with - error flavour TLV option if it ' s a
2005-04-17 02:20:36 +04:00
* ICMP error message or not ( errors should never be send in reply to
* ICMP error messages ) .
2007-02-09 17:24:49 +03:00
*
2005-04-17 02:20:36 +04:00
* But I see no other way to do this . This might need to be reexamined
* when Linux implements ESP ( and maybe AUTH ) headers .
* - - AK
*
2005-04-25 07:16:19 +04:00
* This function parses ( probably truncated ) exthdr set " hdr " .
* " nexthdrp " initially points to some place ,
2005-04-17 02:20:36 +04:00
* where type of the first header can be found .
*
* It skips all well - known exthdrs , and returns pointer to the start
* of unparsable area i . e . the first header with unknown type .
* If it is not NULL * nexthdr is updated by type / protocol of this header .
*
* NOTES : - if packet terminated with NEXTHDR_NONE it returns NULL .
* - it may return pointer pointing beyond end of packet ,
* if the last recognized header is truncated in the middle .
* - if packet is truncated , so that all parsed headers are skipped ,
* it returns NULL .
* - First fragment header is skipped , not - first ones
* are considered as unparsable .
* - ESP is unparsable for now and considered like
* normal payload protocol .
* - Note also special handling of AUTH header . Thanks to IPsec wizards .
*
* - - ANK ( 980726 )
*/
2005-04-25 07:16:19 +04:00
int ipv6_skip_exthdr ( const struct sk_buff * skb , int start , u8 * nexthdrp )
2005-04-17 02:20:36 +04:00
{
u8 nexthdr = * nexthdrp ;
while ( ipv6_ext_hdr ( nexthdr ) ) {
struct ipv6_opt_hdr _hdr , * hp ;
int hdrlen ;
if ( nexthdr = = NEXTHDR_NONE )
return - 1 ;
hp = skb_header_pointer ( skb , start , sizeof ( _hdr ) , & _hdr ) ;
if ( hp = = NULL )
2005-04-25 07:16:19 +04:00
return - 1 ;
2005-04-17 02:20:36 +04:00
if ( nexthdr = = NEXTHDR_FRAGMENT ) {
2006-11-15 07:56:00 +03:00
__be16 _frag_off , * fp ;
2005-04-17 02:20:36 +04:00
fp = skb_header_pointer ( skb ,
start + offsetof ( struct frag_hdr ,
frag_off ) ,
sizeof ( _frag_off ) ,
& _frag_off ) ;
if ( fp = = NULL )
return - 1 ;
if ( ntohs ( * fp ) & ~ 0x7 )
break ;
hdrlen = 8 ;
} else if ( nexthdr = = NEXTHDR_AUTH )
2007-02-09 17:24:49 +03:00
hdrlen = ( hp - > hdrlen + 2 ) < < 2 ;
2005-04-17 02:20:36 +04:00
else
2007-02-09 17:24:49 +03:00
hdrlen = ipv6_optlen ( hp ) ;
2005-04-17 02:20:36 +04:00
nexthdr = hp - > nexthdr ;
start + = hdrlen ;
}
* nexthdrp = nexthdr ;
return start ;
}
EXPORT_SYMBOL ( ipv6_ext_hdr ) ;
EXPORT_SYMBOL ( ipv6_skip_exthdr ) ;