- 论坛徽章:
- 0
|
在linux2.0.X下skb_replace实现如下,linux2.2X下也是类似实现:
static struct sk_buff * skb_replace(struct sk_buff *skb, int pri, char *o_buf, int o_len, char *n_buf, int n_len)
{
int maxsize, diff, o_offset;
struct sk_buff *n_skb;
int offset;
maxsize = skb->truesize;
diff = n_len - o_len;
o_offset = o_buf - (char*) skb->data;
/*
*此处很不明白,maxsize应该是之前skb实际buffer的程度,n_len是新的buffer的长度,
*如下的这种做法是不是反了?
*/
if (maxsize <= n_len) {
if (diff != 0) {
memcpy(skb->data + o_offset + n_len,o_buf + o_len,
skb->len - (o_offset + o_len));
}
memcpy(skb->data + o_offset, n_buf, n_len);
n_skb = skb;
skb->len = n_len;
skb->end = skb->head+n_len;
} else {
/*
* Sizes differ, make a copy.
*
* FIXME: move this to core/sbuff.c:skb_grow()
*/
n_skb = alloc_skb(MAX_HEADER + skb->len + diff, pri);
if (n_skb == NULL) {
IP_MASQ_ERR("skb_replace(): no room left (from %p)\n",
__builtin_return_address(0));
return skb;
}
skb_reserve(n_skb, MAX_HEADER);
skb_put(n_skb, skb->len + diff);
/*
* Copy as much data from the old skb as possible. Even
* though we're only forwarding packets, we need stuff
* like skb->protocol (PPP driver wants it).
*/
offset = n_skb->data - skb->data;
n_skb->nh.raw = skb->nh.raw + offset;
n_skb->h.raw = skb->h.raw + offset;
n_skb->dev = skb->dev;
n_skb->mac.raw = skb->mac.raw + offset;
n_skb->pkt_type = skb->pkt_type;
n_skb->protocol = skb->protocol;
n_skb->ip_summed = skb->ip_summed;
n_skb->dst = dst_clone(skb->dst);
/*
* Copy pkt in new buffer
*/
memcpy(n_skb->data, skb->data, o_offset);
memcpy(n_skb->data + o_offset, n_buf, n_len);
memcpy(n_skb->data + o_offset + n_len, o_buf + o_len,
skb->len - (o_offset + o_len) );
/*
* Problem, how to replace the new skb with old one,
* preferably inplace
*/
kfree_skb(skb);
}
return n_skb;
}
[ 本帖最后由 fangshi168775 于 2009-3-30 09:58 编辑 ] |
|