linux 内核自组报文发送 3.10版本

这个问题纠结了一个星期,现在可以用了。以下是自己在调试过程中一个杂记。新手一个,不合适的地方欢迎大家来喷


1,生成一个新包,注意事项直接baidu  skb函数

我使用的是alloc_skb,当然也可以用skb_copy_expand等,看个人需求了。


2,对新生成的包进行自组内容

就四个部分,二层,三层,四层,和数据内容。不考虑分片。直接skb_share_info一个结构全部0。

组包时需要注意,最好能用内核提供的接口就用接口,不要自己想着写一个或是干什么,这些数据在以后发包的时候要做一些查询和验证,如果自己写到时候就傻了。

我的一段代码


skb_t = alloc_skb(pkt_len, GFP_ATOMIC);//pkt_len是报文总长度
if( skb_t == NULL)
{
goto truncation_drop;
}

dev = dev_get_by_name(&init_net, "br-lan");
// dev = dev_get_by_name(&init_net, "eth0.2");
if (NULL == dev)
{
return FAIL;
}
DEBUG(" get dev name %s\n",dev->name);


skb_t->dev = dev;
dev_hold(skb_t->dev);
skb_t->pkt_type = PACKET_HOST;
skb_t->protocol = __constant_htons(ETH_P_IP);
skb_t->ip_summed = CHECKSUM_NONE;
skb_t->priority = 0;
skb_t->mac_len = eth_hdr_len;

skb_reserve(skb_t, eth_hdr_len + ipv4_hdr_len + tcp_hdr_len);
//Ïòβ²¿À©Õ¹data room
skb_put(skb_t, data_len);
memcpy(skb_t->data, (void *)data_hdr_t, (s32)data_len);


skb_push(skb_t, tcp_hdr_len);
memcpy(skb_t->data, (void *)tcp_hdr_t, (s32)tcp_hdr_len);
skb_reset_transport_header(skb_t);

skb_push(skb_t, ipv4_hdr_len);
memcpy(skb_t->data, (void *)ipv4_hdr_t, (s32)ipv4_hdr_len);
skb_reset_network_header(skb_t);

skb_push(skb_t, eth_hdr_len);
memcpy(skb_t->data, (void *)eth_hdr_t, (s32)eth_hdr_len);
skb_reset_mac_header(skb_t);
skb_t->data = skb_t->data + eth_hdr_len;



3,对dev_queue_xmit 和 ip_route_input , dst_output 的个人理解


dev_queue_xmit调用这个函数这前需要完成对skb->dev结构的赋值,它直接会把skb挂到相应接口的发送队列等待发送了。


ip_route_input , dst_output ,使用这两个函数就是和走linux 内核的转发差不多,先查下路由,得到rt->dst  和相应dev结构,再去查二层。之后挂到发送队列。目前我用的是这个。对于不同版本的内核,接口函数的参数也不一定一样,所以没有一个统一的东西。上网找也没找到,我的发送函数

static u32 skb_send_to_route(struct sk_buff *skb, struct iphdr *iph, struct tcphdr *tcphdr)
{
    struct rtable *rt = NULL;
    //struct iphdr *iph = (struct iphdr *)skb->network_header;
    struct flowi4 fl4;
int err;


//struct tcphdr *tcphdr = (struct tcphdr *)skb->transport_header;


fl4.daddr = iph->daddr;
//fl4.saddr = iph->saddr;,//这个不要是因为查路由的时候会去验证一些东西,量后就直接所回查找失败,后正我用不到直接不管了。
fl4.flowi4_tos = RT_TOS(iph->tos);


fl4.flowi4_oif = skb->dev->ifindex;


err = ip_route_input_noref(skb, iph->daddr, iph->saddr,
  iph->tos, skb->dev);
if (unlikely(err)) {
DEBUG("ip route input fail\n\n");
   return FAIL;
}
//看查成功没有,
rt = skb_rtable(skb);
if (IS_ERR(rt))
{
DEBUG("rt is error\n\n");
kfree_skb(skb);
   return FAIL;
    }
err = dst_output(skb);
DEBUG(" return NF_STOLEN ret = %d!\n\n",err);


return OK;
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Brickie-liu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值