Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 34580
b: refs/heads/master
c: a831f5b
h: refs/heads/master
v: v3
  • Loading branch information
Masahide NAKAMURA authored and David S. Miller committed Sep 22, 2006
1 parent 9c98c72 commit ee8e376
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 2 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 842426e719f86cd5709617208efae93ff1a1e2d8
refs/heads/master: a831f5bbc89a9978795504be9e1ff412043f8f77
3 changes: 3 additions & 0 deletions trunk/include/linux/ipv6.h
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,9 @@ struct inet6_skb_parm {
__u16 dst0;
__u16 srcrt;
__u16 dst1;
#ifdef CONFIG_IPV6_MIP6
__u16 dsthao;
#endif
__u16 lastopt;
__u32 nhoff;
__u16 flags;
Expand Down
84 changes: 83 additions & 1 deletion trunk/net/ipv6/exthdrs.c
Original file line number Diff line number Diff line change
Expand Up @@ -196,15 +196,90 @@ static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff **skbp)
Destination options header.
*****************************/

#ifdef CONFIG_IPV6_MIP6
static int ipv6_dest_hao(struct sk_buff **skbp, int optoff)
{
struct sk_buff *skb = *skbp;
struct ipv6_destopt_hao *hao;
struct inet6_skb_parm *opt = IP6CB(skb);
struct ipv6hdr *ipv6h = (struct ipv6hdr *)skb->nh.raw;
struct in6_addr tmp_addr;
int ret;

if (opt->dsthao) {
LIMIT_NETDEBUG(KERN_DEBUG "hao duplicated\n");
goto discard;
}
opt->dsthao = opt->dst1;
opt->dst1 = 0;

hao = (struct ipv6_destopt_hao *)(skb->nh.raw + optoff);

if (hao->length != 16) {
LIMIT_NETDEBUG(
KERN_DEBUG "hao invalid option length = %d\n", hao->length);
goto discard;
}

if (!(ipv6_addr_type(&hao->addr) & IPV6_ADDR_UNICAST)) {
LIMIT_NETDEBUG(
KERN_DEBUG "hao is not an unicast addr: " NIP6_FMT "\n", NIP6(hao->addr));
goto discard;
}

ret = xfrm6_input_addr(skb, (xfrm_address_t *)&ipv6h->daddr,
(xfrm_address_t *)&hao->addr, IPPROTO_DSTOPTS);
if (unlikely(ret < 0))
goto discard;

if (skb_cloned(skb)) {
struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);
if (skb2 == NULL)
goto discard;

kfree_skb(skb);

/* update all variable using below by copied skbuff */
*skbp = skb = skb2;
hao = (struct ipv6_destopt_hao *)(skb2->nh.raw + optoff);
ipv6h = (struct ipv6hdr *)skb2->nh.raw;
}

if (skb->ip_summed == CHECKSUM_COMPLETE)
skb->ip_summed = CHECKSUM_NONE;

ipv6_addr_copy(&tmp_addr, &ipv6h->saddr);
ipv6_addr_copy(&ipv6h->saddr, &hao->addr);
ipv6_addr_copy(&hao->addr, &tmp_addr);

if (skb->tstamp.off_sec == 0)
__net_timestamp(skb);

return 1;

discard:
kfree_skb(skb);
return 0;
}
#endif

static struct tlvtype_proc tlvprocdestopt_lst[] = {
/* No destination options are defined now */
#ifdef CONFIG_IPV6_MIP6
{
.type = IPV6_TLV_HAO,
.func = ipv6_dest_hao,
},
#endif
{-1, NULL}
};

static int ipv6_destopt_rcv(struct sk_buff **skbp)
{
struct sk_buff *skb = *skbp;
struct inet6_skb_parm *opt = IP6CB(skb);
#ifdef CONFIG_IPV6_MIP6
__u16 dstbuf;
#endif

if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) ||
!pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) {
Expand All @@ -215,11 +290,18 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp)

opt->lastopt = skb->h.raw - skb->nh.raw;
opt->dst1 = skb->h.raw - skb->nh.raw;
#ifdef CONFIG_IPV6_MIP6
dstbuf = opt->dst1;
#endif

if (ip6_parse_tlv(tlvprocdestopt_lst, skbp)) {
skb = *skbp;
skb->h.raw += ((skb->h.raw[1]+1)<<3);
#ifdef CONFIG_IPV6_MIP6
opt->nhoff = dstbuf;
#else
opt->nhoff = opt->dst1;
#endif
return 1;
}

Expand Down

0 comments on commit ee8e376

Please sign in to comment.