1

I am exploring network programming in C.The code is supposed to connect to a server on port 80 send an http request and from the response print on what server is the web page running on, but it runs into Invalid Argument error. The error occurs with error message "[ERR] connecting to target server: Invalid argument" so the error should be somewhere in the connect() function.

rec = connect(sockfd, (struct sockaddr *)&target_addr, sizeof(struct sockaddr) == -1);
    if(rec == -1)
        fail("[ERR] connecting to target server");

Although I have seen a lot of similar issues, none of the fixes neither worked or applied to this case, strangely this code works as a standalone program when parsing argc[1] instead of char *name, regardless of what the exact string literal is(ip or hostname, experimented with multiple for both). The only difference between the two being that the entire web server function is written in main and passed command-line arguments(working example) while here it is written as a standalone function and called in main where it was tested on a few web page names and IP addresses. Any help would be appreciated as I feel this might be some simple mistake I overlooked or something I don't understand well enough. Thanks!

int web_server(char *name){
    int sockfd, rec;
    struct hostent *host_info;
    //struct in_addr *address;
    struct sockaddr_in target_addr;
    unsigned char buffer[4096];


    
    if(is_ip(name)){
        target_addr.sin_addr.s_addr = inet_addr(name);
    } else if(host_info = gethostbyname(name)){
        
        if(host_info == NULL){
            fail("[ERR] looking up hostname!");
        }else{
            target_addr.sin_addr = *((struct in_addr *) host_info -> h_addr);
        }
    } else{
        fail("[ERR] getting address");
    }

    target_addr.sin_family = AF_INET;
    target_addr.sin_port = htons(80);
    memset(&(target_addr.sin_zero), 0, 8);
    
    sockfd = socket(PF_INET, SOCK_STREAM, 0);
    if(sockfd == -1){
        fail("[ERR] in socket");
    }

    rec = connect(sockfd, (struct sockaddr *)&target_addr, sizeof(struct sockaddr) == -1);
    if(rec == -1)
        fail("[ERR] connecting to target server");

    send_string(sockfd, "HEAD / HTTP/1.0\r\n\r\n");

    while(recv_line(sockfd, buffer)){
        if(strncasecmp(buffer, "Server: ", 7) == 0){
            printf("The web server for %s is %s\n", name, buffer+8);
        }
    }
    close(sockfd);
    printf("Server line not found\n");
    exit(1);

}
int main(){
  web_server("127.0.0.1");//doesn't work with hostnames either
}
grng3r
  • 63
  • 6
  • 2
    "strangely this code works as a standalone program when parsing argc[1] instead of char *name" -- What is the exact value of the string pointed to by `name` when it works and when it doesn't work? Please verify your answer by using a [debugger](https://stackoverflow.com/q/25385173/12149471). Can you reproduce the error by assigning `name` to a string literal instead? If so, please provide a [mre] of the problem. – Andreas Wenzel Sep 11 '20 at 14:47
  • 1
    I'd like to suggest that you define your function with a `const` parameter: `int web_server (const char *name)` I presume that `web_server` doesn't actually change the values of its argument, so defining `const` will prevent the function changing it accidentally. For example, I don't know whether `is_ip()` might modify `name`. Running the program under `valgrind` or similar will help if the problem is accidents with memory allocation. – Kevin Boone Sep 11 '20 at 14:54
  • @AndreasWenzel Thanks for the tips, I have edited my question a bit, so hopefully it is easier to figure out where exactly is the error. I have singled out that line of code as well. I can upload my gdb output as well when stepping through the web_server function, or the strace comparison of the the two pieces of software mentioned in the question. – grng3r Sep 11 '20 at 15:36
  • 2
    What is the last parameter of `connect` supposed to mean? `sizeof(struct sockaddr) == -1` 1) why not `sizeof ( struct sockaddr_in)`; 2) why `==-1`? The size can never be `-1`. Should that equal comparison go after the closing bracket? You don't pass the size of the struct, but only `FALSE` to `connect`. – Gerhardh Sep 11 '20 at 15:39
  • If you get here `if(host_info == NULL)` the condition can never be true. – Gerhardh Sep 11 '20 at 15:43
  • @KevinBoone thanks for the suggestion for the const parameter, absolutely makes sense after you suggested it. The is_ip function just checks if name is an ip or a hostname and returns 1 or 0(parameter changed to const char as well). – grng3r Sep 11 '20 at 15:44
  • 1
    @Gerhardh thanks I did not realize I left == -1, was suppose to remove that, you are wright about struct sockaddr to struct sockaddr_in change as well, works fine now. But about if(host_info == NULL) do you mean that this check is redundant because of the previous checks or? – grng3r Sep 11 '20 at 15:50

0 Answers0