Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Tips and resources to easily pass the "Computer Networks" practical exam ("Reti di calcolatori") in Padua

NotificationsYou must be signed in to change notification settings

nicomazz/ComputerNetworks-unipd2018

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

26 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Tips and code to easily pass the computer networks practical exam ("Reti di calcolatori") in Padua.You can find everything that is in this readme throughman, and the various RFCs. I've done it just for a fast reference.

TOC

Useful RFCs

Useful links

  • Here you can find a summary of the most important things to know to pass the exam.Anyway, maybe is better to study more in depth every topic.
  • C socket programming online book. There is more than needed, but still interesting.

Something to understand before trying the past exams

An Ethernet frame (data link layer) contains an IP datagram (network layer) that can contains one of the following { tcp_segment (transport layer), icmp_packet } (for the purpose of this exam). An easy way to realize that is:

eth= (structeth_frame*)buffer;ip= (structip_datagram*)eth->payload;tcp= (structtcp_segment*)ip->payload;// oricmp= (structicmp_packet*)ip->payload;

Data types and endianess

Data types and endianess

(depends on the architecture, but you can assume that the following is true for this exam)

  • unsigned char : 1 byte
  • unsigned short: 2 bytes
  • unsiged int : 4 bytes

To transfer on the network is used Big endian. Most of the intel's cpus are little endian. To convert use this 2 functions that automatically understand if a conversion is needed:

  • htonl(x) orhtons(x) to convert x fromHosttoNetwork endianess,l if you have to convert a 4 bytes variable,s a 2 bytes one.
  • ntohl(x) orntohs(x) for the opposite. (You may notice that the implementation of htonx and ntohx is the same)
  • if a variable is 1 byte long we don't have endianess problems (obviously)

Ethernet frame

Ethernet frame

Ethernet frame

// Frame Ethernetstructeth_frame {unsignedchardst[6];// mac addressunsignedcharsrc[6];// mac addressunsigned shorttype;// 0x0800 = ip, 0x0806 = arpcharpayload[1500];//ARP or IP };

Thanks to thetype we can understand where to forward it on the next level (2 examples are ip or arp)

IP datagram

IP datagram

Ip datagram

Header length: check second half ofver_ihl attribute. Example: if it's '5', then the header length is4 * 5 = 20 bytes.
//todo add image

// Datagramma IPstructip_datagram{unsignedcharver_ihl;// first 4 bits: version, second 4 bits: (lenght header)/8unsignedchartos;//type of serviceunsigned shorttotlen;// len header + payloadunsigned shortid;// useful in case of fragmentationunsigned shortflags_offs;//offset/8 related to the original ip packageunsignedcharttl;unsignedcharprotocol;// TCP = 6, ICMP = 1unsigned shortchecksum;// only header checksum (not of payload). Must be at 0 before the calculation.unsignedintsrc;// ip addressunsignedintdst;// ip addressunsignedcharpayload[1500];};

TCP segment

TCP segment

tcp segment

Header (as defined here) length:20

