сбой setsockopt для IPPROTO_TCP IP_TOS в C

#c #linux #sockets #network-programming

#c #linux #сокеты #сетевое программирование

Вопрос:

Мой код завершается с ошибкой. Я запускаюсь от имени root (то же поведение, что и у обычного пользователя)

Сначала я хочу установить TOS, а затем получить значение.

 int tos_local = 0x28;
if (setsockopt(sockfd, IPPROTO_TCP, IP_TOS,  amp;tos_local, sizeof(tos_local))) {
    error("error at socket option");
} else {
    int tos=0;
    int toslen=0;

    if (getsockopt(sockfd, IPPROTO_TCP, IP_TOS,  amp;tos, amp;toslen) < 0) {
            error("error to get option");
    }else {
            printf ("changing tos opt = %dn",tos);
    }
}
  

printf печатает

изменение tos opt = 0

Я бы ожидал напечатать 0x28 (40).

В чем проблема?

Правильный ответ:

     if (setsockopt(sockfd, **IPPROTO_IP**, IP_TOS,  amp;tos_local, sizeof(tos_local))) {

    int tos=0;
    int toslen=sizeof(tos); //that line here

    if (getsockopt(sockfd, IPPROTO_IP, IP_TOS,  amp;tos, amp;toslen) < 0) {
  

Комментарии:

1. 5-й аргумент getsockopt — это размер буфера, на который указывает 4-й аргумент. Поэтому вам нужно удалить amp; в вашем примере кода. Или, еще лучше, поместите туда sizeof (tos), как сказал Сет.

Ответ №1:

IP_TOS имеет уровень IPPROTO_IP , не IPPROTO_TCP .

Смотрите документацию.

Это влияет как на настройку, так и на получение опции.

Кроме того, то, что Сет сказал об инициализации параметра length, который влияет только getsockopt .

Комментарии:

1. Действительно. И IP_TOS оказывается равным 1, как и TCP_NODELAY , так что этот код действительно что-то делает… Просто не то, что было задумано.

2. @Nemo: Да, они должны были разработать их как битовые поля вместо отдельных параметров. Но это еще не все.

Ответ №2:

При вызове getsockopt вы передаете размер памяти, на который указывает amp;tos. Другими словами, инициализируйте toslen значением sizeof(tos).

Комментарии:

1. Я получаю предупреждение компилятора об ошибке: предупреждение: передача аргумента 5 getsockopt преобразует указатель из целого числа без приведения, когда я передаю sizeof (tos). Кроме того, сбой getsockoption с «неверным адресом»

2. @cateof: передача amp;tos_len в качестве параметра правильная, но вам нужно объявить его как int tos_len = sizeof (tos); , а не 0 как.

3. @cateof: @Бен Войт: Я думаю, вы имеете в виду, что передача amp;tos_len в качестве параметра правильная, но вам нужно инициализировать его значением sizeof (tos), а не 0.