setsockopt fails for IPPROTO_TCP IP_TOS in C

13,665

Solution 1

IP_TOS has level IPPROTO_IP, not IPPROTO_TCP.

See the documentation.

This affects both setting and getting the option.

Also, what Seth said about initializing the length parameter, which affects only getsockopt.

Solution 2

When calling getsockopt, you pass in the size of the memory pointed to by &tos. In other words initialize toslen to sizeof(tos).

Share:
13,665
cateof
Author by

cateof

Problem exists between the keyboard and the chair

Updated on June 25, 2022

Comments

  • cateof
    cateof almost 2 years

    My code fails. I am running as root (same behavior as normal user)

    First I want to set the TOS and then get the value.

    int tos_local = 0x28;
    if (setsockopt(sockfd, IPPROTO_TCP, IP_TOS,  &tos_local, sizeof(tos_local))) {
        error("error at socket option");
    } else {
        int tos=0;
        int toslen=0;
    
        if (getsockopt(sockfd, IPPROTO_TCP, IP_TOS,  &tos, &toslen) < 0) {
                error("error to get option");
        }else {
                printf ("changing tos opt = %d\n",tos);
        }
    }
    

    the printf prints

    changing tos opt = 0

    I would expect to print 0x28 (40).

    What is the problem?

    The correct answer:

        if (setsockopt(sockfd, **IPPROTO_IP**, IP_TOS,  &tos_local, sizeof(tos_local))) {
    
        int tos=0;
        int toslen=sizeof(tos); //that line here
    
        if (getsockopt(sockfd, IPPROTO_IP, IP_TOS,  &tos, &toslen) < 0) {
    
  • cateof
    cateof almost 13 years
    I get compiler warning error: warning: passing argument 5 of getsockopt makes pointer from integer without a cast when I pass sizeof(tos). Additionally the getsockoption fails with "Bad Address"
  • Nemo
    Nemo almost 13 years
    Indeed. And IP_TOS happens to equal 1, as does TCP_NODELAY, so this code actually does something... Just not what was intended.
  • Ben Voigt
    Ben Voigt almost 13 years
    @cateof: passing &tos_len as the parameter is correct, but you need to declare it as int tos_len = sizeof (tos); and not 0.
  • Seth Robertson
    Seth Robertson almost 13 years
    @cateof: @Ben Voight: I think you mean, passing &tos_len as the parameter is correct, but you need to initialize it to sizeof(tos) and not 0.
  • Ben Voigt
    Ben Voigt almost 13 years
    @Nemo: Yeah, they should have designed these as bitfields instead of separate parameters. But that's water under the bridge.