2012-09-21 12 views
5

मैं कर्नेल स्पेस से पैकेट पर कुछ डेटा जोड़ने की कोशिश कर रहा हूं। मेरे पास एक गूंज क्लाइंट और सर्वर है। मैं कमांड लाइन में टाइप करता हूं जैसे: ./client "message" और सर्वर बस इसे वापस ले जाता है। सर्वर .ssver के साथ चलाया गया था।कर्नेल स्पेस से पैकेट पर डेटा कैसे जोड़ना है?

अब, ग्राहक और सर्वर दो अलग-अलग मशीनों पर हैं (वीएम हो सकते हैं)। मैं एक कर्नेल मॉड्यूल लिख रहा हूं जो क्लाइंट मशीन पर चलता है। इसका काम "संदेश" के बाद "12345" जोड़ना है जबकि पैकेट मशीन से बाहर निकलता है। मैं नीचे कोड प्रस्तुत कर रहा हूँ।

/* 
* This is ibss_obsf_cat.c 
*/ 

#include <linux/module.h> 
#include <linux/moduleparam.h> 
#include <linux/kernel.h> 
#include <linux/netfilter.h> 
#include <linux/skbuff.h> 
#include <linux/netdevice.h> 
#include <linux/udp.h> 
#include <linux/ip.h> 

#undef __KERNEL__ 
#include <linux/netfilter_ipv4.h> 
#define __KERNEL__ 


/* 
* Function prototypes ... 
*/ 

static unsigned int cat_obsf_begin (unsigned int hooknum, 
       struct sk_buff *skb, 
       const struct net_device *in, 
       const struct net_device *out, 
       int (*okfn)(struct sk_buff *)); 

static void hex_dump (char str[], int len) 
{ 

} 

/* 
* struct nf_hook_ops instance initialization 
*/ 

static struct nf_hook_ops cat_obsf_ops __read_mostly = { 
    .pf = NFPROTO_IPV4, 
    .priority = 1, 
    .hooknum = NF_IP_POST_ROUTING, 
    .hook = cat_obsf_begin, 
}; 

/* 
* Module init and exit functions. 
* No need to worry about that. 
*/ 

static int __init cat_obsf_init (void) 
{ 
    printk(KERN_ALERT "cat_obsf module started...\n"); 
    return nf_register_hook(&cat_obsf_ops); 
} 

static void __exit cat_obsf_exit (void) 
{ 
    nf_unregister_hook(&cat_obsf_ops); 
    printk(KERN_ALERT "cat_obsf module stopped...\n"); 
} 

/* 
* Modification of the code begins here. 
* Here are all the functions and other things. 
*/ 

static unsigned int cat_obsf_begin (unsigned int hooknum, 
       struct sk_buff *skb, 
       const struct net_device *in, 
       const struct net_device *out, 
       int (*okfn)(struct sk_buff *)) 
{ 
    struct iphdr *iph; 
    struct udphdr *udph; 
    unsigned char *data; 
    unsigned char dt[] = "12345"; 
    unsigned char *tmp; 
    unsigned char *ptr; 

    int i, j, len; 

    if (skb){ 
     iph = ip_hdr(skb); 

     if (iph && iph->protocol && (iph->protocol == IPPROTO_UDP)){ 
      udph = (struct udphdr *) ((__u32 *)iph + iph->ihl); 
      data = (char *)udph + 8; 

      if(ntohs(udph->dest) == 6000){ 
       for (i=0; data[i]; i++); 
       len = i; 

       //printk(KERN_ALERT "\nData length without skb: %d", len); 
       //printk(KERN_ALERT "Data is: %s", data); 
       //printk(KERN_ALERT "dt size: %lu", sizeof(dt)); 
       //printk(KERN_ALERT "skb->len: %d", skb->len); 
       tmp = kmalloc(200*sizeof(char), GFP_KERNEL); 

       memcpy(tmp, data, len); 
       ptr = tmp + len; 
       memcpy(ptr, dt, sizeof(dt)); 

       printk(KERN_ALERT "tmp: %s", tmp); 


       printk(KERN_ALERT "skb->tail: %d", skb->tail); 
       //skb_put(skb, sizeof(dt)); 
       printk(KERN_ALERT "skb->end: %d", skb->end); 
       printk(KERN_ALERT "skb->tail: %d", skb->tail); 
       printk(KERN_ALERT "skb->tail(int): %d", (unsigned int)skb->tail); 

       //memset(data, 0, len + sizeof(dt)); 

       //memcpy(data, tmp, len + sizeof(dt)); 

       //skb_add_data(skb, tmp, len+sizeof(dt)); 

       printk(KERN_ALERT "Now data is: %s", data); 
       for(i=0; data[i]; i++); 
       printk(KERN_ALERT "data length: %d", i); 

       kfree(tmp); 

      }  
     } 
    } 
    return NF_ACCEPT; 
} 

