custom target: vlan_t extension problem.
Dawid Ciężarkiewicz <[email protected]>
| Newsgroups | gmane.linux.network.bridge.ebtables.devel |
|---|---|
| Organization | ASN |
| Message-ID | <[email protected]> |
Hi,
I'm trying to develop ebt-vlan_t extension for ebtables. It should change
vlan ID of ethernet frame. Having most of work already done I'm experiencing
problems with changing frame type from non-vlan to vlan.
I derived my work from ebt-mark so I just paste target function which
essential here:
-- BEGIN --
static int ebt_target_vlan(struct sk_buff **pskb, unsigned int hooknr,
const struct net_device *in, const struct net_device *out,
const void *data, unsigned int datalen)
{
struct ebt_vlan_t_info *info = (struct ebt_vlan_t_info *)data;
struct vlan_hdr* vh, frame;
unsigned short vlan_TCI;
struct sk_buff *nskb;
struct sk_buff *skb;
struct vlan_ethhdr * veth;
if ((*pskb)->protocol != __constant_htons(ETH_P_8021Q)) {
printk("no vlan pskb - changing...\n");
/* TODO: is this part needed? */
/* TRY2 - BEGIN */
if (skb_shared(*pskb) || skb_cloned(*pskb)) {
printk("skb_shared(*pskb) || skb_cloned(*pskb)\n");
nskb = skb_copy(*pskb, GFP_ATOMIC);
if (!nskb)
return EBT_DROP;
if ((*pskb)->sk)
skb_set_owner_w(nskb, (*pskb)->sk);
kfree_skb(*pskb);
*pskb = nskb;
}
if (skb_headroom(*pskb) < VLAN_HLEN) {
printk("skb_headroom(*pskb) < VLAN_HLEN\n");
nskb = *pskb;
*pskb = skb_realloc_headroom(nskb, VLAN_HLEN);
if (*pskb == NULL) {
*pskb = nskb;
printk(KERN_ERR "vlan: failed to realloc headroom\n");
return EBT_DROP;
}
kfree_skb(nskb);
}
/* this mechanism is taken c&p from __vlan_put_tag() */
veth = vlan_eth_hdr(skb_push(skb, VLAN_HLEN));
/* Move the mac addresses to the beginning of the new header. */
memmove(veth, veth + VLAN_HLEN, 2 * VLAN_ETH_ALEN);
/* first, the ethernet type */
veth->h_vlan_proto = __constant_htons(ETH_P_8021Q);
/* now, the tag */
veth->h_vlan_TCI = htons(info->id);
veth->h_vlan_proto= __constant_htons(ETH_P_8021Q);
skb->mac.raw -= VLAN_HLEN;
skb->nh.raw -= VLAN_HLEN;
/* TRY1 - BEGIN */
/*
nskb = __vlan_put_tag(*pskb, info->id);
if (nskb == NULL) {
printk("failed - dropping...\n");
return EBT_DROP;
}
*pskb = nskb;
*/
} else {
vh = skb_header_pointer(*pskb, 0, sizeof(frame), &frame);
//printk("vlan_t - old TCI : %hx\n", vh->h_vlan_TCI);
vlan_TCI = ntohs (vh->h_vlan_TCI) & ~VLAN_VID_MASK;
//printk("vlan_t - applying id : %hx\n", info->id);
//printk("vlan_t - new TCI: %hx\n", vlan_TCI | info->id);
vh->h_vlan_TCI = htons(vlan_TCI | info->id);
}
return info->target;
}
--- END ---
While the second part (when (*pskb)->protocol ==
__constant_htons(ETH_P_8021Q)) works perfectly fine and frame VID is changed,
the first one is now mix of my tries not to hang kernel.
At the beginning I was going to use vlan_put_tag(*pskb, info->id); or
__vlan_put_tag(*pskb, info->id);
, but they hang. So I tried many combinations of hand made and
found&look-promising code in kernel source.
I'm probably not aware of many facts, because I'm totally kernel newbie. What
I'd like to ask especially is:
- can ebt target modify pskb or substitute it with another one (struct sk_buff
**pskb is used for that, I suppose); are there any additional conditions
(chains, tables etc.)?
- are there any other limitations for ebt target (locks, interupts ...)?
Of course if anybody can point me anything interesting, like comments and
advices (especially about pasted piece of code) I'd be most thankful. I'm not
afraid of reading code so please point me function&file if you think I should
read it more carefully.
Best Regards,
Dawid
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642