send_udp構造乙個udp資料報並根據網路裝置傳送
int send_udp(struct net_device *odev, u16 local_port, u32 remote_ip, u16 remote_port, u8 *msg, int len) // 設定各個協議資料長度 udp_len = len + sizeof(*udph); ip_len = eth_len = udp_len + sizeof(*iph); total_len = eth_len + eth_hlen + net_ip_align; header_len = total_len - len; // 分配skb skb = alloc_skb( total_len + ll_max_header, gfp_atomic ); if ( !skb ) // 預先保留skb的協議首部長度大小 skb_reserve( skb, ll_max_header + header_len ); // 拷貝負載資料 skb_copy_to_linear_data(skb, msg, len); skb->len += len; // skb->data 移動到udp首部 skb_push(skb, sizeof(*udph)); skb_reset_transport_header(skb); udph = udp_hdr(skb); udph->source = htons(local_port); udph->dest = htons(remote_port); udph->len = htons(udp_len); udph->check = 0; udph->check = csum_tcpudp_magic(htonl(local_ip), htonl(remote_ip), udp_len, ipproto_udp, csum_partial(udph, udp_len, 0)); if (udph->check == 0) udph->check = csum_mangled_0; // skb->data 移動到ip首部 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(htonl(local_ip), &(iph->saddr)); put_unaligned(htonl(remote_ip), &(iph->daddr)); iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); /* // skb->data 移動到eth首部 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, dev_addr, eth_alen); memcpy(eth->h_dest, remote_mac, eth_alen); */ skb->dev = odev; // 直接傳送 //dev_queue_xmit( skb ); // 獲取output rtable if ( ip_route_out( skb, iph ) != 0 ) // 通過系統決定傳送 ip_local_out(skb); return; free_skb: trace( "free skb.\n" ); kfree_skb(skb); return ; }
ip_route_out 函式查詢路由路徑, 獲取output rtable.
int ip_route_out( struct sk_buff *skb, struct iphdr *iph ) ; struct rtable *rt = null; fl.nl_u.ip4_u.daddr = iph->daddr; if (ip_route_output_key( &init_net, &rt, &fl) != 0) trace( "rt_dst="nipquad_fmt " rt_gw=" nipquad_fmt "\n", nipquad( rt->rt_dst ), nipquad( rt->rt_gateway ) ); trace( "route output dev=%s\n", rt->u.dst.dev->name ); //skb->dst = &rt->u.dst; skb->rtable = rt; err = 0; _out: return err; }
Linux核心中關於資料結構操作的乙個問題
在linux核心中的佇列操作都是通過list head來進行的,list head稱為 宿主結構 的 連線件 但是我們真正需要的是宿主結構,而不是這個連線件,如果我們順著乙個佇列取得了其中一項的list head結構時,又怎樣找到其宿主結構呢?剛開始看核心原始碼時,我對這個問題百思不得其解,後來看了...
深度探索Linux核心之傳送乙個UDP資料報
注 下面會好好幾篇文章,我都摘自同乙個作者,他是一位前輩,和高人。我在此先表示感謝,在文章的後面我會注出作者和位址。我這樣做,主要是防止自己以後找不到這些經典的好文章。出自 在socket程式設計中,傳送資料報文可供使用的api函式有send,sendto和sendmsg,下面是關於前兩個系統呼叫的...
udp 傳送乙個整數 udpclient
include include include include include include include include include include include define len 4 位元組序處理函式,我的電腦是小端的 unsigned char serialize int uns...