/* 
* Nothing to be touched hereafter 
*/ 

module_init(cat_obsf_init); 
module_exit(cat_obsf_exit); 

MODULE_AUTHOR("Rifat"); 
MODULE_DESCRIPTION("Module for packet mangling"); 
MODULE_LICENSE("GPL"); 

मैं कर्नेल स्पेस से क्लाइंट मशीन से बाहर भेजते समय "संदेश" संदेश "संदेश 12345" प्राप्त करना चाहता हूं। ताकि सर्वर को "message12345" मिले और इसे वापस गूंजें, और क्लाइंट केवल "message12345" पढ़ेगा लेकिन मुझे skb_put() और skb_add_data() फ़ंक्शंस में समस्या हो रही है। मुझे समझ में नहीं आता कि मेरे द्वारा क्या त्रुटि हुई थी। अगर कोई मुझे कोड के साथ मदद कर सकता है, तो मैं बहुत आभारी रहूंगा। अग्रिम में धन्यवाद। मैं सुविधा के लिए मेकफ़ाइल भी दे रहा हूं। यह वितरण कर्नेल के लिए है, न कि एक निर्मित कर्नेल के लिए। skb-> पूंछ इतना छोटा है कि मैं गिरी अंतरिक्ष में नई पैकेट बनाने के लिए होगा -

#If KERNELRELEASE is defined, we've been invoked from the 
#kernel build system and use its language 
ifneq ($(KERNELRELEASE),) 
    obj-m := ibss_obsf_cat.o 

#Otherwise we were called directly from the command 
#line; invoke the kernel build system. 
else 

    KERNELDIR ?= /lib/modules/$(shell uname -r)/build 
    PWD := $(shell pwd) 

default: 
    $(MAKE) -C $(KERNELDIR) M=$(PWD) modules 

endif 

अब मैं काफी आश्वस्त हैं कि skb-> अंत कर रहा हूँ। मैं alloc_skb() skb_reserve() skb_header_pointer() और एक नया SKB बनाने के लिए अन्य उपयोगी SKB कार्यों का इस्तेमाल किया है, लेकिन बात मैं विचार से बाहर चल रहा है कि कैसे मार्ग पैकेट बह रास्ते में नव निर्मित पैकेट के लिए ।
ip_route_me_harder() का उपयोग कैसे करें मैंने सुझाव के लिए xtables-addons पैकेज में देखा, लेकिन उनके द्वारा उपयोग किया जाने वाला फ़ंक्शन लिनक्स कर्नेल में से एक से अलग है। किसी भी सुझाव का स्वागत है।

उत्तर

3

बारे में एक साल पहले गिरी 2.6.26 के लिए मैं इस तरह यह किया:

// Do we need extra space? 
if(len - skb_tailroom(skb) > 0){ 

    // Expand skb tail until we have enough room for the extra data 
    if (pskb_expand_head(skb, 0, extra_data_len - skb_tailroom(skb), GFP_ATOMIC)) { 
    // allocation failed. Do whatever you need to do 
    } 

    // Allocation succeeded 

    // Reserve space in skb and return the starting point 
    your_favourite_structure* ptr = (your_favourite_structure*) 
            skb_push(skb, sizeof(*ptr)); 

    // Now either set each field of your structure or memcpy into it. 
    // Remember you can use a char* 

} 

