Сетевой драйвер, помогите разобраться.

Тема в разделе "WASM.UNIX", создана пользователем nebula, 15 июл 2009.

  1. nebula

    nebula New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2009
    Сообщения:
    19
    Хочу разобраться с разработкой сетевых драйверов под Linux версии 2.6.x
    И сразу же столкнулся с проблемой...
    Чтоб скомпилировать модуль, нужны исходники линекса, с этим проблем не возникло. Затем начал писать модуль, и бац, dev_base не найден. ( она представляет точку входа в список зарегистрированных сетевых устройств ). Нет проблем, изучил netdevice.h и наткнулся на вот такую функцию

    static inline struct net_device *first_net_device (struct net *net)
    {
    return list_empty(&net->dev_base_head) ? NULL :
    net_device_entry(net->dev_base_head.next);
    }


    Как понял эта функция заменяет dev_base. ( так ли это??? )

    в модуле пишу так
    Код (Text):
    1. struct net_device *current_device; // текущая сетевуха
    2. char *eth = "eth0"; // имя этой сетевухи
    3.  
    4. my_init(struct net_device *current_device)
    5. {
    6.  printk("Внутри my_init \n");
    7.  
    8. if ((current_device = kmalloc(sizeof(struct net_device), GFP_KERNEL)) == NULL )
    9.     printk("Ошибка выделения памяти kmalloc \n");
    10.  
    11. if( (current_device = first_net_device(net)) == NULL )
    12.   printk("НАШЛИ !!! \n"); else printk("НЕ НОШЛИ!! \n");
    13.  
    14. printk("current_device->name = %s \n", current_device->name); // Хочу увидеть что действительно найдено нужное устройство.
    15.   printk("Перед return в my_init \n");
    16.         return 0;
    17. };
    18.  
    19.  
    20. my_cleanup() // выгружаем наш модуль
    21. {
    22.   printk("Внутри my_cleanup \n");
    23.  kfree(current_device);
    24.   printk("Выход из my_cleanup \n");
    25. };
    26.  
    27. module_init(my_init);
    28. module_exit(my_cleanup);
    При загрузке модуля в ядро выводится следующее
    localhost klogd: Внутри my_init
    localhost klogd: НАШЛИ !!!
    localhost klogd: current_device->name = <NULL>
    localhost klogd: Перед return в my_init
    localhost klogd: Внутри my_cleanup
    localhost klogd: Выход из my_cleanup



    Если заменить printk("current_device->name = %s \n", current_device->name); на printk("current_device->name = %s \n", *current_device->name);
    То вылезит вот это и нет возможности выгрузить модуль.
    Код (Text):
    1. Message from syslogd@localhost at Wed Jul 15 17:48:05 2009 ...
    2. localhost klogd: Oops: 0000 [#5] SMP
    3.  
    4. Message from syslogd@localhost at Wed Jul 15 17:48:05 2009 ...
    5. localhost klogd: last sysfs file: /sys/devices/pci0000:00/0000:00:1e.0/0000:02:05.0/net/eth0/ifindex
    6.  
    7. Message from syslogd@localhost at Wed Jul 15 17:48:05 2009 ...
    8. localhost klogd: Process insmod (pid: 22206, ti=d641a000 task=db2fc9e0 task.ti=d641a000)
    9.  
    10. Message from syslogd@localhost at Wed Jul 15 17:48:05 2009 ...
    11. localhost klogd: Stack:
    12.  
    13. Message from syslogd@localhost at Wed Jul 15 17:48:05 2009 ...
    14. localhost klogd:  7fffffff c062a6b0 c062a6b4 d641bdc0 c03c9c6d 000016d0 48f13c13 000016d0
    15.  
    16. Message from syslogd@localhost at Wed Jul 15 17:48:05 2009 ...
    17. localhost klogd:  c180d500 c05eb500 01222000 d641bdc8 d641bda0 c03cb608 d641bdb4 c01bb560
    18.  
    19. Message from syslogd@localhost at Wed Jul 15 17:48:05 2009 ...
    20. localhost klogd: Call Trace:
    21.  
    22. Message from syslogd@localhost at Wed Jul 15 17:48:05 2009 ...
    23. localhost klogd:  [<c0103026>] ? do_one_initcall+0x26/0x1c0
    24.  
    25. Message from syslogd@localhost at Wed Jul 15 17:48:05 2009 ...
    26. localhost klogd:  [<c03c9c6d>] ? schedule_timeout+0xad/0xe0
    27.  
    28. Message from syslogd@localhost at Wed Jul 15 17:48:05 2009 ...
    29. localhost klogd:  [<c03cb608>] ? _spin_lock+0x8/0x10
    30.  
    31. Message from syslogd@localhost at Wed Jul 15 17:48:05 2009 ...
    32. localhost klogd:  [<c01bb560>] ? add_partial+0x40/0x70
    33.  
    34. Message from syslogd@localhost at Wed Jul 15 17:48:05 2009 ...
    35. localhost klogd:  [<c01bce62>] ? __slab_free+0x112/0x2f0
    36.  
    37. Message from syslogd@localhost at Wed Jul 15 17:48:05 2009 ...
    38. localhost klogd:  [<c03cb546>] ? _spin_lock_irq+0x16/0x20
    39.  
    40. Message from syslogd@localhost at Wed Jul 15 17:48:05 2009 ...
    41. localhost klogd:  [<c03c8efb>] ? wait_for_common+0xbb/0x130
    42.  
    43. Message from syslogd@localhost at Wed Jul 15 17:48:05 2009 ...
    44. localhost klogd:  [<c01bfe66>] ? percpu_free+0x46/0x50
    45.  
    46. Message from syslogd@localhost at Wed Jul 15 17:48:05 2009 ...
    47. localhost last message repeated 3 times
    48.  
    49. Message from syslogd@localhost at Wed Jul 15 17:48:05 2009 ...
    50. localhost klogd:  [<c0176f9c>] ? stop_machine_destroy+0x3c/0x40
    51.  
    52. Message from syslogd@localhost at Wed Jul 15 17:48:05 2009 ...
    53. localhost klogd:  [<c0166c05>] ? load_module+0xa5/0x1c50
    54.  
    55. Message from syslogd@localhost at Wed Jul 15 17:48:05 2009 ...
    56. localhost klogd:  [<f85ba000>] ? cleanup_module+0x0/0x30 [index5]
    57.  
    58. Message from syslogd@localhost at Wed Jul 15 17:48:05 2009 ...
    59. localhost klogd:  [<c0188384>] ? marker_update_probe_range+0x194/0x2a0
    60.  
    61. Message from syslogd@localhost at Wed Jul 15 17:48:05 2009 ...
    62. localhost klogd:  [<c0189536>] ? tracepoint_update_probe_range+0x76/0xa0
    63.  
    64. Message from syslogd@localhost at Wed Jul 15 17:48:05 2009 ...
    65. localhost klogd:  [<c018958f>] ? tracepoint_module_notify+0x2f/0x40
    66.  
    67. Message from syslogd@localhost at Wed Jul 15 17:48:05 2009 ...
    68. localhost klogd:  [<c03ce27d>] ? notifier_call_chain+0x2d/0x70
    69.  
    70. Message from syslogd@localhost at Wed Jul 15 17:48:05 2009 ...
    71. localhost klogd:  [<c015783d>] ? __blocking_notifier_call_chain+0x4d/0x60
    72.  
    73. Message from syslogd@localhost at Wed Jul 15 17:48:05 2009 ...
    74. localhost klogd:  [<c015786a>] ? blocking_notifier_call_chain+0x1a/0x20
    75.  
    76. Message from syslogd@localhost at Wed Jul 15 17:48:05 2009 ...
    77. localhost klogd:  [<c0168846>] ? sys_init_module+0x96/0x1d0
    78.  
    79. Message from syslogd@localhost at Wed Jul 15 17:48:05 2009 ...
    80. localhost klogd:  [<c01c01ca>] ? sys_close+0x7a/0xc0
    81.  
    82. Message from syslogd@localhost at Wed Jul 15 17:48:05 2009 ...
    83. localhost klogd:  [<c010ac5b>] ? sysenter_do_call+0x12/0x2f
    84.  
    85. Message from syslogd@localhost at Wed Jul 15 17:48:05 2009 ...
    86. localhost klogd:  [<c03c0000>] ? quirk_usb_early_handoff+0x3c0/0x460
    87.  
    88. Message from syslogd@localhost at Wed Jul 15 17:48:05 2009 ...
    89. localhost klogd: Code: c7 04 24 f3 a0 5b f8 e8 0b ec e0 c7 ba d0 00 00 00 b8 2c b9 56 c0 e8 0f 38 c0 c7 85 c0 74 33 c7 04 24 0a a1 5b f8 e8 ec eb e0 c7 <0f> be 05 00 00 00 00 c7 04 24 1b a1 5b f8 89 44 24 04 e8 d5 eb
    90.  
    91. Message from syslogd@localhost at Wed Jul 15 17:48:05 2009 ...
    92. localhost klogd: EIP: [<f85ba061>] init_module+0x31/0x68 [index5] SS:ESP 0068:d641bd48
    Первый вопрос: почему не могу просмотреть имя сетевого устройств?
    Второй вопрос: что означает вывод консоли, при неверном доступе к памяти (тот что описал чуть выше ) ? как в нём разобраться?
     
  2. agrischuk

    agrischuk New Member

    Публикаций:
    0
    Регистрация:
    12 янв 2009
    Сообщения:
    47
    Таки не нашли. Разименование нулевого указателя черевато. Чтобы стек трейс увидеть неплохо бы дебаг символы включить при компиляции.
     
  3. nebula

    nebula New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2009
    Сообщения:
    19
    agrischuk
    С first_net_device разобрался, теперь находит все сетевые адаптеры.

    А вот с отладкой беда. Никогда не отлаживал приложения работающие в ядре. ( вроде у меня есть литература по отладке ядра в GDB под DDD но там всего пара страниц..попробую разобраться )

    Как включить дебаг символы при компиляции,чтобы увидеть стек трейс?
    Как выгружать модуль после ошибок с памятью??? ( insmod -f не помогает ) А то приходится каждые раз, что бы избежать перезагрузки переименовывать исходник модуля, редактировать Makefile и собственно изменять команду компиляции. ( хоть это и быстро...но очень надоедает )
     
  4. agrischuk

    agrischuk New Member

    Публикаций:
    0
    Регистрация:
    12 янв 2009
    Сообщения:
    47
    У gcc есть ключ -g, его дожно быть достаточно.
    Выгрузить модуль можно с помощью команды rmmod.
     
  5. nebula

    nebula New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2009
    Сообщения:
    19
    agrischuk
    Я в предыдущем посте сделал ошибку..я имел ввиду, что выгрузить модуль через rmmod -f не получается.
     
  6. nebula

    nebula New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2009
    Сообщения:
    19
    И ещё один вопрос, когда пытаюсь вывести через printk, mtu сетевого устройства ( eth - это значение должно быть равно 1500). То пишу это printk( "net_device mtu = %u \n", &dev->mtu );
    Выводится net_device mtu = 4136237260 cовсем не 1500 ))
    Как получить верные данные из &dev->mtu ? ( вывести на консоль )
     
  7. agrischuk

    agrischuk New Member

    Публикаций:
    0
    Регистрация:
    12 янв 2009
    Сообщения:
    47
    Амперсент убери, это взятие адреса.
    Посмотри что выводит rmmod -v. Если есть возможность используй виртуальную машину, там откат идет быстро.
     
  8. nebula

    nebula New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2009
    Сообщения:
    19
    agrischuk
    Ок спасибо за совет.

    И у меня следующий вопрос)
    Касающийся фильтров.
    При insmod модуля консоль как бы зависает, тоесть начинаю грузить модуль в ядро, и окончание загрузки не происходит ( просто чёрная консколь остается..как будто комп чтото считает долго) при нажатии ctrl+c(d) "программа не прерывается" и всё также модуль не выгружается из ядра.
    По фильтрам у меня есть литература, и я достаточно хорошо её освоил. Но теория теорией, а на практике всё всегда по другому.
    Беру пример из интернета вот он
    Код (Text):
    1. #include <linux/kernel.h>
    2. #include <linux/module.h>
    3. #include <linux/netfilter_ipv4.h>
    4. #include <linux/netfilter.h>
    5.  
    6.  
    7. MODULE_LICENSE ("GPL v2");
    8. MODULE_AUTHOR ("ill");
    9. MODULE_DESCRIPTION ("Firewall");
    10.  
    11. /*
    12. * Объявление структур. Мы объявим 2-е структуры.
    13. * 1-я для входящих пакетов
    14. * 2-я для исходящих пакетов
    15. */
    16.  
    17. struct nf_hook_ops nf_incoming;
    18. struct nf_hook_ops nf_outgoing;
    19. int i=1;
    20.  
    21. unsigned int main_hook (unsigned int hooknum,
    22.             struct sk_buff **skb,
    23.             const struct net_device *in,
    24.             const struct net_device *out,
    25.             int (*okfn)(struct sk_buff *))
    26. {
    27.  
    28. /* Для примера, мы будем отбрасывать все пакеты */
    29.    
    30. return NF_DROP;
    31. }
    32.  
    33. int init_module (void)
    34. {
    35.  
    36. /*
    37. * Заполнение структур
    38. * Сначала, заполним структуру для входящих пакетов
    39. */
    40.  
    41. nf_incoming.hook=main_hook;
    42. nf_incoming.pf=PF_INET;
    43. nf_incoming.hooknum=NF_IP_PRE_ROUTING;
    44. nf_incoming.priority=NF_IP_PRI_FIRST;
    45.  
    46. /* Теперь для исходящих */
    47.  
    48. nf_outgoing.hook=main_hook;
    49. nf_outgoing.pf=PF_INET;
    50. nf_outgoing.hooknum=NF_IP_POST_ROUTING;
    51. nf_outgoing.priority=NF_IP_PRI_FIRST;
    52.  
    53. /* Вроде все, осталось только зарегистрировать наши функции */
    54.  
    55. nf_register_hook(&nf_incoming);
    56. nf_register_hook(&nf_outgoing);
    57.  
    58. printk ("FireWall loaded\n");
    59.  
    60. return 0;
    61. }
    62.  
    63. void cleanup_module (void)
    64. {
    65.  
    66. /* Не забываем удалить наши вызовы :), а то конфуз может случиться */
    67.  
    68. nf_unregister_hook(&nf_incoming);
    69. nf_unregister_hook(&nf_outgoing);
    70.  
    71. printk ("FireWall unload\n");
    72.    
    73. }
    В своём коде делаю всё по аналагоии..с кодом данным из интернета.
    Расхождение только в том, что в моей версии ядра, в исходниках
    структура struct nf_hook_ops выглядит так
    struct nf_hook_ops
    {
    struct list_head list;

    /* User fills in from here down. */
    nf_hookfn *hook;
    struct module *owner; Добавлена новая структура.
    u_int8_t pf;
    unsigned int hooknum;
    /* Hooks are ordered in ascending priority. */
    int priority;
    };

    Хочу поинтересоваться, что это за структура такая...и где её определения находятся)


    Для пробы делаю такой код)..

    Код (Text):
    1. unsigned int ip_in_hook(unsigned int hooknum,
    2.                   struct sk_buff *skb,
    3.                   const struct net_device *in,
    4.                   const struct net_device *out,
    5.                   int (*okfn)(struct sk_buff *)  ) // функция перехватчик входящих ip пакетов, сробатывающая в NF_INET_PRE_ROUTING
    6.   {
    7.    
    8.     return NF_DROP;
    9.    
    10.   }
    11.  
    12.   unsigned int ip_out_hook(unsigned int hooknum,
    13.                   struct sk_buff *skb,
    14.                   const struct net_device *in,
    15.                   const struct net_device *out,
    16.                   int (*okfn)(struct sk_buff *)  ) // функция перехватчик исходящих ip пакетов, сробатывающая в NF_INET_PRE_ROUTING
    17.   {
    18.    
    19.     return NF_DROP;
    20.    
    21.   }
    22.  
    23.  
    24. my_init()
    25. {
    26. struct nf_hook_ops   filter_ip_in_ops; // структура функции перехватчика входящих ip пакетов
    27. struct nf_hook_ops   filter_ip_out_ops; // структура функции перехватчика исходящих ip пакетов
    28. struct module *owner;  // ЧТО ЗА СТРУКТУРА???
    29.  
    30. //заполняем структуру перехватчика для входящих ip пакетов
    31. filter_ip_in_ops.hook = ip_in_hook; // ф-я перехватчик для входящих ip пакетов
    32. filter_ip_in_ops.owner = owner ;  // struct module *owner;
    33. filter_ip_in_ops.pf = PF_INET; // семейство протоколов
    34. filter_ip_in_ops.hooknum = NF_INET_PRE_ROUTING ; //
    35. filter_ip_in_ops.priority = NF_IP_PRI_FIRST ; // приоретет обработки hook
    36.  
    37.  
    38. //заполняем структуру перехватчика для исходящих ip пакетов
    39. filter_ip_out_ops.hook = ip_out_hook; // ф-я перехватчик для исходящих ip пакетов
    40. filter_ip_out_ops.owner = owner ; // struct module *owner;
    41. filter_ip_out_ops.pf = PF_INET; // семейство протоколов
    42. filter_ip_out_ops.hooknum = NF_INET_PRE_ROUTING ; //
    43. filter_ip_out_ops.priority = NF_IP_PRI_FIRST ; // приоретет обработки hook
    44.  
    45.         return 0;
    46. };
    47.  
    48. my_cleanup(struct nf_hook_ops   *filter_ip_in_ops,
    49.           struct nf_hook_ops   *filter_ip_out_ops)
    50. {
    51. nf_unregister_hook(&filter_ip_in_ops); //выгружаем перехватчик
    52. nf_unregister_hook(&filter_ip_out_ops); //выгружаем перехватчик
    53. };
    54.  
    55. module_init(my_init);
    56. module_exit(my_cleanup);
    Где ошибка?
    [root@localhost ~]# rmmod -v index
    rmmod index, wait=no
    ERROR: Removing 'index': Device or resource busy
     
  9. nebula

    nebula New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2009
    Сообщения:
    19
    чёрт, редактирования не вижу...
    в попыхах не дописал, что у меня в коде, перед return 0 в my_init()
    есть следующее
    nf_register_hook(&filter_ip_in_ops); // регестрируем перехватчик входящих ip пакетов
    nf_register_hook(&filter_ip_out_ops); // регестрируем перехватчик исходящих ip пакетов



    тоесть вот мой код

    Код (Text):
    1. unsigned int ip_in_hook(unsigned int hooknum,
    2.                   struct sk_buff *skb,
    3.                   const struct net_device *in,
    4.                   const struct net_device *out,
    5.                   int (*okfn)(struct sk_buff *)  ) // функция перехватчик входящих ip пакетов, сробатывающая в NF_INET_PRE_ROUTING
    6.   {
    7.    
    8.     return NF_DROP;
    9.    
    10.   }
    11.  
    12.   unsigned int ip_out_hook(unsigned int hooknum,
    13.                   struct sk_buff *skb,
    14.                   const struct net_device *in,
    15.                   const struct net_device *out,
    16.                   int (*okfn)(struct sk_buff *)  ) // функция перехватчик исходящих ip пакетов, сробатывающая в NF_INET_PRE_ROUTING
    17.   {
    18.    
    19.     return NF_DROP;
    20.    
    21.   }
    22.  
    23.  
    24. my_init()
    25. {
    26. struct nf_hook_ops   filter_ip_in_ops; // структура функции перехватчика входящих ip пакетов
    27. struct nf_hook_ops   filter_ip_out_ops; // структура функции перехватчика исходящих ip пакетов
    28. struct module *owner;  // ЧТО ЗА СТРУКТУРА???
    29.  
    30. //заполняем структуру перехватчика для входящих ip пакетов
    31. filter_ip_in_ops.hook = ip_in_hook; // ф-я перехватчик для входящих ip пакетов
    32. filter_ip_in_ops.owner = owner ;  // struct module *owner;
    33. filter_ip_in_ops.pf = PF_INET; // семейство протоколов
    34. filter_ip_in_ops.hooknum = NF_INET_PRE_ROUTING ; //
    35. filter_ip_in_ops.priority = NF_IP_PRI_FIRST ; // приоретет обработки hook
    36.  
    37.  
    38. //заполняем структуру перехватчика для исходящих ip пакетов
    39. filter_ip_out_ops.hook = ip_out_hook; // ф-я перехватчик для исходящих ip пакетов
    40. filter_ip_out_ops.owner = owner ; // struct module *owner;
    41. filter_ip_out_ops.pf = PF_INET; // семейство протоколов
    42. filter_ip_out_ops.hooknum = NF_INET_PRE_ROUTING ; //
    43. filter_ip_out_ops.priority = NF_IP_PRI_FIRST ; // приоретет обработки hook
    44.  
    45. nf_register_hook(&filter_ip_in_ops); // регестрируем перехватчик входящих ip пакетов
    46. nf_register_hook(&filter_ip_out_ops); // регестрируем перехватчик исходящих ip пакетов
    47.         return 0;
    48. };
    49.  
    50. my_cleanup(struct nf_hook_ops   *filter_ip_in_ops,
    51.           struct nf_hook_ops   *filter_ip_out_ops)
    52. {
    53. nf_unregister_hook(&filter_ip_in_ops); //выгружаем перехватчик
    54. nf_unregister_hook(&filter_ip_out_ops); //выгружаем перехватчик
    55. };
    56.  
    57. module_init(my_init);
    58. module_exit(my_cleanup);
     
  10. agrischuk

    agrischuk New Member

    Публикаций:
    0
    Регистрация:
    12 янв 2009
    Сообщения:
    47
    owner - владелец, просто поставь стандартное значение (уж погугли, будь добр).
    Насчет my_cleanup - кто тебе эти два параметра передает? ИМХО прототип у функции переменное количество или нет аргуметов.
     
  11. bsnake

    bsnake New Member

    Публикаций:
    0
    Регистрация:
    11 сен 2005
    Сообщения:
    91
    А можно поинтересоваться, что за приложение вы пишите?

    Баги:
    filter_ip_in_ops и filter_ip_out_ops вы регистрируете два абсолютно одинаковых хука

    filter_ip_in_ops.hooknum = NF_INET_PRE_ROUTING ;
    filter_ip_out_ops.hooknum = NF_INET_PRE_ROUTING ; // Тут надо POST_ROUTING

    Структуры filter_ip_in_ops и filter_ip_out_ops локальные, распологаются в стеке функции init.
    В module_exit не передается никаких параметров и nf_unregister_hook вы делаете хрен знает для чего. Объявите переменные глобально.
     
  12. nebula

    nebula New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2009
    Сообщения:
    19
    bsnake
    Это даже не приложение, скорее просто стараюсь разобраться в сетевой архитектуре linux, по частям. =)

    Насчёт багов, это да....мои недочеты.
    Кстати, шикарно) пробовал вот этот код. Всё работает.

    Код (Text):
    1. unsigned int ip_in_hook(unsigned int hooknum,
    2.                   struct sk_buff *skb,
    3.                   const struct net_device *in,
    4.                   const struct net_device *out,
    5.                   int (*okfn)(struct sk_buff *)  ) // функция перехватчик входящих ip пакетов, сробатывающая в NF_INET_PRE_ROUTING
    6. { return NF_DROP; }
    7.  
    8. struct nf_hook_ops   filter_ip_in_ops; // структура функции перехватчика входящих ip пакетов
    9. my_init(  )
    10. {
    11.     printk("Внутри my_init \n");
    12. filter_ip_in_ops.hook = ip_in_hook; // ф-я перехватчик для входящих ip пакетов
    13. filter_ip_in_ops.owner = THIS_MODULE ; // УСТАНОВИТЬ УКАЗАТЕЛЬ НА МОДУЛЬ СОЗДАВШИЙ HOOK // struct module *owner;
    14. filter_ip_in_ops.pf = PF_INET; // семейство протаколов
    15. filter_ip_in_ops.hooknum = NF_INET_PRE_ROUTING ; //
    16. filter_ip_in_ops.priority = NF_IP_PRI_FIRST ; // приоретет обработки hook
    17.  
    18. nf_register_hook(&filter_ip_in_ops); // регестрируем перехватчик входящих ip пакетов
    19.         return 0;
    20. };
    21.  
    22. my_cleanup( ) // выгружаем наш модуль
    23. {
    24.   printk("Внутри my_cleanup \n");
    25. nf_unregister_hook(&filter_ip_in_ops); //выгружаем перехватчик
    26.   printk("Конец \n");
    27. };
    28.  
    29. module_init(my_init);
    30. module_exit(my_cleanup);
     
  13. nebula

    nebula New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2009
    Сообщения:
    19
    Поясните пожалуйста, почему вот на этом коде, система намертво виснет???
    iphdr= skb->network_header; // получаем заголовок ip пакета

    эта строка находится в перехватчике ip пакетов.
    вот участок злополучного кода

    unsigned int ip_in_hook(unsigned int hooknum,
    struct sk_buff *skb,
    const struct net_device *in,
    const struct net_device *out,
    int (*okfn)(struct sk_buff *) ) // функция перехватчик входящих ip пакетов, срабатывающая в NF_INET_PRE_ROUTING
    {
    // заполняем структуру iphdr принятого пакета
    struct iphdr *iphdr;
    iphdr = kmalloc (sizeof (struct iphdr), GFP_KERNEL);
    iphdr= skb->network_header; // получаем заголовок ip пакета// Как тока доходим до сюда, каюк системе!
    kfree(iphdr); // сразу удаляем

    return NF_DROP; // это пример
    }
     
  14. bsnake

    bsnake New Member

    Публикаций:
    0
    Регистрация:
    11 сен 2005
    Сообщения:
    91
    Код (Text):
    1. struct sk_buff {
    2.   sk_buff_data_t          network_header;
    3. ...  
    4. #ifdef NET_SKBUFF_DATA_USES_OFFSET
    5.   typedef unsigned int sk_buff_data_t;
    6. #else
    7.   typedef unsigned char *sk_buff_data_t;
    8. #endif
    Может пока вам ещё рано лезть в ядро? Вам пока книжек по С\С++ почитать и документацию на ядро с исходниками, тогда 99% вопрос отпадут сразу.
     
  15. nebula

    nebula New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2009
    Сообщения:
    19
    bsnake
    Книжек по си перечитано уйма, ( да и доки почитываю ). В основном специализируюсь на ассемблере, но в ядре асм мало помогает. Так что не рано. Нужна практика, которой очень мало.
    Я не понимаю, как предо ставленый Вами код, может изменить моё мировоззрение на структуру кода.
    sk_buff_data_t - неизвестный для меня тип, в том плане, что я не знаю из скольких байтов он состоит, в моём понимании это указатель на заголовок ip пакета. А заголовок должен представляться структурой struct iphdr . Значит делаем указатель на ip заголовок struct iphdr *iphdr . В функцию передаём указатель на буфер сокета, получаем что sk_buff->network_header это первый байт указателя на ip заголовок. Значит можно присвоить адрес iphdr = skb->network_header и теперь iphdr указывает на нужный нам заголовок( представляемый структурой struct iphdr ).
    Это рассуждение конечно-же не верное.(ядро то почти моментально падает). Но хочется понять...что я ещё не понимаю))))... Что не понимаю в процессе работы этого кода?(или того, что делаю)

    И я к сожалению не понимаю.
    чем мне может помочь это?
    Код (Text):
    1. #ifdef NET_SKBUFF_DATA_USES_OFFSET
    2.   typedef unsigned int sk_buff_data_t;
    3. #else
    4.   typedef unsigned char *sk_buff_data_t;
    5. #endif
    Разъясните если не сложно.
     
  16. nebula

    nebula New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2009
    Сообщения:
    19
    Пока сайт весел, разобрался с проблемой.
    Но хотел бы пояснения) насчёт
    Код (Text):
    1. #ifdef NET_SKBUFF_DATA_USES_OFFSET
    2.   typedef unsigned int sk_buff_data_t;
    3. #else
    4.   typedef unsigned char *sk_buff_data_t;
    5. #endif
    На что влияет NET_SKBUFF_DATA_USES_OFFSET , где должна быть определена?

    И для совместимости с разными дистрибутивами , нужно код писать с учётом возможности *sk_buff_data_t и sk_buff_data_t Этож сколько #ifdef нужно будет написать..........
     
  17. kamatoz

    kamatoz New Member

    Публикаций:
    0
    Регистрация:
    5 мар 2004
    Сообщения:
    31
    Адрес:
    Russia
    тебе эту структуру не надо юзать, насколько я помню ее пользуют макросы из skbuff.h, а тебе надо типа так
    {{{
    iphdr = ip_hdr( skb );
    }}}
    только хидер валиден если изначально было сделано
    skb_reset_network_header ( skb );
    при условии что в момент вызова skb->data указывал именно на ip заголовок, а вообще чтоб поянть смотри исходники ядра, там все есть
    http://lxr.linux.no/linux+v2.6.22/net/ipv4/ip_input.c#L380
     
  18. kamatoz

    kamatoz New Member

    Публикаций:
    0
    Регистрация:
    5 мар 2004
    Сообщения:
    31
    Адрес:
    Russia
    поясняю
    iphdr = kmalloc (sizeof (struct iphdr), GFP_KERNEL);
    выделяешь память
    iphdr= skb->network_header;
    устанавливаешь iphdr в середину сетевого пакета ( указатель на выделенную память теряется )
    kfrree(iphdr);
    пытаешься грохнуть память в середине сетевого пакета, который система использует, вот тебе и мертво виснет...
     
  19. nebula

    nebula New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2009
    Сообщения:
    19
    kamatoz
    Спасибо за объяснение.
     
  20. nebula

    nebula New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2009
    Сообщения:
    19
    Теперь никак не получается отправить буфер сокета в сетевой адаптер ((..вот код.
    С достаточно хорошими коментами.


    struct new_pkt // структура, которая будет записана в буфер сокета, для отправки в сетевой адаптер
    {
    struct iphdr iphdr; // ip заголовок, тут можно указать, ip назначения и тд
    struct udphdr udphdr; // заголовок транспортного уровня, тут можно будет указать порт принимающего чело
    char new_data[1024]; // данные
    } new_pkt;

    /* Вообще, в буфере сокета, данные должны располагаться так
    MAC header
    IP header
    UDP header
    UDP data


    Если не ошибаюсь, моя структура struct new_pkt должна соответствовать этим требованиям ( Mac header вроде должен быть добавлен уже сетевым адаптером..но я точно не знаю (((...поясните плиз )
    */
    struct new_pkt *new_pkt_ptr ;
    new_pkt_ptr = kmalloc( sizeof(struct new_pkt), GFP_ATOMIC ); // выделяем память для нового пакета ( то что надо передать сначала в sk_buff затем этот буфер сокета в сетевой адаптер )
    // создание буфера сокета для отправки
    struct sk_buff *sk_buff_ptr;
    sk_buff_ptr = dev_alloc_skb(sizeof(struct new_pkt)); // выделяем память для буфера сокета

    sk_buff_ptr->protocol=htons(ETH_P_IP); // if_ether.h /* Internet Protocol packet */
    memcpy(skb_put(sk_buff_ptr, sizeof(struct new_pkt)), new_pkt_ptr, sizeof(struct new_pkt));// skb_put дописывает данные в конец текущего пакета ( увеличивает указатель tail и skb->len)


    // это не обязательно, но желательно понять)..как выставить указатели на инет заголовки в sk_buff ( transport_header; network_header; mac_header (его пока не существует);) указывающие на данные скопированной структуры в буфер данных сокета через skb_put тоесть чтоб, sk_buff_ptr->transport_header указывал на new_pkt_ptr->iphdr а new_pkt_ptr->transport_header на new_pkt_ptr->udphdr ( в буфере сокета)

    //sk_buff_ptr->network_header = sk_buff_ptr->data; ?????
    //sk_buff_ptr->transport_header = sk_buff_ptr->data+sizeof( struct iphdr ) ; ?????

    struct net_device *dev; // указатель на сетевое устройство
    dev = first_net_device(&init_net); // первое устройство net_device Как правило lo
    while ( (dev = next_net_device(dev)) !=NULL ) // пробуем отослать пакет, из каждого сетевого устройства
    {
    printk("Внутри while \n");
    sk_buff_ptr->dev = dev ;
    dev_queue_xmit(sk_buff_ptr); // сетевое устройство указано параметром sk_buff_ptr->dev ..... при выполнении этой команды, система виснет)) намертво!
    }
    kfree_skb(sk_buff_ptr);
    kfree(new_pkt_ptr);


    Как отправить данные в сетевой адаптер?
    Где у меня ошибки??