send_udp 构造一个udp数据包并根据网络设备发送
view plaincopy to clipboardprint?01.int send_udp(struct net_device *odev, u16 local_port,
02. u32 remote_ip, u16 remote_port, u8 *msg, int len)
03.{
04. struct sk_buff *skb;
05. int total_len, eth_len, ip_len, udp_len, header_len;
06. struct udphdr *udph;
07. struct iphdr *iph;
08. struct ethhdr *eth;
09. u32 local_ip;
10.
11. //local_ip = inet_select_addr(odev, remote_ip, RT_SCOPE_LINK); // 选择网络设备地址 local_ip = inet_select_addr(odev, 0, RT_SCOPE_UNIVERSE);
12. printk( "local ip is "NIPQUAD_FMT"\n", NIPQUAD( local_ip ) );
13. local_ip = ntohl( local_ip );
14. if ( !local_ip ) {
15. return;
16. }
17.
18. // 设置各个协议数据长度 udp_len = len + sizeof(*udph);
19. ip_len = eth_len = udp_len + sizeof(*iph);
20. total_len = eth_len + ETH_HLEN + NET_IP_ALIGN;
21. header_len = total_len - len;
22.
23. // 分配skb skb = alloc_skb( total_len + LL_MAX_HEADER, GFP_ATOMIC );
24. if ( !skb ) {
25. dbg_err( "alloc_skb fail.\n" );
26. return;
27. }
28.
29. // 预先保留skb的协议首部长度大小 skb_reserve( skb, LL_MAX_HEADER + header_len );
30.
31. // 拷贝负载数据 skb_copy_to_linear_data(skb, msg, len);
32. skb->len += len;
33.
34. // skb->data 移动到udp首部 skb_push(skb, sizeof(*udph));
35. skb_reset_transport_header(skb);
36. udph = udp_hdr(skb);
37. udph->source = htons(local_port);
38. udph->dest = htons(remote_port);
39. udph->len = htons(udp_len);
40. udph->check = 0;
41. udph->check = csum_tcpudp_magic(htonl(local_ip),
42. htonl(remote_ip),
43. udp_len, IPPROTO_UDP,
44. csum_partial(udph, udp_len, 0));
45. if (udph->check == 0)
46. udph->check = CSUM_MANGLED_0;
47.
48. // skb->data 移动到ip首部 skb_push(skb, sizeof(*iph));
49. skb_reset_network_header(skb);
50. iph = ip_hdr(skb);
51.
52. /* iph->version = 4; iph->ihl = 5; */ put_unaligned(0x45, (unsigned char *)iph);
53. iph->tos = 0;
54. put_unaligned(htons(ip_len), &(iph->tot_len));
55. iph->id = 0;
56. iph->frag_off = 0;
57. iph->ttl = 64;
58. iph->protocol = IPPROTO_UDP;
59. iph->check = 0;
60. put_unaligned(htonl(local_ip), &(iph->saddr));
61. put_unaligned(htonl(remote_ip), &(iph->daddr));
62. iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
63.
64. /*
65. // skb->data 移动到eth首部
66. eth = (struct ethhdr *) skb_push(skb, ETH_HLEN);
67. skb_reset_mac_header(skb);
68. skb->protocol = eth->h_proto = htons(ETH_P_IP);
69. memcpy(eth->h_source, dev_addr, ETH_ALEN);
70. memcpy(eth->h_dest, remote_mac, ETH_ALEN);
71.
72. */
73. skb->dev = odev;
74.
75. // 直接发送 //dev_queue_xmit( skb );
76. // 获取output rtable if ( ip_route_out( skb, iph ) != 0 ) {
77. goto free_skb;
78. }
79.
80. // 通过系统决定发送 ip_local_out(skb);
81. return;
82.
83.free_skb:
84. trace( "free skb.\n" );
85. kfree_skb(skb);
86. return ;
87.}
ip_route_out 函数查找路由路径, 获取output rtable .
view plaincopy to clipboardprint?01.int ip_route_out( struct sk_buff *skb,
02. struct iphdr *iph )
03.{
04. int err = -1;
05. struct flowi fl = {};
06. struct rtable *rt = NULL;
07.
08. fl.nl_u.ip4_u.daddr = iph->daddr;
09. if (ip_route_output_key( &init_net, &rt, &fl) != 0) {
10. dbg_err( "ip_route_output_key call fail.\n" );
11. goto _out;
12. }
13. trace( "rt_dst="NIPQUAD_FMT " rt_gw=" NIPQUAD_FMT "\n",
14. NIPQUAD( rt->rt_dst ),
15. NIPQUAD( rt->rt_gateway )
16. );
17. trace( "route output dev=%s\n", rt->u.dst.dev->name );
18. //skb->dst = &rt->u.dst; skb->rtable = rt;
19. err = 0;
20._out:
21. return err;
22.}
阅读(3266) | 评论(0) | 转发(0) |