Detecting incoming port for TFTP data?

1.4k views Asked by At

I'm working on implementing a TFTP client (UDP socket).

Currently I have to switch off the entire firewall on my Windows 8 machine or else the data doesn't reach the TFTP client. The outgoing connect request happens on port 69, but the first data packet from the TFTP server is transmitted back on a different, random port. So my question is : how do I ensure that the TFTP client (as an application) is able to receive packets on a machine with the firewall on?

When I run the TFTP client in debug mode in Visual Studio 2005, the client doesn't receive packets either unless I turn off the firewall. How do I solve that?

Thanks

UPDATE (code)

void main(void)
{
    unsigned short OPCODE = htons((unsigned short)1);
    char* fileName = "thisfile.cnf.xml";
    WORD wVersionRequested;
    WSADATA wsaData;
    int err;
    SOCKET sockfd;
    int n;
    char buf[256] = {0};
    int L;
    struct sockaddr_in servaddr;
    char recvline[1000];
    int rc;

    wVersionRequested = MAKEWORD( 2, 2 );
    err = WSAStartup( wVersionRequested, &wsaData );
    memcpy(buf, &OPCODE, 2);
    sprintf_s(&buf[2], 254, "%s%c%s%c", fileName, '\0', "octet", '\0');
    L = (int) strlen(fileName) + 9;
    sockfd=socket(AF_INET,SOCK_DGRAM,0);
    memset(&servaddr,0,sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr=inet_addr("212.158.10.33");
    servaddr.sin_port=htons(69);
    rc = sendto(sockfd,buf,L,0, (struct sockaddr *)&servaddr,sizeof(servaddr));

    while (1)
    {
       printf("Receive 1st packet...\n");
       /* This call gets blocked unless firewall is off */
       n=recvfrom(sockfd,recvline,1000,0,NULL,NULL);
       printf("%d bytes received\n", n);
       break;
    }
}
1

There are 1 answers

1
Eugene Sh. On BEST ANSWER

The TFTP protocol has the following flow:

  1. Client sends a RRQ or WRQ request from a randomly selected CTID port to port 69 on the server:

    Client:CTID ------> Server:69

  2. Server replies from a randomly selected STID port to the client's CTID:

    Client:CTID <------ Server:STID

  3. all subsequent packets for that transfer are sent between the client's CTID and the server's STID as needed.

    Client:CTID <-----> Server:STID

Each machine picks its own source TID port for packets that will be sent to the other party's destination TID port.

As you can see above, the CTID and STID are selected by the corresponding machines, preferably randomly. In your code, you are not setting the source port for your requests, so it is randomly selected by the OS. Which is fine for your outgoing packets, but the firewall does not know where the inbound packets will be coming from. So you need to bind() your socket to a specific port that you can then open in your firewall. Otherwise, check your firewall setup to see if it has a rule available that will allow inbound UDP packets from an IP address that an outgoing UDP packet was recently sent to, or similar rule to that effect.