structtcp_segment {unsigned shorts_port;unsigned shortd_port;unsignedintseq;// offset in bytes from the start of the tcp segment in the stream (from initial sequance n)unsignedintack;// useful only if ACK flag is 1. Next seq that sender expectunsignedchard_offs_res;// first 4 bits: (header len/8)unsignedcharflags;// check rfcunsigned shortwin;// usually initially a 0 (?)unsigned shortchecksum;// use tcp_pseudo to calculate it. Must be at 0 before the calculation.unsigned shorturgp;unsignedcharpayload[1000];};

To calculate the checksum of a TCP segment is useful to define an additional structure (check on the relative RFC). Size of it, without the tcp_segment part

structtcp_pseudo{unsignedintip_src,ip_dst;unsignedcharzeroes;unsignedcharproto;// ip datagram protocol field (tcp = 6, ip = 1)unsigned shortentire_len;// tcp length (header + data)unsignedchartcp_segment[20/*to set appropriatly */];// entire tcp packet pointer};

To calculate the size of the entire tcp segment (or of the icmp), or more in general of the ip payload:

unsigned shortip_total_len=ntohs(ip->totlen);unsigned shortip_header_dim= (ip->ver_ihl&0x0F)*4;intip_payload_len=ip_total_len-ip_header_dim;

Checksum calculation

Checksum calculation

We can use this function both for the IP datagram and the TCP segment,but we must take care about thelen parameter.

  • todo: take care about minimum size for tcp, and odd/even corner case
unsigned shortchecksum(unsignedchar*buffer,intlen){inti;unsigned short*p;unsignedinttot=0;p= (unsigned short*)buffer;for(i=0;i<len/2;i++){tot=tot+htons(p[i]);if (tot&0x10000)tot= (tot&0xFFFF)+1;   }return (unsigned short)0xFFFF-tot;}

The 2 cases are:

  • IP:ip->checksum=htons(checksum((unsigned char*) ip, 20));`
  • TCP:
intTCP_TOTAL_LEN=20;structtcp_pseudopseudo;// size of this: 12memcpy(pseudo.tcp_segment,tcp,TCP_TOTAL_LEN);pseudo.zeroes=0;pseudo.ip_src=ip->src;pseudo.ip_dst=ip->dst;pseudo.proto=6;pseudo.entire_len=htons(TCP_TOTAL_LEN);// may varytcp->checksum=htons(checksum((unsignedchar*)&pseudo,TCP_TOTAL_LEN+12));

Convert int IP address in string

Convert int IP address in string

#include<arpa/inet.h>voidprint_ip(unsignedintip){structin_addrip_addr;ip_addr.s_addr=ip;printf("%s\n",inet_ntoa(ip_addr));}

Editor for the exam

I advice VIM. And please, indent your code.

  • :wq to save and quit.
  • Pressesc 2 times if you don't understand what is happening
  • /query to search for "query",n andN to search prev/next result
Put this in ~/.vimrc to save time:

" auto reformat when you pres F7map <F7> mzgg=G`z" F8 to save and compile creating np executablemap <F8> :w <CR> :!gcc % -o np -g <CR>" F9 to executemap <F9> :!./np <CR>" make your code look nicerset tabstop=3set shiftwidth=3set softtabstop=0 expandtabset incsearchset cindent" Ctrl+shift+up/down to swap the line up or doennnoremap <C-S-Up> <Up>"add"ap<Up>nnoremap <C-S-Down> "add"ap" ctrl+h to hilight the last searchnnoremap <C-h> :set hlsearch!<CR>set numberset cursorlineset mouse=aset foldmethod=indent               set foldlevelstart=99let mapleader="\<space>"nnoremap <leader>b :make <CR> :cw <CR>

Quickfix and makefile (aka how not waste time)

First of all create amakefile in the directory with the files to compile, like this:

np : ws18.c        gcc -o np ws18.c

Pay attention to put a tab before "gcc", and not spaces (if you have expandtab enabled in vim, usectrl=v tab).Herenp is what you want generate (the executable), andws18.c the file to compile. In the line below there is the command to call each time you write:make in vim.Then, with the.vimrc provided above, pressspace (release it) andb (build).The command will be excuted, and you will see in the bottom of your code the list of errors.You can fastly jump in the correct line by pressing enter in each entry.To move between the top and bottom split pressCTRL+WW. To close the bottom view (quickfix):q, or:cw.

Past exams

You can find the complete exam statement in the site at the beginning of this readme.The complete code is in the folders.

Past exams

19 June 2018 (ping.c)

Implement TCP three way handshake (ACK+SYN).

Tips:You can check with wireshark if your TCP checksum is correct or not.

  • Is the option field to include?

20 June 2018 (ping.c)

Implement echo reply only for icmp requests of a certain size

Tips:You can calculate the size of an icmp message in this way:

unsigned shortdimension=ntohs(ip->totlen);unsigned shortheader_dim= (ip->ver_ihl&0x0F)*4;inticmp_dimension=dimension-header_dim;

2 September 2016

Implement an HTTP server that:

  • redirect to a default page if the target resource is not available
  • Send a temporary unavailable response if the resource is available, and after a second request gives the output.

Tips:The headerRetry-After is ignored by most web browser, so the redirect will not take place after 10 seconds, but immediately.In the solution there is an array that keeps the state of the connection for each ip.

15 July 2016 (ping.c)

Implement an ICMP "Destination unreachable" that say that the port is unavailable

Tips:you have to send the package in response to a tcp connection.icmp->type = 3,icmp->code=3.And remember to copy in the payload the content of the icmp original payload.


20 June 2016

1 (tcp16.c)

Intercept the first received connection, and print sequence and acknowledge numbers of them. Then reconstruct the 2 streams in 2 different buffers, and print their content.

Tips:To intercept the end of the connection, just check if a package contains the FIN bit at 1 (after having filtered all the packages, maintaining only the ones belonging to the first connection).Use the tcp sequence field to copy the contnet at the right offset in the 2 buffers.DON'T DUPLICATE CODE.


2 (wp16.c)

Modify the proxy to allow the request only from a pool of IP addresses, and allow only the transfer of files with text or html.

Tips:Is better to first receive the response from the server in a buffer, then copy this content to another buffer to extract headers as always.This because the header extraction procedure modifies the buffer.If the condition of the Content-type is fullfilled then just forward the contnet of the initial buffer.


3 (ws18.c)

Send HTTP response with a chunked body.

Tips:AddContent-Type: text/plain\r\nTransfer-Encoding: chunked\r\n to HTTP headers.Then, to build each chunk to send, you can use something like:

Code to build a chunk
intbuild_chunk(char*s,intlen){sprintf(chunk_buffer,"%x\r\n",len);// size in hex// debug   printf("%d in hex: %s",len,chunk_buffer);intfrom=strlen(chunk_buffer);inti=0;for (;i<len;i++)chunk_buffer[from+i]=s[i];chunk_buffer[from+(i++)]='\r';chunk_buffer[from+(i++)]='\n';chunk_buffer[i+from]=0;returni+from;}

24 July 2015 (wc18.c)

Implement theLast-Modified header of HTTP/1.0

Tips:Some useful time conversion functions in the misc section. It could also have been done without the need of these conversions.The HTTP date format is%a, %d %b %Y %H:%M:%S %Z


26 June 2014

1: content length (was already implemented)2: trace (??)


26 June 2014

Modify icmp echo to split the request into two IP datagrams, one with a payloadsize of 16 bytes and the other one with the requested payload size.


Homeworks

During the course some homeworks (not mandatory) are assigned. Even if they are not exams they have more or less the same level of difficulty.

Homeworks

ping.c

Implement a traceroute program, tracking each node the packets visits before reching the destination.Hint: when the time to live becomes 0 a node discards the packet and send a "Time Exceeded Message" to the source IP address of the packet (see RFC793).

ws.c

use the HTTP headerWWW-Authenticate to require the access credentials to the client.

wc.c

implement a client that accepts chunked content.

Misc

HTTP-date

The HTTP date format is%a, %d %b %Y %H:%M:%S %Z

Some useful functions to deal with HTTP time
chardate_buf[1000];char*getNowHttpDate(){time_tnow=time(0);structtmtm=*gmtime(&now);strftime(date_buf,sizeofdate_buf,"%a, %d %b %Y %H:%M:%S %Z",&tm);printf("Time is: [%s]\n",date_buf);returndate_buf;}// parse time and convert it to millisecond from epochtime_thttpTimeToEpoch(char*time){structtmtm;charbuf[255];memset(&tm,0,sizeof(structtm));strptime(time,"%a, %d %b %Y %H:%M:%S %Z",&tm);returnmktime(&tm);}// returns 1 if d1 < d2unsignedcharcompareHttpDates(char*d1,char*d2){returnhttpTimeToEpoch(d1)<httpTimeToEpoch(d2);}unsignedcharexpired(char*uri,char*last_modified){char*complete_name=uriToCachedFile(uri);FILE*fp=fopen(complete_name,"r");if (fp==NULL)return1;//read the first linechar*line=0;size_tlen=0;getline(&line,&len,fp);if (compareHttpDates(last_modified,line))return0;return1;//todo read First line and compare}

rewind

rewind(FILE*) set the cursor at the beginning

Read a file and forward it

Read a file and forward it
FILE*fin;if ((fin=fopen(uri+1,"rt"))==NULL) {// the t is uselessprintf("File %s non aperto\n",uri+1);sprintf(response,"HTTP/1.1 404 File not found\r\n\r\n<html>File non trovato</html>");t=write(s2,response,strlen(response));if (t==-1) {perror("write fallita");return-1;      }}else {content_length=0;while ((c=fgetc(fin))!=EOF)content_length++;// get file lenghtsprintf(response,"HTTP/1.1 200 OK\r\nConnection: keep-alive\r\nContent-Length: %d\r\n\r\n",content_length);printf("Response: %s\n",response);//send headert=write(s2,response,strlen(response));//rewind the filerewind(fin);//re-read the file, char per charwhile ((c=fgetc(fin))!=EOF) {//printf("%c", c);//sending the file, char per charif (write(s2, (unsignedchar*)&c,1)!=1) {perror("Write fallita");      }   }fclose(fin);}

Read from a socket and forward to another socket (like a proxy)

charcar;while (read(s3,&car,1)) {write(s2,&car,1);//   printf("%c",car);}

Check if the target ip is in our network

unsignedchartargetip[4]= {147,162,2,100};unsignedintnetmask=0x00FFFFFF;if ((*((unsignedint*)targetip)&netmask)== (*((unsignedint*)myip)&netmask))nexthop=targetip;elsenexthop=gateway;

gethostbyname

from hostname (likewww.google.it) to ip address

/**struct hostent {   char  *h_name;            // official name of host   char **h_aliases;         // alias list   int    h_addrtype;        // host address type   int    h_length;          // length of address   char **h_addr_list;       // list of addresses}#define h_addr h_addr_list[0] // for backward compatibility*/structhostent*he;he=gethostbyname(hostname);printf("Indirizzo di %s : %d.%d.%d.%d\n",hostname,       (unsignedchar)(he->h_addr[0]), (unsignedchar)(he->h_addr[1]),       (unsignedchar)(he->h_addr[2]), (unsignedchar)(he->h_addr[3]));

socket creation, binding for listening and writing (like http requests)

For listening:

Socket creation and options setting
ints=socket(AF_INET,// domain: ipv4/*SOCK_STREAM     Provides sequenced, reliable, two-way, connection-based  byte  streams.   An  out-of-band  data                       transmission mechanism may be supported.SOCK_DGRAM      Supports datagrams (connectionless, unreliable messages of a fixed maximum length).SOCK_RAW        Provides raw network protocol access.*/SOCK_STREAM,// type: stream0);// protocol (0=ip), check /etc/protocolsif (s==-1) {perror("Socket Fallita");return1;}// https://stackoverflow.com/questions/3229860/what-is-the-meaning-of-so-reuseaddr-setsockopt-option-linux// SO_REUSEADDR allows your server to bind to an address which is in a TIME_WAIT state.intyes=1;if (setsockopt(s,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int))==-1) {perror("setsockopt");return1;}
Binding to a local port
structsockaddr_inindirizzo;indirizzo.sin_family=AF_INET;indirizzo.sin_port=htons(8987);indirizzo.sin_addr.s_addr=0;t=bind(s, (structsockaddr*)&indirizzo,sizeof(structsockaddr_in));if (t==-1) {perror("Bind fallita");return1;}t=listen(s,// backlog defines the maximum length for the queue of pending connections.10);if (t==-1) {perror("Listen Fallita");return1;}
Accepting a connection, and reading the actual content of the buffer
intlunghezza=sizeof(structsockaddr_in);// the remote address will be placed in indirizzo_remotos2=accept(s, (structsockaddr*)&indirizzo_remoto,&lunghezza);if (s2==-1) {perror("Accept Fallita");return1;}// now we can read in this way:charbuffer[10000];inti;for (i=0; (t=read(s2,buffer+i,1))>0;i++);// ps. it's not a good way// if the previous read returned -1if (t==-1) {perror("Read Fallita");return1;}

At the end, remember to close all the sockets withclose(s) (where s in the socket you want to close)

RAW socket creation, binding for listening and writing (to deal with tcp/icmp/arp requests directly)

ints=socket(//AF_PACKET       Low level packet interface       packet(7)AF_PACKET,//SOCK_RAW        Provides raw network protocol access.SOCK_RAW,// When protocol is set to htons(ETH_P_ALL), then all protocols are received.htons(ETH_P_ALL));unsignedcharbuffer[1500];bzero(&sll,sizeof(structsockaddr_ll));structsockaddr_llsll;sll.sll_ifindex=if_nametoindex("eth0");len=sizeof(sll);intt=sendto(s,//socketbuffer,//things to send14+20+28,// len datagram0,//flags   (structsockaddr*)&sll,// destination addrlen// dest addr len);// to receivet=recvfrom(s,buffer,1500,0, (structsockaddr*)&sll,&len);if (t==-1) {perror("recvfrom fallita");return1;}

Useful utils to print packet contents

Ethernet packet
voidstampa_eth(structeth_frame*e ){printf("\n\n ***** PACCHETTO Ethernet *****\n" );printf("Mac destinazione: %x:%x:%x:%x:%x:%x\n",e->dst[0],e->dst[1],e->dst[2],e->dst[3],e->dst[4],e->dst[5] );printf("Mac sorgente: %x:%x:%x:%x:%x:%x\n",e->src[0],e->src[1],e->src[2],e->src[3],e->src[4],e->src[5] );printf("EtherType: 0x%x\n",htons(e->type ) );}
IP datagram
voidstampa_ip(structip_datagram*i ){unsignedintihl= (i->ver_ihl&0x0F)*4;// Lunghezza header IPunsignedinttotlen=htons(i->totlen );// Lunghezza totale pacchettounsignedintopt_len=ihl-20;// Lunghezza campo opzioniprintf("\n\n ***** PACCHETTO IP *****\n" );printf("Version: %d\n",i->ver_ihl&0xF0 );printf("IHL (bytes 60max): %d\n",ihl );printf("TOS: %d\n",i->tos );printf("Lunghezza totale: %d\n",totlen );printf("ID: %x\n",htons(i->id ) );unsignedcharflags= (unsignedchar)(htons(i->flag_offs) >>13);printf("Flags: %d | %d | %d \n",flags&4,flags&2,flags&1 );printf("Fragment Offset: %d\n",htons(i->flag_offs)&0x1FFF  );printf("TTL: %d\n",i->ttl );printf("Protocol: %d\n",i->proto );printf("Checksum: %x\n",htons(i->checksum ) );unsignedchar*saddr= (unsignedchar* )&i->saddr;unsignedchar*daddr= (unsignedchar* )&i->daddr;printf("IP Source: %d.%d.%d.%d\n",saddr[0],saddr[1],saddr[2],saddr[3] );printf("IP Destination: %d.%d.%d.%d\n",daddr[0],daddr[1],daddr[2],daddr[3] );if(ihl>20 ){// Stampa opzioniprintf("Options: " );for(intj=0;j<opt_len ;j++ ){printf("%.3d(%.2x) ",i->payload[j],i->payload[j]);}printf("\n" );}}
ARP
voidstampa_arp(structarp_packet*a ){printf("\n\n ***** PACCHETTO ARP *****\n" );printf("Hardware type: %d\n",htons(a->htype ) );printf("Protocol type: %x\n",htons(a->ptype ) );printf("Hardware Addr len: %d\n",a->hlen );printf("Protocol Addr len: %d\n",a->plen );printf("Operation: %d\n",htons(a->op ) );printf("HW Addr sorgente: %x:%x:%x:%x:%x:%x\n",a->hsrc[0],a->hsrc[1],a->hsrc[2],a->hsrc[3],a->hsrc[4],a->hsrc[5] );printf("IP Source: %d.%d.%d.%d\n",a->psrc[0],a->psrc[1],a->psrc[2],a->psrc[3] );printf("HW Addr Destinazione: %x:%x:%x:%x:%x:%x\n",a->hdst[0],a->hdst[1],a->hdst[2],a->hdst[3],a->hdst[4],a->hdst[5] );printf("IP Dest: %d.%d.%d.%d\n",a->pdst[0],a->pdst[1],a->pdst[2],a->pdst[3] );}
ICMP content
voidstampa_icmp(structicmp_packet*i ){printf("\n\n ***** PACCHETTO ICMP *****\n" );printf("Type: %d\n",i->type );printf("Code: %d\n",i->code );printf("Code: 0x%x\n",htons(i->checksum ) );printf("ID: %d\n",htons(i->id) );printf("Sequence: %d\n",htons(i->seq) );}
TCP
voidstampa_tcp(structtcp_segment*t ){printf("\n\n ***** PACCHETTO TCP *****\n" );printf("Source Port: %d\n",htons(t->s_port ) );printf("Source Port: %d\n",htons(t->d_port ) );printf("Sequence N: %d\n",ntohl(t->seq ) );printf("ACK: %d\n",ntohl(t->ack ) );printf("Data offset (bytes): %d\n", (t->d_offs_res >>4 )*4 );printf("Flags: " );printf("CWR=%d | ", (t->flags&0x80) >>7 );printf("ECE=%d | ", (t->flags&0x40) >>6 );printf("URG=%d | ", (t->flags&0x20) >>5 );printf("ACK=%d | ", (t->flags&0x10) >>4 );printf("PSH=%d | ", (t->flags&0x08) >>3 );printf("RST=%d | ", (t->flags&0x04) >>2 );printf("SYN=%d | ", (t->flags&0x02) >>1 );printf("FIN=%d\n",  (t->flags&0x01) );printf("Windows size: %d\n",htons(t->win ) );printf("Checksum: 0x%x\n",htons(t->checksum ) );printf("Urgent pointer: %d\n",htons(t->urgp ) );}

How to printf the various things

Not really useful, but..

// es. tcp.cprintf("%.4d.  // delta_sec (unsigned int)   %.6d// delta_usec   %.5d->%.5d// ports (unsigned short)   %.2x// tcp flags (unsigned char) in hex: es: "12"   %.10u// seq (unsigned int)   %.10u// ack   %.5u//tcp win   %4.2f\n",delta_sec,delta_usec,htons(tcp->s_port),htons(tcp->d_port),tcp->flags,htonl(tcp->seq)-seqzero,htonl(tcp->ack)-ackzero,htons(tcp->win), (htonl(tcp->ack)-ackzero) / (double)(delta_sec*1000000+delta_usec));

Useful info

  • /etc/services: To know all the TCP ports available at the application level.
  • /etc/protocols
  • nslookup <URL>: finds the ip address of the specified URL (example:www.google.com)
  • netstat -rn shows routing table
  • traceroute routes an ip packet in which path it travels by printing the IP of every gateway that decidesto drop the packet that was forged with low TTL (time to live, decremented on every hop) count.

Releases

No releases published

Packages

No packages published

Contributors3

  •  
  •  
  •  

[8]ページ先頭

©2009-2025 Movatter.jp