को न भूलें:

  • पुनर्गणना यूडीपी चेकसम, क्योंकि आप जाया डेटा में डेटा बदल ।

  • आईपी हेडर में tot_len (कुल लंबाई) फ़ील्ड बदलें, क्योंकि आपने पैकेट में डेटा जोड़ा है।

  • आईपी हेडर चेकसम को पुन: गणना करें, क्योंकि आपने tot_len फ़ील्ड को बदल दिया है।

अतिरिक्त टिप्पणी: यह सिर्फ एक सरल बात है। मैं आपके कोड में देखता हूं कि आप 200 बाइट सरणी के रूप में tmp आवंटित कर रहे हैं और इसका उपयोग अपने संदेश के डेटा को संग्रहीत करने के लिए कर रहे हैं। यदि आप एक बड़ा पैकेट भेजते हैं तो आपको मेमोरी ओवरफ्लो के कारण कर्नेल क्रैश होने के कारण यह एक कठिन समय होगा।

+0

आपकी मदद के लिए धन्यवाद। हां, लंबाई के खेतों ने मुझे बहुत परेशान किया। –

+0

और कर्नेल स्पेस में चेकसमिंग भी पहले मेरे लिए काफी अस्पष्ट था। –

+0

@Fred क्या आप इस पर भी टिप्पणी कर सकते हैं http://stackoverflow.com/questions/12529497/how-to-append-data-on-a-packet-from- कर्नेल- स्पेस – user2087340

1

मैंने समस्या हल कर दी है। यह छोटा था। और मैं जो कुछ करने जा रहा हूं वह भविष्य के संदर्भों और चर्चाओं के लिए अपना कोड पोस्ट करना है।

#include <linux/kernel.h> 
#include <linux/module.h> 
#include <linux/skbuff.h> 
#include <linux/netfilter.h> 
#include <linux/netdevice.h> 
#include <linux/ip.h> 
#include <linux/udp.h> 
#include <linux/mm.h> 
#include <linux/err.h> 
#include <linux/crypto.h> 
#include <linux/init.h> 
#include <linux/crypto.h> 
#include <linux/scatterlist.h> 
#include <net/ip.h> 
#include <net/udp.h> 
#include <net/route.h> 

#undef __KERNEL__ 
#include <linux/netfilter_ipv4.h> 
#define __KERNEL__ 

#define IP_HDR_LEN 20 
#define UDP_HDR_LEN 8 
#define TOT_HDR_LEN 28 

static unsigned int pkt_mangle_begin(unsigned int hooknum, 
         struct sk_buff *skb, 
         const struct net_device *in, 
         const struct net_device *out, 
         int (*okfn)(struct sk_buff *)); 

static struct nf_hook_ops pkt_mangle_ops __read_mostly = { 
    .pf = NFPROTO_IPV4, 
    .priority = 1, 
    .hooknum = NF_IP_LOCAL_OUT, 
    .hook = pkt_mangle_begin, 
}; 

static int __init pkt_mangle_init(void) 
{ 
    printk(KERN_ALERT "\npkt_mangle module started ..."); 
    return nf_register_hook(&pkt_mangle_ops); 
} 

static void __exit pkt_mangle_exit(void) 
{ 
    nf_unregister_hook(&pkt_mangle_ops); 
    printk(KERN_ALERT "pkt_mangle module stopped ..."); 
} 

