日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

实现socket监听所有网络命名空间

發布時間:2023/12/18 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 实现socket监听所有网络命名空间 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
當前Linux內核的實現,一個socket監聽在一個特定的網絡命名空間中,不同的命名空間可有具有相同的socket,即可監聽相同的地址端口,這樣很好的實現網絡隔離虛擬化的功能。但是對于網路設備來說,并不需要如此完全的隔離。比如VPN設備/路由器等,一個ike進程或者quagga進程能監聽在所有的命名空間,更利于實現和管理。

這樣就要求應用層socket能夠接收到所有命名空間的數據包,并且能夠感知當前連接的命名空間。


數據包接收

內核默認創建一個網絡命名空間(init_net),起初所有的socket都監聽在默認的網絡命名空間。要能夠接收其它命名空間的數據包,需要修改sock查找函數。在一個新的連接請求進來之后,查找監聽sock時(__inet_lookup_listener),內核默認僅在接收數據包所在的命名空間查找。修改為在找不到的情況下,去init_net命名空間查找,此時,監聽在init_net的socket就能接收到新的連接了。


sk = __inet_lookup_listener(dev_net(dev), hashinfo, saddr, sport, daddr, hnum, dif, flags); if (!sk) {sk = __inet_lookup_listener(&init_net, hashinfo, saddr, sport, daddr, hnum, dif, flags); }


以上是TCP的sock查找修改,對于UDP可做相同的修改。


數據包發送

sock的查找修改之后已經可以接收到新的連接請求,但是并沒有修改sock結構中的sk_net的值,其還是init_net(socket總監聽在此命名空間),不能使用其查找路由。如要能正常回復此連接請求(SYN+ACK),我們的sock需要使用接收到數據包的接口所在net_namespace的路由。所以在請求路由時,使用接收命名空間查找:


static inline struct net *sock_net(const struct sock *sk) {return read_pnet(&sk->sk_net); } struct dst_entry *inet_csk_route_req(struct sock *sk, struct flowi4 *fl4, const struct request_sock *req) {rt = ip_route_output_flow(skb_real_net, fl4, sk); }


發送連接建立之后正常的數據包涉及到的也是路由問題,如何告訴內核代碼要在哪個命名空間發送?此時需要在創建子sock的時候,把真正的接收命名空間保存在子sock中。在發送時使用。例如ip_queue_xmit函數,查詢路由時使用真正的child_sk_real_net去查:


int ip_queue_xmit(struct sk_buff *skb, struct flowi *fl) {rt = ip_route_output_ports(child_sk_real_net, fl4, sk, daddr, inet->inet_saddr,inet->inet_dport, inet->inet_sport, sk->sk_protocol, RT_CONN_FLAGS(sk), sk->sk_bound_dev_if); }


方能找到正確的出口路由,正常發送數據包。實現應用層socket監聽多個網絡命名空間。



總結

以上是生活随笔為你收集整理的实现socket监听所有网络命名空间的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。