LINUX.ORG.RU

sk_buff - внести изменения в пакет ip

 , ,


0

3

Пробую внести изменения в IPv4 пакет - добавить 4 байта опций. Проверяю конкретно на DNS запросах, смотрю wiresharkом.
Опции добавляются, тело DNS запроса - корректное, а вот в UDP заголовке - все нормально, кроме порта назначения - он может быть какой угодно. При этом проверял на выходе из функции-обработчика - все значения стоят какие надо.
Где этот dstport может перетираться? Почему? Уже не пойму, куда рыть..

Так вешается обработчик:

  nfho.hook     = hook_func;                       
  nfho.hooknum  = NF_INET_POST_ROUTING;
  nfho.pf       = PF_INET;
  nfho.priority = NF_IP_PRI_FIRST;functions
  nf_register_hook(&nfho);
Вот код добавления опций
  switch (ip_hdr(skb)->protocol)
  {
    case IPPROTO_UDP:
      if (skb_is_nonlinear(skb)) {
        if (skb_linearize(skb)) {
          printk(KERN_ERR "LABEL: Can't linearize skb.\n");
          goto out;
        }
      }
      if (skb_tailroom(skb) < 4) {
        if (pskb_expand_head(skb, 0, 4, GFP_ATOMIC)) {
          printk(KERN_ERR "LABEL: Can't get memory for options.\n");
          goto out;
        }
      }
      if (!skb_make_writable(skb, skb->len)) {
        printk(KERN_ERR "LABEL: skb not writable.\n");
        goto out;
      }
      data      = skb_network_header((skb)) + ip_hdrlen((skb)); //char *data;
      data_size = skb_tail_pointer(skb) - data; // int data_size
      memmove(data + 4, data, data_size);
      memmove(data, OWN_OPT, 4); // unsigned char OWN_OPT[4]
      // узакониваем все наши изменения
      skb_put(skb, 4);
      ip_hdr(skb)->ihl += 1;
      ip_hdr(skb)->tot_len = ntohs(skb->len);
      ip_send_check(ip_hdr(skb));
      skb_set_transport_header(skb, ip_hdr(skb)->ihl * 4);
      break;
  }
out:
  return NF_ACCEPT;

★★

Ответ на: комментарий от sergej

ну тут не совсем то.. не меняется размер пакета, в смысле.
у меня такое подозрение, что гдето перерасчитывается контрольная сумма udp, причем по адресу, который был бы, если бы не было этих дополнительных байт.
но вот где и почему..

спасибо в любом случае )) я счас весь такой код штудирую ))

Vinill ★★ ()

Ипатьевский монастырь! Done.
В sk_buff надо еще два поля править. Сам он не умеет, зараза )

  skb->csum_start = skb_transport_header(skb) - skb->head;
  switch (ip_hdr(skb)->protocol)
  {
    case IPPROTO_ICMP:
      skb->csum_offset = offsetof(struct icmphdr, checksum);
      break;
    case IPPROTO_UDP:
      skb->csum_offset = offsetof(struct udphdr, check);
      break;
    case IPPROTO_TCP:
      skb->csum_offset = offsetof(struct tcphdr, check);
      break;
  }

Vinill ★★ ()