static unsigned int pkt_mangle_begin (unsigned int hooknum, 
         struct sk_buff *skb, 
         const struct net_device *in, 
         const struct net_device *out, 
         int (*okfn)(struct sk_buff *)) 
{ 
    struct iphdr *iph; 
    struct udphdr *udph; 
    unsigned char *data; 

    unsigned int data_len; 
    unsigned char extra_data[] = "12345"; 
    unsigned char *temp; 
    unsigned int extra_data_len; 
    unsigned int tot_data_len; 

    unsigned int i; 

    __u16 dst_port, src_port; 

    if (skb) { 
     iph = (struct iphdr *) skb_header_pointer (skb, 0, 0, NULL); 

     if (iph && iph->protocol &&(iph->protocol == IPPROTO_UDP)) { 
      udph = (struct udphdr *) skb_header_pointer (skb, IP_HDR_LEN, 0, NULL); 
      src_port = ntohs (udph->source); 
      dst_port = ntohs (udph->dest); 

      if (src_port == 6000) { 
       printk(KERN_ALERT "UDP packet goes out"); 
       data = (unsigned char *) skb_header_pointer (skb, IP_HDR_LEN+UDP_HDR_LEN, 0, NULL); 
       data_len = skb->len - TOT_HDR_LEN; 

        temp = kmalloc(512 * sizeof(char), GFP_ATOMIC); 
       memcpy(temp, data, data_len); 

       unsigned char *ptr = temp + data_len - 1; 
       extra_data_len = sizeof(extra_data); 
       memcpy(ptr, extra_data, extra_data_len); 
       tot_data_len = data_len + extra_data_len - 1; 

       skb_put(skb, extra_data_len - 1); 

       memcpy(data, temp, tot_data_len); 

       /* Manipulating necessary header fields */ 
       iph->tot_len = htons(tot_data_len + TOT_HDR_LEN); 
       udph->len = htons(tot_data_len + UDP_HDR_LEN); 

       /* Calculation of IP header checksum */ 
       iph->check = 0; 
       ip_send_check (iph); 

       /* Calculation of UDP checksum */ 
       udph->check = 0; 
       int offset = skb_transport_offset(skb); 
       int len = skb->len - offset; 
       udph->check = ~csum_tcpudp_magic((iph->saddr), (iph->daddr), len, IPPROTO_UDP, 0); 

       } 
     } 
    } 
    return NF_ACCEPT; 
} 


module_init(pkt_mangle_init); 
module_exit(pkt_mangle_exit); 

MODULE_AUTHOR("Rifat Rahman Ovi: <[email protected]>"); 
MODULE_DESCRIPTION("Outward Packet Mangling and Decryption in Kernel Space"); 
MODULE_LICENSE("GPL"); 

यहां बात यह है कि, मैं लंबाई फ़ील्ड को अपडेट करना भूल गया और चेकसम अपडेट करना भूल गया। अब, अगर मैं सही ढंग से कोड प्रस्तुत करता हूं, तो सभी को अच्छी तरह से जाना चाहिए।कुछ अन्य सहायक फ़ंक्शन हैं जो यहां शामिल नहीं हैं।

+2

मुझे नहीं लगता कि यह कोड बिल्कुल अच्छा है। 1) आप कभी भी kfree (temp) नहीं करते हैं इसलिए एक मेमोरी रिसाव 2) skb_put बफर का विस्तार नहीं करता है, इसलिए आप वास्तव में उस मेमोरी के स्वामित्व के बिना यूडीपी पेलोड के अंत में बाइट्स का सामना कर रहे हैं और उम्मीद है कि टीआई कारण नहीं है समस्या का। –

+0

या ... आप सही हैं। हैलो दुनिया के अलावा यह मेरा पहला मॉड्यूल था। और यह समस्याएं पैदा करता है। तो, एक पैकेट बढ़ाने के लिए मुझे एक नया बफर आवंटित करने और कुछ संचालन करने की आवश्यकता है। यह गारंटी नहीं है कि skb_put() का उपयोग करने से इस तरह के नुकसान का कारण नहीं होगा। वैसे, यह वास्तव में एक पैकेट में कुछ बाइट पैडिंग के लिए लिखा गया था, अंत में यह कुछ कर्नेल पैनिक्स के बाद मुझे स्पष्ट था। लेकिन मैं इस पद के बारे में भूल गया। बिंदु के लिए धन्यवाद। मैं जल्द ही कोड समायोजित करूंगा। यू मॉड्यूल का विवरण देखता है .. यह केवल एक विशाल परियोजना की शुरूआत थी जिसमें केवल आधा उल्लेख किया गया था। धन्यवाद। –

+0

हैलो! मुझे एहसास है कि यह एक बहुत पुराना धागा है, लेकिन क्या आप मुझे बता सकते हैं कि भेजने/प्राप्त श्रृंखला में वास्तव में यह हुक कहलाता है? –

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