Socket Programming (TCP Tunnel)


Reading

Start by reading Chapters 1  and 3 of 

In the first chapter you will find the code of TCP Daytime Client and Server with brief explanation. A modified version of this code that does not depend on the libraries used in that book is listed below. You can also download it here.   

 

TCP Daytime Client

 

#include <netinet/in.h>

#include <arpa/inet.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <stdlib.h>

#include <strings.h>

#include <stdio.h>

#include <string.h>

#include <unistd.h>

#define MAXLINE 4096 /* max text line length */

#define DAYTIME_PORT 3333

int main(int argc, char **argv)

{

int sockfd, n;

char recvline[MAXLINE + 1];

struct sockaddr_in servaddr;

if (argc != 2) {

printf("usage: client <IPaddress>\n");

exit(1);

}

if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {

printf("socket error\n");

exit(1);

}

bzero(&servaddr, sizeof(servaddr));

servaddr.sin_family = AF_INET;

servaddr.sin_port = htons(DAYTIME_PORT); /* daytime server */

if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0) {

printf("inet_pton error for %s\n", argv[1]);

exit(1);

}

if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) {

printf("connect error\n");

exit(1);

}

while ( (n = read(sockfd, recvline, MAXLINE)) > 0) {

recvline[n] = 0; /* null terminate */

if (fputs(recvline, stdout) == EOF) {

printf("fputs error\n");

exit(1);

}

}

if (n < 0) {

printf("read error\n");

exit(1);

}

exit(0);

}

 

TCP Daytime Server

 

#include <netinet/in.h>

#include <time.h>

#include <strings.h>

#include <stdio.h>

#include <string.h>

#include <unistd.h>

#define MAXLINE 4096 /* max text line length */

#define LISTENQ 1024 /* 2nd argument to listen() */

#define DAYTIME_PORT 3333

 

int main(int argc, char **argv)

{

int listenfd, connfd;

struct sockaddr_in servaddr;

char buff[MAXLINE];

time_t ticks;

listenfd = socket(AF_INET, SOCK_STREAM, 0);

bzero(&servaddr, sizeof(servaddr));

servaddr.sin_family = AF_INET;

servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

servaddr.sin_port = htons(DAYTIME_PORT); /* daytime server */

bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr));

listen(listenfd, LISTENQ);

 

for ( ; ; ) {

connfd = accept(listenfd, (struct sockaddr *) NULL, NULL);

ticks = time(NULL);

snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks));

write(connfd, buff, strlen(buff));

printf("Sending response: %s", buff);

close(connfd);

    }

}



Tasks to do


TCP Tunnel 

Now implement a third piece of code, which we call tcptunnel (tunnel.c). tcptunnel sits between the client and server. The client should now can take UP TO four arguments: tunnel_IP or tunnel_name, tunnel_port, server_IP or server_name, and server_port. That is, if the client is given two arguments (IP/name and port), it would assume that these arguments are for the server and would connect directly to the server. If the client is given forur arguments, it will assume that the first two are for the tunnel and the latter two are for the server.  In case of the tunnel, the client connects to the tunnel and sends a message to it that includes two fields server_IP and server_port. The tunnel forwards the request to the Daytime Server running on server_IP:server_port. When the tunnel gets the response from the server, it forwards it back to the client. The client should print the information of both the server and the tunnel as:

        Server Name:  csil-cpu6.csil.sfu.ca
        IP Address:  206.12.16.22
        Time:  Tue Jan 10  10 : 12 : 40  2017
        Who:  user_1         pts/1         2021-09-07 10:56 (142.58.22.244)
                   user_2         pts/2         2021-09-07 11:27 (142.58.23.69)

        
        Via Tunnel:  csil-cpu2.csil.sfu.ca
         IP Address: 206.12.16.179
         Port Number: 12345


The server should print the information of whoever sent the request (in this case the tunnel), as the server cannot really know whether a tunnel exists or not. 

The tunnel can optionally print some information about the connection, such as:

           Received request from client csil-cpu2.csil.sfu.ca port= 12345 destined to server csil-cpu5.csil.sfu.ca port 5678. 


You should be able to test your code on any three different machines the six machines named: csil-cpu2.csil.sfu.ca, csil-cpu3.csil.sfu.ca, ...,  csil-cpu6.csil.sfu.ca.


Requirements and Submission