TP n°1 TCP client/server with “ident” protocol

Correction for question n°1:

By interrogating the ident server, from the remote end of a communication channel, and by sending it the pair of remote and local ports, we receive in return a reply in the form of a triplet whose each element is separated by the character “:”.

Correction for question n°2:

The program can be written in the following form, taking up (mostly) the code of a server in the function “main” and the code of a connection as a client of the ident server in the function “ident”. We finally integrate the code for sending the question and processing the answer in the “dial” function.

#include <stdio.h>
#include <stdlib.h>
 
#include <sys/types.h>
#include <netdb.h>
#include <sys/socket.h>
 
#include <strings.h>      // for the function bzero
#include <string.h>       // for the functions strlen et strtok
#include <arpa/inet.h>    // for the function inet_addr

#define SRVPORT 2000

void dial(int fd, int port_src, int port_dst) {
    char buf[1024],*p1,*p2,*p3,*p;
    int len;

    sprintf(buf,"%d, %d\n",port_src, port_dst);
    write(fd, buf, strlen(buf));
    len=read(fd, &buf, sizeof(buf)-1);
    buf[len]=0x00;
    strtok(buf,":");
    p1=strtok(NULL,":");
    while (*p1==' ') p1++;
    for (p=p1;*p!=0x00; p++) if (*p==' ') *p=0x00;
    if (strcmp(p1,"USERID")==0) {
        p2=strtok(NULL,":");
        p3=strtok(NULL,"\r\n");
        while (*p3==' ') p3++;
        printf("[%s]\n",p3);
    } else if (strcmp(p1,"ERROR")==0) {
        p2=strtok(NULL,"\r\n");
		if (strcmp(p2,"HIDDEN-USER")==0) printf("hidden user\n");
	}
}

void ident(struct sockaddr_in *src) {
    int     fd;
    struct sockaddr_in  addr;
    int     err;
 
    fd = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (fd<0) {
        printf("Socket creation error!\n");
        exit(1);
    }
 
    bzero(&addr, sizeof(addr));
    addr.sin_family = AF_INET;
    memcpy(&addr.sin_addr, &src->sin_addr, sizeof(src->sin_addr));
    addr.sin_port = htons(113);
    err = connect(fd, (struct sockaddr *) &addr, sizeof(addr));
    if (err != 0) {
        printf("Server connection error!\n");
        exit(1);
    }
 
    printf("Connection established with the ident server!\n");
    dial(fd, ntohs(src->sin_port), SRVPORT);
}

int main()
{
    int fd_srv, fd_con;
    struct sockaddr_in  adr_srv, adr_cli;
    int err;
    socklen_t adr_cli_len;
 
    fd_srv = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (fd_srv<0) {
        printf("Socket creation error!\n");
        exit(1);
    }
 
    bzero(&adr_srv, sizeof(adr_srv));
    adr_srv.sin_family = AF_INET;
    err = inet_aton("0.0.0.0", &adr_srv.sin_addr);
    if (err == 0) {
        printf("Invalid IPv4 address!\n");
        exit(1);
    }
    adr_srv.sin_port = htons(SRVPORT);
    err = bind(fd_srv, (struct sockaddr *) &adr_srv, sizeof(adr_srv));
    if (err != 0) {
        printf("Server port access error!\n");
        exit(1);
    }
    err = listen(fd_srv, 5);
    if (err != 0) {
        printf("Queue creation error!\n");
        exit(1);
    }
    printf("Server launched!\n");
    while(1) {
        adr_cli_len = sizeof(adr_cli);
        fd_con = accept(fd_srv, (struct sockaddr *) &adr_cli, &adr_cli_len);
        if (fd_con<0) {
            printf("Error accepting incoming connection!\n");
            exit(1);
        }
        printf("Connection accepted!\n");
        ident(&adr_cli);
        shutdown(fd_con, SHUT_RDWR);
        close(fd_con);
        printf("Client disconnected by server!\n");
    }
    return 0;
}
  

How to test the solution

You can simply:

Example: To transfer the file tp-ident-en.c to the /home/isenXX directory of the Unix server 10.34.161.21 with the rights of the user isenXX, use the following command from a cmd window on windows or from a terminal on MAC.

scp tp-ident-en.c isenXX@10.34.161.21:/home/isenXX