Skip to content

Instantly share code, notes, and snippets.

@MartelliEnrico
Last active November 21, 2015 17:38
Show Gist options
  • Select an option

  • Save MartelliEnrico/46f89dc5f4ef46caf96c to your computer and use it in GitHub Desktop.

Select an option

Save MartelliEnrico/46f89dc5f4ef46caf96c to your computer and use it in GitHub Desktop.
Send ip packet from client to server, and back again.
/* cliTCP.c spedisce stringa, riceve stringa traslata
su SunOS compilare con gcc -o cliTCP.c -lsocket -lnsl cliTCP.c
su linux gcc -o cliTCP cliTCP.c
eseguire ad esempio su 137.204.72.49 lanciando la seguente riga di comandi
cliTCP 130.136.2.7 5001
*/
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include "header.h"
#define SOCKET_ERROR ((int)-1)
#define SIZEBUF 1000000
#define MAXSIZE 1000000
void usage(void)
{
printf ("usage: cliTCP REMOTE_IP_NUMBER REMOTE_PORT_NUMBER\n");
exit(1);
}
int main(int argc, char *argv[])
{
struct sockaddr_in Local, Serv;
char string_remote_ip_address[100];
short int remote_port_number, local_port_number;
int socketfd, OptVal, msglen, Fromlen, ris;
int n, i, nread, nwrite, len;
char buf[MAXSIZE];
if (argc != 3) { printf ("necessari 2 parametri\n"); usage(); exit(1); }
else {
strncpy(string_remote_ip_address, argv[1], 99);
remote_port_number = atoi(argv[2]);
}
/* get a datagram socket */
//printf ("socket()\n");
socketfd = socket(AF_INET, SOCK_STREAM, 0);
if (socketfd == SOCKET_ERROR) {
printf ("socket() failed, Err: %d \"%s\"\n", errno, strerror(errno));
exit(1);
}
/* avoid EADDRINUSE error on bind() */
OptVal = 1;
//printf ("setsockopt()\n");
ris = setsockopt(socketfd, SOL_SOCKET, SO_REUSEADDR, (char *)&OptVal, sizeof(OptVal));
if (ris == SOCKET_ERROR) {
printf ("setsockopt() SO_REUSEADDR failed, Err: %d \"%s\"\n", errno, strerror(errno));
exit(1);
}
/* name the socket */
memset ( &Local, 0, sizeof(Local) );
Local.sin_family = AF_INET;
/* indicando INADDR_ANY viene collegato il socket all'indirizzo locale IP */
/* dell'interaccia di rete che verrà utilizzata per inoltrare i dati */
Local.sin_addr.s_addr = htonl(INADDR_ANY); /* wildcard */
Local.sin_port = htons(0);
//printf ("bind()\n");
ris = bind(socketfd, (struct sockaddr*) &Local, sizeof(Local));
if (ris == SOCKET_ERROR) {
printf ("bind() failed, Err: %d \"%s\"\n", errno, strerror(errno));
exit(1);
}
/* assign our destination address */
memset ( &Serv, 0, sizeof(Serv) );
Serv.sin_family = AF_INET;
Serv.sin_addr.s_addr = inet_addr(string_remote_ip_address);
Serv.sin_port = htons(remote_port_number);
/* connection request */
//printf ("connect()\n");
ris = connect(socketfd, (struct sockaddr*) &Serv, sizeof(Serv));
if (ris == SOCKET_ERROR) {
printf ("connect() failed, Err: %d \"%s\"\n", errno, strerror(errno));
exit(1);
}
//printf ("dopo connect()\n");
fflush(stdout);
bytes_header h;
h.h.src = inet_network("130.131.100.1");
h.h.dst = inet_network("132.133.200.2");
fill_header(&(h.h), 0b111);
// h.h.flags = 0b101;
// h.h.fragment_offset = 0b0011100111000;
printf("datagram prima:\n");
print_buffer((char *)h.b, 24);
hton_header(&h);
/* scrittura */
len = sizeof(bytes_header);
i = 0;
//printf("write()\n");
//fflush(stdout);
while ((n = write(socketfd, &(h.b[i]), len - i)) > 0)
i += n;
if (n < 0) {
char msgerror[1024];
sprintf(msgerror, "write() failed [err %d] ", errno);
perror(msgerror);
fflush(stdout);
return (1);
}
/* lettura */
nread = 0;
//printf ("read()\n");
//fflush(stdout);
while ((len > nread) && ((n = read(socketfd, &(buf[nread]), len - nread )) > 0))
{
nread += n;
//printf("read effettuata, risultato n = %d, len = %d, nread = %d, len - nread = %d\n", n, len, nread, len - nread );
//fflush(stdout);
}
if (n < 0) {
char msgerror[1024];
sprintf(msgerror, "read() failed [err %d] ", errno);
perror(msgerror);
fflush(stdout);
return (1);
}
/*header res = unserialize_header(buf);*/
for (int i = 0; i < 24; i++) {
h.b[i] = buf[i];
}
ntoh_header(&h);
/* stampa risultato */
printf("\ndatagram dopo:\n");
print_buffer((char *)h.b, 24);
/* sleep(30); inserito per far vedere connessioni con netstat */
/* chiusura */
close(socketfd);
return (0);
}
#ifndef _HEADER_H
#define _HEADER_H
void print_buffer(char* buf, int len) {
char bits[9];
bits[8] = '\0';
printf("0 8 16 24\n");
for (int i = 0; i < len; i++) {
char byte = buf[i];
for (int j = 7; j >= 0; j--) {
bits[j] = '0' + (byte & 0x01);
byte >>= 1;
}
printf("%s ", bits);
if (i % 4 == 3) {
printf("\n");
}
}
fflush(stdout);
}
typedef struct _header {
unsigned char version: 4;
unsigned char ihl: 4;
unsigned char service_type;
unsigned short length;
unsigned short identification;
unsigned char flags: 3;
unsigned short fragment_offset: 13;
unsigned char ttl;
unsigned char protocol;
unsigned short checksum;
unsigned int src;
unsigned int dst;
unsigned int options: 24;
unsigned char padding: 8;
} header;
typedef union _bytes_header {
header h;
unsigned char b[sizeof(header)];
} bytes_header;
void fill_header(header* h, unsigned char fill) {
h->version = fill;
h->ihl = fill;
h->service_type = fill;
h->length = fill;
h->identification = fill;
h->flags = fill;
h->fragment_offset = fill;
h->ttl = fill;
h->protocol = fill;
h->checksum = fill;
h->options = fill;
h->padding = fill;
}
void hton_header(bytes_header* bh) {
uint16_t temp_u16;
uint32_t temp_u32;
bh->h.length = htons(bh->h.length);
bh->h.identification = htons(bh->h.identification);
/*
* Per qualche motivo la struct mette prima in memoria i 13bit di fragment_offset,
* e successivamente i 3bit di flags.
*/
memcpy(&temp_u16, &(bh->b[6]), 2);
bh->h.flags = htons(temp_u16) & 0x8;
bh->h.fragment_offset = htons(temp_u16) >> 3;
bh->h.checksum = htons(bh->h.checksum);
bh->h.src = htonl(bh->h.src);
bh->h.dst = htonl(bh->h.dst);
memcpy(&temp_u32, &(bh->b[20]), 4);
bh->h.options = htonl(temp_u32) >> 8;
bh->h.padding = temp_u32 & 0xFF;
}
void ntoh_header(bytes_header* bh) {
uint16_t temp_u16;
uint32_t temp_u32;
bh->h.length = ntohs(bh->h.length);
bh->h.identification = ntohs(bh->h.identification);
memcpy(&temp_u16, &(bh->b[6]), 2);
bh->h.flags = ntohs(temp_u16) >> 13;
bh->h.fragment_offset = temp_u16 & 0x1FFF;
bh->h.checksum = ntohs(bh->h.checksum);
bh->h.src = ntohl(bh->h.src);
bh->h.dst = ntohl(bh->h.dst);
memcpy(&temp_u32, &(bh->b[20]), 4);
bh->h.options = ntohl(temp_u32) >> 8;
bh->h.padding = temp_u32 & 0xFF;
}
#endif
/* servTCP.c riceve stringa, trasla i caratteri di 2, e
rispedisce al mittente
su SunOS compilare con gcc -o servTCP.c -lsocket -lnsl servTCP.c
su linux gcc -o servTCP servTCP.c
eseguire ad esempio su 130.136.2.7 lanciando la seguente riga di comandi:
servTCP 5001
*/
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include "header.h"
#define SOCKET_ERROR ((int)-1)
#define SIZEBUF 1000000
#define MAXSIZE 1000000
void usage(void)
{ printf ("usage: servTCP LOCAL_PORT_NUMBER\n"); exit(1); }
int main(int argc, char *argv[])
{
struct sockaddr_in Local, Cli;
short int local_port_number;
int socketfd, newsocketfd, OptVal, ris;
unsigned int len;
int n, nread, nwrite;
char buf[MAXSIZE];
if (argc != 2) { printf ("necessario 1 parametri\n"); usage(); exit(1); }
else {
local_port_number = atoi(argv[1]);
}
/* get a stream socket */
//printf ("socket()\n");
socketfd = socket(AF_INET, SOCK_STREAM, 0);
if (socketfd == SOCKET_ERROR) {
printf ("socket() failed, Err: %d \"%s\"\n", errno, strerror(errno));
exit(1);
}
/* name the socket */
memset ( &Local, 0, sizeof(Local) );
Local.sin_family = AF_INET;
/* indicando INADDR_ANY viene collegato il socket all'indirizzo locale IP */
/* dell'interaccia di rete che verrà utilizzata per inoltrare il datagram IP */
Local.sin_addr.s_addr = htonl(INADDR_ANY); /* wildcard */
Local.sin_port = htons(local_port_number);
//printf ("bind()\n");
ris = bind(socketfd, (struct sockaddr*) &Local, sizeof(Local));
if (ris == SOCKET_ERROR) {
printf ("bind() failed, Err: %d \"%s\"\n", errno, strerror(errno));
exit(1);
}
//printf ("listen()\n");
ris = listen(socketfd, 10 );
if (ris == SOCKET_ERROR) {
printf ("listen() failed, Err: %d \"%s\"\n", errno, strerror(errno));
exit(1);
}
/* wait for connection request */
/* while(1) { */
do {
memset ( &Cli, 0, sizeof(Cli) );
len = sizeof(Cli);
//printf ("accept()\n");
newsocketfd = accept(socketfd, (struct sockaddr*) &Cli, &len);
} while ( (newsocketfd < 0) && (errno == EINTR) );
if (newsocketfd == SOCKET_ERROR) {
printf ("accept() failed, Err: %d \"%s\"\n", errno, strerror(errno));
exit(1);
}
/*printf("connection from %s : %d\n",
inet_ntoa(Cli.sin_addr),
ntohs(Cli.sin_port)
);*/
/* wait for data */
nread = 0;
len = sizeof(bytes_header);
//printf ("read()\n");
while ((len > nread) && (n = read(newsocketfd, &(buf[nread]), len - nread )) > 0) {
printf("letti %d bytes tot = %d\n", n, n + nread);
fflush(stdout);
nread += n;
}
if (n <= 0) {
char msgerror[1024];
sprintf(msgerror, "read() failed [err %d] ", errno);
perror(msgerror);
n = close(newsocketfd);
/*
if(n!=0)
{
perror("close failed: ");
exit(2);
}
*/
return (1);
}
bytes_header h;
for (int i = 0; i < 24; i++) { // strano problema con strncpy
h.b[i] = buf[i];
}
ntoh_header(&h);
unsigned long src = h.h.src;
unsigned long dst = h.h.dst;
h.h.src = dst;
h.h.dst = src;
fill_header(&(h.h), 0);
hton_header(&h);
/* scrittura */
nwrite = 0;
//printf ("write()\n");
while ( (n = write(newsocketfd, &(h.b[nwrite]), nread - nwrite)) > 0 )
nwrite += n;
if (n < 0) {
char msgerror[1024];
sprintf(msgerror, "write() failed [err %d] ", errno);
perror(msgerror); return (1);
}
/* chiusura */
//printf ("close()\n");
close(newsocketfd);
close(socketfd);
return (0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment