accept() and getpeername() return 0.0.0.0 - HP UX

This is a discussion on accept() and getpeername() return 0.0.0.0 - HP UX ; I think I'm dealing with a bug in a library or some weird problem. The following code compiles and works as I'd expect on Linux and cygwin, but on the machine that matters (HP PA64, HPUX 11.11) it identifies the ...

+ Reply to Thread
Results 1 to 8 of 8

Thread: accept() and getpeername() return 0.0.0.0

  1. accept() and getpeername() return 0.0.0.0

    I think I'm dealing with a bug in a library or some weird problem. The
    following code compiles and works as I'd expect on Linux and cygwin, but on
    the machine that matters (HP PA64, HPUX 11.11) it identifies the peer as
    0.0.0.0 in both the accept() and getpeername() return vals, also identifies
    the peer port as 0. I'm using gcc 4.1.2, downloaded from HP's site,
    compiling with 'gcc sockprob.c -o sockprob', then running it with
    './sockprob.c MY.I.P.ADD 7890', then connect to the server socket with
    'telnet MY.I.P.ADD 7890'. Cygwin and Linux show the ip and port of the
    connector, but HPUX is showing 0.0.0.0. I run a 'netstat -n' and it shows
    the correct ip/port for the server and client. I just don't get it. Does
    anyone have any advice? Anyone seen stuff like this with gcc on PA64?

    Thanks and sorry in advance. I'm not a newsgroup frequent flyer - I just
    got flamed for posting the same question on comp.lang.c. If you know of a
    good place to ask then please tell me.

    -M

    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include

    char* ipstring;
    int port1;

    void parseargs(int, char**);

    int main(int argc, char* args[])
    { struct sockaddr_in adr1; /* address for the server */
    int ss1, as1; /* file descriptors for server socket, active
    socket */

    struct sockaddr_in from1; /* address for peer */
    socklen_t from1_len;

    parseargs(argc, args);

    if((ss1 = socket(PF_INET, SOCK_STREAM, 0)) < 0)
    { perror("socket failed");
    return 1;
    }

    memset(&adr1, 0, sizeof(adr1));
    adr1.sin_family = AF_INET;
    adr1.sin_port = htons(port1);

    if(!inet_aton(ipstring, (struct in_addr*)&(adr1.sin_addr)))
    { perror("inet_aton failed");
    return 1;
    }

    if(bind(ss1, (struct sockaddr*) &adr1, sizeof(adr1)))
    { perror("bind failed");
    return 1;
    }

    if(listen(ss1, 1) < 0)
    { perror("listen failed");
    return 1;
    }

    from1_len = sizeof(from1);
    memset(&from1, 0, sizeof(from1));
    from1.sin_family = AF_INET;

    if((as1 = accept(ss1, (struct sockaddr*) &from1, &from1_len)) == -1)
    { perror("Error accepting");
    return 1;
    }

    printf("peer address from accept() is %s %d\n",
    inet_ntoa(from1.sin_addr), ntohs(from1.sin_port));


    if(getpeername(as1, (struct sockaddr*) &from1, &from1_len))
    { perror("getpeername failed");
    return 1;
    }

    printf("peer add/port from getpeername() is %s %d\n",
    inet_ntoa(from1.sin_addr), ntohs(from1.sin_port));

    return 0;
    }

    void parseargs(int argc, char* args[])
    {
    /* command line is sockprob ip port */
    ipstring = args[1];
    sscanf(args[2], "%d", &port1);
    return;
    }





  2. Re: accept() and getpeername() return 0.0.0.0

    >
    > from1_len = sizeof(from1);
    > memset(&from1, 0, sizeof(from1));
    > from1.sin_family = AF_INET;
    >
    > if((as1 = accept(ss1, (struct sockaddr*) &from1, &from1_len)) == -1)
    > { perror("Error accepting");
    > return 1;
    > }


    What is the value of "from1_len" after the accept call ^ ?

    Also, could you compile the same with HP C compiler
    and see if there is any difference ?

    >
    > printf("peer address from accept() is %s %d\n",
    > inet_ntoa(from1.sin_addr), ntohs(from1.sin_port));
    >


    If "from1_len" is zero (or invalid) above, you need to
    re-initialize it here.

    >
    > if(getpeername(as1, (struct sockaddr*) &from1, &from1_len))
    > { perror("getpeername failed");
    > return 1;
    > }


    --vishwas.

  3. Re: accept() and getpeername() return 0.0.0.0

    Thanks for the reply - from1_len is 16 before and 16 after the accept()
    call. I did a printf for each of the 16 bytes and it's all 0 except the
    second byte (socket family) which is 2, which is what the sys/socket.h
    header says for AF_INET.

    Unfortunately, I don't have the full ansi cc product at my disposal, but if
    you think that's the solution then I'll pursue that.

    Thanks,
    Mike

    "Vishwas Pai" wrote in message
    news:Y0PEh.526$Gc5.402@news.cpqcorp.net...
    >>
    >> from1_len = sizeof(from1);
    >> memset(&from1, 0, sizeof(from1));
    >> from1.sin_family = AF_INET;
    >>
    >> if((as1 = accept(ss1, (struct sockaddr*) &from1, &from1_len)) == -1)
    >> { perror("Error accepting");
    >> return 1;
    >> }

    >
    > What is the value of "from1_len" after the accept call ^ ?
    >
    > Also, could you compile the same with HP C compiler
    > and see if there is any difference ?
    >
    >>
    >> printf("peer address from accept() is %s %d\n",
    >> inet_ntoa(from1.sin_addr), ntohs(from1.sin_port));
    >>

    >
    > If "from1_len" is zero (or invalid) above, you need to
    > re-initialize it here.
    >
    >>
    >> if(getpeername(as1, (struct sockaddr*) &from1, &from1_len))
    >> { perror("getpeername failed");
    >> return 1;
    >> }

    >
    > --vishwas.




  4. Re: accept() and getpeername() return 0.0.0.0

    Mike King wrote:
    > Thanks for the reply - from1_len is 16 before and 16 after the accept()
    > call. I did a printf for each of the 16 bytes and it's all 0 except the
    > second byte (socket family) which is 2, which is what the sys/socket.h
    > header says for AF_INET.
    >
    > Unfortunately, I don't have the full ansi cc product at my disposal, but if
    > you think that's the solution then I'll pursue that.
    >


    I don't think you need to test this with HP CC.

    You can try installing the latest transport patches
    (PHNE_35183 ,which has few dependencies, is the latest
    transport patch for 11.11).

    --vishwas.

  5. Re: accept() and getpeername() return 0.0.0.0

    A 32-bit compilation of the program appears to work on my PA-RISC
    11.11 system:

    $ ./tryme 127.0.0.1 12345
    peer address from accept() is 127.0.0.1 55063
    peer add/port from getpeername() is 127.0.0.1 55063

    I do though get the following warnings in the compile:

    cc -o tryme tryme.c
    cc: "tryme.c", line 54: warning 604: Pointers are not assignment-compatible.
    cc: "tryme.c", line 54: warning 563: Argument #3 is not the correct type.
    cc: "tryme.c", line 63: warning 604: Pointers are not assignment-compatible.
    cc: "tryme.c", line 63: warning 563: Argument #3 is not the correct type.


    However a 64-bit compilation does not:

    $ ./tryme 127.0.0.1 12345
    peer address from accept() is 0.0.0.0 0
    peer add/port from getpeername() is 0.0.0.0 0


    The 64-bit compilation gave me the following warnings:

    cc +DD64 -o tryme tryme.c
    cc: "tryme.c", line 54: warning 728: Argument #3 converts long* to int*.
    cc: "tryme.c", line 63: warning 728: Argument #3 converts long* to int*.

    I believe this all stems from the use of socklen_t, which IMO HP-UX
    11.11 has rather well and truly botched. By default there is a
    socklen_t available, but the "default" socket calls do not use it,
    they use an int. Only the XOPEN (IIRC) socket calls use the
    socklen_t, and you only get those calls when setting the apropriate
    XOPEN define.

    That is all well and good save for the observation that socklen_t is
    (IIRC) defined as a size_t, which is then defined as a long. In
    64-bit a long is 8 bytes and an int is 4 bytes (hence that warning -
    64-bit HP-UX is "LP64" - Longs and Pointers 64-bit - Ints remain
    32-bit) and the nature of the things (I'm guessing) is such that the
    pointer is to the high-order bytes, which the call will take as the
    int and so will believe that the value you are passing-in is actually
    0 rather than 16. So, it says you have no space for the from and so
    it puts nothing there.

    If in your source I replace "socklen_t" with "int" the 64-bit
    compilation warnings go away:

    cc +DD64 -o tryme tryme.c

    and the code behaves correctly:

    $ ./tryme 127.0.0.1 12345
    peer address from accept() is 127.0.0.1 55080
    peer add/port from getpeername() is 127.0.0.1 55080

    (the 32-bit compilation warnings go away too)

    hth,

    rick jones

    PS - there is a bunch of backflipping in the netperf configure script
    to decide on the "right" value to use for socklen_t to take care of
    compilation warnings. You might examine that for ideas if this code
    is to be compiled on multiple platforms. http://www.netperf.org/


    --
    web2.0 n, the dot.com reunion tour...
    these opinions are mine, all mine; HP might not want them anyway...
    feel free to post, OR email to rick.jones2 in hp.com but NOT BOTH...

  6. Re: accept() and getpeername() return 0.0.0.0

    You nailed it. I replaced socklen_t with int and it works. Funny that with
    gcc it actually introduced a compile warning about passing int* when
    socklen_t* was expected. So I changed it back to socklen_t, then put a

    'from1_len = from1_len << 32;'

    line in there to shift the value into the 4 high bytes. It worked.

    Thank you very much for your time - you and Vishwas both. I'm also going to
    install the arpa patch at our next scheduled downtime.

    Sincerely,
    Mike

    "Rick Jones" wrote in message
    news:TQ%Eh.541$Xy5.505@news.cpqcorp.net...
    >A 32-bit compilation of the program appears to work on my PA-RISC
    > 11.11 system:
    >
    > $ ./tryme 127.0.0.1 12345
    > peer address from accept() is 127.0.0.1 55063
    > peer add/port from getpeername() is 127.0.0.1 55063
    >
    > I do though get the following warnings in the compile:
    >
    > cc -o tryme tryme.c
    > cc: "tryme.c", line 54: warning 604: Pointers are not
    > assignment-compatible.
    > cc: "tryme.c", line 54: warning 563: Argument #3 is not the correct type.
    > cc: "tryme.c", line 63: warning 604: Pointers are not
    > assignment-compatible.
    > cc: "tryme.c", line 63: warning 563: Argument #3 is not the correct type.
    >
    >
    > However a 64-bit compilation does not:
    >
    > $ ./tryme 127.0.0.1 12345
    > peer address from accept() is 0.0.0.0 0
    > peer add/port from getpeername() is 0.0.0.0 0
    >
    >
    > The 64-bit compilation gave me the following warnings:
    >
    > cc +DD64 -o tryme tryme.c
    > cc: "tryme.c", line 54: warning 728: Argument #3 converts long* to int*.
    > cc: "tryme.c", line 63: warning 728: Argument #3 converts long* to int*.
    >
    > I believe this all stems from the use of socklen_t, which IMO HP-UX
    > 11.11 has rather well and truly botched. By default there is a
    > socklen_t available, but the "default" socket calls do not use it,
    > they use an int. Only the XOPEN (IIRC) socket calls use the
    > socklen_t, and you only get those calls when setting the apropriate
    > XOPEN define.
    >
    > That is all well and good save for the observation that socklen_t is
    > (IIRC) defined as a size_t, which is then defined as a long. In
    > 64-bit a long is 8 bytes and an int is 4 bytes (hence that warning -
    > 64-bit HP-UX is "LP64" - Longs and Pointers 64-bit - Ints remain
    > 32-bit) and the nature of the things (I'm guessing) is such that the
    > pointer is to the high-order bytes, which the call will take as the
    > int and so will believe that the value you are passing-in is actually
    > 0 rather than 16. So, it says you have no space for the from and so
    > it puts nothing there.
    >
    > If in your source I replace "socklen_t" with "int" the 64-bit
    > compilation warnings go away:
    >
    > cc +DD64 -o tryme tryme.c
    >
    > and the code behaves correctly:
    >
    > $ ./tryme 127.0.0.1 12345
    > peer address from accept() is 127.0.0.1 55080
    > peer add/port from getpeername() is 127.0.0.1 55080
    >
    > (the 32-bit compilation warnings go away too)
    >
    > hth,
    >
    > rick jones
    >
    > PS - there is a bunch of backflipping in the netperf configure script
    > to decide on the "right" value to use for socklen_t to take care of
    > compilation warnings. You might examine that for ideas if this code
    > is to be compiled on multiple platforms. http://www.netperf.org/
    >
    >
    > --
    > web2.0 n, the dot.com reunion tour...
    > these opinions are mine, all mine; HP might not want them anyway...
    > feel free to post, OR email to rick.jones2 in hp.com but NOT BOTH...




  7. Re: accept() and getpeername() return 0.0.0.0

    Mike King wrote:
    > You nailed it. I replaced socklen_t with int and it works. Funny
    > that with gcc it actually introduced a compile warning about passing
    > int* when socklen_t* was expected.


    Odd - unless gcc was doing something funny, an int * should have been
    expected.

    > So I changed it back to socklen_t, then put a
    > 'from1_len = from1_len << 32;'


    > line in there to shift the value into the 4 high bytes. It worked.


    Stick with using an int if you can - or switch to the XOPEN socket
    style. I'd suggest staying far away from the shift experiment

    rick jones
    --
    oxymoron n, Hummer H2 with California Save Our Coasts and Oceans plates
    these opinions are mine, all mine; HP might not want them anyway...
    feel free to post, OR email to rick.jones2 in hp.com but NOT BOTH...

  8. Re: accept() and getpeername() return 0.0.0.0

    Don't worry, I'm not going to get creative with shifting - I just did that
    to confirm your theory. I think gcc is using it's own headers that came
    with it because the man pages show that int* is expected as you say. The
    gcc headers must have gratuitously changed the int* to socklen_t*, hence the
    compile warning. I supposed that's what I get for using a non-native
    compiler.

    Mike

    "Rick Jones" wrote in message
    news:Z86Fh.559$by5.196@news.cpqcorp.net...
    > Mike King wrote:
    >> You nailed it. I replaced socklen_t with int and it works. Funny
    >> that with gcc it actually introduced a compile warning about passing
    >> int* when socklen_t* was expected.

    >
    > Odd - unless gcc was doing something funny, an int * should have been
    > expected.
    >
    >> So I changed it back to socklen_t, then put a
    >> 'from1_len = from1_len << 32;'

    >
    >> line in there to shift the value into the 4 high bytes. It worked.

    >
    > Stick with using an int if you can - or switch to the XOPEN socket
    > style. I'd suggest staying far away from the shift experiment
    >
    > rick jones
    > --
    > oxymoron n, Hummer H2 with California Save Our Coasts and Oceans plates
    > these opinions are mine, all mine; HP might not want them anyway...
    > feel free to post, OR email to rick.jones2 in hp.com but NOT BOTH...




+ Reply to Thread