Question

I'm making a FTP server in C. At the client side I'm using FileZilla. My code so far contains only the handshaking part.

The problem I've got is that the strings I print out for the terminal are sent to FileZilla. My question is how can I keep these two seperated, i've tried a couple of things, but none of them give the correct result.

This is only a part of my code, but for my question is this the useful part:

while (FOREVER){
    addr_size = sizeof their_addr;

    newfd = accept(listener, (struct sockaddr*) &their_addr, &addr_size);
    if (newfd == -1){
        perror("accept");
        continue;
    }
    if ((send(newfd, "220 JEDI FTP is ready", 50, 0)) <= 0)
        perror("error sending");

    puts("connection established");
    puts("waiting for user & connection");
  while (!login){
        // username
        if (!user){
            if ((recv(newfd, buffer, BUFFCON, 0)) <= 0){
                puts("error receiving username");

            }
            else{

                if (strstr(buffer, "USER") != NULL){

                    if (strstr(buffer, name) != NULL){

                        send(newfd, "331 password required", 50, 0);
                        puts("username correct");

                        user = 1;
                    }
                    else{
                        puts("username incorrect");
                        send(newfd, "430 username incorrect", 50, 0);
                    }//else
                }//if
            }//else
        }//if user

And this is the output in FileZilla:

  • Status: Adres bepalen van localhost
  • Status: Verbinden met [::1]:21...
  • Status: Verbinding aangemaakt, welkomstbericht afwachten...
  • Antwoord: 220 JEDI FTP is ready
  • Commando: USER yoda
  • Antwoord: connection established
  • Fout: Kan niet verbinden met server

So instead of sending "331 password required" it sends "connection established"

Hope you can help me with this, Thanks a lot.

Was it helpful?

Solution

The problem is that your len parameter for send is too large. send has no concept of null-terminated strings; it only works with raw sequences of bytes. So the call send(newfd, "220 JEDI FTP is ready", 50, 0) sends the string "220 JEDI FTP is ready", and then whatever happens to come in memory after it. Technically, this is undefined behavior, so literally anything could happen (usually a segfault). In your case, because constant literal strings are usually stored sequentially in memory, send is reading the given string, and then reading a different string after it.

What you want to do is only send the exact string (which, by the way, needs the CR-LF sequence \r\n after each command). No more, no less. You can implement a sends function to send a string like so:

ssize_t sends(int fd, const char *str)
{
    size_t len = strlen(str);
    return send(fd, str, len, 0);
}

Also note that the data sent does not include the null-terminator, because the TCP packet specifies the size of the string.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top