RAW-Sockets должны игнорировать MTU

У меня небольшая проблема с моим RAW-Socket. Мне нужно перехватывать пакеты в сети, чтобы модифицировать их. Для этого мне нужно добавить специальные данные, например временные метки. Все работает нормально, но у меня проблема с MTU (Linux).

Если какое-то приложение верхних уровней генерирует пакеты, близкие к MTU, я не могу добавить свои данные. Поэтому я решил уменьшить MTU систем. Таким образом, я получил пакеты меньшего размера, и мои данные можно рекламировать. Но когда я пытаюсь отправить свои пакеты с помощью RAW-Socket, это не работает.

Я обнаружил (через Google, в старых потоках Stackoverflow и на справочных страницах Linux), что может помочь параметр IP_MTU_DISCOVER. Но когда я использую его с setsockopt, ничего не меняется.

if ((s = socket(AF_PACKET, SOCK_RAW, ETH_P_ALL)) < 0) {
     printf("Error: could not open socket\n");
     return -1;
}

char socket_mtu = IP_PMTUDISC_DONT;
setsockopt(s,IPPROTO_IP,IP_MTU_DISCOVER,socket_mtu, 1);

Может быть, это важно. Было сделано уменьшение MTU, потому что, когда я добавляю свои собственные данные, результирующий пакет не будет больше 1500 + ETH-Header. Моя проблема в том, чтобы заставить Raw-Sockets игнорировать локальный MTU моей Linux-системы.

  1. Является ли IP_MTU_DISCOVER правильным способом игнорировать значение, установленное в MTU?
  2. Действительно ли IP_MTU_DISCOVER можно использовать с моим RAW-SOCKET?
  3. Есть ли другие способы уменьшить размер сегмента протоколов на уровне 3 и выше?

Я читал, что sendto() возвращает EMSGSIZE (=90), когда размер слишком велик. Итак, я провел следующий тест.

int k = sendto(s, frame.buffer, frame_len, 0,
             (struct sockaddr*)&saddrll, sizeof(saddrll));
    printf("K:%i\n", k);

После вызова sendto() "k" содержит "-1". Но если это зависит от размера пакета, разве это не должно быть "90"??

Когда я устанавливаю размер пакета, который мне нравится отправлять, меньше, чем MTU, он работает нормально... Немного странно.

Любая помощь будет приятной :-)

С уважением, Андреас


person AndiDT    schedule 11.07.2016    source источник


Ответы (1)


Ok. Я нашел решение изменить MTU из моей программы C.

установить MTU в C программно

buffer.ifr_mtu = 1500;
  if(!ioctl(s, SIOCSIFMTU, &buffer)) {
      printf("MTU changed\n");
  }

В первый момент это работает. Но это всего лишь обходной путь, он не очень чистый. Проблема может заключаться в том, что если приложение отправляет пакет в тот момент, когда я изменяю размер MTU, пакет может быть слишком большим. Есть идеи получше?

С уважением, Андреас

person AndiDT    schedule 11.07.2016