当前位置: 技术问答>linux和unix
【求助】怎么填充一个sk_buffer,发送一个UDP包?
来源: 互联网 发布时间:2016-08-04
本文导语: 请问哪位大侠有在内核态,申请sk_buffer空间,并填充,发送UDP包的代码?借来学习学习,研究了1个星期了,还没发送成功过。 | 内核里面本来就有这种代码,见netpoll实现 void netpoll_send_udp(str...
请问哪位大侠有在内核态,申请sk_buffer空间,并填充,发送UDP包的代码?借来学习学习,研究了1个星期了,还没发送成功过。
|
内核里面本来就有这种代码,见netpoll实现
void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
{
int total_len, eth_len, ip_len, udp_len;
struct sk_buff *skb;
struct udphdr *udph;
struct iphdr *iph;
struct ethhdr *eth;
udp_len = len + sizeof(*udph);
ip_len = eth_len = udp_len + sizeof(*iph);
total_len = eth_len + ETH_HLEN + NET_IP_ALIGN;
skb = find_skb(np, total_len, total_len - len);
if (!skb)
return;
skb_copy_to_linear_data(skb, msg, len);
skb->len += len;
skb_push(skb, sizeof(*udph));
skb_reset_transport_header(skb);
udph = udp_hdr(skb);
udph->source = htons(np->local_port);
udph->dest = htons(np->remote_port);
udph->len = htons(udp_len);
udph->check = 0;
udph->check = csum_tcpudp_magic(np->local_ip,
np->remote_ip,
udp_len, IPPROTO_UDP,
csum_partial(udph, udp_len, 0));
if (udph->check == 0)
udph->check = CSUM_MANGLED_0;
skb_push(skb, sizeof(*iph));
skb_reset_network_header(skb);
iph = ip_hdr(skb);
/* iph->version = 4; iph->ihl = 5; */
put_unaligned(0x45, (unsigned char *)iph);
iph->tos = 0;
put_unaligned(htons(ip_len), &(iph->tot_len));
iph->id = 0;
iph->frag_off = 0;
iph->ttl = 64;
iph->protocol = IPPROTO_UDP;
iph->check = 0;
put_unaligned(np->local_ip, &(iph->saddr));
put_unaligned(np->remote_ip, &(iph->daddr));
iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
eth = (struct ethhdr *) skb_push(skb, ETH_HLEN);
skb_reset_mac_header(skb);
skb->protocol = eth->h_proto = htons(ETH_P_IP);
memcpy(eth->h_source, np->dev->dev_addr, ETH_ALEN);
memcpy(eth->h_dest, np->remote_mac, ETH_ALEN);
skb->dev = np->dev;
netpoll_send_skb(np, skb);
}
|
参数UDP的发送过程嘛。
|
去看源码吧吗,应该在ip_input.c
|
一个发送 tcp rst 的例子
改改就好了
void send_reset(struct sk_buff *oldskb)
{
struct sk_buff *nskb;
const struct iphdr *oiph;
struct iphdr *niph;
const struct tcphdr *oth;
struct tcphdr _otcph, *tcph;
struct ethhdr *neth;
char *pad;
int len;
int padlen = 0;
int tcplen = 0;
//struct dst_entry *dst = NULL;
//struct rtable *rt = NULL;
struct net_device *odev = NULL;
/* IP header checks: fragment. */
if ( giph( oldskb )->frag_off & htons(IP_OFFSET))
return;
//oth = skb_header_pointer(oldskb, giph( oldskb ) dev = odev;
//nskb->pkt_type = PACKET_HOST;
//nskb->protocol = __constant_htons( ETH_P_IP );
// 取得ethhdr地址,
skb_reset_mac_header(nskb);
neth = (struct ethhdr *)skb_put(nskb, sizeof( struct ethhdr ) );
/*
if ( skb_mac_header_was_set( oldskb ) ) {
memcpy( neth->h_dest, eth_hdr( oldskb )->h_source, ETH_ALEN );
memcpy( neth->h_source, eth_hdr( oldskb )->h_dest, ETH_ALEN );
neth->h_proto = eth_hdr( oldskb )->h_proto;
}
*/
niph = (struct iphdr *)skb_put(nskb, sizeof(struct iphdr));
niph->version = 4;
niph->ihl = sizeof(struct iphdr) / 4;
niph->tos = 0;
niph->id = 0;
niph->frag_off = htons(IP_DF);
niph->protocol = IPPROTO_TCP;
niph->check = 0;
niph->saddr = oiph->daddr;
niph->daddr = oiph->saddr;
#if 0
niph->saddr = MKNL( 192, 168, 1, 12 );
//niph->daddr = MKNL( 8, 8, 8, 8 );
niph->daddr = MKNL( 192, 168, 1, 18 );
#endif
tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr));
memset(tcph, 0, sizeof(*tcph));
tcph->source = oth->dest;
tcph->dest = oth->source;
tcph->doff = sizeof(struct tcphdr) / 4;
if (oth->ack)
tcph->seq = oth->ack_seq;
else {
tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn + oth->fin +
oldskb->len - ip_hdrlen(oldskb) -
(oth->doff rst = 1;
pad = NULL;
//pad = skb_put( nskb, padlen );
//memset( pad, 0x0, padlen );
tcplen = sizeof(struct tcphdr) + padlen ;
tcph->check = 0;
tcph->check = tcp_v4_check( tcplen,
niph->saddr, niph->daddr,
csum_partial(tcph,
tcplen, 0));
niph->ttl = oiph->ttl;
#if 0
niph->tot_len = htons( len - ETH_HLEN );
niph->check = 0;
niph->check = ip_fast_csum( ( u8 * )niph, niph->ihl );
#endif
// 查找output route
if ( ip_route_out( nskb, niph ) != 0 ) {
goto free_nskb;
}
// 设置skb networker layer地址
__skb_pull( nskb, ETH_HLEN );
skb_reset_network_header(nskb);
//xmit_enqueue( nskb );
//local_out_enqueue( nskb );
ip_local_out(nskb);
return;
free_nskb:
trace( "free nskb.n" );
kfree_skb(nskb);
return ;
}
改改就好了
void send_reset(struct sk_buff *oldskb)
{
struct sk_buff *nskb;
const struct iphdr *oiph;
struct iphdr *niph;
const struct tcphdr *oth;
struct tcphdr _otcph, *tcph;
struct ethhdr *neth;
char *pad;
int len;
int padlen = 0;
int tcplen = 0;
//struct dst_entry *dst = NULL;
//struct rtable *rt = NULL;
struct net_device *odev = NULL;
/* IP header checks: fragment. */
if ( giph( oldskb )->frag_off & htons(IP_OFFSET))
return;
//oth = skb_header_pointer(oldskb, giph( oldskb ) dev = odev;
//nskb->pkt_type = PACKET_HOST;
//nskb->protocol = __constant_htons( ETH_P_IP );
// 取得ethhdr地址,
skb_reset_mac_header(nskb);
neth = (struct ethhdr *)skb_put(nskb, sizeof( struct ethhdr ) );
/*
if ( skb_mac_header_was_set( oldskb ) ) {
memcpy( neth->h_dest, eth_hdr( oldskb )->h_source, ETH_ALEN );
memcpy( neth->h_source, eth_hdr( oldskb )->h_dest, ETH_ALEN );
neth->h_proto = eth_hdr( oldskb )->h_proto;
}
*/
niph = (struct iphdr *)skb_put(nskb, sizeof(struct iphdr));
niph->version = 4;
niph->ihl = sizeof(struct iphdr) / 4;
niph->tos = 0;
niph->id = 0;
niph->frag_off = htons(IP_DF);
niph->protocol = IPPROTO_TCP;
niph->check = 0;
niph->saddr = oiph->daddr;
niph->daddr = oiph->saddr;
#if 0
niph->saddr = MKNL( 192, 168, 1, 12 );
//niph->daddr = MKNL( 8, 8, 8, 8 );
niph->daddr = MKNL( 192, 168, 1, 18 );
#endif
tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr));
memset(tcph, 0, sizeof(*tcph));
tcph->source = oth->dest;
tcph->dest = oth->source;
tcph->doff = sizeof(struct tcphdr) / 4;
if (oth->ack)
tcph->seq = oth->ack_seq;
else {
tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn + oth->fin +
oldskb->len - ip_hdrlen(oldskb) -
(oth->doff rst = 1;
pad = NULL;
//pad = skb_put( nskb, padlen );
//memset( pad, 0x0, padlen );
tcplen = sizeof(struct tcphdr) + padlen ;
tcph->check = 0;
tcph->check = tcp_v4_check( tcplen,
niph->saddr, niph->daddr,
csum_partial(tcph,
tcplen, 0));
niph->ttl = oiph->ttl;
#if 0
niph->tot_len = htons( len - ETH_HLEN );
niph->check = 0;
niph->check = ip_fast_csum( ( u8 * )niph, niph->ihl );
#endif
// 查找output route
if ( ip_route_out( nskb, niph ) != 0 ) {
goto free_nskb;
}
// 设置skb networker layer地址
__skb_pull( nskb, ETH_HLEN );
skb_reset_network_header(nskb);
//xmit_enqueue( nskb );
//local_out_enqueue( nskb );
ip_local_out(nskb);
return;
free_nskb:
trace( "free nskb.n" );
kfree_skb(nskb);
return ;
}
您可能感兴趣的文章:
本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。
本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。