2017-11-25 60 views
5

मैं दो अनुप्रयोगों से एक बंदरगाह का उपयोग करने की कोशिश कर रहा हूं और उनमें से प्रत्येक को आईपी पते के एक अलग सेट से पैकेट प्राप्त होता है। इसे प्राप्त करने के लिए, मैं SO_REUSEPORT और SO_ATTACH_REUSEPORT_CBPF सॉकेट विकल्पों का उपयोग करता हूं। मेरे कोड इस प्रकार है:SO_ATTACH_REUSEPORT_CBPF सॉकेट विकल्प अप्रत्याशित व्यवहार

parentfd = socket(AF_INET, SOCK_STREAM, 0); 
if (parentfd < 0) 
    error("ERROR opening socket"); 

struct sock_filter code[]={ 
    { 0x28, 0, 0, 0x0000000c }, 
    { 0x15, 0, 3, 0x00000800 }, 
    { 0x20, 0, 0, 0x0000001a }, 
    { 0x15, 2, 0, 0xc0a8ff01 }, 
    { 0x6, 0, 0, 0x00000000 }, 
    { 0x6, 0, 0, 0x00040000 }, 
    { 0x6, 0, 0, 0x00000001 }, 
}; 

struct sock_fprog bpf = { 
    .len = ARRAY_SIZE(code), 
    .filter = code, 
}; 

if (setsockopt(parentfd, SOL_SOCKET, SO_REUSEPORT, (const void *)&optval,sizeof(optval))) 
    error("ERROR setting SO_REUSEPORT"); 

if (setsockopt(parentfd, SOL_SOCKET, SO_ATTACH_REUSEPORT_CBPF, (const void *)&bpf, sizeof(bpf))) 
    error("ERROR setting SO_ATTACH_REUSEPORT_CBPF); 

मैं भी एक अलग प्रक्रिया है कि एक ही बंदरगाह केवल SO_REUSEPORT ध्वज का उपयोग को सुनता है। आईपी ​​192.168.255.1 वाली मशीन से मैं चला रहा हूं। मेरे फ़िल्टर के आधार पर मैं दूसरी प्रक्रिया द्वारा उस आईपी पते से प्राप्त होने वाले सभी ट्रैफिक की अपेक्षा करता हूं। हालांकि, यह सब पहले प्राप्त किया गया है। जब मैं एक सरल करने के लिए फिल्टर बदलने के लिए:

struct sock_filter code[]={ { 0x6, 0, 0, 0x00000001 }, };

यह काम करता है की उम्मीद है और सभी पैकेट दूसरी प्रक्रिया के द्वारा प्राप्त कर रहे हैं। कोई विचार क्यों यह हो रहा है?

+1

वापस जाने के लिए कैसे आप मूल फिल्टर के साथ आया है ? –

उत्तर

1

मुझे पता चला कि समस्या क्या थी। फिल्टर सभी पैकेट, यहां तक ​​कि टीसीपी हैंडशेक पैकेट पर भी लागू होता है। इसके अलावा, बेस पॉइंटर पैकेट पेलोड के पहले बाइट को इंगित करता है, हेडर नहीं। इसलिए, यह जब कार्यान्वित

ldh[12] 

यह पैकेट की सीमा (SYN पैकेट पेलोड के 0 बाइट्स है) से बाहर हो जाता है और डिफ़ॉल्ट व्यवहार 0.

0

गैर काम कर कोड है:

l0: ldh [12]     /* read EtherType (2 bytes), which is found at offset 12 (decimal) */ 
l1: jeq #0x800, l2, l5   /* if EtherType == `0x800` (IPv4), jump to `l2`, otherwise jump to `l5` */ 
l2: ld [26]     /* read source IP address (4 bytes) */ 
l3: jeq #0xc0a8ff01, l6, l4 /* if source IP address == 192.168.255.1, jump to l6 (return 1), else jump to l4 (return 0) */ 
l4: ret #0 
l5: ret #0x40000 
l6: ret #0x1 

काम कर कोड है:

ret #0x1 

socket (7) का कहना है:

बीपीएफ कार्यक्रम 0 और एन के बीच एक सूचकांक लौटना चाहिए -1 सॉकेट का प्रतिनिधित्व करता है जो पैकेट प्राप्त करना चाहिए (जहां एन समूह में सॉकेट की संख्या है)। यदि बीपीएफ प्रोग्राम एक अवैध इंडेक्स देता है, तो सॉकेट चयन सादे SO_REUSEPORT तंत्र पर वापस आ जाएगा।

मेरी मशीन tcpdump -i lo -ddd 'src host 192.168.255.1' पर

10 
40 0 0 12 
21 0 2 2048 
32 0 0 26 
21 4 5 3232300801 
21 1 0 2054 
21 0 3 32821 
32 0 0 28 
21 0 1 3232300801 
6 0 0 262144 
6 0 0 0 

कौन सा

l0: ldh [12] 
l1: jeq #0x800, l2, l4 
l2: ld [26] 
l3: jeq #0xc0a8ff01, l8, l9 
l4: jeq #0x806, l6, l5 
l5: jeq #0x8035, l6, l9 
l6: ld [28] 
l7: jeq #0xc0a8ff01, l8, l9 
l8: ret #0x40000 
l9: ret #0 

मैं कुछ भी है कि स्पष्ट रूप से अपने कोड के साथ गलत क्या है देखने के लिए असफल है पैदा करता है।

क्या आपने सर्वर पर tcpdump चलाने का प्रयास किया है? शायद आप क्लाइंट पर एक अतिरिक्त आईपी पता निकालना भूल गए हैं, या कहीं भूल गए एसएनएटी नियम है?

आप कौन से कर्नेल संस्करण चल रहे हैं? क्या आप एक न्यूनतम सी एप्लिकेशन पोस्ट कर सकते हैं जो समस्या को पुन: उत्पन्न करता है?

संबंधित मुद्दे