├── 090909-tcp_request └── tcp_request.c ├── 100701-record_route └── record_route.c ├── 100902-unreachable_ping └── 100902_unreachable_ping.c ├── 100917-statistics └── statistics.c ├── 140626-ContentLength?? ├── np └── wc18.c ├── 140626-TRACE ├── np └── wc18.c ├── 140722-ICMP_split └── ping_split.c ├── 150713-cache ├── cache │ ├── _42 │ ├── _43 │ └── _45_abc ├── np └── wc18.c ├── 160620-IP_list_proxy ├── np ├── whitelisted_proxy.c └── wp18.c ├── 160620-TCP_reconstruction ├── np └── tcp.c ├── 160620-V2_TCP_reconstruction ├── np └── tcp.c ├── 160620-V3_TCP_reconstruction └── tcp.c ├── 160620-chunked ├── Makefile ├── filetemp ├── index.html ├── np └── ws18.c ├── 160715-PING_unreachable_telnet ├── np └── ping.c ├── 160902-HTTP_delayed ├── default.html ├── makefile ├── np └── ws18.c ├── 170621-window_scale └── window_scale.c ├── 180619-SYNACK ├── np ├── ping ├── ping.c └── ping_bk_1.c ├── 180620-ICMP_size ├── np ├── ping └── ping.c ├── 190618-SYSACKv2 ├── np └── ping.c ├── 190627-max_mtu └── max_mtu.c ├── Homeworks ├── auth_server.c ├── chunked_client.c └── traceroute.c ├── Makefile ├── Past exams ├── 20090909-tcp_request.txt ├── 20100701-record_route.txt ├── 20100716-time_exceeded.txt ├── 20100902-unreachable_ping.txt ├── 20100917-statistics.txt ├── 20130709-echo_reply.txt ├── 20140626-TRACE.txt ├── 20140626-content_length.txt ├── 20140722-ICMP_split.txt ├── 20150724-last_modified.jpg ├── 20160620-IP_list_proxy.txt ├── 20160620-chunked.txt ├── 20160620-tcp_stream_reconstruction.txt ├── 20160715-unreachable_telnet.txt ├── 20170621-window_scale.txt ├── 20180619-SYNACK.txt ├── 20180620-echo_reply.txt ├── 20180711-NAT.txt ├── 20180712-multiple_http_request.txt ├── 20190201-blacklist.txt └── Esami Teoria │ ├── ESAME_DI_RETI_DI_CALCOLATORI-Teoria-2013-07-09-1.pdf │ └── ESAME_DI_RETI_DI_CALCOLATORI-Teoria-2013-07-09-2.pdf ├── _config.yml └── readme.md /090909-tcp_request/tcp_request.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include /* See NOTES */ 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include /* the L2 protocols */ 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | unsigned char miomac[6] = {0xf2, 0x3c, 0x91, 0xdb, 0xc2, 0x98}; 14 | unsigned char broadcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 15 | unsigned char mioip[4] = {88, 80, 187, 84}; 16 | unsigned char netmask[4] = {255, 255, 255, 0}; 17 | unsigned char gateway[4] = {88, 80, 187, 1}; 18 | 19 | //unsigned char iptarget[4] = {88,80,187,80}; 20 | unsigned char iptarget[4] = {147,162,2,100}; 21 | 22 | struct sockaddr_ll sll; 23 | 24 | struct eth_frame 25 | { 26 | unsigned char dst[6]; 27 | unsigned char src[6]; 28 | unsigned short int type; //0x0800=IP, 0x0806=ARP 29 | unsigned char payload[1]; 30 | }; 31 | 32 | struct arp_packet 33 | { 34 | unsigned short int htype; //tipo protocollo di rete. Eth=1 35 | unsigned short int ptype; //IPv4=0x0800 36 | unsigned char hlen; //lunghezza indirizzi hardware. Ethernet=6 37 | unsigned char plen; //lunghezza protocollo superiore. IPv4=4 38 | unsigned short int op; //operazione del mittente: 1=richiesta, 2=risposta 39 | unsigned char hsrc[6]; 40 | unsigned char psrc[4]; 41 | unsigned char hdst[6]; 42 | unsigned char pdst[4]; 43 | }; 44 | 45 | struct ip_datagram 46 | { 47 | unsigned char ver_ihl; // first 4 bits: version, second 4 bits: (lenght header)/32 48 | unsigned char tos; //type of service 49 | unsigned short totlen; // len header + payload 50 | unsigned short id; // useful in case of fragmentation 51 | unsigned short flag_offs; //offset/8 related to the original ip package 52 | unsigned char ttl; 53 | unsigned char proto; // TCP = 6, ICMP = 1 54 | unsigned short checksum; // only header checksum (not of payload). Must be at 0 before the calculation. 55 | unsigned int saddr; // ip address 56 | unsigned int daddr; // ip address 57 | unsigned char payload[1]; 58 | }; 59 | 60 | struct tcp_segment { 61 | unsigned short s_port; 62 | unsigned short d_port; 63 | unsigned int seq; // offset in bytes from the start of the tcp segment in the stream (from initial sequance n) 64 | unsigned int ack; // useful only if ACK flag is 1. Next seq that sender expect 65 | unsigned char d_offs_res;// first 4 bits: (header len/8) 66 | unsigned char flags; // check rfc 67 | unsigned short win; // usually initially a 0 (?) 68 | unsigned short checksum; // use tcp_pseudo to calculate it. Must be at 0 before the calculation. 69 | unsigned short urgp; 70 | unsigned char payload[1000]; 71 | }; 72 | 73 | struct tcp_pseudo{ 74 | unsigned int ip_src, ip_dst; 75 | unsigned char zeroes; 76 | unsigned char proto; // ip datagram protocol field (tcp = 6, ip = 1) 77 | unsigned short entire_len; // tcp length (header + data) 78 | unsigned char tcp_segment[20/*to set appropriatly */]; // entire tcp packet pointer 79 | }; 80 | 81 | void stampa_buffer(unsigned char *b, int quanti); 82 | 83 | void crea_eth(struct eth_frame *e, unsigned char *dest, unsigned short type) 84 | { 85 | int i; 86 | for (i = 0; i < 6; i++) 87 | { 88 | e->dst[i] = dest[i]; 89 | e->src[i] = miomac[i]; 90 | } 91 | e->type = htons(type); 92 | } 93 | 94 | void crea_arp(struct arp_packet *a, unsigned short op, unsigned char *ptarget) 95 | { 96 | int i; 97 | a->htype = htons(1); 98 | a->ptype = htons(0x0800); 99 | a->hlen = 6; 100 | a->plen = 4; 101 | a->op = htons(op); 102 | for (i = 0; i < 6; i++) 103 | { 104 | a->hsrc[i] = miomac[i]; 105 | a->hdst[i] = 0; 106 | } 107 | for (i = 0; i < 4; i++) 108 | { 109 | a->psrc[i] = mioip[i]; 110 | a->pdst[i] = ptarget[i]; 111 | } 112 | } 113 | 114 | int risolvi(unsigned char *target, unsigned char *mac_incognito) 115 | { 116 | unsigned char buffer[1500]; 117 | struct eth_frame *eth; 118 | struct arp_packet *arp; 119 | int i, n, s; 120 | int lungh; 121 | s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); 122 | if (s == -1) 123 | { 124 | perror("socket fallita"); 125 | return 1; 126 | } 127 | 128 | eth = (struct eth_frame *)buffer; 129 | arp = (struct arp_packet *)eth->payload; 130 | 131 | crea_arp(arp, 1, target); 132 | crea_eth(eth, broadcast, 0x0806); 133 | //stampa_buffer(buffer, 14+sizeof(struct arp_packet)); 134 | 135 | sll.sll_family = AF_PACKET; 136 | sll.sll_ifindex = 3; 137 | lungh = sizeof(sll); 138 | n = sendto(s, buffer, 14 + sizeof(struct arp_packet), 0, (struct sockaddr *)&sll, lungh); 139 | if (n == -1) 140 | { 141 | perror("sendto fallita"); 142 | return 1; 143 | } 144 | 145 | while (1) 146 | { 147 | n = recvfrom(s, buffer, 1500, 0, (struct sockaddr *)&sll, &lungh); 148 | if (n == -1) 149 | { 150 | perror("recvfrom fallita"); 151 | return 1; 152 | } 153 | if (eth->type == htons(0x0806)) 154 | if (arp->op == htons(2)) 155 | if (!memcmp(arp->psrc, target, 4)) 156 | { 157 | for (i = 0; i < 6; i++) 158 | mac_incognito[i] = arp->hsrc[i]; 159 | break; 160 | } 161 | } 162 | close(s); 163 | return 0; 164 | } 165 | 166 | void stampa_buffer(unsigned char *b, int quanti) { 167 | int i; 168 | for (i = 0; i < quanti; i++) { 169 | printf("%.3d(%.2x) ", b[i], b[i]); 170 | if ((i % 4) == 3) 171 | printf("\n"); 172 | } 173 | } 174 | 175 | unsigned short checksum( unsigned char * buffer, int len) { 176 | int i; 177 | unsigned short *p; 178 | unsigned int tot=0; 179 | p = (unsigned short *) buffer; 180 | for(i=0;iver_ihl = 0x45; 190 | ip->tos = 0; 191 | ip->totlen = htons(payloadsize + 20); 192 | ip->id = htons(0xABCD); 193 | ip->flag_offs = htons(0); 194 | ip->ttl = 128; 195 | ip->proto = proto; 196 | ip->checksum = htons(0); 197 | ip->saddr = *(unsigned int *)mioip; 198 | ip->daddr = *(unsigned int *)ipdest; 199 | ip->checksum = htons(checksum((unsigned char *)ip, 20)); 200 | }; 201 | 202 | void crea_tcp(struct tcp_segment *tcp, unsigned short s_port, unsigned int seq) { 203 | tcp->s_port = htons(s_port); 204 | tcp->d_port = htons(80); 205 | tcp->seq = htonl(seq); // offset in bytes from the start of the tcp segment in the stream (from initial sequance n) 206 | tcp->d_offs_res = 80;// first 4 bits: (header len/8) 207 | tcp->flags = 2; // check rfc 208 | tcp->win = htons(0xFFFF); // usually initially a 0 (?) 209 | tcp->checksum = 0; 210 | tcp->urgp = 0; 211 | } 212 | 213 | int main() 214 | { 215 | int t, s; 216 | unsigned char mac[6]; 217 | unsigned char buffer[1500]; 218 | struct tcp_segment *tcp; 219 | struct ip_datagram *ip; 220 | struct eth_frame *eth; 221 | int lungh, n; 222 | 223 | srandom(time(NULL)); 224 | 225 | if ((*(unsigned int *)mioip & *(unsigned int *)netmask) == (*(unsigned int *)iptarget & *(unsigned int *)netmask)) 226 | { 227 | t = risolvi(iptarget, mac); 228 | } 229 | else 230 | t = risolvi(gateway, mac); 231 | 232 | if (t == 0) 233 | { 234 | printf("Mac incognito:\n"); 235 | stampa_buffer(mac, 6); 236 | printf("\n"); 237 | } 238 | s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); 239 | if (s == -1) 240 | { 241 | perror("Socket fallita"); 242 | return 1; 243 | } 244 | eth = (struct eth_frame *)buffer; 245 | ip = (struct ip_datagram *)eth->payload; 246 | tcp = (struct tcp_segment*)ip->payload; 247 | 248 | unsigned short port = random(); 249 | unsigned short seq = random(); 250 | 251 | crea_tcp(tcp, port, seq); 252 | crea_ip(ip, 20, 6, iptarget); 253 | crea_eth(eth, mac, 0x0800); 254 | 255 | int TCP_TOTAL_LEN = 20; 256 | struct tcp_pseudo pseudo; // size of this: 12 257 | memcpy(pseudo.tcp_segment,tcp,TCP_TOTAL_LEN); 258 | pseudo.zeroes = 0; 259 | pseudo.ip_src = ip->saddr; 260 | pseudo.ip_dst = ip->daddr; 261 | pseudo.proto = 6; 262 | pseudo.entire_len = htons(TCP_TOTAL_LEN); // may vary 263 | tcp->checksum = htons(checksum((unsigned char*)&pseudo,TCP_TOTAL_LEN+12)); 264 | 265 | stampa_buffer(buffer, 14 + 20 + 20); 266 | 267 | lungh = sizeof(struct sockaddr_ll); 268 | bzero(&sll, lungh); 269 | sll.sll_ifindex = 3; 270 | 271 | n = sendto(s, buffer, 14 + 20 + 20, 0, (struct sockaddr *)&sll, lungh); 272 | if (n == -1) 273 | { 274 | perror("sendto fallita"); 275 | return 1; 276 | } 277 | printf("Attendo risposta...\n"); 278 | while (1) 279 | { 280 | n = recvfrom(s, buffer, 1500, 0, (struct sockaddr *)&sll, &lungh); 281 | if (n == -1) 282 | { 283 | perror("recvfrom fallita"); 284 | return 1; 285 | } 286 | if (eth->type == htons(0x0800)) 287 | if (ip->proto == 6) 288 | if (tcp->s_port == htons(80)) 289 | { 290 | if(tcp->d_port == htons(port)) 291 | { 292 | if(tcp->ack == htonl(seq+1)) 293 | if(tcp->flags == 0x12) { 294 | stampa_buffer(buffer, n); 295 | break; 296 | } 297 | } 298 | } 299 | } 300 | } 301 | -------------------------------------------------------------------------------- /100701-record_route/record_route.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include /* See NOTES */ 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include /* the L2 protocols */ 8 | #include 9 | #include 10 | 11 | unsigned char miomac[6] = {0xf2, 0x3c, 0x91, 0xdb, 0xc2, 0x98}; 12 | unsigned char broadcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 13 | unsigned char mioip[4] = {88, 80, 187, 84}; 14 | unsigned char netmask[4] = {255, 255, 255, 0}; 15 | unsigned char gateway[4] = {88, 80, 187, 1}; 16 | 17 | //unsigned char iptarget[4] = {88,80,187,80}; 18 | unsigned char iptarget[4] = {212,71,253,5}; 19 | 20 | struct sockaddr_ll sll; 21 | 22 | struct eth_frame 23 | { 24 | unsigned char dst[6]; 25 | unsigned char src[6]; 26 | unsigned short int type; //0x0800=IP, 0x0806=ARP 27 | unsigned char payload[1]; 28 | }; 29 | 30 | struct arp_packet 31 | { 32 | unsigned short int htype; //tipo protocollo di rete. Eth=1 33 | unsigned short int ptype; //IPv4=0x0800 34 | unsigned char hlen; //lunghezza indirizzi hardware. Ethernet=6 35 | unsigned char plen; //lunghezza protocollo superiore. IPv4=4 36 | unsigned short int op; //operazione del mittente: 1=richiesta, 2=risposta 37 | unsigned char hsrc[6]; 38 | unsigned char psrc[4]; 39 | unsigned char hdst[6]; 40 | unsigned char pdst[4]; 41 | }; 42 | 43 | struct icmp_packet 44 | { 45 | unsigned char type; //8=echo; 0=echo reply 46 | unsigned char code; 47 | unsigned short checksum; 48 | unsigned short id; 49 | unsigned short seq; 50 | unsigned char payload[1]; 51 | }; 52 | struct ip_datagram 53 | { 54 | unsigned char ver_ihl; // first 4 bits: version, second 4 bits: (lenght header)/32 55 | unsigned char tos; //type of service 56 | unsigned short totlen; // len header + payload 57 | unsigned short id; // useful in case of fragmentation 58 | unsigned short flag_offs; //offset/8 related to the original ip package 59 | unsigned char ttl; 60 | unsigned char proto; // TCP = 6, ICMP = 1 61 | unsigned short checksum; // only header checksum (not of payload). Must be at 0 before the calculation. 62 | unsigned int saddr; // ip address 63 | unsigned int daddr; // ip address 64 | unsigned char option_type; 65 | unsigned char option_length; 66 | unsigned char option_pointer; 67 | unsigned char route_data[37]; 68 | unsigned char payload[1]; 69 | }; 70 | 71 | void stampa_buffer(unsigned char *b, int quanti); 72 | 73 | void crea_eth(struct eth_frame *e, unsigned char *dest, unsigned short type) 74 | { 75 | int i; 76 | for (i = 0; i < 6; i++) 77 | { 78 | e->dst[i] = dest[i]; 79 | e->src[i] = miomac[i]; 80 | } 81 | e->type = htons(type); 82 | } 83 | 84 | void crea_arp(struct arp_packet *a, unsigned short op, unsigned char *ptarget) 85 | { 86 | int i; 87 | a->htype = htons(1); 88 | a->ptype = htons(0x0800); 89 | a->hlen = 6; 90 | a->plen = 4; 91 | a->op = htons(op); 92 | for (i = 0; i < 6; i++) 93 | { 94 | a->hsrc[i] = miomac[i]; 95 | a->hdst[i] = 0; 96 | } 97 | for (i = 0; i < 4; i++) 98 | { 99 | a->psrc[i] = mioip[i]; 100 | a->pdst[i] = ptarget[i]; 101 | } 102 | } 103 | 104 | int risolvi(unsigned char *target, unsigned char *mac_incognito) 105 | { 106 | unsigned char buffer[1500]; 107 | struct eth_frame *eth; 108 | struct arp_packet *arp; 109 | int i, n, s; 110 | int lungh; 111 | s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); 112 | if (s == -1) 113 | { 114 | perror("socket fallita"); 115 | return 1; 116 | } 117 | 118 | eth = (struct eth_frame *)buffer; 119 | arp = (struct arp_packet *)eth->payload; 120 | 121 | crea_arp(arp, 1, target); 122 | crea_eth(eth, broadcast, 0x0806); 123 | //stampa_buffer(buffer, 14+sizeof(struct arp_packet)); 124 | 125 | sll.sll_family = AF_PACKET; 126 | sll.sll_ifindex = 3; 127 | lungh = sizeof(sll); 128 | n = sendto(s, buffer, 14 + sizeof(struct arp_packet), 0, (struct sockaddr *)&sll, lungh); 129 | if (n == -1) 130 | { 131 | perror("sendto fallita"); 132 | return 1; 133 | } 134 | 135 | while (1) 136 | { 137 | n = recvfrom(s, buffer, 1500, 0, (struct sockaddr *)&sll, &lungh); 138 | if (n == -1) 139 | { 140 | perror("recvfrom fallita"); 141 | return 1; 142 | } 143 | if (eth->type == htons(0x0806)) 144 | if (arp->op == htons(2)) 145 | if (!memcmp(arp->psrc, target, 4)) 146 | { 147 | for (i = 0; i < 6; i++) 148 | mac_incognito[i] = arp->hsrc[i]; 149 | break; 150 | } 151 | } 152 | close(s); 153 | return 0; 154 | } 155 | 156 | void stampa_buffer(unsigned char *b, int quanti) { 157 | int i; 158 | for (i = 0; i < quanti; i++) { 159 | printf("%.3d(%.2x) ", b[i], b[i]); 160 | if ((i % 4) == 3) 161 | printf("\n"); 162 | } 163 | } 164 | 165 | unsigned short checksum( unsigned char * buffer, int len) { 166 | int i; 167 | unsigned short *p; 168 | unsigned int tot=0; 169 | p = (unsigned short *) buffer; 170 | for(i=0;itype = 8; 180 | icmp->code = 0; 181 | icmp->checksum = htons(0); 182 | icmp->id = htons(id); 183 | icmp->seq = htons(seq); 184 | for (i = 0; i < 20; i++) 185 | icmp->payload[i] = i; 186 | icmp->checksum = htons(checksum((unsigned char *)icmp, 28)); 187 | } 188 | 189 | void crea_ip(struct ip_datagram *ip, int payloadsize, unsigned char proto, unsigned char *ipdest) 190 | { 191 | ip->ver_ihl = 0x4F; 192 | ip->tos = 0; 193 | ip->totlen = htons(payloadsize+20+40); 194 | ip->id = htons(0xABCD); 195 | ip->flag_offs = htons(0); 196 | ip->ttl = 5; 197 | ip->proto = proto; 198 | ip->checksum = htons(0); 199 | ip->saddr = *(unsigned int *)mioip; 200 | ip->daddr = *(unsigned int *)ipdest; 201 | ip->option_type = 7; 202 | ip->option_length = 40; 203 | ip->option_pointer = 4; 204 | for(int i=0;i<37;i++) ip->route_data[i]=0; 205 | ip->checksum = htons(checksum((unsigned char *)ip, 60)); 206 | }; 207 | 208 | int main() 209 | { 210 | int t, s; 211 | unsigned char mac[6]; 212 | unsigned char buffer[1500]; 213 | struct icmp_packet *icmp; 214 | struct ip_datagram *ip; 215 | struct eth_frame *eth; 216 | int lungh, n; 217 | 218 | if ((*(unsigned int *)mioip & *(unsigned int *)netmask) == (*(unsigned int *)iptarget & *(unsigned int *)netmask)) 219 | { 220 | t = risolvi(iptarget, mac); 221 | } 222 | else 223 | t = risolvi(gateway, mac); 224 | 225 | if (t == 0) 226 | { 227 | printf("Mac incognito:\n"); 228 | stampa_buffer(mac, 6); 229 | } 230 | s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); 231 | if (s == -1) 232 | { 233 | perror("Socket fallita"); 234 | return 1; 235 | } 236 | eth = (struct eth_frame *)buffer; 237 | ip = (struct ip_datagram *)eth->payload; 238 | icmp = (struct icmp_packet *)ip->payload; 239 | 240 | crea_icmp_echo(icmp, 0x1234, 1); 241 | crea_ip(ip, 28, 1, iptarget); 242 | crea_eth(eth, mac, 0x0800); 243 | printf("ICMP/IP/ETH\n"); 244 | stampa_buffer(buffer, 14 + 20 + 8 + 20 +40); 245 | lungh = sizeof(struct sockaddr_ll); 246 | bzero(&sll, lungh); 247 | sll.sll_ifindex = 3; 248 | n = sendto(s, buffer, 14 + 20 + 8 + 20 + 40, 0, (struct sockaddr *)&sll, lungh); 249 | if (n == -1) 250 | { 251 | perror("sendto fallita"); 252 | return 1; 253 | } 254 | printf("Attendo risposta...\n"); 255 | while (1) 256 | { 257 | n = recvfrom(s, buffer, 1500, 0, (struct sockaddr *)&sll, &lungh); 258 | if (n == -1) 259 | { 260 | perror("recvfrom fallita"); 261 | return 1; 262 | } 263 | if (eth->type == htons(0x0800)) 264 | if (ip->proto == 1) 265 | //if (icmp->type == 0) 266 | { 267 | stampa_buffer(buffer, n); 268 | break; 269 | } 270 | } 271 | } 272 | -------------------------------------------------------------------------------- /100902-unreachable_ping/100902_unreachable_ping.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include /* See NOTES */ 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include /* the L2 protocols */ 8 | #include 9 | #include 10 | 11 | unsigned char miomac[6] = {0xf2, 0x3c, 0x91, 0xdb, 0xc2, 0x98}; 12 | unsigned char broadcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 13 | unsigned char mioip[4] = {88, 80, 187, 84}; 14 | unsigned char netmask[4] = {255, 255, 255, 0}; 15 | unsigned char gateway[4] = {88, 80, 187, 1}; 16 | 17 | //unsigned char iptarget[4] = {88,80,187,80}; 18 | unsigned char iptarget[4] = {20,30,40,50}; 19 | 20 | struct sockaddr_ll sll; 21 | 22 | struct eth_frame 23 | { 24 | unsigned char dst[6]; 25 | unsigned char src[6]; 26 | unsigned short int type; //0x0800=IP, 0x0806=ARP 27 | unsigned char payload[1]; 28 | }; 29 | 30 | struct arp_packet 31 | { 32 | unsigned short int htype; //tipo protocollo di rete. Eth=1 33 | unsigned short int ptype; //IPv4=0x0800 34 | unsigned char hlen; //lunghezza indirizzi hardware. Ethernet=6 35 | unsigned char plen; //lunghezza protocollo superiore. IPv4=4 36 | unsigned short int op; //operazione del mittente: 1=richiesta, 2=risposta 37 | unsigned char hsrc[6]; 38 | unsigned char psrc[4]; 39 | unsigned char hdst[6]; 40 | unsigned char pdst[4]; 41 | }; 42 | 43 | struct icmp_packet 44 | { 45 | unsigned char type; //8=echo; 0=echo reply 46 | unsigned char code; 47 | unsigned short checksum; 48 | unsigned short id; 49 | unsigned short seq; 50 | unsigned char payload[1]; 51 | }; 52 | struct ip_datagram 53 | { 54 | unsigned char ver_ihl; // first 4 bits: version, second 4 bits: (lenght header)/32 55 | unsigned char tos; //type of service 56 | unsigned short totlen; // len header + payload 57 | unsigned short id; // useful in case of fragmentation 58 | unsigned short flag_offs; //offset/8 related to the original ip package 59 | unsigned char ttl; 60 | unsigned char proto; // TCP = 6, ICMP = 1 61 | unsigned short checksum; // only header checksum (not of payload). Must be at 0 before the calculation. 62 | unsigned int saddr; // ip address 63 | unsigned int daddr; // ip address 64 | unsigned char payload[1]; 65 | }; 66 | 67 | void stampa_buffer(unsigned char *b, int quanti); 68 | 69 | void crea_eth(struct eth_frame *e, unsigned char *dest, unsigned short type) 70 | { 71 | int i; 72 | for (i = 0; i < 6; i++) 73 | { 74 | e->dst[i] = dest[i]; 75 | e->src[i] = miomac[i]; 76 | } 77 | e->type = htons(type); 78 | } 79 | 80 | void crea_arp(struct arp_packet *a, unsigned short op, unsigned char *ptarget) 81 | { 82 | int i; 83 | a->htype = htons(1); 84 | a->ptype = htons(0x0800); 85 | a->hlen = 6; 86 | a->plen = 4; 87 | a->op = htons(op); 88 | for (i = 0; i < 6; i++) 89 | { 90 | a->hsrc[i] = miomac[i]; 91 | a->hdst[i] = 0; 92 | } 93 | for (i = 0; i < 4; i++) 94 | { 95 | a->psrc[i] = mioip[i]; 96 | a->pdst[i] = ptarget[i]; 97 | } 98 | } 99 | 100 | int risolvi(unsigned char *target, unsigned char *mac_incognito) 101 | { 102 | unsigned char buffer[1500]; 103 | struct eth_frame *eth; 104 | struct arp_packet *arp; 105 | int i, n, s; 106 | int lungh; 107 | s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); 108 | if (s == -1) 109 | { 110 | perror("socket fallita"); 111 | return 1; 112 | } 113 | 114 | eth = (struct eth_frame *)buffer; 115 | arp = (struct arp_packet *)eth->payload; 116 | 117 | crea_arp(arp, 1, target); 118 | crea_eth(eth, broadcast, 0x0806); 119 | //stampa_buffer(buffer, 14+sizeof(struct arp_packet)); 120 | 121 | sll.sll_family = AF_PACKET; 122 | sll.sll_ifindex = 3; 123 | lungh = sizeof(sll); 124 | n = sendto(s, buffer, 14 + sizeof(struct arp_packet), 0, (struct sockaddr *)&sll, lungh); 125 | if (n == -1) 126 | { 127 | perror("sendto fallita"); 128 | return 1; 129 | } 130 | 131 | while (1) 132 | { 133 | n = recvfrom(s, buffer, 1500, 0, (struct sockaddr *)&sll, &lungh); 134 | if (n == -1) 135 | { 136 | perror("recvfrom fallita"); 137 | return 1; 138 | } 139 | if (eth->type == htons(0x0806)) 140 | if (arp->op == htons(2)) 141 | if (!memcmp(arp->psrc, target, 4)) 142 | { 143 | for (i = 0; i < 6; i++) 144 | mac_incognito[i] = arp->hsrc[i]; 145 | break; 146 | } 147 | } 148 | close(s); 149 | return 0; 150 | } 151 | 152 | void stampa_buffer(unsigned char *b, int quanti) { 153 | int i; 154 | for (i = 0; i < quanti; i++) { 155 | printf("%.3d(%.2x) ", b[i], b[i]); 156 | if ((i % 4) == 3) 157 | printf("\n"); 158 | } 159 | } 160 | 161 | void print_ip(unsigned int ip){ 162 | struct in_addr ip_addr; 163 | ip_addr.s_addr = ip; 164 | printf("%s\n",inet_ntoa(ip_addr)); 165 | } 166 | 167 | unsigned short checksum( unsigned char * buffer, int len) { 168 | int i; 169 | unsigned short *p; 170 | unsigned int tot=0; 171 | p = (unsigned short *) buffer; 172 | for(i=0;itype = 8; 182 | icmp->code = 0; 183 | icmp->checksum = htons(0); 184 | icmp->id = htons(id); 185 | icmp->seq = htons(seq); 186 | for (i = 0; i < 20; i++) 187 | icmp->payload[i] = i; 188 | icmp->checksum = htons(checksum((unsigned char *)icmp, 28)); 189 | } 190 | 191 | void crea_ip(struct ip_datagram *ip, int payloadsize, unsigned char proto, unsigned char *ipdest, unsigned char ttl) 192 | { 193 | ip->ver_ihl = 0x45; 194 | ip->tos = 0; 195 | ip->totlen = htons(payloadsize + 20); 196 | ip->id = htons(0xABCD); 197 | ip->flag_offs = htons(0); 198 | ip->ttl = ttl; 199 | ip->proto = proto; 200 | ip->checksum = htons(0); 201 | ip->saddr = *(unsigned int *)mioip; 202 | ip->daddr = *(unsigned int *)ipdest; 203 | ip->checksum = htons(checksum((unsigned char *)ip, 20)); 204 | }; 205 | 206 | int main() 207 | { 208 | int t, s; 209 | unsigned char mac[6]; 210 | unsigned char buffer[1500]; 211 | struct icmp_packet *icmp; 212 | struct ip_datagram *ip; 213 | struct eth_frame *eth; 214 | int lungh, n; 215 | 216 | if ((*(unsigned int *)mioip & *(unsigned int *)netmask) == (*(unsigned int *)iptarget & *(unsigned int *)netmask)) 217 | { 218 | t = risolvi(iptarget, mac); 219 | } 220 | else 221 | t = risolvi(gateway, mac); 222 | 223 | if (t == 0) 224 | { 225 | printf("Mac incognito:\n"); 226 | stampa_buffer(mac, 6); 227 | } 228 | s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); 229 | if (s == -1) 230 | { 231 | perror("Socket fallita"); 232 | return 1; 233 | } 234 | eth = (struct eth_frame *)buffer; 235 | ip = (struct ip_datagram *)eth->payload; 236 | icmp = (struct icmp_packet *)ip->payload; 237 | 238 | char stop= 0; 239 | for(int ttl=1; ttl<128 && !stop; ttl++) { 240 | crea_icmp_echo(icmp, 0x1234, 1); 241 | crea_ip(ip, 28, 1, iptarget, ttl); 242 | crea_eth(eth, mac, 0x0800); 243 | printf("ICMP/IP/ETH\n"); 244 | stampa_buffer(buffer, 14 + 20 + 8 + 20); 245 | lungh = sizeof(struct sockaddr_ll); 246 | bzero(&sll, lungh); 247 | sll.sll_ifindex = 3; 248 | n = sendto(s, buffer, 14 + 20 + 8 + 20, 0, (struct sockaddr *)&sll, lungh); 249 | if (n == -1) 250 | { 251 | perror("sendto fallita"); 252 | return 1; 253 | } 254 | printf("Attendo risposta...\n"); 255 | for(int j=0; j<100; j++) 256 | { 257 | n = recvfrom(s, buffer, 1500, 0, (struct sockaddr *)&sll, &lungh); 258 | if (n == -1) 259 | { 260 | perror("recvfrom fallita"); 261 | return 1; 262 | } 263 | if (eth->type == htons(0x0800)) 264 | if (ip->proto == 1){ 265 | if (icmp->type == 0) 266 | { 267 | printf("icmp echo reply from:\n"); 268 | stop = 1; 269 | } 270 | else if(icmp->type == 3) { 271 | printf("icmp destination unreachable from:"); 272 | stop = 1; 273 | } 274 | else if(icmp->type == 11) { 275 | printf("icmp time exceeded from:\n"); 276 | } 277 | else { 278 | printf("icmp type %d received from:", (int)icmp->type); 279 | } 280 | print_ip(ip->saddr); 281 | stampa_buffer(buffer, n); 282 | } 283 | } 284 | } 285 | } 286 | -------------------------------------------------------------------------------- /100917-statistics/statistics.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nicomazz/ComputerNetworks-unipd2018/ee64f21ccb57208d272c08a81bd8de0d9dd89950/100917-statistics/statistics.c -------------------------------------------------------------------------------- /140626-ContentLength??/np: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nicomazz/ComputerNetworks-unipd2018/ee64f21ccb57208d272c08a81bd8de0d9dd89950/140626-ContentLength??/np -------------------------------------------------------------------------------- /140626-ContentLength??/wc18.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include /* superset of previous */ 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include // Per il comando write 9 | 10 | // Prototipi di funzioni 11 | unsigned short myhtons(unsigned short s); 12 | unsigned char *myhtonx(unsigned char *s, unsigned char *o, int size); 13 | long hexToLong(char *str); 14 | 15 | // Indirizzo IPv4 16 | struct sockaddr_in indirizzo; 17 | 18 | //Struttura singono header (nome, valore) 19 | struct header { 20 | char *n; 21 | char *v; 22 | }; 23 | struct header h[100]; //Header ricevuto dalla Full-Response (array di strutture) 24 | 25 | int main() { 26 | long dim; 27 | int s, k, t, i, j; //s:file descriptor socket per inviare 28 | char *p; 29 | char primiduepunti, chunked = 0; //chunked indica se l'header Transfer-Encodind=chunked 30 | char *status_line, *entity, *chunksize; // Puntatori a: StatusLine, EntityBody, ChunkSize 31 | int content_length; //Valore che verrà reperito dall'header Content-Length 32 | char request[1000]; 33 | char response[100000]; 34 | unsigned short u, v; 35 | u = 0xABCD; 36 | myhtonx((unsigned char *)&u, (unsigned char *)&v, sizeof(unsigned short)); 37 | printf("%X %X\n", u, v); 38 | 39 | //APRIRE COMUNICAZIONE 40 | /*socket restituisce un INT che è un file descriptor 41 | ovvero l'indice della tabella con tutto ciò che serve per gestire la comunicazione*/ 42 | s = socket(AF_INET, SOCK_STREAM, 0); //AF_INET=IPv4, SOCK_STREAM:apre uno stream, protocol:0 (default) 43 | if (s == -1) { 44 | perror("Socket Fallita"); 45 | } 46 | 47 | //CONNESSIONE 48 | indirizzo.sin_family = AF_INET; //IPv4 49 | indirizzo.sin_port = htons(80); //Porta80 50 | ((unsigned char *)&(indirizzo.sin_addr.s_addr))[0] = 216; 51 | ((unsigned char *)&(indirizzo.sin_addr.s_addr))[1] = 58; 52 | ((unsigned char *)&(indirizzo.sin_addr.s_addr))[2] = 213; 53 | ((unsigned char *)&(indirizzo.sin_addr.s_addr))[3] = 228; 54 | // google.com 216.58.213.228 55 | // google.co.uk 74.125.206.94 56 | // unipd.it 147.162.235.155 57 | 58 | t = connect(s, (struct sockaddr *)&indirizzo, sizeof(struct sockaddr_in)); 59 | if (t == -1) perror("Connect fallita\n"); 60 | 61 | //RICHIESTA 62 | /*Full-Request = Request-Line 63 | *( General-Header 64 | | Request-Header 65 | | Entity-Header ) 66 | CRLF 67 | [ Entity-Body ] */ 68 | // Request-Line = Method SP Request-URI SP HTTP-Version CRLF (con CRLF=\r\n) 69 | // Header = nome: valore 70 | 71 | // Preparo la richiesta: (scrivo sull'array di char request) 72 | sprintf(request, "GET /?gfe_rd=cr&dcr=0&ei=7qmvWvjcMdfEaM21i4AK HTTP/1.1\r\nHost:www.google.co.uk\r\n\r\n"); 73 | //sprintf(request,"GET / HTTP/1.1\r\nHost:www.google.com\r\n\r\n"); 74 | 75 | // Invio la richiesta: 76 | write(s, request, strlen(request)); // Scrivo sul file descriptor s del socket 77 | 78 | //RICEVO LA FULL-RESPONSE 79 | /*Full-Response = Status-Line 80 | *( General-Header 81 | | Response-Header 82 | | Entity-Header ) 83 | CRLF 84 | [ Entity-Body ] */ 85 | // Status-Line = HTTP-version SP Status-Code SP Reason-Phrase CRLF 86 | // Header = nome: valore 87 | 88 | // Status Line: 89 | h[0].n = response; 90 | status_line = h[0].n; 91 | h[0].v = h[0].n; 92 | 93 | //Headers 94 | for (i = 0, j = 0; read(s, response + i, 1); i++) { 95 | if ((i > 1) && (response[i] == '\n') && (response[i - 1] == '\r')) { 96 | primiduepunti = 1; 97 | response[i - 1] = 0; 98 | if (h[j].n[0] == 0) break; 99 | h[++j].n = response + i + 1; 100 | } 101 | if (primiduepunti && (response[i] == ':')) { 102 | h[j].v = response + i + 1; 103 | response[i] = 0; 104 | primiduepunti = 0; 105 | } 106 | } 107 | 108 | //Visualizzo a schermo La StatusLine e gli Headers ricevuti 109 | printf("Status Line: %s\n", status_line); 110 | content_length = 0; 111 | for (i = 1; i < j; i++) { 112 | printf("%s ===> %s\n", h[i].n, h[i].v); 113 | if (strcmp("Content-Length", h[i].n) == 0) 114 | content_length = atoi(h[i].v); //Atoi:string to integer 115 | else if (strcmp("Transfer-Encoding", h[i].n) == 0 && strcmp(" chunked", h[i].v) == 0) 116 | chunked = 1; 117 | } 118 | 119 | //Se la dimensione non è nulla: 120 | if (content_length != 0) { 121 | entity = malloc(content_length + 1); //alloca la memoria per l'entity body 122 | //Legge (content_lenghtsocket-i)byte dal socket s partendo dall'indirizzo (entity+i) 123 | for (i = 0; (i < content_length) && (t = read(s, entity + i, content_length - i)); i = i + t) 124 | ; 125 | //Visualizzo a schermo il BODY 126 | entity[i] = 0; 127 | printf("%s", entity); 128 | free(entity); 129 | } else if (chunked) { 130 | chunksize = response + i; 131 | for (k = 0; (t = read(s, response + i + k, 1)) > 0; k++) { 132 | if (response[i + k] == '\n' && response[i + k - 1] == '\r') { 133 | response[i + k - 1] = 0; 134 | dim = hexToLong(chunksize); 135 | printf("<%s> %ld\n", chunksize, dim); 136 | for (j = 0; (t = read(s, response + i + k, dim - j)) > 0 && j < dim; j += t, k += t) 137 | ; 138 | t = read(s, response + i + k, 2); 139 | //response[i+k+t]=0; 140 | //printf("***%s***\n",response+i+k); 141 | 142 | k += 2; 143 | if (dim == 0) { 144 | printf("Fine body"); 145 | break; 146 | } 147 | chunksize = response + i + k; 148 | k--; 149 | } 150 | } 151 | } 152 | if (t < 0) { 153 | perror("read fallita"); 154 | return 1; 155 | } 156 | 157 | //Visualizzo a schermo il BODY 158 | //entity[i]=0; 159 | //printf("%s",entity); 160 | //free(entity); 161 | 162 | /* 163 | p = response; 164 | while (t=read(s,p,100000)){ 165 | p = p + t; 166 | *p=0; 167 | } 168 | */ 169 | } //Fine main 170 | 171 | long hexToLong(char *str) { 172 | long val = 0; 173 | int n, k; 174 | for (k = 0; str[k]; k++) { 175 | if (str[k] <= '9' && str[k] >= '0') n = str[k] - '0'; 176 | if (str[k] <= 'Z' && str[k] >= 'A') n = str[k] - 'A' + 10; 177 | if (str[k] <= 'z' && str[k] >= 'a') n = str[k] - 'a' + 10; 178 | val = val * 16 + n; 179 | } 180 | return val; 181 | } 182 | 183 | unsigned short myhtons(unsigned short s) { 184 | unsigned short tmp = 1; 185 | unsigned char *p; 186 | p = (unsigned char *)&tmp; 187 | if (p[0]) { 188 | p[0] = ((unsigned char *)&s)[1]; 189 | p[1] = ((unsigned char *)&s)[0]; 190 | } else 191 | tmp = s; 192 | 193 | return tmp; 194 | } 195 | 196 | unsigned char *myhtonx(unsigned char *s, unsigned char *o, int size) { 197 | unsigned short tmp = 1; 198 | int i; 199 | unsigned char *p; 200 | unsigned char appoggio; 201 | p = (unsigned char *)&tmp; 202 | if (p[0]) 203 | for (i = 0; i < size / 2; i++) { 204 | appoggio = s[i]; 205 | o[i] = s[size - i - 1]; 206 | o[size - i - 1] = appoggio; 207 | } 208 | return o; 209 | } 210 | 211 | -------------------------------------------------------------------------------- /140626-TRACE/np: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nicomazz/ComputerNetworks-unipd2018/ee64f21ccb57208d272c08a81bd8de0d9dd89950/140626-TRACE/np -------------------------------------------------------------------------------- /140626-TRACE/wc18.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include /* superset of previous */ 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include // Per il comando write 9 | 10 | // Prototipi di funzioni 11 | unsigned short myhtons(unsigned short s); 12 | unsigned char *myhtonx(unsigned char *s, unsigned char *o, int size); 13 | long hexToLong(char *str); 14 | 15 | // Indirizzo IPv4 16 | struct sockaddr_in indirizzo; 17 | 18 | //Struttura singono header (nome, valore) 19 | struct header { 20 | char *n; 21 | char *v; 22 | }; 23 | struct header h[100]; //Header ricevuto dalla Full-Response (array di strutture) 24 | 25 | int main() { 26 | long dim; 27 | int s, k, t, i, j; //s:file descriptor socket per inviare 28 | char *p; 29 | char primiduepunti, chunked = 0; //chunked indica se l'header Transfer-Encodind=chunked 30 | char *status_line, *entity, *chunksize; // Puntatori a: StatusLine, EntityBody, ChunkSize 31 | int content_length; //Valore che verrà reperito dall'header Content-Length 32 | char request[1000]; 33 | char response[100000]; 34 | unsigned short u, v; 35 | u = 0xABCD; 36 | myhtonx((unsigned char *)&u, (unsigned char *)&v, sizeof(unsigned short)); 37 | printf("%X %X\n", u, v); 38 | 39 | //APRIRE COMUNICAZIONE 40 | /*socket restituisce un INT che è un file descriptor 41 | ovvero l'indice della tabella con tutto ciò che serve per gestire la comunicazione*/ 42 | s = socket(AF_INET, SOCK_STREAM, 0); //AF_INET=IPv4, SOCK_STREAM:apre uno stream, protocol:0 (default) 43 | if (s == -1) { 44 | perror("Socket Fallita"); 45 | } 46 | 47 | //CONNESSIONE 48 | indirizzo.sin_family = AF_INET; //IPv4 49 | indirizzo.sin_port = htons(80); //Porta80 50 | ((unsigned char *)&(indirizzo.sin_addr.s_addr))[0] = 184; 51 | ((unsigned char *)&(indirizzo.sin_addr.s_addr))[1] = 168; 52 | ((unsigned char *)&(indirizzo.sin_addr.s_addr))[2] = 221; 53 | ((unsigned char *)&(indirizzo.sin_addr.s_addr))[3] = 96; 54 | // google.com 216.58.213.228 55 | // google.co.uk 74.125.206.94 56 | // unipd.it 147.162.235.155 57 | 58 | t = connect(s, (struct sockaddr *)&indirizzo, sizeof(struct sockaddr_in)); 59 | if (t == -1) perror("Connect fallita\n"); 60 | 61 | //RICHIESTA 62 | /*Full-Request = Request-Line 63 | *( General-Header 64 | | Request-Header 65 | | Entity-Header ) 66 | CRLF 67 | [ Entity-Body ] */ 68 | // Request-Line = Method SP Request-URI SP HTTP-Version CRLF (con CRLF=\r\n) 69 | // Header = nome: valore 70 | 71 | // Preparo la richiesta: (scrivo sull'array di char request) 72 | const char * HOST = "www.webtrace.com"; 73 | sprintf(request, "TRACE / HTTP/1.1\r\nHost: %s\r\nConnection: keep-alive\r\nMax-Forwards: 1\r\n\r\n",HOST); 74 | 75 | printf("request to send: \n%s",request); 76 | //sprintf(request,"GET / HTTP/1.1\r\nHost:www.google.com\r\n\r\n"); 77 | 78 | // Invio la richiesta: 79 | write(s, request, strlen(request)); // Scrivo sul file descriptor s del socket 80 | 81 | //RICEVO LA FULL-RESPONSE 82 | /*Full-Response = Status-Line 83 | *( General-Header 84 | | Response-Header 85 | | Entity-Header ) 86 | CRLF 87 | [ Entity-Body ] */ 88 | // Status-Line = HTTP-version SP Status-Code SP Reason-Phrase CRLF 89 | // Header = nome: valore 90 | 91 | // Status Line: 92 | h[0].n = response; 93 | status_line = h[0].n; 94 | h[0].v = h[0].n; 95 | 96 | //Headers 97 | for (i = 0, j = 0; read(s, response + i, 1); i++) { 98 | if ((i > 1) && (response[i] == '\n') && (response[i - 1] == '\r')) { 99 | primiduepunti = 1; 100 | response[i - 1] = 0; 101 | if (h[j].n[0] == 0) break; 102 | h[++j].n = response + i + 1; 103 | } 104 | if (primiduepunti && (response[i] == ':')) { 105 | h[j].v = response + i + 1; 106 | response[i] = 0; 107 | primiduepunti = 0; 108 | } 109 | } 110 | 111 | //Visualizzo a schermo La StatusLine e gli Headers ricevuti 112 | printf("Status Line: %s\n", status_line); 113 | content_length = 0; 114 | for (i = 1; i < j; i++) { 115 | printf("%s ===> %s\n", h[i].n, h[i].v); 116 | if (strcmp("Content-Length", h[i].n) == 0) 117 | content_length = atoi(h[i].v); //Atoi:string to integer 118 | else if (strcmp("Transfer-Encoding", h[i].n) == 0 && strcmp(" chunked", h[i].v) == 0) 119 | chunked = 1; 120 | } 121 | 122 | //Se la dimensione non è nulla: 123 | if (content_length != 0) { 124 | entity = malloc(content_length + 1); //alloca la memoria per l'entity body 125 | //Legge (content_lenghtsocket-i)byte dal socket s partendo dall'indirizzo (entity+i) 126 | for (i = 0; (i < content_length) && (t = read(s, entity + i, content_length - i)); i = i + t) 127 | ; 128 | //Visualizzo a schermo il BODY 129 | entity[i] = 0; 130 | printf("%s", entity); 131 | free(entity); 132 | } else if (chunked) { 133 | chunksize = response + i; 134 | for (k = 0; (t = read(s, response + i + k, 1)) > 0; k++) { 135 | if (response[i + k] == '\n' && response[i + k - 1] == '\r') { 136 | response[i + k - 1] = 0; 137 | dim = hexToLong(chunksize); 138 | printf("<%s> %ld\n", chunksize, dim); 139 | int initial_inx = i+k; 140 | for (j = 0; (t = read(s, response + i + k, dim - j)) > 0 && j < dim; j += t, k += t) 141 | ; 142 | t = read(s, response + i + k, 2); 143 | response[i+k+t]=0; 144 | printf("***%s***\n",response+initial_inx); 145 | 146 | k += 2; 147 | if (dim == 0) { 148 | printf("Fine body"); 149 | break; 150 | } 151 | chunksize = response + i + k; 152 | k--; 153 | } 154 | } 155 | printf("%s",response); 156 | } 157 | if (t < 0) { 158 | perror("read fallita"); 159 | return 1; 160 | } 161 | 162 | //Visualizzo a schermo il BODY 163 | //entity[i]=0; 164 | //printf("%s",entity); 165 | //free(entity); 166 | 167 | /* 168 | p = response; 169 | while (t=read(s,p,100000)){ 170 | p = p + t; 171 | *p=0; 172 | } 173 | */ 174 | } //Fine main 175 | 176 | long hexToLong(char *str) { 177 | long val = 0; 178 | int n, k; 179 | for (k = 0; str[k]; k++) { 180 | if (str[k] <= '9' && str[k] >= '0') n = str[k] - '0'; 181 | if (str[k] <= 'Z' && str[k] >= 'A') n = str[k] - 'A' + 10; 182 | if (str[k] <= 'z' && str[k] >= 'a') n = str[k] - 'a' + 10; 183 | val = val * 16 + n; 184 | } 185 | return val; 186 | } 187 | 188 | unsigned short myhtons(unsigned short s) { 189 | unsigned short tmp = 1; 190 | unsigned char *p; 191 | p = (unsigned char *)&tmp; 192 | if (p[0]) { 193 | p[0] = ((unsigned char *)&s)[1]; 194 | p[1] = ((unsigned char *)&s)[0]; 195 | } else 196 | tmp = s; 197 | 198 | return tmp; 199 | } 200 | 201 | unsigned char *myhtonx(unsigned char *s, unsigned char *o, int size) { 202 | unsigned short tmp = 1; 203 | int i; 204 | unsigned char *p; 205 | unsigned char appoggio; 206 | p = (unsigned char *)&tmp; 207 | if (p[0]) 208 | for (i = 0; i < size / 2; i++) { 209 | appoggio = s[i]; 210 | o[i] = s[size - i - 1]; 211 | o[size - i - 1] = appoggio; 212 | } 213 | return o; 214 | } 215 | 216 | -------------------------------------------------------------------------------- /140722-ICMP_split/ping_split.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include /* the L2 protocols */ 5 | #include 6 | #include 7 | #include 8 | #include /* See NOTES */ 9 | #include 10 | 11 | /* 12 | unsigned char miomac[6] = { 0xf2,0x3c,0x91,0xdb,0xc2,0x98 }; 13 | unsigned char broadcast[6] = { 0xff, 0xff, 0xff, 0xff,0xff,0xff}; 14 | unsigned char mioip[4] = {88,80,187,84}; 15 | unsigned char netmask[4] = { 255,255,255,0}; 16 | unsigned char gateway[4] = { 88,80,187,1}; 17 | */ 18 | unsigned char miomac[6] = {0x99, 0x99, 0x99, 0x99, 0x99, 0x99}; 19 | unsigned char broadcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 20 | unsigned char mioip[4] = {192, 168, 1, 12}; 21 | unsigned char netmask[4] = {255, 255, 255, 0}; 22 | unsigned char gateway[4] = {192, 168, 1, 1}; 23 | 24 | //unsigned char iptarget[4] = {88,80,187,80}; 25 | unsigned char iptarget[4] = {147, 162, 2, 100}; 26 | //unsigned char iptarget[4] = {192,168,1,11}; 27 | 28 | struct sockaddr_ll sll; 29 | 30 | struct eth_frame { 31 | unsigned char dst[6]; 32 | unsigned char src[6]; 33 | unsigned short int type; // ARP -> 0x0806, IP -> 0x0800 34 | unsigned char payload[1]; 35 | }; 36 | 37 | struct arp_packet { 38 | unsigned short int htype; // 1 -> eth 39 | unsigned short int ptype; // 0x0800 -> ip 40 | unsigned char hlen; 41 | unsigned char plen; 42 | unsigned short int op; // operation: request -> 1, response -> 2 43 | unsigned char hsrc[6]; 44 | unsigned char psrc[4]; 45 | unsigned char hdst[6]; 46 | unsigned char pdst[4]; 47 | }; 48 | 49 | struct icmp_packet { 50 | unsigned char type; 51 | unsigned char code; 52 | unsigned short checksum; // checksum of ICMP header + ICMP payload 53 | unsigned short id; 54 | unsigned short seq; 55 | unsigned char payload[1]; 56 | }; 57 | 58 | struct ip_datagram { 59 | unsigned char ver_ihl; // usually 0x45 60 | unsigned char tos; // 0 61 | unsigned short totlen; // 20 (ip header) + payload size 62 | unsigned short id; // id chosen by sender 63 | unsigned short flag_offs; 64 | unsigned char ttl; // time to live 65 | unsigned char proto; // icmp -> 1, 6 -> TCP 66 | unsigned short checksum; // checksum of header only 67 | unsigned int saddr; 68 | unsigned int daddr; 69 | unsigned char payload[1]; 70 | }; 71 | 72 | void stampa_buffer(unsigned char *b, int quanti); 73 | 74 | void crea_eth(struct eth_frame *e, unsigned char *dest, unsigned short type) { 75 | int i; 76 | for (i = 0; i < 6; i++) { 77 | e->dst[i] = dest[i]; 78 | e->src[i] = miomac[i]; 79 | } 80 | e->type = htons(type); 81 | } 82 | 83 | void crea_arp(struct arp_packet *a, unsigned short op, unsigned char *ptarget) { 84 | int i; 85 | a->htype = htons(1); 86 | a->ptype = htons(0x0800); 87 | a->hlen = 6; 88 | a->plen = 4; 89 | a->op = htons(op); 90 | for (i = 0; i < 6; i++) { 91 | a->hsrc[i] = miomac[i]; 92 | a->hdst[i] = 0; 93 | } 94 | for (i = 0; i < 4; i++) { 95 | a->psrc[i] = mioip[i]; 96 | a->pdst[i] = ptarget[i]; 97 | } 98 | } 99 | 100 | int risolvi(unsigned char *target, unsigned char *mac_incognito) { 101 | unsigned char buffer[1500]; 102 | struct eth_frame *eth; 103 | struct arp_packet *arp; 104 | int i, n, s; 105 | int lungh; 106 | 107 | // init raw socket 108 | s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); 109 | if (s == -1) { 110 | perror("socket fallita"); 111 | return 1; 112 | } 113 | 114 | eth = (struct eth_frame *)buffer; 115 | arp = (struct arp_packet *)eth->payload; 116 | 117 | crea_arp(arp, 1, target); 118 | crea_eth(eth, broadcast, 0x0806); 119 | //stampa_buffer(buffer, 14+sizeof(struct arp_packet)); 120 | 121 | sll.sll_family = AF_PACKET; 122 | sll.sll_ifindex = 3; 123 | 124 | lungh = sizeof(sll); 125 | n = sendto(s, buffer, 14 + sizeof(struct arp_packet), 0, (struct sockaddr *)&sll, lungh); 126 | if (n == -1) { 127 | perror("sendto fallita"); 128 | return 1; 129 | } 130 | 131 | while (1) { 132 | n = recvfrom(s, buffer, 1500, 0, (struct sockaddr *)&sll, &lungh); 133 | if (n == -1) { 134 | perror("recvfrom fallita"); 135 | return 1; 136 | } 137 | if (eth->type == htons(0x0806)) 138 | if (arp->op == htons(2)) 139 | if (!memcmp(arp->psrc, target, 4)) { 140 | for (i = 0; i < 6; i++) 141 | mac_incognito[i] = arp->hsrc[i]; 142 | break; 143 | } 144 | } 145 | close(s); 146 | return 0; 147 | } 148 | 149 | void stampa_buffer(unsigned char *b, int quanti) { 150 | int i; 151 | for (i = 0; i < quanti; i++) { 152 | printf("%.3d(%.2x) ", b[i], b[i]); 153 | if ((i % 4) == 3) 154 | printf("\n"); 155 | } 156 | } 157 | 158 | unsigned short checksum(unsigned char *b, int n) { 159 | int i; 160 | unsigned short prev, tot = 0, *p = (unsigned short *)b; 161 | for (i = 0; i < n / 2; i++) { 162 | prev = tot; 163 | tot += htons(p[i]); 164 | if (tot < prev) tot++; 165 | } 166 | return (0xFFFF - tot); 167 | } 168 | 169 | void crea_icmp_echo(struct icmp_packet *icmp, unsigned short id, unsigned short seq) { 170 | int i; 171 | icmp->type = 8; 172 | icmp->code = 0; 173 | icmp->checksum = htons(0); 174 | icmp->id = htons(id); 175 | icmp->seq = htons(seq); 176 | for (i = 0; i < 20; i++) 177 | icmp->payload[i] = i; 178 | icmp->checksum = htons(checksum((unsigned char *)icmp, 28)); 179 | } 180 | 181 | // offset must be a power of 2 182 | void crea_ip(struct ip_datagram *ip, char more_frag, unsigned char offset, unsigned char proto, unsigned char *ipdest, unsigned char *payload_p, int payloadsize) { 183 | ip->ver_ihl = 0x45; 184 | ip->tos = 0; 185 | ip->totlen = htons(payloadsize + 20); 186 | ip->id = htons(0xABCD); 187 | 188 | unsigned short offs = offset; 189 | 190 | offs = offs & 0x1FFF; // mask first 3 bits 191 | if (more_frag) { 192 | //offs = offs | 0x2000; 193 | offs |= 1UL << 13; 194 | } 195 | printf("\nflag_offs: %.2x\n", offs); 196 | ip->flag_offs = htons(offs); 197 | 198 | ip->ttl = 128; 199 | ip->proto = proto; 200 | ip->checksum = htons(0); 201 | ip->saddr = *(unsigned int *)mioip; 202 | ip->daddr = *(unsigned int *)ipdest; 203 | for (int i = 0; i < payloadsize; i++) 204 | ip->payload[i] = payload_p[i]; 205 | 206 | ip->checksum = htons(checksum((unsigned char *)ip, 20)); 207 | }; 208 | 209 | int main() { 210 | int t, s; 211 | unsigned char mac[6]; 212 | unsigned char buffer[1500]; 213 | struct icmp_packet *icmp; 214 | struct icmp_packet *recvd_icmp; 215 | struct ip_datagram *ip; 216 | struct eth_frame *eth; 217 | int lungh, n; 218 | 219 | // get target mac 220 | if ((*(unsigned int *)mioip & *(unsigned int *)netmask) == (*(unsigned int *)iptarget & *(unsigned int *)netmask)) 221 | t = risolvi(iptarget, mac); 222 | else 223 | t = risolvi(gateway, mac); 224 | if (t == 0) { 225 | printf("Mac incognito:\n"); 226 | stampa_buffer(mac, 6); 227 | } 228 | 229 | // init raw socket 230 | s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); 231 | if (s == -1) { 232 | perror("Socket fallita"); 233 | return 1; 234 | } 235 | 236 | lungh = sizeof(struct sockaddr_ll); 237 | bzero(&sll, lungh); 238 | sll.sll_ifindex = 3; 239 | 240 | eth = (struct eth_frame *)buffer; 241 | ip = (struct ip_datagram *)eth->payload; 242 | recvd_icmp = (struct icmp_packet *)ip->payload; 243 | // icmp = (struct icmp_packet *) ip->payload; 244 | 245 | // split an ICMP echo message in 2 ip datagrams by choosing an ID for both 246 | // datagrams and: 247 | // 1st packet will have MF = 1 (more fragments) and Offset = 0, size 16 bytes 248 | // 2nd packet will have MF = 0 and Offset = 17 249 | // total size will be the same: 28 bytes (8 ICMP head, 20 useless payload) 250 | 251 | // create the ICMP echo 252 | unsigned char temp[1000]; 253 | icmp = (struct icmp_packet *)temp; 254 | crea_icmp_echo(icmp, 0x1234, 1); 255 | 256 | // create an IP datagram with first 16 bytes 257 | // void crea_ip(struct ip_datagram *ip, char more_frag, char offset, unsigned char proto, unsigned char *ipdest, unsigned char *payload_p, int payloadsize) 258 | crea_ip( 259 | ip, 260 | 1, // more fragments 261 | 0, // offset 262 | 1, // ICMP protocol 263 | iptarget, 264 | temp, // payload pointer 265 | 16 // payload size: first 16 bytes of ICMP echo 266 | ); 267 | crea_eth(eth, mac, 0x0800); 268 | 269 | // printf("ICMP/IP/ETH:\n"); 270 | // stampa_buffer(buffer,14+20+8+20); 271 | 272 | // 14 eth, 20 IP head, 16 first bytes of icmp echo 273 | n = sendto(s, buffer, 14 + 20 + 16, 0, (struct sockaddr *)&sll, lungh); 274 | if (n == -1) { 275 | perror("sendto fallita"); 276 | return 1; 277 | } 278 | 279 | // create the ip packetint total_size, containing the rest of the ICMP echo 280 | crea_ip( 281 | ip, 282 | 0, // no more fragments 283 | 2, // offset: misured in units of 8 octets 284 | 1, // ICMP protocol 285 | iptarget, 286 | temp + 16, // payload pointer 287 | 12 // payload size: rest of ICMP echo 28-16=12 288 | ); 289 | 290 | // stampa_buffer( buffer, 14+20+12); 291 | n = sendto(s, buffer, 14 + 20 + 12, 0, (struct sockaddr *)&sll, lungh); 292 | if (n == -1) { 293 | perror("sendto fallita"); 294 | return 1; 295 | } 296 | 297 | printf("Attendo risposta...\n"); 298 | while (1) { 299 | n = recvfrom(s, buffer, 1500, 0, (struct sockaddr *)&sll, &lungh); 300 | if (n == -1) { 301 | perror("recvfrom fallita"); 302 | return 1; 303 | } 304 | if (eth->type == htons(0x0800) && ip->proto == 1 && recvd_icmp->type == 0) { 305 | printf("Risposta echo ricevuta!\n"); 306 | break; 307 | } 308 | } 309 | } 310 | -------------------------------------------------------------------------------- /150713-cache/cache/_42: -------------------------------------------------------------------------------- 1 | Thu, 03 Jan 2019 22:30:41 GMT 2 | 3 | 4 | 5 | Example Domain 6 | 7 | 8 | 9 | 10 | 41 | 42 | 43 | 44 |
45 |

Example Domain

46 |

This domain is established to be used for illustrative examples in documents. You may use this 47 | domain in examples without prior coordination or asking for permission.

48 |

More information...

49 |
50 | 51 | 52 | -------------------------------------------------------------------------------- /150713-cache/cache/_43: -------------------------------------------------------------------------------- 1 | Thu, 03 Jan 2019 22:32:02 GMT 2 | 3 | 4 | Example Domain 5 | 6 | 7 | 8 | 9 | 40 | 41 | 42 | 43 |
44 |

Example Domain

45 |

This domain is established to be used for illustrative examples in documents. You may use this 46 | domain in examples without prior coordination or asking for permission.

47 |

More information...

48 |
49 | 50 | 51 | -------------------------------------------------------------------------------- /150713-cache/cache/_45_abc: -------------------------------------------------------------------------------- 1 | Thu, 03 Jan 2019 22:35:04 GMT 2 | 3 | 4 | 5 | Example Domain 6 | 7 | 8 | 9 | 10 | 41 | 42 | 43 | 44 |
45 |

Example Domain

46 |

This domain is established to be used for illustrative examples in documents. You may use this 47 | domain in examples without prior coordination or asking for permission.

48 |

More information...

49 |
50 | 51 | 52 | -------------------------------------------------------------------------------- /150713-cache/np: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nicomazz/ComputerNetworks-unipd2018/ee64f21ccb57208d272c08a81bd8de0d9dd89950/150713-cache/np -------------------------------------------------------------------------------- /150713-cache/wc18.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include /* superset of previous */ 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include // Per il comando write 9 | #include 10 | #include 11 | #include 12 | // Prototipi di funzioni 13 | unsigned short myhtons(unsigned short s); 14 | unsigned char *myhtonx(unsigned char *s, unsigned char *o, int size); 15 | long hexToLong(char *str); 16 | 17 | // Indirizzo IPv4 18 | struct sockaddr_in indirizzo; 19 | 20 | //Struttura singono header (nome, valore) 21 | struct header { 22 | char *n; 23 | char *v; 24 | }; 25 | struct header h[100]; //Header ricevuto dalla Full-Response (array di strutture) 26 | char file_name_buff[1000]; 27 | //return d1 < d2 28 | char date_buf[1000]; 29 | 30 | char* getNowHttpDate(){ 31 | time_t now = time(0); 32 | struct tm tm = *gmtime(&now); 33 | strftime(date_buf, sizeof date_buf, "%a, %d %b %Y %H:%M:%S %Z", &tm); 34 | printf("Time is: [%s]\n", date_buf); 35 | return date_buf; 36 | } 37 | time_t httpTimeToEpoch(char * time){ 38 | struct tm tm; 39 | char buf[255]; 40 | memset(&tm, 0, sizeof(struct tm)); 41 | strptime(time,"%a, %d %b %Y %H:%M:%S %Z", &tm); 42 | return mktime(&tm); 43 | } 44 | 45 | unsigned char compareHttpDates(char * d1, char * d2){ 46 | return httpTimeToEpoch(d1) < httpTimeToEpoch(d2); 47 | } 48 | char * uriToCachedFile(char * uri){ 49 | sprintf(file_name_buff,"./cache/%s",uri); 50 | return file_name_buff; 51 | } 52 | unsigned char expired(char * uri, char * last_modified){ 53 | char * complete_name = uriToCachedFile(uri); 54 | FILE * fp = fopen(complete_name,"r"); 55 | if (fp == NULL) return 1; 56 | char * line = 0; size_t len = 0; 57 | getline(&line,&len,fp); 58 | if (compareHttpDates(last_modified,line)) return 0; 59 | return 1; 60 | //todo read First line and compare 61 | } 62 | void printFile(char * uri){ 63 | char * file_name = uriToCachedFile(uri); 64 | FILE * fp = fopen(file_name, "r"); 65 | if (fp == NULL){ 66 | printf("It was not present!\n"); 67 | exit(EXIT_FAILURE); 68 | } 69 | char * line= 0; 70 | size_t n = 0; 71 | ssize_t nread; 72 | char first = 1; 73 | while ((nread = getline(&line, &n, fp)) != -1) { 74 | if (first) {first = 0; continue;} 75 | // printf("Retrieved line of length %zu:\n", read); 76 | printf("%s", line); 77 | } 78 | 79 | fclose(fp); 80 | } 81 | void saveToCache(char * uri,char * body){ 82 | char * file_name = uriToCachedFile(uri); 83 | FILE * fp = fopen(file_name, "w"); 84 | if (fp == NULL) 85 | exit(EXIT_FAILURE); 86 | char * now_date = getNowHttpDate(); 87 | while (*now_date) fputc(*(now_date++),fp); 88 | fputc('\n',fp); 89 | while (*body) fputc(*(body++),fp); 90 | printf("CACHED WITH SUCCESS!\n"); 91 | } 92 | int main() { 93 | long dim; 94 | int s, k, t, i, j; //s:file descriptor socket per inviare 95 | char *p; 96 | char primiduepunti, chunked = 0; //chunked indica se l'header Transfer-Encodind=chunked 97 | char *status_line, *entity, *chunksize; // Puntatori a: StatusLine, EntityBody, ChunkSize 98 | int content_length; //Valore che verrà reperito dall'header Content-Length 99 | char request[1000]; 100 | char response[100000]; 101 | unsigned short u, v; 102 | u = 0xABCD; 103 | myhtonx((unsigned char *)&u, (unsigned char *)&v, sizeof(unsigned short)); 104 | printf("%X %X\n", u, v); 105 | 106 | //APRIRE COMUNICAZIONE 107 | /*socket restituisce un INT che è un file descriptor 108 | ovvero l'indice della tabella con tutto ciò che serve per gestire la comunicazione*/ 109 | s = socket(AF_INET, SOCK_STREAM, 0); //AF_INET=IPv4, SOCK_STREAM:apre uno stream, protocol:0 (default) 110 | if (s == -1) { 111 | perror("Socket Fallita"); 112 | } 113 | 114 | //CONNESSIONE 115 | indirizzo.sin_family = AF_INET; //IPv4 116 | indirizzo.sin_port = htons(80); //Porta80 117 | ((unsigned char *)&(indirizzo.sin_addr.s_addr))[0] = 93; 118 | ((unsigned char *)&(indirizzo.sin_addr.s_addr))[1] = 184; 119 | ((unsigned char *)&(indirizzo.sin_addr.s_addr))[2] = 216; 120 | ((unsigned char *)&(indirizzo.sin_addr.s_addr))[3] = 3; 121 | // google.com 216.58.213.228 122 | // google.co.uk 74.125.206.94 123 | // unipd.it 147.162.235.155 124 | // example.com 93.184.216.3 125 | t = connect(s, (struct sockaddr *)&indirizzo, sizeof(struct sockaddr_in)); 126 | if (t == -1) perror("Connect fallita\n"); 127 | 128 | //RICHIESTA 129 | /*Full-Request = Request-Line 130 | *( General-Header 131 | | Request-Header 132 | | Entity-Header ) 133 | CRLF 134 | [ Entity-Body ] */ 135 | // Request-Line = Method SP Request-URI SP HTTP-Version CRLF (con CRLF=\r\n) 136 | // Header = nome: valore 137 | 138 | // Preparo la richiesta: (scrivo sull'array di char request) 139 | const char * URI = "/45/abc"; 140 | sprintf(request, "GET %s HTTP/1.1\r\nHost:www.example.com\r\n\r\n",URI); 141 | //sprintf(request,"GET / HTTP/1.1\r\nHost:www.google.com\r\n\r\n"); 142 | 143 | // Invio la richiesta: 144 | write(s, request, strlen(request)); // Scrivo sul file descriptor s del socket 145 | 146 | //RICEVO LA FULL-RESPONSE 147 | /*Full-Response = Status-Line 148 | *( General-Header 149 | | Response-Header 150 | | Entity-Header ) 151 | CRLF 152 | [ Entity-Body ] */ 153 | // Status-Line = HTTP-version SP Status-Code SP Reason-Phrase CRLF 154 | // Header = nome: valore 155 | 156 | // Status Line: 157 | h[0].n = response; 158 | status_line = h[0].n; 159 | h[0].v = h[0].n; 160 | 161 | //Headers 162 | for (i = 0, j = 0; read(s, response + i, 1); i++) { 163 | if ((i > 1) && (response[i] == '\n') && (response[i - 1] == '\r')) { 164 | primiduepunti = 1; 165 | response[i - 1] = 0; 166 | if (h[j].n[0] == 0) break; 167 | h[++j].n = response + i + 1; 168 | } 169 | if (primiduepunti && (response[i] == ':')) { 170 | h[j].v = response + i + 1; 171 | response[i] = 0; 172 | primiduepunti = 0; 173 | } 174 | } 175 | 176 | //Visualizzo a schermo La StatusLine e gli Headers ricevuti 177 | printf("Status Line: %s\n", status_line); 178 | 179 | // di interesse per ciò che dobbiamo fare 180 | char * last_modified = 0; 181 | char uri[100]; 182 | unsigned char body[100000]; 183 | strcpy(uri,URI); 184 | for (int i = 0;uri[i]; i++) if (uri[i] == '/') uri[i] = '_'; 185 | 186 | // prendo gli headers 187 | content_length = 0; 188 | for (i = 1; i < j; i++) { 189 | //printf("%s ===> %s\n", h[i].n, h[i].v); 190 | if (strcmp("Content-Length", h[i].n) == 0) 191 | content_length = atoi(h[i].v); //Atoi:string to integer 192 | else if (strcmp("Transfer-Encoding", h[i].n) == 0 && strcmp(" chunked", h[i].v) == 0) 193 | chunked = 1; 194 | else if (strcmp("Last-Modified",h[i].n) == 0){ 195 | last_modified = h[i].v+1; 196 | } 197 | } 198 | 199 | printf("Last-Modified value: \"%s\"\n",last_modified); 200 | printf("uri: \"%s\"\n", uri); 201 | 202 | if (!expired(uri, last_modified)){ 203 | printf("USING CACHED VERSION\n!"); 204 | printFile(uri); 205 | return 0; 206 | } 207 | 208 | //Se la dimensione non è nulla: 209 | if (content_length != 0) { 210 | printf("USING WEB VERSION. NOW CACHING!\n"); 211 | //Legge (content_lenghtsocket-i)byte dal socket s partendo dall'indirizzo (entity+i) 212 | for (i = 0; (i < content_length) && (t = read(s, body + i, content_length - i)); i = i + t) 213 | ; 214 | //Visualizzo a schermo il BODY 215 | body[i] = 0; 216 | printf("%s",body); 217 | saveToCache(uri,body); 218 | 219 | } else if (chunked) { 220 | printf("CHUNKED NON GESTITO PER PIGRIZIA\n"); 221 | chunksize = response + i; 222 | for (k = 0; (t = read(s, response + i + k, 1)) > 0; k++) { 223 | if (response[i + k] == '\n' && response[i + k - 1] == '\r') { 224 | response[i + k - 1] = 0; 225 | dim = hexToLong(chunksize); 226 | printf("<%s> %ld\n", chunksize, dim); 227 | for (j = 0; (t = read(s, response + i + k, dim - j)) > 0 && j < dim; j += t, k += t) 228 | ; 229 | t = read(s, response + i + k, 2); 230 | //response[i+k+t]=0; 231 | //printf("***%s***\n",response+i+k); 232 | 233 | k += 2; 234 | if (dim == 0) { 235 | printf("Fine body"); 236 | break; 237 | } 238 | chunksize = response + i + k; 239 | k--; 240 | } 241 | } 242 | } 243 | if (t < 0) { 244 | perror("read fallita"); 245 | return 1; 246 | } 247 | 248 | //Visualizzo a schermo il BODY 249 | //entity[i]=0; 250 | //printf("%s",entity); 251 | //free(entity); 252 | 253 | /* 254 | p = response; 255 | while (t=read(s,p,100000)){ 256 | p = p + t; 257 | *p=0; 258 | } 259 | */ 260 | } //Fine main 261 | 262 | long hexToLong(char *str) { 263 | long val = 0; 264 | int n, k; 265 | for (k = 0; str[k]; k++) { 266 | if (str[k] <= '9' && str[k] >= '0') n = str[k] - '0'; 267 | if (str[k] <= 'Z' && str[k] >= 'A') n = str[k] - 'A' + 10; 268 | if (str[k] <= 'z' && str[k] >= 'a') n = str[k] - 'a' + 10; 269 | val = val * 16 + n; 270 | } 271 | return val; 272 | } 273 | 274 | unsigned short myhtons(unsigned short s) { 275 | unsigned short tmp = 1; 276 | unsigned char *p; 277 | p = (unsigned char *)&tmp; 278 | if (p[0]) { 279 | p[0] = ((unsigned char *)&s)[1]; 280 | p[1] = ((unsigned char *)&s)[0]; 281 | } else 282 | tmp = s; 283 | 284 | return tmp; 285 | } 286 | 287 | unsigned char *myhtonx(unsigned char *s, unsigned char *o, int size) { 288 | unsigned short tmp = 1; 289 | int i; 290 | unsigned char *p; 291 | unsigned char appoggio; 292 | p = (unsigned char *)&tmp; 293 | if (p[0]) 294 | for (i = 0; i < size / 2; i++) { 295 | appoggio = s[i]; 296 | o[i] = s[size - i - 1]; 297 | o[size - i - 1] = appoggio; 298 | } 299 | return o; 300 | } 301 | 302 | -------------------------------------------------------------------------------- /160620-IP_list_proxy/np: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nicomazz/ComputerNetworks-unipd2018/ee64f21ccb57208d272c08a81bd8de0d9dd89950/160620-IP_list_proxy/np -------------------------------------------------------------------------------- /160620-IP_list_proxy/whitelisted_proxy.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include /* See NOTES */ 9 | #include 10 | 11 | struct hostent *he; 12 | 13 | int yes = 1; 14 | int pid; 15 | unsigned char car; 16 | 17 | struct header { 18 | char *n; 19 | char *v; 20 | } h[100]; 21 | 22 | FILE *f; 23 | struct sockaddr_in myaddr, remote_addr; 24 | struct sockaddr_in server; 25 | char filename[100], command[1000]; 26 | char request[10000]; 27 | char response[10000]; 28 | char req_server[10000]; 29 | char server_content[10000]; 30 | char temp[10000]; 31 | 32 | unsigned char whitelist_addrs[2][4] = { 33 | {127, 0, 0, 1}, 34 | {192, 168, 1, 2}}; 35 | int whitelisted_size = 2; 36 | 37 | int main() { 38 | char *method, *scheme, *hostname, *path, *ver, *port; 39 | int c; 40 | int duepunti; 41 | int i, k, j, n, t, s, s2, s3; 42 | int length, lungh; 43 | s = socket(AF_INET, SOCK_STREAM, 0); 44 | if (s == -1) { 45 | perror("socket fallita"); 46 | return 1; 47 | } 48 | if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) { 49 | perror("setsockopt fallita"); 50 | return 1; 51 | } 52 | 53 | myaddr.sin_family = AF_INET; 54 | myaddr.sin_port = htons(7888); 55 | 56 | if (bind(s, (struct sockaddr *)&myaddr, sizeof(struct sockaddr_in)) == -1) { 57 | perror("bind fallita"); 58 | return 1; 59 | } 60 | if (listen(s, 10) == -1) { 61 | perror("Listen Fallita"); 62 | return 1; 63 | } 64 | 65 | lungh = sizeof(struct sockaddr_in); 66 | while (1) { 67 | s2 = accept(s, (struct sockaddr *)&remote_addr, &lungh); 68 | 69 | int is_ip_whitelisted = 0; 70 | // check if remote_addr is in whitelist 71 | for (t = 0; t < whitelisted_size; t++) { 72 | if (*(unsigned int *)whitelist_addrs[t] == remote_addr.sin_addr.s_addr) { 73 | is_ip_whitelisted = 1; 74 | break; 75 | } 76 | } 77 | if (!is_ip_whitelisted) { 78 | printf("IP address not whitelisted.\n"); 79 | close(s2); 80 | continue; 81 | } 82 | 83 | // let childs handle the connection 84 | if (fork() == 0) { 85 | printf("%d\n", s2); 86 | if (s2 == -1) { 87 | perror("accept fallita"); 88 | return 1; 89 | } 90 | 91 | // parse header 92 | j = 0; 93 | k = 0; 94 | h[0].n = request; 95 | while (read(s2, request + j, 1)) { 96 | //printf("%c(%d)",request[j],request[j]); 97 | //printf("%c",request[j]); 98 | if ((request[j] == '\n') && (request[j - 1] == '\r')) { 99 | //printf("LF\n"); 100 | request[j - 1] = 0; 101 | duepunti = 0; 102 | if (h[k].n[0] == 0) break; 103 | h[++k].n = request + j + 1; 104 | } 105 | if ((request[j] == ':') && (!duepunti) && (k != 0)) { 106 | duepunti = 1; 107 | request[j] = 0; 108 | h[k].v = request + j + 1; 109 | } 110 | j++; 111 | } 112 | if (k == 0) { 113 | close(s2); 114 | continue; 115 | } 116 | 117 | printf("Command-Line: %s\n", h[0].n); 118 | 119 | method = h[0].n; 120 | for (i = 0; h[0].n[i] != ' '; i++) 121 | ; 122 | h[0].n[i] = 0; 123 | i++; 124 | printf("method=%s\n", method); 125 | 126 | if (!strcmp(method, "GET")) { 127 | // parse command line 128 | scheme = &h[0].n[i]; 129 | for (; h[0].n[i] != ':'; i++) 130 | ; 131 | h[0].n[i] = 0; 132 | i += 3; 133 | printf("schema:%s\n", scheme); 134 | hostname = &h[0].n[i]; 135 | for (; h[0].n[i] != '/'; i++) 136 | ; 137 | h[0].n[i] = 0; 138 | i++; 139 | printf("hostname:%s\n", hostname); 140 | path = &h[0].n[i]; 141 | for (; h[0].n[i] != ' '; i++) 142 | ; 143 | h[0].n[i] = 0; 144 | i++; 145 | ver = &h[0].n[i]; 146 | printf("REPORT:%s %s %s %s %s\n", method, scheme, hostname, path, ver); 147 | 148 | he = gethostbyname(hostname); 149 | if (he == NULL) { 150 | printf("gethostbyname fallita\n"); 151 | return 1; 152 | } 153 | printf("Indirizzo server: %u.%u.%u.%u\n", (unsigned char)he->h_addr[0], (unsigned char)he->h_addr[1], (unsigned char)he->h_addr[2], (unsigned char)he->h_addr[3]); 154 | 155 | // connect to requested server 156 | s3 = socket(AF_INET, SOCK_STREAM, 0); 157 | if (s3 == -1) { 158 | perror("socket verso server fallita"); 159 | return 1; 160 | } 161 | server.sin_family = AF_INET; 162 | server.sin_port = htons(80); 163 | server.sin_addr.s_addr = (*(unsigned int *)((*he).h_addr)); 164 | t = connect(s3, (struct sockaddr *)&server, sizeof(server)); 165 | if (t == -1) { 166 | perror("connect fallita"); 167 | return 1; 168 | } 169 | 170 | // request content and forward it to client 171 | sprintf(req_server, "GET /%s HTTP/1.1\r\nHost:%s\r\nConnection:close\r\n\r\n", path, hostname); 172 | printf("richiesta:%s\n", req_server); 173 | write(s3, req_server, strlen(req_server)); 174 | 175 | // parse server headers 176 | j = 0; 177 | k = 0; 178 | h[0].n = server_content; 179 | while (read(s3, server_content + j, 1)) { 180 | //printf("%c(%d)",request[j],request[j]); 181 | //printf("%c",request[j]); 182 | temp[j] = server_content[j]; 183 | 184 | if ((server_content[j] == '\n') && (server_content[j - 1] == '\r')) { 185 | //printf("LF\n"); 186 | server_content[j - 1] = 0; 187 | duepunti = 0; 188 | if (h[k].n[0] == 0) break; 189 | h[++k].n = server_content + j + 1; 190 | } 191 | if ((server_content[j] == ':') && (!duepunti) && (k != 0)) { 192 | duepunti = 1; 193 | server_content[j] = 0; 194 | h[k].v = server_content + j + 1; 195 | } 196 | j++; 197 | } 198 | if (k == 0) { 199 | close(s2); 200 | close(s2); 201 | exit(0); 202 | } 203 | 204 | int is_content_text_or_html = 0; 205 | for (i = 0; i < k; i++) { 206 | printf("%s --> %s\n", h[i].n, h[i].v); 207 | if (!strcmp(h[i].n, "Content-Type") && strcasestr(h[i].v, " text/html")) 208 | is_content_text_or_html = 1; 209 | } 210 | 211 | if (!is_content_text_or_html) { 212 | printf("Content not allowed!\n"); 213 | sprintf(response, "HTTP/1.1 405 Method Not Allowed\r\n\r\n"); 214 | write(s2, response, strlen(response)); 215 | close(s2); 216 | exit(0); 217 | } 218 | 219 | //write(s2, temp, j); 220 | 221 | while (read(s3, &car, 1)) { 222 | write(s2, &car, 1); 223 | printf("%c", car); 224 | } 225 | close(s3); 226 | 227 | } else { 228 | sprintf(response, "HTTP/1.1 501 Not implemented\r\n\r\n"); 229 | write(s2, response, strlen(response)); 230 | } 231 | close(s2); 232 | exit(0); 233 | } 234 | } 235 | close(s); 236 | } 237 | -------------------------------------------------------------------------------- /160620-IP_list_proxy/wp18.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include /* superset of previous */ 10 | #include 11 | 12 | struct hostent * he; //Puntatore alla struttura IPv4 dell'hostname 13 | 14 | int lunghezza; //Lunghezza indirizzo per accept() 15 | int yes=1; //Flag utilizzato per settare un opzione del socket 16 | 17 | //Struttura singono header (nome, valore) 18 | struct header { 19 | char * n; 20 | char * v; 21 | }; 22 | struct header h[100];//Header (array di strutture) 23 | 24 | // Indirizzo IPv4 25 | struct sockaddr_in indirizzo,indirizzo_server; 26 | struct sockaddr_in indirizzo_remoto; 27 | 28 | int primiduepunti; // Flag usato per leggere gli headers 29 | 30 | char request[10000]; 31 | char request[10000]; 32 | char proxyrequest[10000]; 33 | char response[10000]; 34 | char* request_line; //Puntatore alla request line 35 | char * method, *uri, *http_ver; //Puntatori che indicano i parametri della RequestLine 36 | char * scheme, *hostname, *filename; //Puntatori che indicano i parametri della URI 37 | 38 | int c; //Carattere utilizato per leggere ogni carattere del file 39 | FILE *fin; //File che dovrà essere trasmesso 40 | 41 | #define ADDRESSES_LIST_SIZE 4 42 | char* allowed_ip[ADDRESSES_LIST_SIZE] = {"151.49.159.117", "88.80.187.84","127.0.0.1",""}; 43 | char allowedAddress(char * ip){ 44 | for (int i = 0 ; i < ADDRESSES_LIST_SIZE; i++) 45 | if (strcmp(allowed_ip[i],ip) == 0) return 1; 46 | return 0; 47 | } 48 | int main(){ 49 | int s,s2,s3,t,j,i; //s:socket per ricevere, t:variabile di supporto per gli errori 50 | char command[1000]; //Stringa che contiene il comando di shell eseguire 51 | char car; //Singolo carattere ricevuto dal server 52 | 53 | //APRIRE COMUNICAZIONE 54 | /*socket restituisce un INT che è un file descriptor 55 | ovvero l'indice della tabella con tutto ciò che serve per gestire la comunicazione*/ 56 | s = socket(AF_INET,SOCK_STREAM,0); 57 | if (s == -1){ 58 | perror("Socket Fallita"); 59 | return 1; 60 | } 61 | /* Opzioni del socket: opzioni a levello socket(SOL_SOCKET), 62 | riutilizzo degli indirizi(SO_REUSEADDR), 63 | 1(si), 64 | sizeof(int) 65 | ritorna 0 se tutto va bene, altrimenti -1*/ 66 | if ( setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1 ) { 67 | perror("setsockopt"); 68 | return 1; 69 | } 70 | 71 | //CONNESSIONE 72 | indirizzo.sin_family=AF_INET; //IPv4 73 | indirizzo.sin_port=htons(7888); //Porta 74 | indirizzo.sin_addr.s_addr=0; 75 | 76 | // Bind assegna un indirizzo al socket, t=0 se tutto va bene altrimenti -1 77 | t=bind(s,(struct sockaddr *) &indirizzo, sizeof(struct sockaddr_in)); 78 | if (t==-1){ 79 | perror("Bind fallita"); 80 | return 1; 81 | } 82 | 83 | //Listen: marca il socket s come passivo, ovvero che deve ricevere 84 | t=listen(s,10); 85 | if(t==-1){ 86 | perror("Listen Fallita"); 87 | return 1; 88 | } 89 | 90 | while( 1 ){ 91 | lunghezza = sizeof(struct sockaddr_in); 92 | 93 | //Accept: restituisce il file descriptor di un nuovo socket che 94 | // eredita tutto da quello vecchio ma è già connesso, 95 | // pronto per il read e write. Questo perchè l'altro è impegnato con listen. 96 | s2=accept(s,(struct sockaddr *)&indirizzo_remoto, &lunghezza); 97 | 98 | uint32_t rem_ip = indirizzo_remoto.sin_addr.s_addr; 99 | char * ip_addr = inet_ntoa(indirizzo_remoto.sin_addr); 100 | printf("connection from : %s\n",ip_addr); 101 | 102 | if (!allowedAddress(ip_addr)){ 103 | printf("NOT ALLOWED! NO REPLY!\n"); 104 | close(s2); 105 | continue; 106 | } 107 | 108 | //Fork() crea un processo figlio che eredita tutto dal padre e differisce solo per il PID 109 | //restituisce 0 se va tutto bene altrimenti -1 110 | //Usata perchè così una connessione da un client è già accettata 111 | //e possono essere eseguiti più processi senza eseguirli uno per uno 112 | if (fork()==0){ 113 | if (s2 == -1){ 114 | perror("Accept Fallita"); 115 | return 1; 116 | } 117 | 118 | //RICEVO RICHIESTA 119 | /*Full-Request = Request-Line 120 | *( General-Header 121 | | Request-Header 122 | | Entity-Header ) 123 | CRLF 124 | [ Entity-Body ] */ 125 | // Request-Line = Method SP Request-URI SP HTTP-Version CRLF (con CRLF=\r\n) 126 | // Header = nome: valore 127 | 128 | //Requst Line: 129 | h[0].n=request; 130 | request_line=h[0].n; 131 | h[0].v=h[0].n; 132 | 133 | //Headers: 134 | for(i=0,j=0; (t=read(s2,request+i,1))>0;i++){ 135 | if (( i>1) && (request[i]=='\n') && (request[i-1]=='\r')){ 136 | primiduepunti=1; 137 | request[i-1]=0; 138 | if(h[j].n[0]==0) break; 139 | h[++j].n=request+i+1; 140 | } 141 | if (j>0 && primiduepunti && (request[i]==':')){ 142 | h[j].v = request+i+1; 143 | request[i]=0; 144 | primiduepunti=0; 145 | } 146 | } 147 | if (t == -1 ) { 148 | perror("Read Fallita"); 149 | return 1; 150 | } 151 | 152 | // Visualizzo a schermo la RequestLine e gli Headers ricevuti 153 | printf("Request: %s\n",request_line); 154 | for(i=1;i %s\n",h[i].n,h[i].v); 156 | } 157 | 158 | // Ricavo Method, URI e HTTP-Version dalla RequestLine 159 | method = request_line; 160 | for(i=0;request_line[i]!=' '&& request_line[i];i++){}; 161 | if (request_line[i]!=0) { request_line[i]=0; i++;} 162 | uri = request_line + i; 163 | for(;request_line[i]!=' '&& request_line[i];i++){}; 164 | if (request_line[i]!=0) { request_line[i]=0; i++;} 165 | http_ver = request_line +i; 166 | 167 | //Visualizzo a schermo Method, URI e HTTP-Version 168 | printf("Method = %s, URI = %s, Http-Version = %s\n", method, uri, http_ver); 169 | 170 | 171 | //Se il Method non è GET rispondo che non è implementato 172 | if (strcmp(method,"GET")){//se methon=GET restituisce 0 173 | sprintf(response,"HTTP/1.1 501 Not implemented\r\n\r\n"); 174 | write(s2,response,strlen(response)); 175 | close(s2); 176 | continue; // esco dal if(fork()==0) 177 | } 178 | 179 | //Ricavo lo scheme (http) dall URI 180 | scheme = uri; 181 | for(i=0;uri[i]!=':' && uri[i];i++); 182 | if(uri[i]!=0){uri[i]=0; i++;} 183 | if((uri[i]=='/') && (uri[i+1]=='/')) i=i+2;//http:// 184 | else { 185 | printf("Errore hostname%s",uri+i); 186 | close(s2); 187 | continue; 188 | } 189 | 190 | //Ricavo hostname dall URI 191 | hostname = uri+i; 192 | for(;uri[i]!='/' && uri[i];i++); 193 | if(uri[i]!=0){uri[i]=0; i++;} 194 | 195 | //Ricavo il filename dall URI 196 | filename = uri+i; 197 | 198 | //Visualizzo a schermo scheme, hostname e filename 199 | printf("Scheme:%s, hostname:%s, filename:%s\n",scheme,hostname,filename); 200 | 201 | // Ritorna una struct IPv4 dato l'hostname 202 | he = gethostbyname(hostname); 203 | printf("Indirizzo di %s : %d.%d.%d.%d\n",hostname, (unsigned char) (he->h_addr[0]), (unsigned char) (he->h_addr[1]), (unsigned char) (he->h_addr[2]), (unsigned char) (he->h_addr[3])); 204 | 205 | 206 | //COMUNICAZIONE COL SERVER 207 | //APRIRE COMUNICAZIONE 208 | /*socket restituisce un INT che è un file descriptor 209 | ovvero l'indice della tabella con tutto ciò che serve per gestire la comunicazione*/ 210 | s3 = socket(AF_INET,SOCK_STREAM,0); 211 | if (s == -1){ 212 | perror("Socket Fallita"); 213 | } 214 | 215 | //CONNESSIONE 216 | indirizzo_server.sin_family = AF_INET; //IPv4 217 | indirizzo_server.sin_port = htons(80); //Porta 218 | indirizzo_server.sin_addr.s_addr = *((uint32_t *)he->h_addr); 219 | 220 | t=connect(s3,(struct sockaddr *)&indirizzo_server, sizeof(struct sockaddr_in)); 221 | if ( t== -1){ 222 | perror("Connect fallita\n"); 223 | } 224 | 225 | //RICHIESTA 226 | // Preparo la richiesta: (scrivo sull'array di char proxyrequest) 227 | sprintf(proxyrequest,"GET /%s HTTP/1.1\r\nHost:%s\r\nConnection:Close\r\n\r\n",filename,hostname); 228 | printf("\nproxyrequest: %s",proxyrequest); 229 | 230 | // Invio la richiesta: 231 | write(s3,proxyrequest,strlen(proxyrequest)); 232 | 233 | 234 | printf("Ricevo la full response del server\n"); 235 | //RICEVO LA FULL-RESPONSE dal server 236 | /*Full-Response = Status-Line 237 | *( General-Header 238 | | Response-Header 239 | | Entity-Header ) 240 | CRLF 241 | [ Entity-Body ] */ 242 | // Status-Line = HTTP-version SP Status-Code SP Reason-Phrase CRLF 243 | // Header = nome: valore 244 | 245 | // Status Line: 246 | h[0].n = response; 247 | //status_line = h[0].n; 248 | h[0].v = h[0].n; 249 | 250 | primiduepunti = 0; 251 | //Headers 252 | char plain_response[100000]; 253 | int inx_pr = 0; 254 | while(read(s3,&car,1)) 255 | plain_response[inx_pr++] = car; 256 | 257 | 258 | for (i = 0, j = 0; i 1) && (response[i] == '\n') && (response[i - 1] == '\r')) { 261 | primiduepunti = 1; 262 | response[i - 1] = 0; 263 | if (h[j].n[0] == 0) break; 264 | h[++j].n = response + i + 1; 265 | } 266 | if (primiduepunti && (response[i] == ':')) { 267 | h[j].v = response + i + 1; 268 | response[i] = 0; 269 | primiduepunti = 0; 270 | } 271 | } 272 | int read_from_s3 = i; 273 | //Visualizzo a schermo La StatusLine e gli Headers ricevuti 274 | printf("Status Line: %s\n", h[0].n); 275 | //content_length = 0; 276 | char * content_type = 0; 277 | for (i = 1; i < j; i++) { 278 | printf("%s ===> %s\n", h[i].n, h[i].v); 279 | if (strcmp("Content-Type",h[i].n) == 0) 280 | content_type = h[i].v;//strstr(h[i].n,"text") != NULL ; 281 | /* else if (strcmp("Content-Length", h[i].n) == 0) 282 | content_length = atoi(h[i].v); //Atoi:string to integer 283 | else if (strcmp("Transfer-Encoding", h[i].n) == 0 && strcmp(" chunked", h[i].v) == 0) 284 | chunked = 1;*/ 285 | } 286 | printf("print headers finito\n"); 287 | if ( content_type == 0 || strstr(content_type,"text") == NULL){ 288 | printf("Droppo una richiesta in cui il content type non era text ma %s\n",content_type); 289 | close(s2); 290 | close(s3); 291 | continue; 292 | } 293 | printf("inoltro la richiesta, dato ha content type %s\n",content_type); 294 | //inoltro ciò che ho ricevuto fino ad ora 295 | printf("ciò che ho letto fino ad ora: ***"); 296 | // for (i = 0 ; i < inx_pr; i++) printf("%c",*(plain_response+i)); 297 | printf("***\n"); 298 | fflush(stdout); 299 | write(s2,plain_response,inx_pr); 300 | 301 | 302 | //Leggo la risposta dal Server, o quel che ne rimane 303 | /*while(read(s3,&car,1)){ 304 | write(s2,&car,1); //Scrivo al Client quello che leggo dal server 305 | //printf("%c",car); 306 | }*/ 307 | close(s2); 308 | close(s3); 309 | exit(0); 310 | }//Fine fork() 311 | }//Fine while(1) 312 | }//Fine main() 313 | -------------------------------------------------------------------------------- /160620-TCP_reconstruction/np: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nicomazz/ComputerNetworks-unipd2018/ee64f21ccb57208d272c08a81bd8de0d9dd89950/160620-TCP_reconstruction/np -------------------------------------------------------------------------------- /160620-TCP_reconstruction/tcp.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | #include /* See NOTES */ 7 | 8 | #include 9 | #include /* the L2 protocols */ 10 | 11 | #include 12 | #include 13 | struct timeval tcptime, timezero; //??? 14 | struct sockaddr_ll sll; //Indirizzo ethernet mio 15 | unsigned int delta_sec, delta_usec; //??? 16 | int primo; //??? 17 | 18 | unsigned char dstip[4] = {88, 80, 187, 80}; //IP destinazione 19 | unsigned char miomac[6] = {0xf2, 0x3c, 0x91, 0xdb, 0xc2, 0x98}; //ifconfig 20 | unsigned char mioip[4] = {88, 80, 187, 84}; 21 | unsigned char gateway[4] = {88, 80, 187, 1}; //comando linux: route -n 22 | unsigned char netmask[4] = {255, 255, 255, 0}; 23 | unsigned char broadcastmac[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; //MAC con tutti 1, pacchetto indirizzato a tutti 24 | 25 | int progr = 0; //??? 26 | 27 | //Segmento TCP 28 | struct tcp_segment { 29 | unsigned short s_port; 30 | unsigned short d_port; 31 | unsigned int seq; 32 | unsigned int ack; 33 | unsigned char d_offs_res; 34 | unsigned char flags; 35 | unsigned short win; 36 | unsigned short checksum; 37 | unsigned short urgp; 38 | unsigned char payload[1000]; 39 | }; 40 | 41 | // Frame Ethernet 42 | struct eth_frame { 43 | unsigned char dst[6]; 44 | unsigned char src[6]; 45 | unsigned short type; //2byte 46 | char payload[1500]; //ARP o IP 47 | }; 48 | 49 | // Datagramma IP 50 | struct ip_datagram { 51 | unsigned char ver_ihl; 52 | unsigned char tos; 53 | unsigned short totlen; 54 | unsigned short id; 55 | unsigned short flag_offs; 56 | unsigned char ttl; 57 | unsigned char proto; 58 | unsigned short checksum; 59 | unsigned int saddr; 60 | unsigned int daddr; 61 | unsigned char payload[1]; //??? 62 | }; 63 | 64 | //Funzione checksum per pacchetto IP 65 | unsigned short int checksum(char *b, int l) { 66 | unsigned short *p; 67 | 68 | int i; 69 | unsigned short int tot = 0; 70 | unsigned short int prec; 71 | /*Assunzione: l pari */ 72 | p = (unsigned short *)b; 73 | 74 | for (i = 0; i < l / 2; i++) { 75 | prec = tot; 76 | tot += htons(p[i]); 77 | if (tot < prec) tot = tot + 1; 78 | } 79 | return (0xFFFF - tot); 80 | } 81 | 82 | //Port 0-65536 83 | struct tcp_status { 84 | unsigned int forwzero, backzero; 85 | struct timeval timezero; 86 | } st[65536]; 87 | 88 | //Crea pacchetto IP 89 | void creaip(struct ip_datagram *ip, unsigned int dstip, int payload_len, unsigned char proto) { 90 | ip->ver_ihl = 0x45; //primi 4 bit: versione=4, ultimi 4 bit:IHL=5word(32bit*5=20byte) 91 | ip->tos = 0x0; 92 | ip->totlen = htons(payload_len + 20); 93 | ip->id = progr++; //??? 94 | ip->flag_offs = htons(0); 95 | ip->ttl = 64; //Può attraversare massimo 64 router 96 | ip->proto = proto; 97 | ip->checksum = 0; 98 | ip->saddr = *(unsigned int *)mioip; 99 | ip->daddr = dstip; 100 | ip->checksum = htons(checksum((unsigned char *)ip, 20)); 101 | }; 102 | char * ipToText(unsigned int ip){ 103 | struct in_addr ip_addr; 104 | ip_addr.s_addr = ip; 105 | return inet_ntoa(ip_addr); 106 | } 107 | 108 | char forward_buffer[100000]; 109 | char backward_buffer[100000]; 110 | // MAIN 111 | int main(int argc, char **argv) { 112 | unsigned int ackzero, seqzero, forwzero, backzero; //Contatori per 113 | unsigned char buffer[1600]; 114 | unsigned short other_port; // Variabile di supporto per salvare la porta di sorgente/dest 115 | int i, l, s, lunghezza; //??? 116 | 117 | struct eth_frame *eth; //Frame ethernet 118 | struct ip_datagram *ip; // Datagramma IP che contiene anche TCP 119 | struct tcp_segment *tcp; //Segmento TCP 120 | 121 | //Costruisco un frame ethernet con pacchetto IP-TCP all'interno 122 | eth = (struct eth_frame *)buffer; 123 | ip = (struct ip_datagram *)eth->payload; 124 | tcp = (struct tcp_segment *)ip->payload; 125 | 126 | //APRIRE COMUNICAZIONE 127 | /*socket restituisce un INT che è un file descriptor 128 | ovvero l'indice della tabella con tutto ciò che serve per gestire la comunicazione*/ 129 | s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); //AF_INET=IPv4, SOCK_RAW=non elaborato, htons(ETH_P_ALL) 130 | 131 | //Preparo l'indirizzo 132 | lunghezza = sizeof(struct sockaddr_ll); 133 | bzero(&sll, sizeof(struct sockaddr_ll)); 134 | sll.sll_ifindex = 3; 135 | 136 | unsigned short s_p_tg = 0, d_p_tg = 0; 137 | unsigned int saddr = 0, daddr = 0; 138 | char syn_preso = 0; 139 | char syn_ack_preso = 0; 140 | struct timeval first_tcptime; 141 | unsigned int sseq_st = 0; 142 | unsigned int dseq_st = 0; 143 | int max_forward = 0; 144 | int max_backward = 0; 145 | while (1) { 146 | //Ricevo 147 | l = recvfrom(s, buffer, 1600, 0, (struct sockaddr *)&sll, &lunghezza); 148 | 149 | //Inserisco in tcptime quando ho ricevuto il pacchetto 150 | gettimeofday(&tcptime, NULL); 151 | 152 | //Se il frame Ethernet ricevuto contiene un pacchetto IP 153 | if (eth->type == htons(0x0800)){ 154 | 155 | if (ip->proto == 1) 156 | printf("ICMP\n"); 157 | //Se il protocollo all'interno del payload IP è TCP=6 158 | if (ip->proto == 6) { 159 | // if (tcp->d_port == htons(80) && primo){ 160 | // other_port=htons(tcp->s_port); 161 | // timezero=tcptime; 162 | // primo=0; 163 | // } 164 | 165 | //Se hanno come sorgente o destinazione il port80 166 | if ((tcp->s_port != htons(80)) && (tcp->d_port != htons(80))) continue; 167 | //Se la portSorgente=80 in other_port inserisco la portDestinazione sennò il contrario 168 | // other_port = (tcp->s_port == htons(80)) ? htons(tcp->d_port) : htons(tcp->s_port); 169 | 170 | //risposta al primo pacchetto (syn e ack a 1) 171 | if (syn_preso && !syn_ack_preso && tcp->flags & 0x12){ 172 | dseq_st = ntohl(tcp->seq); 173 | syn_ack_preso = 1; 174 | } 175 | //Se il SYN è a 1, e ack a 0 (il primo davvero) 176 | else if (!syn_ack_preso && !syn_preso && tcp->flags & 0x02 && !(tcp->flags & 0x10)) { 177 | s_p_tg = tcp->s_port; 178 | d_p_tg = tcp->d_port; 179 | saddr = ip->saddr; 180 | daddr = ip->daddr; 181 | first_tcptime = tcptime; 182 | sseq_st = ntohl(tcp->seq); 183 | char sa[20]; char * c = ipToText(saddr); strcpy(sa,c); 184 | char da[20]; c = ipToText(daddr); strcpy(da,c); 185 | printf("intercettata una connessione tra %s e %s su porte %d->%d\n",sa,da, ntohs(s_p_tg),ntohs(d_p_tg)); 186 | syn_preso = 1; 187 | } 188 | char type = 0; 189 | #define FORWARD 1 190 | #define BACKWARD 2 191 | if ( tcp->s_port == s_p_tg && tcp->d_port == d_p_tg && 192 | ip-> saddr == saddr && ip->daddr == daddr)type = FORWARD; 193 | else if (tcp->s_port == d_p_tg && tcp->d_port == s_p_tg && 194 | ip->saddr == daddr && ip->daddr == saddr) type = BACKWARD; 195 | 196 | if (!type) { 197 | // printf("intercettato pacchetto di un'altra connessione, skippo\n"); 198 | continue; 199 | } 200 | 201 | if (tcp->flags & 0x01){// chiusura connessione 202 | printf("Connessione in chiusura. Buffer 1:\n\n"); 203 | for (int i = 0; i < max_forward;i++) printf("%c",forward_buffer[i]); 204 | printf("\n\n buffer 2:\n"); 205 | for (int i = 0; i < max_backward;i++) printf("%c",backward_buffer[i]); 206 | return 0; 207 | } 208 | seqzero = (type == FORWARD) ? sseq_st:dseq_st; 209 | ackzero = (type == FORWARD) ? dseq_st:sseq_st; 210 | //Vedo la differenza in secondi tra il tempo 0(primo pacchetto) e tempo attuale 211 | delta_sec = tcptime.tv_sec - first_tcptime.tv_sec; 212 | 213 | //Differenza microsecondi 214 | if (tcptime.tv_usec < first_tcptime.tv_usec) { 215 | delta_sec--; 216 | delta_usec = 1000000 + tcptime.tv_usec - first_tcptime.tv_usec; 217 | } else 218 | delta_usec = tcptime.tv_usec - first_tcptime.tv_usec; 219 | 220 | printf("%d->%d seq: %u ack: %u %.6d\n",ntohs(tcp->s_port),ntohs(tcp->d_port), ntohl(tcp->seq)-seqzero, ntohl(tcp->ack)-ackzero,delta_usec); 221 | 222 | int ip_header_size = (4 * (ip->ver_ihl & 0x0F)); 223 | int tcp_header_size = ((tcp->d_offs_res & 0xF0) >> 2); 224 | 225 | int tcp_data_size = ntohs(ip->totlen) - ip_header_size - tcp_header_size; 226 | //printf("tcp data size: %d\n",tcp_data_size); 227 | 228 | int offset = ntohl(tcp->seq)-seqzero; 229 | char * dest = type == FORWARD ? forward_buffer : backward_buffer; 230 | memcpy(dest+offset,tcp->payload,tcp_data_size); 231 | if (type == FORWARD) max_forward = offset+tcp_data_size; 232 | else max_backward = offset+tcp_data_size; 233 | // for (int i = 0; i < tcp_data_size; i++) 234 | // printf("%c",tcp->payload[i]); 235 | // printf("\n"); 236 | //Per ogni pacchetto stampo una riga che dice i dati, stma della banda,... 237 | //printf("%.4d.%.6d %.5d->%.5d %.2x %.10u %.10u %.5u %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)); 238 | 239 | } 240 | } 241 | } //Fine while 242 | 243 | } //Fine main 244 | -------------------------------------------------------------------------------- /160620-V2_TCP_reconstruction/np: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nicomazz/ComputerNetworks-unipd2018/ee64f21ccb57208d272c08a81bd8de0d9dd89950/160620-V2_TCP_reconstruction/np -------------------------------------------------------------------------------- /160620-V2_TCP_reconstruction/tcp.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | #include /* See NOTES */ 8 | 9 | #include 10 | #include /* the L2 protocols */ 11 | 12 | #include 13 | 14 | struct timeval tcptime, timezero; //??? 15 | struct sockaddr_ll sll; //Indirizzo ethernet mio 16 | unsigned int delta_sec, delta_usec; //??? 17 | int primo; //??? 18 | 19 | unsigned char dstip[4] = {88, 80, 187, 80}; //IP destinazione 20 | unsigned char miomac[6] = {0xf2, 0x3c, 0x91, 0xdb, 0xc2, 0x98}; //ifconfig 21 | unsigned char mioip[4] = {88, 80, 187, 84}; 22 | unsigned char gateway[4] = {88, 80, 187, 1}; //comando linux: route -n 23 | unsigned char netmask[4] = {255, 255, 255, 0}; 24 | unsigned char broadcastmac[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; //MAC con tutti 1, pacchetto indirizzato a tutti 25 | 26 | int progr = 0; //??? 27 | 28 | //Segmento TCP 29 | struct tcp_segment { 30 | unsigned short s_port; 31 | unsigned short d_port; 32 | unsigned int seq; 33 | unsigned int ack; 34 | unsigned char d_offs_res; 35 | unsigned char flags; 36 | unsigned short win; 37 | unsigned short checksum; 38 | unsigned short urgp; 39 | unsigned char payload[1000]; 40 | }; 41 | 42 | // Frame Ethernet 43 | struct eth_frame { 44 | unsigned char dst[6]; 45 | unsigned char src[6]; 46 | unsigned short type; //2byte 47 | char payload[1500]; //ARP o IP 48 | }; 49 | 50 | // Datagramma IP 51 | struct ip_datagram { 52 | unsigned char ver_ihl; 53 | unsigned char tos; 54 | unsigned short totlen; 55 | unsigned short id; 56 | unsigned short flag_offs; 57 | unsigned char ttl; 58 | unsigned char proto; 59 | unsigned short checksum; 60 | unsigned int saddr; 61 | unsigned int daddr; 62 | unsigned char payload[1]; //??? 63 | }; 64 | 65 | //Funzione checksum per pacchetto IP 66 | unsigned short int checksum(char *b, int l) { 67 | unsigned short *p; 68 | 69 | int i; 70 | unsigned short int tot = 0; 71 | unsigned short int prec; 72 | /*Assunzione: l pari */ 73 | p = (unsigned short *)b; 74 | 75 | for (i = 0; i < l / 2; i++) { 76 | prec = tot; 77 | tot += htons(p[i]); 78 | if (tot < prec) tot = tot + 1; 79 | } 80 | return (0xFFFF - tot); 81 | } 82 | 83 | //Port 0-65536 84 | struct tcp_status { 85 | unsigned int forwzero, backzero; 86 | struct timeval timezero; 87 | } st[65536]; 88 | 89 | //Crea pacchetto IP 90 | void creaip(struct ip_datagram *ip, unsigned int dstip, int payload_len, unsigned char proto) { 91 | ip->ver_ihl = 0x45; //primi 4 bit: versione=4, ultimi 4 bit:IHL=5word(32bit*5=20byte) 92 | ip->tos = 0x0; 93 | ip->totlen = htons(payload_len + 20); 94 | ip->id = progr++; //??? 95 | ip->flag_offs = htons(0); 96 | ip->ttl = 64; //Può attraversare massimo 64 router 97 | ip->proto = proto; 98 | ip->checksum = 0; 99 | ip->saddr = *(unsigned int *)mioip; 100 | ip->daddr = dstip; 101 | ip->checksum = htons(checksum((unsigned char *)ip, 20)); 102 | }; 103 | 104 | // MAIN 105 | int main(int argc, char **argv) { 106 | unsigned int ackzero, seqzero, forwzero, backzero; //Contatori per 107 | unsigned char buffer[1600]; 108 | unsigned char buffer_1[100000]; 109 | unsigned char buffer_2[100000]; 110 | int len_1 = 0, len_2 = 0; 111 | unsigned short other_port; // Variabile di supporto per salvare la porta di sorgente/dest 112 | int i, l, s, lunghezza; //??? 113 | 114 | struct eth_frame *eth; //Frame ethernet 115 | struct ip_datagram *ip; // Datagramma IP che contiene anche TCP 116 | struct tcp_segment *tcp; //Segmento TCP 117 | 118 | //Costruisco un frame ethernet con pacchetto IP-TCP all'interno 119 | eth = (struct eth_frame *)buffer; 120 | ip = (struct ip_datagram *)eth->payload; 121 | tcp = (struct tcp_segment *)ip->payload; 122 | 123 | //APRIRE COMUNICAZIONE 124 | /*socket restituisce un INT che è un file descriptor 125 | ovvero l'indice della tabella con tutto ciò che serve per gestire la comunicazione*/ 126 | s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); //AF_INET=IPv4, SOCK_RAW=non elaborato, htons(ETH_P_ALL) 127 | 128 | //Preparo l'indirizzo 129 | lunghezza = sizeof(struct sockaddr_ll); 130 | bzero(&sll, sizeof(struct sockaddr_ll)); 131 | sll.sll_ifindex = 3; 132 | 133 | primo = 1; 134 | while (1) { 135 | //Ricevo 136 | l = recvfrom(s, buffer, 1600, 0, (struct sockaddr *)&sll, &lunghezza); 137 | 138 | //Inserisco in tcptime quando ho ricevuto il pacchetto 139 | gettimeofday(&tcptime, NULL); 140 | 141 | //Se il frame Ethernet ricevuto contiene un pacchetto IP 142 | if (eth->type == htons(0x0800)){ 143 | 144 | if (ip->proto == 1) 145 | printf("ICMP\n"); 146 | //Se il protocollo all'interno del payload IP è TCP=6 147 | if (ip->proto == 6) { 148 | 149 | if (tcp->d_port == htons(80) && primo){ 150 | other_port=htons(tcp->s_port); 151 | timezero=tcptime; 152 | struct in_addr ip_addr; 153 | ip_addr.s_addr = ip->saddr; 154 | printf("The IP address is %s\n", inet_ntoa(ip_addr));; 155 | } 156 | 157 | //Se hanno come sorgente o destinazione il port80 158 | if ((tcp->s_port == htons(80)) || (tcp->d_port == htons(80))) { 159 | //Se la portSorgente=80 in other_port inserisco la portDestinazione sennò il contrario 160 | unsigned short other_p = (tcp->s_port == htons(80)) ? htons(tcp->d_port) : htons(tcp->s_port); 161 | if (other_p != other_port) continue; // not the first connection 162 | 163 | //Se il SYN è a 1 164 | if (tcp->flags & 0x02) { 165 | st[other_port].timezero = tcptime; //Salvo quando ho visto pasare il primo SYN 166 | //Salvo il contatore dei byte del segmento in base alla direzione (entrata/uscita) 167 | if (tcp->d_port == htons(80)) st[other_port].forwzero = htonl(tcp->seq); 168 | if (tcp->s_port == htons(80)) st[other_port].backzero = htonl(tcp->seq); 169 | } 170 | //Se la portDestinazine=80 in seqzero inserisco forwzero dell'altra porta altrimenti backzero 171 | seqzero = (tcp->d_port == htons(80)) ? st[other_port].forwzero : st[other_port].backzero; 172 | //Se la portSorgente=80 in ackzero inserisco forwzero dell'altra porta altrimenti backzero 173 | ackzero = (tcp->s_port == htons(80)) ? st[other_port].forwzero : st[other_port].backzero; 174 | 175 | int offset = ntohl(tcp->seq) - seqzero; 176 | int ip_header_size = (ip->ver_ihl & 0x4) * 4; 177 | int tcp_header_size = (tcp->d_offs_res >> 4) * 4; 178 | unsigned char* data_start = (unsigned char *)tcp + tcp_header_size; 179 | unsigned char* target_buffer = (tcp->d_port == htons(80)) ? buffer_1 : buffer_2; 180 | size_t data_len = ntohs(ip->totlen) - tcp_header_size - ip_header_size; 181 | printf("offset:%d, data len: %d, tcp_header: %d, ip_ header: %d\n",offset, data_len, tcp_header_size,ip_header_size); 182 | memcpy(target_buffer+offset,data_start,data_len); 183 | if (tcp->d_port == htons(80)) { 184 | if (offset+data_len > len_1) len_1 = offset+data_len; 185 | } else if (offset+data_len > len_2) len_2 = offset+data_len; 186 | 187 | 188 | //Vedo la differenza in secondi tra il tempo 0(primo pacchetto) e tempo attuale 189 | delta_sec = tcptime.tv_sec - st[other_port].timezero.tv_sec; 190 | 191 | //Differenza microsecondi 192 | if (tcptime.tv_usec < st[other_port].timezero.tv_usec) { 193 | delta_sec--; 194 | delta_usec = 1000000 + tcptime.tv_usec - st[other_port].timezero.tv_usec; 195 | } else 196 | delta_usec = tcptime.tv_usec - st[other_port].timezero.tv_usec; 197 | 198 | 199 | printf("%.5d->%.5d %.2x seq: %.10u ack: %.10u %4.2f\n", 200 | htons(tcp->s_port), 201 | htons(tcp->d_port), 202 | tcp->flags, 203 | htonl(tcp->seq) - seqzero, 204 | htonl(tcp->ack) - ackzero, 205 | (htonl(tcp->ack) - ackzero) / (double)(delta_sec * 1000000 + delta_usec)); 206 | 207 | if (tcp->flags & 0x01){ // FIN a 1 208 | printf("connessione terminata!\ncontenuto buffer 1:\n---\n"); 209 | for (int i = 0; i < len_1; i++) 210 | printf("%c", buffer_1[i]); 211 | printf("\n---\n\ncontenuto buffer 2:\n---\n"); 212 | for (int i = 0; i < len_2; i++) 213 | printf("%c", buffer_2[i]); 214 | printf("\n"); 215 | return 0; 216 | } 217 | } 218 | } 219 | } 220 | } //Fine while 221 | 222 | } //Fine main 223 | -------------------------------------------------------------------------------- /160620-V3_TCP_reconstruction/tcp.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include /* the L2 protocols */ 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include /* See NOTES */ 9 | 10 | struct eth_frame { 11 | unsigned char dst[6]; 12 | unsigned char src[6]; 13 | unsigned short type; 14 | char payload[1500]; 15 | }; 16 | 17 | struct ip_datagram { 18 | unsigned char ver_ihl; 19 | unsigned char tos; 20 | unsigned short totlen; 21 | unsigned short id; 22 | unsigned short flag_offs; 23 | unsigned char ttl; 24 | unsigned char proto; 25 | unsigned short checksum; 26 | unsigned int saddr; 27 | unsigned int daddr; 28 | unsigned char payload[1]; 29 | }; 30 | 31 | struct tcp_segment { 32 | unsigned short s_port; 33 | unsigned short d_port; 34 | unsigned int seq; 35 | unsigned int ack; 36 | unsigned char d_offs_res; 37 | unsigned char flags; 38 | unsigned short win; 39 | unsigned short checksum; 40 | unsigned short urgp; 41 | unsigned char payload[1000]; 42 | }; 43 | 44 | struct tcp_status { 45 | unsigned int forwzero; 46 | unsigned int backzero; 47 | struct timeval timezero; 48 | } st[65536]; 49 | 50 | struct sockaddr_ll sll; 51 | 52 | char forw_buffer[10000]; 53 | int forw_size; 54 | char back_buffer[10000]; 55 | int back_size; 56 | 57 | int main() { 58 | unsigned int ackzero, seqzero, forwzero, backzero; 59 | unsigned char buffer[1600]; 60 | unsigned short other_port; 61 | int i, l, s, lunghezza; 62 | 63 | struct eth_frame *eth; 64 | struct ip_datagram *ip; 65 | struct tcp_segment *tcp; 66 | eth = (struct eth_frame *)buffer; 67 | ip = (struct ip_datagram *)eth->payload; 68 | tcp = (struct tcp_segment *)ip->payload; 69 | 70 | s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); 71 | lunghezza = sizeof(struct sockaddr_ll); 72 | 73 | bzero(&sll, sizeof(struct sockaddr_ll)); 74 | sll.sll_ifindex = 3; 75 | 76 | int first_connection_port = 0; 77 | 78 | while (1) { 79 | l = recvfrom(s, buffer, 1600, 0, (struct sockaddr *)&sll, &lunghezza); 80 | 81 | if (eth->type == htons(0x0800) // IP? 82 | && ip->proto == 6 // TCP? 83 | && (tcp->s_port == htons(80) || tcp->d_port == htons(80)) // HTTP traffic? 84 | ) { 85 | other_port = (tcp->s_port == htons(80)) ? htons(tcp->d_port) : htons(tcp->s_port); 86 | 87 | if (!first_connection_port) { 88 | first_connection_port = other_port; 89 | } 90 | 91 | // skip packet if it doesn't belong to this connection 92 | if (other_port != first_connection_port) 93 | continue; 94 | 95 | // sync start of communication 96 | if (tcp->flags & 0x02) { 97 | if (tcp->d_port == htons(80)) { 98 | st[other_port].forwzero = htonl(tcp->seq); 99 | printf("SYN: %hu\n", tcp->seq); 100 | } 101 | 102 | if (tcp->s_port == htons(80)) { 103 | st[other_port].backzero = htonl(tcp->seq); 104 | printf("ACK: %hu\n", tcp->ack); 105 | } 106 | } 107 | 108 | // get starting SEQ, ACK 109 | seqzero = (tcp->d_port == htons(80)) ? st[other_port].forwzero : st[other_port].backzero; 110 | ackzero = (tcp->s_port == htons(80)) ? st[other_port].forwzero : st[other_port].backzero; 111 | unsigned int curr_seq = htonl(tcp->seq); 112 | 113 | unsigned short totlen = ntohs(ip->totlen); 114 | unsigned short ip_header_size = (ip->ver_ihl & 0x0F) * 4; 115 | unsigned short tcp_header_size = (tcp->d_offs_res >> 4) * 4; // logic shift right 116 | 117 | unsigned short payload_size = totlen - ip_header_size - tcp_header_size; 118 | 119 | // copy data to buffer and update tot buffer size 120 | if (tcp->d_port == htons(80)) { 121 | for (i = 0; i < payload_size; i++) 122 | forw_buffer[curr_seq - seqzero + i] = tcp->payload[i]; 123 | 124 | if ((curr_seq - seqzero + payload_size) > forw_size) 125 | forw_size = curr_seq - seqzero + payload_size; 126 | 127 | } else { 128 | for (i = 0; i < payload_size; i++) 129 | back_buffer[curr_seq - seqzero + i] = tcp->payload[i]; 130 | 131 | if ((curr_seq - seqzero + payload_size) > back_size) 132 | back_size = curr_seq - seqzero + payload_size; 133 | } 134 | 135 | // handle end of communication 136 | if (tcp->flags & 0x1) { 137 | printf("=============Forwarded data ============= \n\n"); 138 | for (i = 0; i < forw_size; i++) 139 | printf("%c", forw_buffer[i]); 140 | 141 | printf("\n\n==============Received data===========\n\n"); 142 | for (i = 0; i < back_size; i++) 143 | printf("%c", back_buffer[i]); 144 | 145 | return 0; 146 | } 147 | } 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /160620-chunked/Makefile: -------------------------------------------------------------------------------- 1 | np : ws18.c 2 | gcc -o np ws18.c 3 | -------------------------------------------------------------------------------- /160620-chunked/filetemp: -------------------------------------------------------------------------------- 1 | I Don't know html 2 | -------------------------------------------------------------------------------- /160620-chunked/index.html: -------------------------------------------------------------------------------- 1 | I Don't know html 2 | -------------------------------------------------------------------------------- /160620-chunked/np: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nicomazz/ComputerNetworks-unipd2018/ee64f21ccb57208d272c08a81bd8de0d9dd89950/160620-chunked/np -------------------------------------------------------------------------------- /160620-chunked/ws18.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include /* superset of previous */ 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | int lunghezza; //Lunghezza indirizzo per accept() 11 | int yes = 1; //Flag utilizzato per settare un opzione del socket 12 | 13 | //Struttura singono header (nome, valore) 14 | struct header { 15 | char *n; 16 | char *v; 17 | }; 18 | struct header h[100]; //Header (array di strutture) 19 | 20 | // Indirizzo IPv4 21 | struct sockaddr_in indirizzo; 22 | struct sockaddr_in indirizzo_remoto; 23 | 24 | int primiduepunti; // Flag usato per leggere gli headers 25 | char request[10000]; 26 | char response[10000]; 27 | char chunk_buffer[10000]; 28 | char *request_line; //Puntatore alla request line 29 | char *method, *uri, *http_ver; //Puntatori che indicano i parametri della RequestLine 30 | 31 | int c; //Carattere utilizato per leggere ogni carattere del file 32 | FILE *fin; //File che dovrà essere trasmesso 33 | 34 | void send_chunk(int socket, unsigned char * c, int len); 35 | int main() { 36 | int s, s2, t, j, i; //s:socket per ricevere, t:variabile di supporto per gli errori 37 | char command[1000]; //Stringa che contiene il comando di shell eseguire 38 | 39 | //APRIRE COMUNICAZIONE 40 | /*socket restituisce un INT che è un file descriptor 41 | ovvero l'indice della tabella con tutto ciò che serve per gestire la comunicazione*/ 42 | s = socket(AF_INET, SOCK_STREAM, 0); //AF_INET=IPv4, SOCK_STREAM:apre uno stream, protocol:0 (default) 43 | if (s == -1) { 44 | perror("Socket Fallita"); 45 | return 1; 46 | } 47 | /* Opzioni del socket: opzioni a levello socket(SOL_SOCKET), 48 | riutilizzo degli indirizi(SO_REUSEADDR), 49 | 1(si), 50 | sizeof(int) 51 | ritorna 0 se tutto va bene, altrimenti -1*/ 52 | if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) { 53 | perror("setsockopt"); 54 | return 1; 55 | } 56 | 57 | //CONNESSIONE 58 | indirizzo.sin_family = AF_INET; //IPv4 59 | indirizzo.sin_port = htons(7888); //Porta 60 | indirizzo.sin_addr.s_addr = 0; 61 | 62 | // Bind assegna un indirizzo al socket, t=0 se tutto va bene altrimenti -1 63 | t = bind(s, (struct sockaddr *)&indirizzo, sizeof(struct sockaddr_in)); 64 | if (t == -1) { 65 | perror("Bind fallita"); 66 | return 1; 67 | } 68 | 69 | //Listen: marca il socket s come passivo, ovvero che deve ricevere 70 | t = listen(s, 10); 71 | if (t == -1) { 72 | perror("Listen Fallita"); 73 | return 1; 74 | } 75 | 76 | while (1) { 77 | lunghezza = sizeof(struct sockaddr_in); 78 | 79 | //Accept: restituisce il file descriptor di un nuovo socket che 80 | // eredita tutto da quello vecchio ma è già connesso, 81 | // pronto per il read e write. Questo perchè l'altro è impegnato con listen. 82 | s2 = accept(s, (struct sockaddr *)&indirizzo_remoto, &lunghezza); 83 | if (s2 == -1) { 84 | perror("Accept Fallita"); 85 | return 1; 86 | } 87 | 88 | //RICEVO RICHIESTA 89 | /*Full-Request = Request-Line 90 | *( General-Header 91 | | Request-Header 92 | | Entity-Header ) 93 | CRLF 94 | [ Entity-Body ] */ 95 | // Request-Line = Method SP Request-URI SP HTTP-Version CRLF (con CRLF=\r\n) 96 | // Header = nome: valore 97 | 98 | //Requst Line: 99 | h[0].n = request; 100 | request_line = h[0].n; 101 | h[0].v = h[0].n; 102 | 103 | //Headers: 104 | for (i = 0, j = 0; (t = read(s2, request + i, 1)) > 0; i++) { 105 | if ((i > 1) && (request[i] == '\n') && (request[i - 1] == '\r')) { 106 | primiduepunti = 1; 107 | request[i - 1] = 0; 108 | if (h[j].n[0] == 0) break; 109 | h[++j].n = request + i + 1; 110 | } 111 | if (primiduepunti && (request[i] == ':')) { 112 | h[j].v = request + i + 1; 113 | request[i] = 0; 114 | primiduepunti = 0; 115 | } 116 | } 117 | if (t == -1) { 118 | perror("Read Fallita"); 119 | return 1; 120 | } 121 | 122 | // Visualizzo a schermo la RequestLine e gli Headers ricevuti 123 | printf("Request Line: %s\n", request_line); 124 | for (i = 1; i < j; i++) { 125 | printf("%s ===> %s\n", h[i].n, h[i].v); 126 | } 127 | 128 | // Ricavo Method, URI e HTTP-Version dalla RequestLine 129 | method = request_line; 130 | for (i = 0; request_line[i] != ' ' && request_line[i]; i++) { 131 | }; 132 | if (request_line[i] != 0) { 133 | request_line[i] = 0; 134 | i++; 135 | } 136 | uri = request_line + i; 137 | for (; request_line[i] != ' ' && request_line[i]; i++) { 138 | }; 139 | if (request_line[i] != 0) { 140 | request_line[i] = 0; 141 | i++; 142 | } 143 | http_ver = request_line + i; 144 | 145 | //Visualizzo a schermo Method, URI e HTTP-Version 146 | printf("Method = %s, URI = %s, Http-Version = %s\n", method, uri, http_ver); 147 | 148 | //Se l'URI è "/exec/" 149 | if (!strncmp(uri, "/exec/", 6)) { //confronto i primi 6 caratteri 150 | sprintf(command, "%s > filetemp\n", uri + 6); //Metto in "filetemp" il file richiesto dall'URI 151 | printf("Eseguo il comando %s", command); 152 | if ((t = system(command)) == 0) { //Eseguo il comando 153 | uri = "/filetemp"; 154 | } else 155 | printf("system ha restituito %d\n", t); 156 | } 157 | 158 | if ((fin = fopen(uri + 1, "rt")) == NULL) { // Se non riesco ad aprire il file invio "FIle non trovato" 159 | printf("File %s non aperto\n", uri + 1); 160 | sprintf(response, "HTTP/1.1 404 File not found\r\n\r\nFile non trovato"); 161 | t = write(s2, response, strlen(response)); 162 | if (t == -1) { 163 | perror("write fallita"); 164 | return -1; 165 | } 166 | } else { //Altrimenti invio il file 167 | printf("File aperto, ora invio!\n"); 168 | sprintf(response, "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nTransfer-Encoding: chunked\r\n\r\n"); 169 | t = write(s2, response, strlen(response)); 170 | const int CHUNKS_SIZE = 10; 171 | unsigned char att_buff[CHUNKS_SIZE]; 172 | int taken = 0; 173 | while ((c = fgetc(fin)) != EOF) { //fgetc ritorna il carattere sucessivo 174 | att_buff[taken++] = c; 175 | if (taken == CHUNKS_SIZE){ 176 | send_chunk(s2,att_buff,taken); 177 | taken = 0; 178 | } 179 | } 180 | if (taken != 0){ 181 | send_chunk(s2,att_buff,taken); 182 | taken = 0; 183 | } 184 | //last-chunk 185 | send_chunk(s2,att_buff,0); 186 | 187 | fclose(fin); 188 | } 189 | close(s2); //Chiudo il socket che risponde 190 | } //Fine while 191 | } //Fine main 192 | 193 | void stampabytes(unsigned char * buffer, int quanti){ 194 | int i; 195 | for(i=0;i 2 | #include 3 | #include /* See NOTES */ 4 | #include 5 | #include 6 | #include 7 | #include /* the L2 protocols */ 8 | #include 9 | #include 10 | 11 | 12 | unsigned char broadcast[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};//MAC con tutti 1, pacchetto indirizzato a tutti 13 | unsigned char mymac[6]={0xf2,0x3c,0x91,0xdb,0xc2,0x98}; //ifconfig 14 | unsigned char myip[4]={88,80,187,84}; 15 | unsigned char gateway[4]={88,80,187,1};//comando linux: route -n 16 | unsigned int netmask = 0x00FFFFFF; 17 | 18 | // Frame Ethernet 19 | struct eth_frame { 20 | unsigned char dst[6]; 21 | unsigned char src[6]; 22 | unsigned short type; //2byte 23 | char payload[1500]; //ARP o IP 24 | }; 25 | 26 | //Pacchetto ICMP ECHO 27 | struct icmp_packet{ 28 | unsigned char type; 29 | unsigned char code; 30 | unsigned short checksum; 31 | unsigned short id; 32 | unsigned short seq; 33 | char payload[128]; //Dati 34 | }; 35 | 36 | // Datagramma IP 37 | struct ip_datagram{ 38 | unsigned char ver_ihl; 39 | unsigned char tos; 40 | unsigned short totlen; 41 | unsigned short id; 42 | unsigned short flags_offs; 43 | unsigned char ttl; 44 | unsigned char protocol; 45 | unsigned short checksum; 46 | unsigned int src; 47 | unsigned int dst; 48 | unsigned char payload[1500];//ICMP o solo dati 49 | }; 50 | 51 | // Pacchetto ARP 52 | struct arp_packet{ 53 | unsigned short htype;//HardwareType: Ethernet=1 54 | unsigned short ptype;//ProtocolType IPv4=0x0800 55 | unsigned char hlen; //LunghezzaIndirizzoHardware = 6 byte 56 | unsigned char plen; //LunghezzaIndirizzoProtocol = 4 byte 57 | unsigned short opcode;//Operazione: 1=Richiesta, 2=Risposta 58 | unsigned char hsrc[6];//IndirizzoHardware di chi ha fatto la richiesta 59 | unsigned char psrc[4];//IndirizzoIP di chi ha fatto la richiesta 60 | unsigned char hdst[6];//IndirizzoHardware del destinatario della richiesta(in una richiesta è nullo) 61 | unsigned char pdst[4];//IndirizzoIP del destinatario della richiesta 62 | }; 63 | 64 | //Segmento TCP 65 | struct tcp_segment { 66 | unsigned short s_port; 67 | unsigned short d_port; 68 | unsigned int seq; 69 | unsigned int ack; 70 | unsigned char d_offs_res; 71 | unsigned char flags; 72 | unsigned short win; 73 | unsigned short checksum; 74 | unsigned short urgp; 75 | unsigned char payload[1000]; 76 | }; 77 | 78 | 79 | 80 | //Prototipi di funzioni 81 | void crea_eth(struct eth_frame *e, unsigned char * src, unsigned char*dst,unsigned short type); 82 | void crea_arp(struct arp_packet* a,unsigned char *mymac,unsigned char *myip,unsigned char *dstip); 83 | void crea_ip( struct ip_datagram* ip, int payloadlen,unsigned char payloadtype,unsigned int ipdest ); 84 | int crea_icmp_unreachable(struct icmp_packet * icmp, struct ip_datagram * ip,int tot_dimension); 85 | unsigned short checksum(unsigned char *buffer,int len); 86 | void stampabytes(unsigned char * buffer, int quanti); 87 | int trovamac(unsigned char *mac_incognito, unsigned char*dstip); 88 | 89 | void crea_icmp_reply(struct icmp_packet * icmp,int size); 90 | 91 | unsigned char old_ip_buffer[1500]; //to save ip headers 92 | 93 | int main(){ 94 | struct sockaddr_ll sll; //Indirizzo ethernet mio 95 | unsigned char mac_incognito[6]; 96 | unsigned char buffer[1500]; //Conterrà i pacchetti di inviare 97 | unsigned char * nexthop; //prossimo router 98 | struct eth_frame * eth; //Pacchetto ethernet che contiene anche ARP 99 | struct ip_datagram * ip;// Datagramma IP che contiene anche ICMP 100 | struct icmp_packet * icmp;// pachetto ICMP 101 | struct tcp_segment * tcp; 102 | //unsigned char targetip[4]={88,80,187,2}; 103 | unsigned char targetip[4]={147,162,2,100};//Padova 104 | int m,i,s,len,t; //Variabili di supporto 105 | 106 | //APRIRE COMUNICAZIONE 107 | /*socket restituisce un INT che è un file descriptor 108 | ovvero l'indice della tabella con tutto ciò che serve per gestire la comunicazione*/ 109 | s = socket(AF_PACKET, SOCK_RAW,htons(ETH_P_ALL));//AF_INET=IPv4, SOCK_RAW=non elaborato, htons(ETH_P_ALL) 110 | 111 | //Se l'host è nella mia stessa sotto rete tengo il suo IP per cercalre l'indirizzo ethernet 112 | //altrimenti uso l'indirizzo del mio gateway. 113 | if ((*((unsigned int *)targetip)&netmask) == (*((unsigned int*)myip)&netmask)) 114 | nexthop = targetip; 115 | else nexthop = gateway; 116 | 117 | //Trovo l'indirizzo mac di destinazione avendo l'IP 118 | if(!trovamac(mac_incognito,nexthop)){ 119 | printf("MAC incognito:"); 120 | //stampabytes(mac_incognito,6); 121 | } 122 | else printf("trovamac fallita\n"); 123 | 124 | //Costruisco un frame ethernet con pacchetto IP-ICMP all'interno 125 | eth = (struct eth_frame *) buffer; 126 | ip = (struct ip_datagram *) eth->payload; 127 | icmp = (struct icmp_packet*) ip->payload; 128 | tcp = (struct tcp_segment*) ip->payload; 129 | 130 | 131 | //Ricevo la risposta 132 | for(m=0;m<1000;m++){ 133 | t = recvfrom(s, buffer, 1500, 0, (struct sockaddr *) &sll, &len); 134 | if (t == -1 ){ 135 | perror("recvfrom fallita"); 136 | return 1; 137 | } 138 | 139 | //Se il frame Ethernet ricevuto contiene un pacchetto IP 140 | if (eth->type == htons(0x0800) && 141 | ip->protocol == 6 && ntohs(tcp->d_port) == 19599){ // tcp 142 | printf("tcp trovato!\n"); 143 | unsigned int source_ip = ip->src; 144 | //Se il protocollo all'interno del payload IP è ICMP=1 145 | 146 | //Se il tipo di ICMP è 0: Echo message (request to get a reply) 147 | //Se l'host è nella mia stessa sotto rete tengo il suo IP per cercalre l'indirizzo ethernet 148 | //altrimenti uso l'indirizzo del mio gateway. 149 | // TODO AGGIUNGERE PARTE DEL CHECK STESSA RETE (ANCHE SE ALLA FINE IL GATEWAY PUO GESTIRE TUTTO 150 | nexthop = gateway; 151 | 152 | //Trovo l'indirizzo mac di destinazione avendo l'IP 153 | if(!trovamac(mac_incognito,nexthop)){ 154 | printf("MAC incognito:"); 155 | // stampabytes(mac_incognito,6); 156 | } 157 | else printf("trovamac fallita\n"); 158 | 159 | //Costruisco un frame ethernet con pacchetto IP-ICMP all'interno 160 | eth = (struct eth_frame *) buffer;//14 bytes 161 | ip = (struct ip_datagram *) eth->payload; // 20 bytes 162 | icmp = (struct icmp_packet*) ip->payload; 163 | 164 | 165 | int ip_header_len = (ip->ver_ihl & 0x0F) *8; 166 | int icmp_dimension = 8 + //base 167 | ip_header_len + //ip header_dim 168 | 8; //original data datagram ; 169 | 170 | memcpy(old_ip_buffer,ip,icmp_dimension-8); 171 | crea_eth(eth,mymac,mac_incognito,0x0800); 172 | crea_ip(ip,icmp_dimension,1,source_ip); 173 | crea_icmp_unreachable(icmp,ip, icmp_dimension); 174 | 175 | //Visualizzo a schermo il pacchetto creato 176 | printf("\nPacchetto ETH+IP+ICMP da inviare:"); 177 | //stampabytes(buffer,14+20+icmp_dimension);//+14 header ethernet, +20 IP +28 ICMP(8+20 di payload) 178 | 179 | //Preparo l'indirizzo 180 | bzero(&sll,sizeof(struct sockaddr_ll));//Metto tutto a 0 181 | sll.sll_ifindex = if_nametoindex("eth0"); 182 | printf("ifindex = %d\n",sll.sll_ifindex); 183 | len = sizeof(sll); 184 | 185 | //Invio il pacchetto ethernet che contiene IP 186 | t = sendto(s, buffer, 14+20+icmp_dimension, 0, (struct sockaddr *) &sll, len); 187 | if (t == -1 ){ 188 | perror("sendto fallita"); 189 | return 1; 190 | } 191 | 192 | } 193 | 194 | }//Fine for 195 | 196 | }//Fine main 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | //Invia un Pacchetto Ethernet con dentro il pacchetto ARP e ricevo in risposta il MAC del destinatario 205 | //Ritorna 0 se tutto ok altrimenti 1. 206 | int trovamac(unsigned char *mac_incognito, unsigned char*dstip){ 207 | struct sockaddr_ll sll;//Struttura indirizzo per il sendto 208 | int len,i,t,m,s; 209 | char ifname[50]; 210 | unsigned char buffer[1500]; 211 | struct arp_packet * arp; 212 | struct eth_frame * eth; 213 | eth = (struct eth_frame *) buffer; 214 | arp = (struct arp_packet *) eth->payload; 215 | crea_eth(eth,mymac,broadcast,0x0806); 216 | crea_arp(arp,mymac,myip,dstip); 217 | 218 | //Visualizzo a schermo il pacchetto creato 219 | printf("Pacchetto ETH+ARP creato:"); 220 | //stampabytes(buffer,14+sizeof(struct arp_packet));//+14 è il frame Ethernet 221 | 222 | //APRIRE COMUNICAZIONE 223 | /*socket restituisce un INT che è un file descriptor 224 | ovvero l'indice della tabella con tutto ciò che serve per gestire la comunicazione*/ 225 | s = socket(AF_PACKET, SOCK_RAW,htons(ETH_P_ALL)); 226 | 227 | //Prepara l'indirizzo 228 | bzero(&sll,sizeof(struct sockaddr_ll));//Mette tutti i byte a 0 229 | sll.sll_family = AF_PACKET;//Livello ethernet8(NO IP) 230 | //for(i=1;i<4;i++) 231 | // printf("%s\n",if_indextoname(i,ifname)); 232 | 233 | printf("\n"); 234 | sll.sll_ifindex = if_nametoindex("eth0"); 235 | len = sizeof(sll);//Grandezza della struttura indirizzo 236 | 237 | //Invia il pacchetto ethernet 238 | t = sendto(s, buffer, 14+sizeof(struct arp_packet), 0, (struct sockaddr *) &sll, len); 239 | if (t == -1 ){ 240 | perror("sendto fallita"); 241 | return 1; 242 | } 243 | 244 | //Ricevo il pacchetto ethernet di risposta che contiene un ARP 245 | for(m=0;m<1000;m++){ 246 | t = recvfrom(s, buffer, 1500, 0, (struct sockaddr *) &sll, &len); 247 | if (t == -1 ){ 248 | perror("recvfrom fallita"); 249 | return 1; 250 | } 251 | 252 | //Se il frame Ethernet ricevuto contiene un ARP 253 | if (eth->type == htons(0x0806)){ 254 | if(arp->opcode == htons(2))//Se l'ARP è di risposta=2 255 | 256 | //Se i primi 4 byte di dell'IP di sorgente ricevuto sono quelli di destinazione precedenti 257 | if(!memcmp(arp->psrc,dstip,4)){ 258 | memcpy(mac_incognito,arp->hsrc,6); 259 | return 0; 260 | } 261 | } 262 | } 263 | 264 | return 1; 265 | } 266 | 267 | //Crea pacchetto ethernet 268 | void crea_eth(struct eth_frame * e, unsigned char * src, unsigned char*dst,unsigned short type){ 269 | int i; 270 | e->type = htons(type); 271 | for(i=0;i<6;i++) e->src[i]=src[i]; 272 | for(i=0;i<6;i++) e->dst[i]=dst[i]; 273 | } 274 | 275 | //Crea pacchetto ARP 276 | void crea_arp(struct arp_packet* a,unsigned char *mymac,unsigned char *myip,unsigned char *dstip){ 277 | int i; 278 | a-> htype = htons(1);//Ethernet=1 279 | a-> ptype = htons(0x0800);//IPv4=0x0800 280 | a-> hlen = 6;//Lunghezza indirizzo hardware(Ethernet)=6byte 281 | a-> plen = 4;//Lunghezza indirizzo di rete (IP)=4byte 282 | a-> opcode =htons(1);//Richiesta=1, risposta=2 283 | for(i=0;i<6;i++) a-> hsrc[i]=mymac[i]; 284 | for(i=0;i<4;i++) a-> psrc[i]=myip[i]; 285 | for(i=0;i<6;i++) a-> hdst[i]=0; 286 | for(i=0;i<4;i++) a-> pdst[i]=dstip[i]; 287 | } 288 | 289 | //Stampa un numero di byte da un buffer 290 | void stampabytes(unsigned char * buffer, int quanti){ 291 | int i; 292 | for(i=0;iver_ihl = 0x45; //primi 4 bit: versione=4, ultimi 4 bit:IHL=5word(32bit*5=20byte) 302 | ip->tos= 0; 303 | ip->totlen=htons(20+payloadlen); 304 | ip->id=htons(0xABCD); 305 | ip->flags_offs=htons(0); 306 | ip->ttl=128; //Può attraversare massimo 128 router 307 | ip->protocol=payloadtype; 308 | ip->src=*((unsigned int*)myip); 309 | ip->dst=ipdest; 310 | ip->checksum=htons(0); 311 | ip->checksum=htons(checksum((unsigned char*) ip, 20)); 312 | }; 313 | 314 | //header Checksum del pacchetto IP 315 | unsigned short checksum( unsigned char * buffer, int len){ 316 | int i; 317 | unsigned short *p; 318 | unsigned int tot=0; 319 | p = (unsigned short *) buffer; 320 | for(i=0;itype=0; //Echo (request) 332 | icmp->code=0; 333 | icmp->checksum=htons(0); 334 | icmp->id=htons(0x1234); 335 | icmp->seq = htons(1); 336 | for(i=0;ipayload[i]=i; 337 | icmp->checksum = htons(checksum((unsigned char*)icmp,size)); 338 | } 339 | 340 | //Crea pachetto ICMP ECHO 341 | int crea_icmp_unreachable(struct icmp_packet * icmp, struct ip_datagram * ip,int tot_dimension){ 342 | int i; 343 | icmp->type=3; //Echo (request) 344 | icmp->code=3; 345 | icmp->checksum=htons(0); 346 | icmp->id=htons(0x1234); // not used 347 | icmp->seq = htons(1); //not used 348 | memcpy(icmp->payload, old_ip_buffer, tot_dimension-8); //ip header + 64 bits 349 | //for(i=0;i<20;i++) icmp->payload[i]=i;//numeri da 0a 19 350 | icmp->checksum = htons(checksum((unsigned char*)icmp,tot_dimension)); 351 | //final size = 28+8 352 | return tot_dimension; 353 | } 354 | 355 | 356 | 357 | 358 | -------------------------------------------------------------------------------- /160902-HTTP_delayed/default.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Dummy Page 6 | 7 | 8 | 9 | 10 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 37 | 38 | 39 | 40 |
41 |
42 |

Reti di calcolatori default page!

43 |

Tempo rimanente findo alla fine dell'esame:

44 |
45 | 00 days 46 | 00 hours 47 | 00 minutes 48 | 00 seconds 49 |
50 |
51 |
52 | 53 | 76 | 77 | -------------------------------------------------------------------------------- /160902-HTTP_delayed/makefile: -------------------------------------------------------------------------------- 1 | np : ws18.c 2 | gcc -o np ws18.c 3 | -------------------------------------------------------------------------------- /160902-HTTP_delayed/np: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nicomazz/ComputerNetworks-unipd2018/ee64f21ccb57208d272c08a81bd8de0d9dd89950/160902-HTTP_delayed/np -------------------------------------------------------------------------------- /160902-HTTP_delayed/ws18.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include /* superset of previous */ 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | int lunghezza; //Lunghezza indirizzo per accept() 12 | int yes = 1; //Flag utilizzato per settare un opzione del socket 13 | 14 | //Struttura singono header (nome, valore) 15 | struct header { 16 | char *n; 17 | char *v; 18 | }; 19 | struct header h[100]; //Header (array di strutture) 20 | 21 | // Indirizzo IPv4 22 | struct sockaddr_in indirizzo; 23 | struct sockaddr_in indirizzo_remoto; 24 | 25 | int primiduepunti; // Flag usato per leggere gli headers 26 | char request[10000]; 27 | char response[10000]; 28 | char *request_line; //Puntatore alla request line 29 | char *method, *uri, *http_ver; //Puntatori che indicano i parametri della RequestLine 30 | 31 | int c; //Carattere utilizato per leggere ogni carattere del file 32 | FILE *fin; //File che dovrà essere trasmesso 33 | int first_time = 1; 34 | time_t old_time; 35 | void print_ip(unsigned int ip){ 36 | struct in_addr ip_addr; 37 | ip_addr.s_addr = ip; 38 | printf("%s\n",inet_ntoa(ip_addr)); 39 | } 40 | #define MAXN 1000 41 | unsigned char state[MAXN]; 42 | unsigned char getStateAndToggle(unsigned int ip){ 43 | unsigned char prev = state[ip % MAXN]; 44 | printf("previous state: %d\n",prev); 45 | state[ip%MAXN] ^=1; 46 | return prev; 47 | } 48 | int main() { 49 | int s, s2, t, j, i; //s:socket per ricevere, t:variabile di supporto per gli errori 50 | char command[1000]; //Stringa che contiene il comando di shell eseguire 51 | 52 | //APRIRE COMUNICAZIONE 53 | /*socket restituisce un INT che è un file descriptor 54 | ovvero l'indice della tabella con tutto ciò che serve per gestire la comunicazione*/ 55 | s = socket(AF_INET, SOCK_STREAM, 0); //AF_INET=IPv4, SOCK_STREAM:apre uno stream, protocol:0 (default) 56 | if (s == -1) { 57 | perror("Socket Fallita"); 58 | return 1; 59 | } 60 | /* Opzioni del socket: opzioni a levello socket(SOL_SOCKET), 61 | riutilizzo degli indirizi(SO_REUSEADDR), 62 | 1(si), 63 | sizeof(int) 64 | ritorna 0 se tutto va bene, altrimenti -1*/ 65 | if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) { 66 | perror("setsockopt"); 67 | return 1; 68 | } 69 | 70 | //CONNESSIONE 71 | indirizzo.sin_family = AF_INET; //IPv4 72 | indirizzo.sin_port = htons(7888); //Porta 73 | indirizzo.sin_addr.s_addr = 0; 74 | 75 | // Bind assegna un indirizzo al socket, t=0 se tutto va bene altrimenti -1 76 | t = bind(s, (struct sockaddr *)&indirizzo, sizeof(struct sockaddr_in)); 77 | if (t == -1) { 78 | perror("Bind fallita"); 79 | return 1; 80 | } 81 | 82 | //Listen: marca il socket s come passivo, ovvero che deve ricevere 83 | t = listen(s, 10); 84 | if (t == -1) { 85 | perror("Listen Fallita"); 86 | return 1; 87 | } 88 | 89 | while (1) { 90 | lunghezza = sizeof(struct sockaddr_in); 91 | 92 | //Accept: restituisce il file descriptor di un nuovo socket che 93 | // eredita tutto da quello vecchio ma è già connesso, 94 | // pronto per il read e write. Questo perchè l'altro è impegnato con listen. 95 | s2 = accept(s, (struct sockaddr *)&indirizzo_remoto, &lunghezza); 96 | 97 | 98 | printf("-------------------new request\n"); 99 | printf("indirizzo remoto: "); 100 | print_ip((unsigned int)(indirizzo_remoto.sin_addr.s_addr)); 101 | printf("porta remota: %d\n", indirizzo_remoto.sin_port); 102 | 103 | unsigned int remote_ip = (unsigned int) indirizzo_remoto.sin_addr.s_addr; 104 | 105 | if (s2 == -1) { 106 | perror("Accept Fallita"); 107 | return 1; 108 | } 109 | 110 | //RICEVO RICHIESTA 111 | /*Full-Request = Request-Line 112 | *( General-Header 113 | | Request-Header 114 | | Entity-Header ) 115 | CRLF 116 | [ Entity-Body ] */ 117 | // Request-Line = Method SP Request-URI SP HTTP-Version CRLF (con CRLF=\r\n) 118 | // Header = nome: valore 119 | 120 | //Requst Line: 121 | h[0].n = request; 122 | request_line = h[0].n; 123 | h[0].v = h[0].n; 124 | 125 | //Headers: 126 | for (i = 0, j = 0; (t = read(s2, request + i, 1)) > 0; i++) { 127 | if ((i > 1) && (request[i] == '\n') && (request[i - 1] == '\r')) { 128 | primiduepunti = 1; 129 | request[i - 1] = 0; 130 | if (h[j].n[0] == 0) break; 131 | h[++j].n = request + i + 1; 132 | } 133 | if (primiduepunti && (request[i] == ':')) { 134 | h[j].v = request + i + 1; 135 | request[i] = 0; 136 | primiduepunti = 0; 137 | } 138 | } 139 | if (t == -1) { 140 | perror("Read Fallita"); 141 | return 1; 142 | } 143 | 144 | // Visualizzo a schermo la RequestLine e gli Headers ricevuti 145 | printf("Request Line: %s\n", request_line); 146 | for (i = 1; i < j; i++) { 147 | printf("%s ===> %s\n", h[i].n, h[i].v); 148 | } 149 | 150 | // Ricavo Method, URI e HTTP-Version dalla RequestLine 151 | method = request_line; 152 | for (i = 0; request_line[i] != ' ' && request_line[i]; i++) { 153 | }; 154 | if (request_line[i] != 0) { 155 | request_line[i] = 0; 156 | i++; 157 | } 158 | uri = request_line + i; 159 | for (; request_line[i] != ' ' && request_line[i]; i++) { 160 | }; 161 | if (request_line[i] != 0) { 162 | request_line[i] = 0; 163 | i++; 164 | } 165 | http_ver = request_line + i; 166 | 167 | //Visualizzo a schermo Method, URI e HTTP-Version 168 | printf("Method = %s, URI = %s, Http-Version = %s\n", method, uri, http_ver); 169 | 170 | //Se l'URI è "/exec/" 171 | if (!strncmp(uri, "/exec/", 6)) { //confronto i primi 6 caratteri 172 | sprintf(command, "%s > filetemp\n", uri + 6); //Metto in "filetemp" il file richiesto dall'URI 173 | printf("Eseguo il comando %s", command); 174 | if ((t = system(command)) == 0) { //Eseguo il comando 175 | uri = "/filetemp"; 176 | } else 177 | printf("system ha restituito %d\n", t); 178 | } 179 | 180 | if ((fin = fopen(uri + 1, "rt")) == NULL) { // Se non riesco ad aprire il file invio "FIle non trovato" 181 | // todo riprovare tra 10 secondi e salvare service unavailable 182 | 183 | printf("File %s non aperto\n", uri + 1); 184 | 185 | sprintf(response, "HTTP/1.1 307 Temporary Redirect\r\nRetry-After: 10\r\nLocation: /default.html\r\n\r\n redirected to /default.html"); 186 | // sprintf(response, "HTTP/1.1 404 File not found\r\n\r\nFile non trovato"); 187 | t = write(s2, response, strlen(response)); 188 | if (t == -1) { 189 | perror("write fallita"); 190 | return -1; 191 | } 192 | } else { //Altrimenti invio il file (se è la seconda richiesta) 193 | if (strcmp("/default.html",uri) != 0 && getStateAndToggle(remote_ip) == 0){ 194 | sprintf(response, "HTTP/1.1 503 Service Unavailable\r\nRetry-After: 10\r\n\r\nRetry in 10 seconds, please."); 195 | t = write(s2, response, strlen(response)); 196 | } else { 197 | sprintf(response, "HTTP/1.1 200 OK\r\n\r\n"); 198 | t = write(s2, response, strlen(response)); 199 | while ((c = fgetc(fin)) != EOF) { //fgetc ritorna il carattere sucessivo 200 | if (write(s2, (unsigned char *)&c, 1) != 1) { 201 | perror("Write fallita"); 202 | } 203 | } 204 | } 205 | fclose(fin); 206 | } 207 | close(s2); //Chiudo il socket che risponde 208 | } //Fine while 209 | } //Fine main 210 | -------------------------------------------------------------------------------- /170621-window_scale/window_scale.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nicomazz/ComputerNetworks-unipd2018/ee64f21ccb57208d272c08a81bd8de0d9dd89950/170621-window_scale/window_scale.c -------------------------------------------------------------------------------- /180619-SYNACK/np: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nicomazz/ComputerNetworks-unipd2018/ee64f21ccb57208d272c08a81bd8de0d9dd89950/180619-SYNACK/np -------------------------------------------------------------------------------- /180619-SYNACK/ping: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nicomazz/ComputerNetworks-unipd2018/ee64f21ccb57208d272c08a81bd8de0d9dd89950/180619-SYNACK/ping -------------------------------------------------------------------------------- /180620-ICMP_size/np: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nicomazz/ComputerNetworks-unipd2018/ee64f21ccb57208d272c08a81bd8de0d9dd89950/180620-ICMP_size/np -------------------------------------------------------------------------------- /180620-ICMP_size/ping: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nicomazz/ComputerNetworks-unipd2018/ee64f21ccb57208d272c08a81bd8de0d9dd89950/180620-ICMP_size/ping -------------------------------------------------------------------------------- /180620-ICMP_size/ping.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include /* See NOTES */ 4 | #include 5 | #include 6 | #include 7 | #include /* the L2 protocols */ 8 | #include 9 | #include 10 | 11 | 12 | unsigned char broadcast[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};//MAC con tutti 1, pacchetto indirizzato a tutti 13 | unsigned char mymac[6]={0xf2,0x3c,0x91,0xdb,0xc2,0x98}; //ifconfig 14 | unsigned char myip[4]={88,80,187,84}; 15 | unsigned char gateway[4]={88,80,187,1};//comando linux: route -n 16 | unsigned int netmask = 0x00FFFFFF; 17 | 18 | // Frame Ethernet 19 | struct eth_frame { 20 | unsigned char dst[6]; 21 | unsigned char src[6]; 22 | unsigned short type; //2byte 23 | char payload[1500]; //ARP o IP 24 | }; 25 | 26 | //Pacchetto ICMP ECHO 27 | struct icmp_packet{ 28 | unsigned char type; 29 | unsigned char code; 30 | unsigned short checksum; 31 | unsigned short id; 32 | unsigned short seq; 33 | char payload[128]; //Dati 34 | }; 35 | 36 | // Datagramma IP 37 | struct ip_datagram{ 38 | unsigned char ver_ihl; 39 | unsigned char tos; 40 | unsigned short totlen; 41 | unsigned short id; 42 | unsigned short flags_offs; 43 | unsigned char ttl; 44 | unsigned char protocol; 45 | unsigned short checksum; 46 | unsigned int src; 47 | unsigned int dst; 48 | unsigned char payload[1500];//ICMP o solo dati 49 | }; 50 | 51 | // Pacchetto ARP 52 | struct arp_packet{ 53 | unsigned short htype;//HardwareType: Ethernet=1 54 | unsigned short ptype;//ProtocolType IPv4=0x0800 55 | unsigned char hlen; //LunghezzaIndirizzoHardware = 6 byte 56 | unsigned char plen; //LunghezzaIndirizzoProtocol = 4 byte 57 | unsigned short opcode;//Operazione: 1=Richiesta, 2=Risposta 58 | unsigned char hsrc[6];//IndirizzoHardware di chi ha fatto la richiesta 59 | unsigned char psrc[4];//IndirizzoIP di chi ha fatto la richiesta 60 | unsigned char hdst[6];//IndirizzoHardware del destinatario della richiesta(in una richiesta è nullo) 61 | unsigned char pdst[4];//IndirizzoIP del destinatario della richiesta 62 | }; 63 | 64 | //Prototipi di funzioni 65 | void crea_eth(struct eth_frame *e, unsigned char * src, unsigned char*dst,unsigned short type); 66 | void crea_arp(struct arp_packet* a,unsigned char *mymac,unsigned char *myip,unsigned char *dstip); 67 | void crea_ip( struct ip_datagram* ip, int payloadlen,unsigned char payloadtype,unsigned int ipdest ); 68 | void crea_icmp_echo(struct icmp_packet * icmp); 69 | unsigned short checksum(unsigned char *buffer,int len); 70 | void stampabytes(unsigned char * buffer, int quanti); 71 | int trovamac(unsigned char *mac_incognito, unsigned char*dstip); 72 | 73 | void crea_icmp_reply(struct icmp_packet * icmp,int size); 74 | 75 | 76 | int main(){ 77 | struct sockaddr_ll sll; //Indirizzo ethernet mio 78 | unsigned char mac_incognito[6]; 79 | unsigned char buffer[1500]; //Conterrà i pacchetti di inviare 80 | unsigned char * nexthop; //prossimo router 81 | struct eth_frame * eth; //Pacchetto ethernet che contiene anche ARP 82 | struct ip_datagram * ip;// Datagramma IP che contiene anche ICMP 83 | struct icmp_packet * icmp;// pachetto ICMP 84 | //unsigned char targetip[4]={88,80,187,2}; 85 | unsigned char targetip[4]={147,162,2,100};//Padova 86 | int m,i,s,len,t; //Variabili di supporto 87 | 88 | //APRIRE COMUNICAZIONE 89 | /*socket restituisce un INT che è un file descriptor 90 | ovvero l'indice della tabella con tutto ciò che serve per gestire la comunicazione*/ 91 | s = socket(AF_PACKET, SOCK_RAW,htons(ETH_P_ALL));//AF_INET=IPv4, SOCK_RAW=non elaborato, htons(ETH_P_ALL) 92 | 93 | //Se l'host è nella mia stessa sotto rete tengo il suo IP per cercalre l'indirizzo ethernet 94 | //altrimenti uso l'indirizzo del mio gateway. 95 | if ((*((unsigned int *)targetip)&netmask) == (*((unsigned int*)myip)&netmask)) 96 | nexthop = targetip; 97 | else nexthop = gateway; 98 | 99 | //Trovo l'indirizzo mac di destinazione avendo l'IP 100 | if(!trovamac(mac_incognito,nexthop)){ 101 | printf("MAC incognito:"); 102 | //stampabytes(mac_incognito,6); 103 | } 104 | else printf("trovamac fallita\n"); 105 | 106 | //Costruisco un frame ethernet con pacchetto IP-ICMP all'interno 107 | eth = (struct eth_frame *) buffer; 108 | ip = (struct ip_datagram *) eth->payload; 109 | icmp = (struct icmp_packet*) ip->payload; 110 | 111 | crea_eth(eth,mymac,mac_incognito,0x0800); 112 | crea_ip(ip,28,1,*(unsigned int*)targetip); 113 | crea_icmp_echo(icmp); 114 | 115 | //Visualizzo a schermo il pacchetto creato 116 | printf("\nPacchetto ETH+IP+ICMP da inviare:"); 117 | // stampabytes(buffer,14+20+28);//+14 header ethernet, +20 IP +28 ICMP(8+20 di payload) 118 | 119 | //Preparo l'indirizzo 120 | bzero(&sll,sizeof(struct sockaddr_ll));//Metto tutto a 0 121 | sll.sll_ifindex = if_nametoindex("eth0"); 122 | printf("ifindex = %d\n",sll.sll_ifindex); 123 | len = sizeof(sll); 124 | 125 | //Invio il pacchetto ethernet che contiene IP 126 | t = sendto(s, buffer, 14+20+28, 0, (struct sockaddr *) &sll, len); 127 | if (t == -1 ){ 128 | perror("sendto fallita"); 129 | return 1; 130 | } 131 | 132 | //Ricevo la risposta 133 | for(m=0;m<1000;m++){ 134 | t = recvfrom(s, buffer, 1500, 0, (struct sockaddr *) &sll, &len); 135 | if (t == -1 ){ 136 | perror("recvfrom fallita"); 137 | return 1; 138 | } 139 | 140 | //Se il frame Ethernet ricevuto contiene un pacchetto IP 141 | if (eth->type == htons(0x0800)){ 142 | 143 | //Se il protocollo all'interno del payload IP è ICMP=1 144 | if((ip->protocol == 1 )){ 145 | 146 | //Se il tipo di ICMP è 0: Echo Reply 147 | if((icmp->type == 0)){ 148 | // printf("\nPacchetto ICMP ECHO REPLY ricevuto:\n"); 149 | //stampabytes(buffer,t); 150 | //packet dimension: 151 | unsigned short dimension = ntohs(ip->totlen); 152 | unsigned short header_dim = (ip->ver_ihl & 0x0F) * 4; 153 | int icmp_dimension = dimension-header_dim; 154 | // return 0; 155 | } 156 | if (icmp->type == 8){ 157 | printf("\nPacchetto echo REQUEST ricevuto:\n"); 158 | 159 | unsigned short dimension = ntohs(ip->totlen); 160 | unsigned short header_dim = (ip->ver_ihl & 0x0F) * 4; 161 | int icmp_dimension = dimension-header_dim; 162 | if (icmp_dimension != 100+8) continue; 163 | printf("dimension: %d\n",icmp_dimension); 164 | 165 | //Se l'host è nella mia stessa sotto rete tengo il suo IP per cercalre l'indirizzo ethernet 166 | //altrimenti uso l'indirizzo del mio gateway. 167 | nexthop = gateway; 168 | 169 | //Trovo l'indirizzo mac di destinazione avendo l'IP 170 | if(!trovamac(mac_incognito,nexthop)){ 171 | printf("MAC incognito:"); 172 | // stampabytes(mac_incognito,6); 173 | } 174 | else printf("trovamac fallita\n"); 175 | 176 | //Costruisco un frame ethernet con pacchetto IP-ICMP all'interno 177 | eth = (struct eth_frame *) buffer; 178 | ip = (struct ip_datagram *) eth->payload; 179 | icmp = (struct icmp_packet*) ip->payload; 180 | 181 | crea_eth(eth,mymac,mac_incognito,0x0800); 182 | crea_ip(ip,icmp_dimension,1,*(unsigned int*)targetip); 183 | crea_icmp_reply(icmp,icmp_dimension); 184 | 185 | //Visualizzo a schermo il pacchetto creato 186 | printf("\nPacchetto ETH+IP+ICMP da inviare:"); 187 | //stampabytes(buffer,14+20+icmp_dimension);//+14 header ethernet, +20 IP +28 ICMP(8+20 di payload) 188 | 189 | //Preparo l'indirizzo 190 | bzero(&sll,sizeof(struct sockaddr_ll));//Metto tutto a 0 191 | sll.sll_ifindex = if_nametoindex("eth0"); 192 | printf("ifindex = %d\n",sll.sll_ifindex); 193 | len = sizeof(sll); 194 | 195 | //Invio il pacchetto ethernet che contiene IP 196 | t = sendto(s, buffer, 14+20+icmp_dimension, 0, (struct sockaddr *) &sll, len); 197 | if (t == -1 ){ 198 | perror("sendto fallita"); 199 | return 1; 200 | } 201 | 202 | } 203 | 204 | } 205 | 206 | } 207 | 208 | }//Fine for 209 | 210 | }//Fine main 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | //Invia un Pacchetto Ethernet con dentro il pacchetto ARP e ricevo in risposta il MAC del destinatario 219 | //Ritorna 0 se tutto ok altrimenti 1. 220 | int trovamac(unsigned char *mac_incognito, unsigned char*dstip){ 221 | struct sockaddr_ll sll;//Struttura indirizzo per il sendto 222 | int len,i,t,m,s; 223 | char ifname[50]; 224 | unsigned char buffer[1500]; 225 | struct arp_packet * arp; 226 | struct eth_frame * eth; 227 | eth = (struct eth_frame *) buffer; 228 | arp = (struct arp_packet *) eth->payload; 229 | crea_eth(eth,mymac,broadcast,0x0806); 230 | crea_arp(arp,mymac,myip,dstip); 231 | 232 | //Visualizzo a schermo il pacchetto creato 233 | printf("Pacchetto ETH+ARP creato:"); 234 | //stampabytes(buffer,14+sizeof(struct arp_packet));//+14 è il frame Ethernet 235 | 236 | //APRIRE COMUNICAZIONE 237 | /*socket restituisce un INT che è un file descriptor 238 | ovvero l'indice della tabella con tutto ciò che serve per gestire la comunicazione*/ 239 | s = socket(AF_PACKET, SOCK_RAW,htons(ETH_P_ALL)); 240 | 241 | //Prepara l'indirizzo 242 | bzero(&sll,sizeof(struct sockaddr_ll));//Mette tutti i byte a 0 243 | sll.sll_family = AF_PACKET;//Livello ethernet8(NO IP) 244 | //for(i=1;i<4;i++) 245 | // printf("%s\n",if_indextoname(i,ifname)); 246 | 247 | printf("\n"); 248 | sll.sll_ifindex = if_nametoindex("eth0"); 249 | len = sizeof(sll);//Grandezza della struttura indirizzo 250 | 251 | //Invia il pacchetto ethernet 252 | t = sendto(s, buffer, 14+sizeof(struct arp_packet), 0, (struct sockaddr *) &sll, len); 253 | if (t == -1 ){ 254 | perror("sendto fallita"); 255 | return 1; 256 | } 257 | 258 | //Ricevo il pacchetto ethernet di risposta che contiene un ARP 259 | for(m=0;m<1000;m++){ 260 | t = recvfrom(s, buffer, 1500, 0, (struct sockaddr *) &sll, &len); 261 | if (t == -1 ){ 262 | perror("recvfrom fallita"); 263 | return 1; 264 | } 265 | 266 | //Se il frame Ethernet ricevuto contiene un ARP 267 | if (eth->type == htons(0x0806)){ 268 | if(arp->opcode == htons(2))//Se l'ARP è di risposta=2 269 | 270 | //Se i primi 4 byte di dell'IP di sorgente ricevuto sono quelli di destinazione precedenti 271 | if(!memcmp(arp->psrc,dstip,4)){ 272 | memcpy(mac_incognito,arp->hsrc,6); 273 | return 0; 274 | } 275 | } 276 | } 277 | 278 | return 1; 279 | } 280 | 281 | //Crea pacchetto ethernet 282 | void crea_eth(struct eth_frame * e, unsigned char * src, unsigned char*dst,unsigned short type){ 283 | int i; 284 | e->type = htons(type); 285 | for(i=0;i<6;i++) e->src[i]=src[i]; 286 | for(i=0;i<6;i++) e->dst[i]=dst[i]; 287 | } 288 | 289 | //Crea pacchetto ARP 290 | void crea_arp(struct arp_packet* a,unsigned char *mymac,unsigned char *myip,unsigned char *dstip){ 291 | int i; 292 | a-> htype = htons(1);//Ethernet=1 293 | a-> ptype = htons(0x0800);//IPv4=0x0800 294 | a-> hlen = 6;//Lunghezza indirizzo hardware(Ethernet)=6byte 295 | a-> plen = 4;//Lunghezza indirizzo di rete (IP)=4byte 296 | a-> opcode =htons(1);//Richiesta=1, risposta=2 297 | for(i=0;i<6;i++) a-> hsrc[i]=mymac[i]; 298 | for(i=0;i<4;i++) a-> psrc[i]=myip[i]; 299 | for(i=0;i<6;i++) a-> hdst[i]=0; 300 | for(i=0;i<4;i++) a-> pdst[i]=dstip[i]; 301 | } 302 | 303 | //Stampa un numero di byte da un buffer 304 | void stampabytes(unsigned char * buffer, int quanti){ 305 | int i; 306 | for(i=0;iver_ihl = 0x45; //primi 4 bit: versione=4, ultimi 4 bit:IHL=5word(32bit*5=20byte) 316 | ip->tos= 0; 317 | ip->totlen=htons(20+payloadlen); 318 | ip->id=htons(0xABCD); 319 | ip->flags_offs=htons(0); 320 | ip->ttl=128; //Può attraversare massimo 128 router 321 | ip->protocol=payloadtype; 322 | ip->src=*((unsigned int*)myip); 323 | ip->dst=ipdest; 324 | ip->checksum=htons(0); 325 | ip->checksum=htons(checksum((unsigned char*) ip, 20)); 326 | }; 327 | 328 | //header Checksum del pacchetto IP 329 | unsigned short checksum( unsigned char * buffer, int len){ 330 | int i; 331 | unsigned short *p; 332 | unsigned int tot=0; 333 | p = (unsigned short *) buffer; 334 | for(i=0;itype=0; //Echo (request) 346 | icmp->code=0; 347 | icmp->checksum=htons(0); 348 | icmp->id=htons(0x1234); 349 | icmp->seq = htons(1); 350 | for(i=0;ipayload[i]=i; 351 | icmp->checksum = htons(checksum((unsigned char*)icmp,size)); 352 | } 353 | 354 | //Crea pachetto ICMP ECHO 355 | void crea_icmp_echo(struct icmp_packet * icmp){ 356 | int i; 357 | icmp->type=8; //Echo (request) 358 | icmp->code=0; 359 | icmp->checksum=htons(0); 360 | icmp->id=htons(0x1234); 361 | icmp->seq = htons(1); 362 | for(i=0;i<20;i++) icmp->payload[i]=i;//numeri da 0a 19 363 | icmp->checksum = htons(checksum((unsigned char*)icmp,28)); 364 | } 365 | 366 | 367 | 368 | 369 | -------------------------------------------------------------------------------- /190618-SYSACKv2/np: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nicomazz/ComputerNetworks-unipd2018/ee64f21ccb57208d272c08a81bd8de0d9dd89950/190618-SYSACKv2/np -------------------------------------------------------------------------------- /190627-max_mtu/max_mtu.c: -------------------------------------------------------------------------------- 1 | /* 2 | a) mando più ping incrementando di volta in volta il payload dell'icmp. Setto il flag Don't fragment del pacchetto ip. 3 | Appena vedo che ad una certa dimensione del payload non ricevo più la echo response, questo significa che il pacchetto è stato scartato 4 | in quanto la dimensione è troppo grande e tale pacchetto non può essere frammentata. 5 | la dimesione mtu dell'ultimo ping del quale si ha una echo reply è la dimensione richiesta. 6 | b) 7 | 1. aggiungo un parametro in crea_icmp_echo che specifica la dimensione del payload 8 | 2. metto la creazione e l'invio del ping in un ciclo for che incrementa ad ogni iterazione la dimensione del payload, di 4 byte alla volta. 9 | 3. setto il flag Don't Fragment nel pacchetto IP 10 | 4. stampo ad ogni iterazione la mtu 11 | 5. se dopo 3 tentativi non ricevo alcun echo reply esco dal ciclo for e stampo la mtu dell'ultimo pacchetto del quale si ha ricevuto la echo reply. 12 | c) dalle rilevazioni misuro che la mtu più piccola attraverso cui deve transitare il pacchetto IP è: 1500 bytes, verso l'indirizzo 147.162.2.100. 13 | Questa dimensione è la massima dimensione di un pacchetto IP senza dover essere frammentata durante il percorso di rete. 14 | */ 15 | #include 16 | #include /* See NOTES */ 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include /* the L2 protocols */ 22 | #include 23 | #include 24 | #include 25 | 26 | unsigned char miomac[6] = {0xf2, 0x3c, 0x91, 0xdb, 0xc2, 0x98}; 27 | unsigned char broadcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 28 | unsigned char mioip[4] = {88, 80, 187, 84}; 29 | unsigned char netmask[4] = {255, 255, 255, 0}; 30 | unsigned char gateway[4] = {88, 80, 187, 1}; 31 | 32 | //unsigned char iptarget[4] = {88,80,187,80}; 33 | unsigned char iptarget[4] = {147,162,2,100}; 34 | //unsigned char iptarget[4] = {35,185,190,72}; 35 | 36 | 37 | struct sockaddr_ll sll; 38 | struct timeval stop, start; 39 | 40 | struct eth_frame 41 | { 42 | unsigned char dst[6]; 43 | unsigned char src[6]; 44 | unsigned short int type; //0x0800=IP, 0x0806=ARP 45 | unsigned char payload[1]; 46 | }; 47 | 48 | struct arp_packet 49 | { 50 | unsigned short int htype; //tipo protocollo di rete. Eth=1 51 | unsigned short int ptype; //IPv4=0x0800 52 | unsigned char hlen; //lunghezza indirizzi hardware. Ethernet=6 53 | unsigned char plen; //lunghezza protocollo superiore. IPv4=4 54 | unsigned short int op; //operazione del mittente: 1=richiesta, 2=risposta 55 | unsigned char hsrc[6]; 56 | unsigned char psrc[4]; 57 | unsigned char hdst[6]; 58 | unsigned char pdst[4]; 59 | }; 60 | 61 | struct icmp_packet 62 | { 63 | unsigned char type; //8=echo; 0=echo reply 64 | unsigned char code; 65 | unsigned short checksum; 66 | unsigned short id; 67 | unsigned short seq; 68 | unsigned char payload[1]; 69 | }; 70 | struct ip_datagram 71 | { 72 | unsigned char ver_ihl; // first 4 bits: version, second 4 bits: (lenght header)/32 73 | unsigned char tos; //type of service 74 | unsigned short totlen; // len header + payload 75 | unsigned short id; // useful in case of fragmentation 76 | unsigned short flag_offs; //offset/8 related to the original ip package 77 | unsigned char ttl; 78 | unsigned char proto; // TCP = 6, ICMP = 1 79 | unsigned short checksum; // only header checksum (not of payload). Must be at 0 before the calculation. 80 | unsigned int saddr; // ip address 81 | unsigned int daddr; // ip address 82 | unsigned char payload[1]; 83 | }; 84 | 85 | void stampa_buffer(unsigned char *b, int quanti); 86 | 87 | void crea_eth(struct eth_frame *e, unsigned char *dest, unsigned short type) 88 | { 89 | int i; 90 | for (i = 0; i < 6; i++) 91 | { 92 | e->dst[i] = dest[i]; 93 | e->src[i] = miomac[i]; 94 | } 95 | e->type = htons(type); 96 | } 97 | 98 | void crea_arp(struct arp_packet *a, unsigned short op, unsigned char *ptarget) 99 | { 100 | int i; 101 | a->htype = htons(1); 102 | a->ptype = htons(0x0800); 103 | a->hlen = 6; 104 | a->plen = 4; 105 | a->op = htons(op); 106 | for (i = 0; i < 6; i++) 107 | { 108 | a->hsrc[i] = miomac[i]; 109 | a->hdst[i] = 0; 110 | } 111 | for (i = 0; i < 4; i++) 112 | { 113 | a->psrc[i] = mioip[i]; 114 | a->pdst[i] = ptarget[i]; 115 | } 116 | } 117 | 118 | int risolvi(unsigned char *target, unsigned char *mac_incognito) 119 | { 120 | unsigned char buffer[1500]; 121 | struct eth_frame *eth; 122 | struct arp_packet *arp; 123 | int i, n, s; 124 | int lungh; 125 | s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); 126 | if (s == -1) 127 | { 128 | perror("socket fallita"); 129 | return 1; 130 | } 131 | 132 | eth = (struct eth_frame *)buffer; 133 | arp = (struct arp_packet *)eth->payload; 134 | 135 | crea_arp(arp, 1, target); 136 | crea_eth(eth, broadcast, 0x0806); 137 | //stampa_buffer(buffer, 14+sizeof(struct arp_packet)); 138 | 139 | sll.sll_family = AF_PACKET; 140 | sll.sll_ifindex = 3; 141 | lungh = sizeof(sll); 142 | n = sendto(s, buffer, 14 + sizeof(struct arp_packet), 0, (struct sockaddr *)&sll, lungh); 143 | if (n == -1) 144 | { 145 | perror("sendto fallita"); 146 | return 1; 147 | } 148 | 149 | while (1) 150 | { 151 | n = recvfrom(s, buffer, 1500, 0, (struct sockaddr *)&sll, &lungh); 152 | if (n == -1) 153 | { 154 | perror("recvfrom fallita"); 155 | return 1; 156 | } 157 | if (eth->type == htons(0x0806)) 158 | if (arp->op == htons(2)) 159 | if (!memcmp(arp->psrc, target, 4)) 160 | { 161 | for (i = 0; i < 6; i++) 162 | mac_incognito[i] = arp->hsrc[i]; 163 | break; 164 | } 165 | } 166 | close(s); 167 | return 0; 168 | } 169 | 170 | void stampa_buffer(unsigned char *b, int quanti) { 171 | int i; 172 | for (i = 0; i < quanti; i++) { 173 | printf("%.3d(%.2x) ", b[i], b[i]); 174 | if ((i % 4) == 3) 175 | printf("\n"); 176 | } 177 | } 178 | 179 | unsigned short checksum( unsigned char * buffer, int len) { 180 | int i; 181 | unsigned short *p; 182 | unsigned int tot=0; 183 | p = (unsigned short *) buffer; 184 | for(i=0;itype = 8; 194 | icmp->code = 0; 195 | icmp->checksum = htons(0); 196 | icmp->id = htons(id); 197 | icmp->seq = htons(seq); 198 | for (i = 0; i < payload_size; i++) 199 | icmp->payload[i] = i; 200 | icmp->checksum = htons(checksum((unsigned char *)icmp, payload_size+8)); 201 | } 202 | 203 | void crea_ip(struct ip_datagram *ip, int payloadsize, unsigned char proto, unsigned char *ipdest) 204 | { 205 | ip->ver_ihl = 0x45; 206 | ip->tos = 0; 207 | ip->totlen = htons(payloadsize + 20); 208 | ip->id = htons(0x1177); 209 | //ip->flag_offs = 0; 210 | ip->flag_offs = htons(1UL<<14); 211 | ip->ttl = 128; 212 | ip->proto = proto; 213 | ip->checksum = htons(0); 214 | ip->saddr = *(unsigned int *)mioip; 215 | ip->daddr = *(unsigned int *)ipdest; 216 | ip->checksum = htons(checksum((unsigned char *)ip, 20)); 217 | }; 218 | 219 | 220 | /* Stampa pacchetto IP */ 221 | void stampa_ip( struct ip_datagram* i ){ 222 | unsigned int ihl = ( i->ver_ihl & 0x0F) * 4; // Lunghezza header IP 223 | unsigned int totlen = htons( i->totlen ); // Lunghezza totale pacchetto 224 | unsigned int opt_len = ihl-20; // Lunghezza campo opzioni 225 | 226 | printf( "\n\n ***** PACCHETTO IP *****\n" ); 227 | printf( "Version: %d\n", i->ver_ihl & 0xF0 ); 228 | printf( "IHL (bytes 60max): %d\n", ihl ); 229 | printf( "TOS: %d\n", i->tos ); 230 | printf( "Lunghezza totale: %d\n", totlen ); 231 | printf( "ID: %x\n", htons( i->id ) ); 232 | unsigned char flags = (unsigned char)( htons( i->flag_offs) >> 13); 233 | printf( "Flags: %d | %d | %d \n", flags & 4, flags & 2, flags & 1 ); 234 | printf( "Fragment Offset: %d\n", htons( i->flag_offs) & 0x1FFF ); 235 | printf( "TTL: %d\n", i->ttl ); 236 | printf( "Protocol: %d\n", i->proto ); 237 | printf( "Checksum: %x\n", htons( i->checksum ) ); 238 | 239 | unsigned char* saddr = ( unsigned char* )&i->saddr; 240 | unsigned char* daddr = ( unsigned char* )&i->daddr; 241 | 242 | printf( "IP Source: %d.%d.%d.%d\n", saddr[0], saddr[1], saddr[2], saddr[3] ); 243 | printf( "IP Destination: %d.%d.%d.%d\n", daddr[0], daddr[1], daddr[2], daddr[3] ); 244 | 245 | if( ihl > 20 ){ 246 | // Stampa opzioni 247 | printf( "Options: " ); 248 | for(int j=0; j < opt_len ; j++ ){ 249 | printf("%.3d(%.2x) ", i->payload[j], i->payload[j]); 250 | } 251 | printf( "\n" ); 252 | } 253 | } 254 | 255 | void stampa_icmp_e( struct icmp_packet* i ){ 256 | printf( "\n\n ***** PACCHETTO ICMP *****\n" ); 257 | printf( "Type: %d\n", i->type ); 258 | printf( "Code: %d\n", i->code ); 259 | printf( "Code: 0x%x\n", htons( i->checksum ) ); 260 | printf( "ID: %d\n", htons(i->id) ); 261 | printf( "Sequence: %d\n", htons(i->seq) ); 262 | } 263 | 264 | int main() 265 | { 266 | int t, s, i; 267 | unsigned char mac[6]; 268 | unsigned char buffer[40000]; 269 | struct icmp_packet *icmp; 270 | struct ip_datagram *ip; 271 | struct eth_frame *eth; 272 | int lungh, n, tentativi=0, icmp_payload; 273 | 274 | if ((*(unsigned int *)mioip & *(unsigned int *)netmask) == (*(unsigned int *)iptarget & *(unsigned int *)netmask)) 275 | { 276 | t = risolvi(iptarget, mac); 277 | } 278 | else 279 | t = risolvi(gateway, mac); 280 | 281 | if (t == 0) 282 | { 283 | printf("Mac incognito:\n"); 284 | stampa_buffer(mac, 6); 285 | } 286 | s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); 287 | if (s == -1) 288 | { 289 | perror("Socket fallita"); 290 | return 1; 291 | } 292 | eth = (struct eth_frame *)buffer; 293 | ip = (struct ip_datagram *)eth->payload; 294 | icmp = (struct icmp_packet *)ip->payload; 295 | 296 | for(icmp_payload=20; icmp_payload<30000 && tentativi<3; icmp_payload+=4){ 297 | crea_icmp_echo(icmp, 0x1177, 1, icmp_payload); 298 | crea_ip(ip, icmp_payload+8, 1, iptarget); 299 | crea_eth(eth, mac, 0x0800); 300 | //printf("ICMP/IP/ETH\n"); 301 | //stampa_buffer(buffer, 14 + 20 + 8 + icmp_payload); 302 | //stampa_ip(ip); 303 | //stampa_icmp_e(icmp); 304 | lungh = sizeof(struct sockaddr_ll); 305 | bzero(&sll, lungh); 306 | sll.sll_ifindex = 3; 307 | n = sendto(s, buffer, 14 + 20 + 8 + icmp_payload, 0, (struct sockaddr *)&sll, lungh); 308 | if (n == -1) 309 | { 310 | perror("sendto fallita"); 311 | return 1; 312 | } 313 | printf("Inviato icmp_payload=%d Attendo risposta...\n", icmp_payload); 314 | 315 | for(i=0; i<1000; i++){ 316 | 317 | n = recvfrom(s, buffer, 30000, 0, (struct sockaddr *)&sll, &lungh); 318 | //printf("sono qui"); 319 | if (n == -1) 320 | { 321 | perror("recvfrom fallita"); 322 | return 1; 323 | } 324 | if (eth->type == htons(0x0800)) 325 | if (ip->proto == 1) 326 | if (icmp->type == 0 && icmp->id==htons(0x1177)) 327 | { 328 | printf("ricevuto icmp echo reply. mtu=%d\n", icmp_payload+8+20); 329 | //stampa_buffer(buffer, n); 330 | break; 331 | } 332 | } 333 | if(i==1000) { 334 | icmp_payload-=4; //retry 335 | tentativi++; 336 | } 337 | } 338 | icmp_payload-=4; 339 | int max_mtu = icmp_payload+8+20; 340 | printf("max mtu = %d", max_mtu); 341 | } 342 | 343 | -------------------------------------------------------------------------------- /Homeworks/auth_server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define PORT 8004 12 | 13 | struct sockaddr_in server, client; 14 | 15 | struct header { 16 | char* k; 17 | char* v; 18 | } h[100]; 19 | 20 | char request[10000]; 21 | char response[10000]; 22 | 23 | int main() { 24 | int i, j, k, s, cs, n, ch; 25 | int flag; 26 | int len; 27 | char *method, *path, *ver; 28 | char* credentials; 29 | s = socket(AF_INET, SOCK_STREAM, 0); 30 | if (s == -1) { 31 | printf("Error opening socket"); 32 | exit(1); 33 | } 34 | 35 | server.sin_family = AF_INET; 36 | server.sin_port = htons(PORT); 37 | if (-1 == bind(s, (struct sockaddr*)&server, sizeof(struct sockaddr))) { 38 | printf("Error binding socket."); 39 | exit(1); 40 | } 41 | 42 | if (-1 == listen(s, 10)) { 43 | printf("Error listening on socket."); 44 | exit(1); 45 | } 46 | len = sizeof(client); 47 | while (1) { 48 | cs = accept(s, (struct sockaddr*)&client, &len); 49 | 50 | //PARSE HEADERS 51 | j = 0; 52 | k = 0; 53 | h[0].k = request; 54 | flag = 0; 55 | while (ch = read(cs, request + j, 1)) { 56 | //printf("%c", request[j]); 57 | if (request[j] == '\n' && request[j - 1] == '\r') { 58 | request[j - 1] = 0; 59 | if (h[k].k[0] == 0) 60 | break; 61 | 62 | flag = 0; 63 | h[++k].k = request + j + 1; 64 | } 65 | if (request[j] == ':' && !flag) { 66 | flag = 1; 67 | request[j] = 0; 68 | h[k].v = request + j + 1; 69 | } 70 | j++; 71 | } 72 | printf("=========HEADERS==========\n"); 73 | for (i = 0; i < k; i++) { 74 | printf("%s --> %s\n", h[i].k, h[i].v); 75 | } 76 | 77 | //parse request 78 | //ex GET / HTTP/1.1 79 | i = 0; 80 | method = &h[0].k[0]; 81 | for (; h[0].k[i] != ' '; i++) 82 | ; 83 | h[0].k[i] = 0; 84 | i++; 85 | path = &h[0].k[i]; 86 | for (; h[0].k[i] != ' '; i++) 87 | ; 88 | h[0].k[i] = 0; 89 | i++; 90 | ver = &h[0].k[i]; 91 | 92 | printf("\n\nmethod: %s \npath: %s \nver: %s\n", method, path, ver); 93 | 94 | //find auth header 95 | flag = 0; 96 | for (i = 0; i < k; i++) { 97 | if (!strcmp("Authorization", h[i].k)) { 98 | flag = 1; 99 | break; 100 | } 101 | } 102 | 103 | //get credentials 104 | if (flag) { 105 | //printf("%s", h[i].v); 106 | j = 0; 107 | for (; h[i].v[j] == ' '; j++) 108 | ; 109 | for (; h[i].v[j] != ' '; j++) 110 | ; 111 | for (; h[i].v[j] == ' '; j++) 112 | ; 113 | credentials = &h[i].v[j]; 114 | printf("\n\nCREDENTIALS: %s\n\n", credentials); 115 | } 116 | // User id: Aladdin 117 | // pwd: open sesame 118 | if (!flag || strcmp("QWxhZGRpbjpvcGVuIHNlc2FtZQ==", credentials)) { 119 | sprintf(response, "HTTP/1.1 401 Unauthorized\r\nConnection:close\r\nWWW-Authenticate: Basic realm=\"WallyWorld\"\r\n\r\n"); 120 | write(cs, response, strlen(response)); 121 | } else { 122 | sprintf(response, "HTTP/1.1 200 OK\r\n\r\nbella\r\n\r\n"); 123 | write(cs, response, strlen(response)); 124 | } 125 | close(cs); 126 | } 127 | 128 | return 0; 129 | } 130 | -------------------------------------------------------------------------------- /Homeworks/chunked_client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | extern int h_errno; 7 | #include 8 | 9 | #define PORT 8001 10 | 11 | const char *host = "www.padovanet.it"; 12 | char request[10000]; 13 | char buffer[100000]; 14 | char content[100000]; 15 | 16 | struct sockaddr_in saddr; 17 | struct hostent *he; 18 | 19 | struct header { 20 | char *k; 21 | char *v; 22 | } h[100]; 23 | 24 | int main() { 25 | int i, j, s, k, n; 26 | char flag, isChunked; 27 | char ch; 28 | 29 | // send server req 30 | s = socket(AF_INET, SOCK_STREAM, 0); 31 | 32 | he = gethostbyname(host); 33 | if (he == NULL) { 34 | printf("Error resolving host name.\n"); 35 | return 1; 36 | } 37 | 38 | saddr.sin_family = AF_INET; 39 | saddr.sin_port = htons(80); 40 | saddr.sin_addr.s_addr = *(unsigned int *)he->h_addr; 41 | 42 | if (-1 == connect(s, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in))) { 43 | printf("Error connecting to host.\n"); 44 | return 1; 45 | } 46 | 47 | sprintf(request, "GET / HTTP/1.1\r\nHost:%s\r\nConnection:close\r\n\r\n", host); 48 | write(s, request, strlen(request)); 49 | 50 | // parse headers 51 | k = 0; 52 | j = 0; 53 | flag = 0; 54 | h[0].k = buffer; 55 | while (read(s, buffer + j, 1)) { 56 | if (buffer[j] == '\n' && buffer[j - 1] == '\r') { // new header key found 57 | buffer[j - 1] = 0; // add string terminator for prev header / request 58 | if (h[k].k[0] == 0) // double CRLF found -> no more headers 59 | break; 60 | h[++k].k = buffer + j + 1; // point to the header key 61 | flag = 0; 62 | } 63 | if (buffer[j] == ':' && !flag) { 64 | flag = 1; // avoid recognizing header value's ':' as separator 65 | buffer[j] = 0; 66 | h[k].v = buffer + j + 1; 67 | } 68 | j++; 69 | } 70 | 71 | // check if trasmission is chunked 72 | for (i = 0; i < k; i++) { 73 | //printf("%s --> %s\n", h[i].k, h[i].v); 74 | if (!strcmp(h[i].k, "Transfer-Encoding") && strcasestr(h[i].v, "chunked")) 75 | isChunked = 1; 76 | } 77 | 78 | if (isChunked) { 79 | int total_content_size = 0; 80 | 81 | long int chunk_size = 0, i = 0; // i will store total content size 82 | n = 0; 83 | // read first chunk size 84 | char *chunk_size_p = buffer + j; 85 | while (read(s, buffer + j, 1)) { 86 | if (buffer[j] == ':') // replace separators with string terminators 87 | buffer[j] = 0; 88 | if (buffer[j] == '\n' && buffer[j - 1] == '\r') 89 | break; 90 | j++; 91 | } 92 | chunk_size = strtol(chunk_size_p, NULL, 16); // convert from b16 to long 93 | 94 | while (chunk_size > 0) { 95 | printf("chunk size: %d\n", chunk_size); 96 | total_content_size += chunk_size; 97 | 98 | // print chunck data 99 | for (i = 0; i < chunk_size + 2; i++) { 100 | if (!read(s, &ch, 1)) { 101 | printf("Error reading\n"); 102 | return 1; 103 | } 104 | printf("%c", ch); 105 | } 106 | 107 | // read successive chunk size 108 | j = 0; 109 | char *chunk_size_p = buffer; 110 | while (read(s, buffer + j, 1)) { 111 | if (buffer[j] == ':') // replace separators with string terminators 112 | buffer[j] = 0; 113 | if (buffer[j] == '\n' && buffer[j - 1] == '\r') 114 | break; 115 | j++; 116 | } 117 | chunk_size = strtol(chunk_size_p, NULL, 16); 118 | } 119 | 120 | //printf("Total content size: %d\n", total_content_size); 121 | 122 | } else { 123 | printf("Server response is not chunked.\n"); 124 | } 125 | 126 | close(s); 127 | 128 | return 0; 129 | } 130 | -------------------------------------------------------------------------------- /Homeworks/traceroute.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include /* the L2 protocols */ 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include /* See NOTES */ 10 | #include 11 | 12 | /* 13 | unsigned char miomac[6] = { 0xf2,0x3c,0x91,0xdb,0xc2,0x98 }; 14 | unsigned char broadcast[6] = { 0xff, 0xff, 0xff, 0xff,0xff,0xff}; 15 | unsigned char mioip[4] = {88,80,187,84}; 16 | unsigned char netmask[4] = { 255,255,255,0}; 17 | unsigned char gateway[4] = { 88,80,187,1}; 18 | */ 19 | unsigned char miomac[6] = {0xb0, 0xc0, 0x90, 0xa6, 0x78, 0xfb}; 20 | unsigned char broadcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 21 | unsigned char mioip[4] = {192, 168, 1, 12}; 22 | unsigned char netmask[4] = {255, 255, 255, 0}; 23 | unsigned char gateway[4] = {192, 168, 1, 1}; 24 | 25 | //unsigned char iptarget[4] = {88,80,187,80}; 26 | unsigned char iptarget[4] = {147, 162, 2, 100}; 27 | 28 | struct sockaddr_ll sll; 29 | struct timeval stop, start; 30 | 31 | struct eth_frame { 32 | unsigned char dst[6]; 33 | unsigned char src[6]; 34 | unsigned short int type; // ARP -> 0x0806, IP -> 0x0800 35 | unsigned char payload[1]; 36 | }; 37 | 38 | struct arp_packet { 39 | unsigned short int htype; // 1 -> eth 40 | unsigned short int ptype; // 0x0800 -> ip 41 | unsigned char hlen; 42 | unsigned char plen; 43 | unsigned short int op; // operation: request -> 1, response -> 2 44 | unsigned char hsrc[6]; 45 | unsigned char psrc[4]; 46 | unsigned char hdst[6]; 47 | unsigned char pdst[4]; 48 | }; 49 | 50 | struct icmp_packet { 51 | unsigned char type; 52 | unsigned char code; 53 | unsigned short checksum; // checksum of ICMP header + ICMP payload 54 | unsigned short id; 55 | unsigned short seq; 56 | unsigned char payload[1]; 57 | }; 58 | 59 | struct ip_datagram { 60 | unsigned char ver_ihl; // usually 0x45 61 | unsigned char tos; // 0 62 | unsigned short totlen; // 20 (ip header) + payload size 63 | unsigned short id; // id chosen by sender 64 | unsigned short flag_offs; 65 | unsigned char ttl; // time to live 66 | unsigned char proto; // icmp -> 1, 6 -> TCP 67 | unsigned short checksum; // checksum of header only 68 | unsigned int saddr; 69 | unsigned int daddr; 70 | unsigned char payload[1]; 71 | }; 72 | 73 | void stampa_buffer(unsigned char *b, int quanti); 74 | 75 | void crea_eth(struct eth_frame *e, unsigned char *dest, unsigned short type) { 76 | int i; 77 | for (i = 0; i < 6; i++) { 78 | e->dst[i] = dest[i]; 79 | e->src[i] = miomac[i]; 80 | } 81 | e->type = htons(type); 82 | } 83 | 84 | void crea_arp(struct arp_packet *a, unsigned short op, unsigned char *ptarget) { 85 | int i; 86 | a->htype = htons(1); 87 | a->ptype = htons(0x0800); 88 | a->hlen = 6; 89 | a->plen = 4; 90 | a->op = htons(op); 91 | for (i = 0; i < 6; i++) { 92 | a->hsrc[i] = miomac[i]; 93 | a->hdst[i] = 0; 94 | } 95 | for (i = 0; i < 4; i++) { 96 | a->psrc[i] = mioip[i]; 97 | a->pdst[i] = ptarget[i]; 98 | } 99 | } 100 | 101 | int risolvi(unsigned char *target, unsigned char *mac_incognito) { 102 | unsigned char buffer[1500]; 103 | struct eth_frame *eth; 104 | struct arp_packet *arp; 105 | int i, n, s; 106 | int lungh; 107 | 108 | // init raw socket 109 | s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); 110 | if (s == -1) { 111 | perror("socket fallita"); 112 | return 1; 113 | } 114 | 115 | eth = (struct eth_frame *)buffer; 116 | arp = (struct arp_packet *)eth->payload; 117 | 118 | crea_arp(arp, 1, target); 119 | crea_eth(eth, broadcast, 0x0806); 120 | //stampa_buffer(buffer, 14+sizeof(struct arp_packet)); 121 | 122 | sll.sll_family = AF_PACKET; 123 | sll.sll_ifindex = 3; 124 | 125 | lungh = sizeof(sll); 126 | n = sendto(s, buffer, 14 + sizeof(struct arp_packet), 0, (struct sockaddr *)&sll, lungh); 127 | if (n == -1) { 128 | perror("sendto fallita"); 129 | return 1; 130 | } 131 | 132 | while (1) { 133 | n = recvfrom(s, buffer, 1500, 0, (struct sockaddr *)&sll, &lungh); 134 | if (n == -1) { 135 | perror("recvfrom fallita"); 136 | return 1; 137 | } 138 | if (eth->type == htons(0x0806)) 139 | if (arp->op == htons(2)) 140 | if (!memcmp(arp->psrc, target, 4)) { 141 | for (i = 0; i < 6; i++) 142 | mac_incognito[i] = arp->hsrc[i]; 143 | break; 144 | } 145 | } 146 | close(s); 147 | return 0; 148 | } 149 | 150 | void stampa_buffer(unsigned char *b, int quanti) { 151 | int i; 152 | for (i = 0; i < quanti; i++) { 153 | printf("%.3d(%.2x) ", b[i], b[i]); 154 | if ((i % 4) == 3) 155 | printf("\n"); 156 | } 157 | } 158 | 159 | unsigned short checksum(unsigned char *b, int n) { 160 | int i; 161 | unsigned short prev, tot = 0, *p = (unsigned short *)b; 162 | for (i = 0; i < n / 2; i++) { 163 | prev = tot; 164 | tot += htons(p[i]); 165 | if (tot < prev) tot++; 166 | } 167 | return (0xFFFF - tot); 168 | } 169 | 170 | void crea_icmp_echo(struct icmp_packet *icmp, unsigned short id, unsigned short seq) { 171 | int i; 172 | icmp->type = 8; 173 | icmp->code = 0; 174 | icmp->checksum = htons(0); 175 | icmp->id = htons(id); 176 | icmp->seq = htons(seq); 177 | for (i = 0; i < 20; i++) 178 | icmp->payload[i] = i; 179 | icmp->checksum = htons(checksum((unsigned char *)icmp, 28)); 180 | } 181 | 182 | void crea_ip(struct ip_datagram *ip, int payloadsize, unsigned char proto, unsigned char *ipdest, unsigned char ttl) { 183 | ip->ver_ihl = 0x45; 184 | ip->tos = 0; 185 | ip->totlen = htons(payloadsize + 20); 186 | ip->id = htons(0xABCD); 187 | ip->flag_offs = htons(0); 188 | ip->ttl = ttl; 189 | ip->proto = proto; 190 | ip->checksum = htons(0); 191 | ip->saddr = *(unsigned int *)mioip; 192 | ip->daddr = *(unsigned int *)ipdest; 193 | ip->checksum = htons(checksum((unsigned char *)ip, 20)); 194 | }; 195 | 196 | int main() { 197 | int t, s; 198 | unsigned char mac[6]; 199 | unsigned char buffer[1500]; 200 | struct icmp_packet *icmp; 201 | struct ip_datagram *ip; 202 | struct eth_frame *eth; 203 | int lungh, n; 204 | 205 | // get target mac 206 | if ((*(unsigned int *)mioip & *(unsigned int *)netmask) == (*(unsigned int *)iptarget & *(unsigned int *)netmask)) 207 | t = risolvi(iptarget, mac); 208 | else 209 | t = risolvi(gateway, mac); 210 | if (t == 0) { 211 | printf("Mac incognito:\n"); 212 | stampa_buffer(mac, 6); 213 | } 214 | 215 | // init raw socket 216 | s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); 217 | if (s == -1) { 218 | perror("Socket fallita"); 219 | return 1; 220 | } 221 | 222 | eth = (struct eth_frame *)buffer; 223 | ip = (struct ip_datagram *)eth->payload; 224 | icmp = (struct icmp_packet *)ip->payload; 225 | 226 | // printf("ICMP/IP/ETH:\n"); 227 | // stampa_buffer(buffer,14+20+8+20); 228 | 229 | lungh = sizeof(struct sockaddr_ll); 230 | bzero(&sll, lungh); 231 | sll.sll_ifindex = 3; 232 | 233 | // send ICMP echos with increasing ttl and wait for response: 234 | // if the response is an echo response then we reached the target, 235 | // otherwise we get a time exceed message 236 | int ttl = 1; 237 | int flag_host_reached = 0; 238 | 239 | while (!flag_host_reached) { 240 | crea_icmp_echo(icmp, 0x1234, 1); 241 | // 28: ICMP head + ICMP payload 242 | crea_ip(ip, 28, 1, iptarget, ttl); 243 | crea_eth(eth, mac, 0x0800); 244 | 245 | // re-write lungh as recvfrom modify it 246 | lungh = sizeof(struct sockaddr_ll); 247 | n = sendto(s, buffer, 14 + 20 + 8 + 20, 0, (struct sockaddr *)&sll, lungh); 248 | if (n == -1) { 249 | perror("sendto fallita"); 250 | return 1; 251 | } 252 | printf("Sent echo message with ttl = %d\n", ttl); 253 | 254 | gettimeofday(&start, NULL); 255 | while (1) { 256 | gettimeofday(&stop, NULL); 257 | if ((stop.tv_usec - start.tv_usec) > 500000) { 258 | printf("\nTime exceeded. Retrying\n"); 259 | ttl--; 260 | break; 261 | } 262 | n = recvfrom(s, buffer, 1500, 0, (struct sockaddr *)&sll, &lungh); 263 | if (n == -1) { 264 | perror("recvfrom fallita"); 265 | return 1; 266 | } 267 | 268 | // check if it's an echo response 269 | if (eth->type == htons(0x0800) // ip? 270 | && ip->proto == 1 // icmp? 271 | && icmp->type == 0 // echo resp 272 | && icmp->code == 0) { 273 | printf("Echo response received, host reached!\n"); 274 | flag_host_reached = 1; 275 | break; 276 | } 277 | 278 | if (eth->type = htons(0x0800) && ip->proto == 1 && icmp->type == 11 // time exceeded message? 279 | //&& icmp->code == 0 280 | ) { 281 | printf("Found intermediary host n. %d\twith ip: ", ttl); 282 | for (int i = 0; i < 4; i++) 283 | printf("%d.", ((unsigned char *)&ip->saddr)[i]); 284 | printf("\n"); 285 | 286 | break; 287 | } 288 | } // end while 1 289 | ttl++; 290 | } // end while not reached 291 | } 292 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | np : ws18.c 2 | gcc -o np ws18.c 3 | -------------------------------------------------------------------------------- /Past exams/20090909-tcp_request.txt: -------------------------------------------------------------------------------- 1 | Facoltà di Scienze Statistiche 2 | 3 | PROVA SCRITTA DI RETI DI CALCOLATORI II 4 | 9 Settembre 2009 5 | 6 | Prof. N.Zingirian 7 | 8 | 9 | 10 | Si modifichi il programma nodo_ip.c, in modo tale che, anziché inviare una richiesta di tipo icmp echo request su un pacchetto IP, invii una richiesta di connessione TCP a un servizio web su un pacchetto IP indirizzato a 147.162..X e attenda ed elabori la risposta. 11 | 12 | La richiesta di connessione TCP ha il seguente formato: 13 | 14 | 15 | Con i seguenti requisiti 16 | 17 | • Il flag SYN è posto a 1 per indicare la richiesta di connessione 18 | • Il port destinazione è quello standard del servizio web 19 | • Il port sorgente è un numero arbitrario sempre diverso ad ogni richiesta di connessione 20 | • Il campo Sequence contiene un numero arbitrario sempre diverso ad ogni richiesta di connessione. 21 | • Il campo Acknowledgment è irrilevante 22 | • Il campo checksum viene calcolato utilizzando lo stesso algoritmo del checksum del pacchetto IP, e applicato ai seguenti campi: indirizzo IP sorgente (contenuto nel pacchetto IP), indirizzo IP (contenuto nel pacchetto IP) destinazione port sorgente e port destinazione (contenuti nel segmento TCP). 23 | • Il campo urgent pointer è messo a 0. 24 | • Il campo advertised window 0xFFFF 25 | • Il campo payload è vuoto. 26 | • Nessuna option. 27 | 28 | 29 | Per verificare il corretto funzionamento, controllare in modo automatico che venga ricevuta una segmento TCP in risposta avente i seguenti requisiti: 30 | 31 | • Che il port sorgente corrisponda al port standard del servizio web 32 | • Che il port destinazione, corrisponda al port sorgente indicato nella richiesta 33 | • Che il campo Acknowledgment riporti un pari al numero Sequence riportato sulla richiesta incrementato di 1 34 | • Abbia i flag SYN e ACK posti a 1. 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /Past exams/20100701-record_route.txt: -------------------------------------------------------------------------------- 1 | FACOLTA’ DI SCIENZE STATISTICHE 2 | RETI DI CALCOLATORI 3 | prof. Massimo Maresca, prof. Nicola Zingirian 4 | 1 Luglio 2010 5 | 6 | 7 | Il datagram IP costruito dal programma icmp_ip.c sviluppato a lezione è dotato di un header a lunghezza minima possibile (20 caratteri), poiché privo di campi opzionali. Tuttavia, il protocollo IP consente di estendere l’header IP, aggiungendo alcuni campi opzionali che permettono di richiedere o inviare informazioni aggiuntive ai nodi di rete attraversati dal pacchetto. Si intende ora esplorare questa possibilità. 8 | 9 | Si modifichi il programma icmp_ip.c sviluppato a lezione in modo tale che costruisca il datagram IP aggiungendo all’header IP il campo opzionale di tipo “Record Route” (descritto nella RFC 791, v. sotto). Questo campo riserva un’area libera (chiamata route data) all’interno dell’ header IP esteso, destinata a contenere la lista degli indirizzi IP dei nodi attraversati dal pacchetto. Ciascun nodo attraversato, infatti, in presenza dell’opzione “Record Route”, scrive il proprio indirizzo IP nell’area route data in coda agli indirizzi IP già salvati dai nodi precedenti. I campi length e pointer permettono di gestire l'area di memoria durante il viaggio del pacchetto, secondo quanto riportato nel testo tratto dalla RFC 791: 10 | 11 | Record Route 12 | 13 | +--------+--------+--------+---------//--------+ 14 | |00000111| length | pointer| route data | 15 | +--------+--------+--------+---------//--------+ 16 | Type=7 17 | 18 | The record route option provides a means to record the route of 19 | an internet datagram. 20 | 21 | The option begins with the option type code. The second octet 22 | is the option length which includes the option type code and the 23 | length octet, the pointer octet, and length – 3 octets of route 24 | data. The third octet is the pointer into the route data 25 | indicating the octet which begins the next area to store a route 26 | address. The pointer is relative to this option, and the 27 | smallest legal value for the pointer is 4. 28 | 29 | A recorded route is composed of a series of internet addresses. 30 | Each internet address is 32 bits or 4 octets. If the pointer is 31 | greater than the length, the recorded route data area is full. 32 | The originating host must compose this option with a large 33 | enough route data area to hold all the address expected. The 34 | size of the option does not change due to adding addresses. The 35 | intitial contents of the route data area must be zero. 36 | 37 | When an internet module routes a datagram it checks to see if 38 | the record route option is present. If it is, it inserts its 39 | own internet address as known in the environment into which this 40 | datagram is being forwarded into the recorded route begining at 41 | the octet indicated by the pointer, and increments the pointer 42 | by four. 43 | 44 | If the route data area is already full (the pointer exceeds the 45 | length) the datagram is forwarded without inserting the address 46 | into the recorded route. If there is some room but not enough 47 | room for a full address to be inserted, the original datagram is 48 | considered to be in error and is discarded. In either case an 49 | ICMP parameter problem message may be sent to the source host. 50 | 51 | 52 | Il candidato saprà di aver formato bene l’header IP esteso, se verificherà che la echo reply di ritorno dalla destinazione porterà nell’header IP l’opzione “Record Route” contenente nel campo “route data” la lista di indirizzi IP dei nodi attraversati durante il percorso della echo request. 53 | 54 | Ai fini dello svolgimento del compito si tenga altresì presente quanto segue: 55 | • Riservare la dimensione massima possibile di bytes a questo campo, tenendo conto di tutti i vincoli dello standard IP 56 | • Inviare il pacchetto al nodo 147.162.2.100 57 | • Se l’opzione non è formata correttamente, il primo nodo intermedio che riconosce un errore invia al nostro nodo un messaggio ICMP di tipo 12 (0xC) descritto dalla RFC792 (v. seguente) 58 | 59 | 0 1 2 3 60 | 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 61 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 62 | | Type | Code | Checksum | 63 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 64 | | Pointer | unused | 65 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 66 | | Internet Header + 64 bits of Original Data Datagram | 67 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 68 | 69 | IP Fields: 70 | 71 | Destination Address 72 | 73 | The source network and address from the original datagram's data. 74 | 75 | ICMP Fields: 76 | 77 | Type 78 | 79 | 12 80 | 81 | Code 82 | 83 | 0 = pointer indicates the error. 84 | 85 | Checksum 86 | 87 | The checksum is the 16-bit ones's complement of the one's 88 | complement sum of the ICMP message starting with the ICMP Type. 89 | For computing the checksum , the checksum field should be zero. 90 | This checksum may be replaced in the future. 91 | 92 | Pointer 93 | 94 | If code = 0, identifies the octet where an error was detected. 95 | 96 | Internet Header + 64 bits of Data Datagram 97 | 98 | The internet header plus the first 64 bits of the original 99 | datagram's data. This data is used by the host to match the 100 | message to the appropriate process. If a higher level protocol 101 | uses port numbers, they are assumed to be in the first 64 data 102 | bits of the original datagram's data. 103 | 104 | Description 105 | 106 | If the gateway or host processing a datagram finds a problem with 107 | the header parameters such that it cannot complete processing the 108 | datagram it must discard the datagram. One potential source of 109 | such a problem is with incorrect arguments in an option. The 110 | gateway or host may also notify the source host via the parameter 111 | problem message. This message is only sent if the error caused 112 | the datagram to be discarded. 113 | 114 | The pointer identifies the octet of the original datagram's header 115 | where the error was detected (it may be in the middle of an 116 | option). For example, 1 indicates something is wrong with the 117 | Type of Service, and (if there are options present) 20 indicates 118 | something is wrong with the type code of the first option. 119 | -------------------------------------------------------------------------------- /Past exams/20100716-time_exceeded.txt: -------------------------------------------------------------------------------- 1 | FACOLTA’ DI SCIENZE STATISTICHE 2 | RETI DI CALCOLATORI 3 | prof. Massimo Maresca, prof. Nicola Zingirian 4 | 16 Luglio 2010 5 | 6 | 7 | Si modifichi il programma icmp_ip.c sviluppato a lezione in modo tale che costruisca il datagram IP dotato di un “time to live” sufficientemente piccolo da impedire che il datagram IP giunga a destinazione. 8 | Si intercetti il messaggio ICMP “Time Exceeded” (v. documentazione sotto tratta da RFC 792) proveniente dal nodo intermedio che ha scartato il pacchetto e si stampi su schermo l’indirizzo IP che ha originato tale messaggio. 9 | 10 | Time Exceeded Message 11 | 12 | 0 1 2 3 13 | 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 14 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 15 | | Type | Code | Checksum | 16 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 17 | | unused | 18 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 19 | | Internet Header + 64 bits of Original Data Datagram | 20 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 21 | 22 | IP Fields: 23 | 24 | Destination Address 25 | 26 | The source network and address from the original datagram's data. 27 | 28 | ICMP Fields: 29 | 30 | Type 31 | 32 | 11 33 | 34 | Code 35 | 36 | 0 = time to live exceeded in transit; 37 | 38 | 1 = fragment reassembly time exceeded. 39 | 40 | Checksum 41 | 42 | The checksum is the 16-bit ones's complement of the one's 43 | complement sum of the ICMP message starting with the ICMP Type. 44 | For computing the checksum , the checksum field should be zero. 45 | This checksum may be replaced in the future. 46 | 47 | Internet Header + 64 bits of Data Datagram 48 | 49 | The internet header plus the first 64 bits of the original 50 | datagram's data. This data is used by the host to match the 51 | message to the appropriate process. If a higher level protocol 52 | uses port numbers, they are assumed to be in the first 64 data 53 | bits of the original datagram's data. 54 | 55 | Description 56 | 57 | If the gateway processing a datagram finds the time to live field 58 | is zero it must discard the datagram. The gateway may also notify 59 | the source host via the time exceeded message. 60 | 61 | If a host reassembling a fragmented datagram cannot complete the 62 | reassembly due to missing fragments within its time limit it 63 | discards the datagram, and it may send a time exceeded message. 64 | 65 | If fragment zero is not available then no time exceeded need be 66 | sent at all. 67 | 68 | Code 0 may be received from a gateway. Code 1 may be received 69 | from a host. 70 | -------------------------------------------------------------------------------- /Past exams/20100902-unreachable_ping.txt: -------------------------------------------------------------------------------- 1 | Facoltà di Scienze Statistiche 2 | 3 | PROVA SCRITTA DI RETI DI CALCOLATORI 4 | 5 | 2 Settembre 2010 6 | 7 | Prof. M. Maresca, N. Zingirian 8 | 9 | 10 | Si modifichi il programma che implementa le funzioni base del nodo IP, in modo che sia in grado di riconoscere, in ricezione, oltre che il consueto messaggio ICMP “echo reply”, anche un altro tipo di messaggio ICMP, chiamato “unreachable destination” di cui si riporta la documentazione dalla RFC 792. 11 | 12 | Si tenga presente che il messaggio “unreachable destination” viene generato da un router della rete, nel caso in cui rileva che il datagram IP che sta inoltrando è destinato ad un indirizzo che non potrà mai essere raggiunto. In tal caso il router: 13 | 1) elimina quel pacchetto IP (ossia non lo inoltra ad alcun altro router). 14 | 2) crea il messaggio ICMP “unreachable destination” 15 | 3) spedisce il messaggio ICMP al nodo che ha generato il pacchetto IP privo di destinazione raggiungibile per avvertirlo che ha eliminato il pacchetto. 16 | 17 | Per effettuare il test del programma, si invii un’ “echo request” ad un indirizzo inesistente (es. indirizzo 10.20.30.40) per ottenere in risposta un messaggio di “Destination Unreachable” e si scriva su schermo l’indirizzo IP del nodo della rete che ha generato quel messaggio. 18 | 19 | ________________ 20 | 21 | Dalla RFC 792: 22 | 23 | Destination Unreachable Message 24 | 25 | 0 1 2 3 26 | 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 27 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 28 | | Type | Code | Checksum | 29 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 30 | | unused | 31 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 32 | | Internet Header + 64 bits of Original Data Datagram | 33 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 34 | 35 | IP Fields: 36 | 37 | Destination Address 38 | 39 | The source network and address from the original datagram's data. 40 | 41 | ICMP Fields: 42 | 43 | Type 44 | 45 | 3 46 | 47 | Code 48 | 49 | 0 = net unreachable; 50 | 51 | 1 = host unreachable; 52 | 53 | 2 = protocol unreachable; 54 | 55 | 3 = port unreachable; 56 | 57 | 4 = fragmentation needed and DF set; 58 | 59 | 5 = source route failed. 60 | 61 | Checksum 62 | 63 | The checksum is the 16-bit ones's complement of the one's 64 | complement sum of the ICMP message starting with the ICMP Type. 65 | For computing the checksum , the checksum field should be zero. 66 | This checksum may be replaced in the future. 67 | 68 | Internet Header + 64 bits of Data Datagram 69 | 70 | The internet header plus the first 64 bits of the original 71 | datagram's data. This data is used by the host to match the 72 | message to the appropriate process. If a higher level protocol 73 | uses port numbers, they are assumed to be in the first 64 data 74 | bits of the original datagram's data. 75 | 76 | Description 77 | 78 | If, according to the information in the gateway's routing tables, 79 | the network specified in the internet destination field of a 80 | datagram is unreachable, e.g., the distance to the network is 81 | infinity, the gateway may send a destination unreachable message 82 | to the internet source host of the datagram. In addition, in some 83 | networks, the gateway may be able to determine if the internet 84 | destination host is unreachable. Gateways in these networks may 85 | send destination unreachable messages to the source host when the 86 | destination host is unreachable. 87 | 88 | If, in the destination host, the IP module cannot deliver the 89 | datagram because the indicated protocol module or process port is 90 | not active, the destination host may send a destination 91 | unreachable message to the source host. 92 | 93 | Another case is when a datagram must be fragmented to be forwarded 94 | by a gateway yet the Don't Fragment flag is on. In this case the 95 | gateway must discard the datagram and may return a destination 96 | unreachable message. 97 | 98 | Codes 0, 1, 4, and 5 may be received from a gateway. Codes 2 and 99 | 3 may be received from a host. 100 | 101 | 102 | -------------------------------------------------------------------------------- /Past exams/20100917-statistics.txt: -------------------------------------------------------------------------------- 1 | Facoltà di Scienze Statistiche 2 | 3 | PROVA SCRITTA DI RETI DI CALCOLATORI II 4 | 17 Settembre 2010 5 | 6 | Prof. M.Maresca N.Zingirian 7 | 8 | 9 | Si scriva un programma in grado di ricevere i frame ethernet dalla rete e calcoli le seguenti statistiche : 10 | 11 | su tutti i pacchetti ethernet: 12 | % frame contenenti pacchetti IP 13 | % frame contenenti pacchetti ARP 14 | % frame contenenti pacchetti né IP né ARP 15 | 16 | Su tutti i pacchetti IP 17 | % pacchetti contententi segmenti TCP 18 | % pacchetti contententi segmenti UDP 19 | % pacchetti contententi pacchetti ICMP 20 | % pacchetti contententi altro payload 21 | 22 | 23 | Il programma riceve 1000 pacchetti dalla rete, effettua il conteggio e, dopo aver ricevuto il millesimo scrive le statistiche. 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /Past exams/20130709-echo_reply.txt: -------------------------------------------------------------------------------- 1 | ESAME DI RETI DI CALCOLATORI 2 | Corso di Laurea Triennale in Ingegneria Informatica 3 | 09 Luglio 2013 4 | Prof. Nicola Zingirian 5 | Si modifichi il programma di invio/attesa di messaggio ICMP Echo Request/Response 6 | sviluppato durante il corso in modo che il programma - anziché inviare una Echo Request 7 | al nodo remoto - sia al contrario in grado di rispondere ad una Echo Request proveniente 8 | da un nodo esterno. 9 | Il programma modificato si comporterà come segue: 10 | 1. Si blocca in attesa di una ICMP Echo Request 11 | 2. Quando riceve una Echo Request 12 | a) stampa su schermo l’indirizzo IP del nodo remoto che l’ha inviata 13 | b) invia una Echo Response secondo le modalità previste dal protocollo ICMP 14 | (RFC 791) 15 | c) termina l’esecuzione 16 | Effettuare il test del programma modificato attraverso il comando “ping” eseguito su una 17 | macchina remota verso il nodo “lab” e commentare i risultati. 18 | 19 | -------------------------------------------------------------------------------- /Past exams/20140626-TRACE.txt: -------------------------------------------------------------------------------- 1 | Universit degli Studi di Padova 2 | Dipartimento di Ingegneria dell’informazione 3 | Esame di Reti di Calcolatori - 26 Giugno 2014 4 | Prof. ing. Nicola Zingirian 5 | 6 | Si modifichi il programma che implementa il Client Web in modo che utilizzi il metodo TRACE 7 | definito nell’HTTP/1.1 definito alla sezione 9.8 della RFC 2616 e identifichi se la Request viene 8 | modificata da proxy trasparenti prima di giungere al server. 9 | Si colleghi il Client Web modificato al servizio web esposto dai seguenti indirizzi IP: 10 | 184.168.221.96 (www.webtrace.com) 11 | 46.37.17.205 (www.radioamatori.it) 12 | 13 | -------------------------------------------------------------------------------- /Past exams/20140626-content_length.txt: -------------------------------------------------------------------------------- 1 | Universit degli Studi di Padova 2 | Dipartimento di Ingegneria dell’informazione 3 | Esame di Reti di Calcolatori - 26 Giugno 2014 4 | Prof. ing. Nicola Zingirian 5 | 6 | Si modifichi il programma che implementa il Client Web in modo tale che sia in grado di gestire 7 | l’header Content-Length descritto nella RFC 1945 alla sezione 10.4 8 | 9 | -------------------------------------------------------------------------------- /Past exams/20140722-ICMP_split.txt: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | ESAME DI RETI DI CALCOLATORI 5 | Corso di Laurea Triennale in Ingegneria Informatica 6 | 22 Luglio 2014 7 | Prof. Nicola Zingirian 8 | 9 | 10 | Si modifichi il programma sviluppato durante il corso che implementa la funzione di ICMP echo in modo tale che l’echo request venga veicolata da due frammenti di un pacchetto IP, il primo avente un payload di lunghezza 16 bytes e il secondo avente un payload della lunghezza necessaria. Se ne verifichi il corretto funzionamento nella rete. 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /Past exams/20150724-last_modified.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nicomazz/ComputerNetworks-unipd2018/ee64f21ccb57208d272c08a81bd8de0d9dd89950/Past exams/20150724-last_modified.jpg -------------------------------------------------------------------------------- /Past exams/20160620-IP_list_proxy.txt: -------------------------------------------------------------------------------- 1 | Dipartimento di Ingegneria dell'Informazione 2 | PROVA DI ESAME DI RETI DI CALCOLATORI 3 | 20 Giugno 2016 4 | prof. Nicola Zingirian 5 | 6 | 7 | Si modifichi il programma wp16.c in modo tale che: 8 | 9 | se l'indirizzo IP del client che vi si collega e' presente in una lista 10 | 11 | di indirizzi IP memorizzata nel programma wp16.c (massimo 4 indirizzi) 12 | 13 | allora il proxy consente solo il passaggio di file con contenuto testo o html. 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Past exams/20160620-chunked.txt: -------------------------------------------------------------------------------- 1 | Dipartimento di Ingegneria dell'Informazione 2 | PROVA DI ESAME DI RETI DI CALCOLATORI 3 | 20 Giugno 2016 4 | prof. Nicola Zingirian 5 | 6 | 7 | 8 | Si modifichi il programma ws16.c in modo che invii l'entity body con codifica di trasferimento 9 | Chunked. 10 | 11 | 12 | Si riporta la grammatica relativa alla codifica Chunked dalla RFC 2616 13 | 14 | 15 | The chunked encoding modifies the body of a message in order to 16 | transfer it as a series of chunks, each with its own size indicator, 17 | followed by an OPTIONAL trailer containing entity-header fields. This 18 | allows dynamically produced content to be transferred along with the 19 | information necessary for the recipient to verify that it has 20 | received the full message. 21 | 22 | Chunked-Body = *chunk 23 | last-chunk 24 | trailer 25 | CRLF 26 | 27 | chunk = chunk-size [ chunk-extension ] CRLF 28 | chunk-data CRLF 29 | chunk-size = 1*HEX 30 | last-chunk = 1*("0") [ chunk-extension ] CRLF 31 | 32 | chunk-extension= *( ";" chunk-ext-name [ "=" chunk-ext-val ] ) 33 | chunk-ext-name = token 34 | chunk-ext-val = token | quoted-string 35 | chunk-data = chunk-size(OCTET) 36 | trailer = *(entity-header CRLF) 37 | 38 | The chunk-size field is a string of hex digits indicating the size of 39 | the chunk. The chunked encoding is ended by any chunk whose size is 40 | zero, followed by the trailer, which is terminated by an empty line. 41 | 42 | The trailer allows the sender to include additional HTTP header 43 | fields at the end of the message. The Trailer header field can be 44 | used to indicate which header fields are included in a trailer (see 45 | section 14.40). 46 | 47 | 48 | 49 | NB: i campi opzionali chunk-estension non sono da considerare 50 | il campo trailer lo si effettui vuoto. 51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /Past exams/20160620-tcp_stream_reconstruction.txt: -------------------------------------------------------------------------------- 1 | Dipartimento di Ingegneria dell'Informazione 2 | PROVA DI ESAME DI RETI DI CALCOLATORI 3 | 20 Giugno 2016 4 | prof. Nicola Zingirian 5 | 6 | 7 | Si modifichi il programma tcp16.c in modo tale che: 8 | 9 | 10 | 1) Visualizzi i numeri di sequenza e acknowledgment dei pacchetti appartenenti unicamente alla prima connessione che intercetta 11 | 12 | 13 | 2) Ricostruisca ciascuno dei due stream su due buffer distinti e ne stampi su schermo i contenuti al termine della connessione. 14 | 15 | 16 | -------------------------------------------------------------------------------- /Past exams/20160715-unreachable_telnet.txt: -------------------------------------------------------------------------------- 1 |  2 | Università degli Studi di Padova -Dipartimento di Ingegneria Informatica 3 | Esame di Reti di Calcolatori - 15 Luglio 2016 4 | Prof. ing. Nicola Zingirian 5 | 6 | Il server cloud (88.80.187.84) e’ stato configurato per non rispondere alle richieste di connessione TCP destinate ai port che ricadono nel range [20000:30000]. In seguito a tale configurazione ogni richiesta di connessione destinata a tali port non ottiene risposta. Modificare il programma ping16.c sviluppato durante il corso in modo tale che sia in grado di generare un messaggio ICMP di “Destination Unreachable” che comunichi che il port non e’ disponibile. 7 | 8 | Al fine di verificare l’effettivo funzionamento del programma utilizzare da un client locale il comando 9 | 10 | telnet 88.80.187.84 11 | 12 | Se il comando telnet rimane appeso, significa che non ha ricevuto il messaggio ICMP (va quindi terminato con i tasti CTRL+C). 13 | Se il comando termina con indicazione di mancata raggiungibilita’, significa che il messaggio ICMP e’ stato ricevuto e quindi il test e’ riuscito. 14 | 15 | NB: Si scelga un opportuno numero di port individuale compreso tra 20000 e 30000 (ossia 2XXXX dove XXXX sono le ultime 4 cifre del proprio numero di matricola) e predispondendo il programma a reagire solo per quel determinato port. 16 | 17 | 18 | Fare riferimento ai documenti RFC792 e RFC793. 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Past exams/20170621-window_scale.txt: -------------------------------------------------------------------------------- 1 |  2 | Università degli Studi di Padova -Dipartimento di Ingegneria Informatica 3 | Esame di Reti di Calcolatori - 21 Giugno 2017 4 | Prof. Ing. Nicola Zingirian 5 | 6 | 7 | 8 | Si modifichi il programma tcp.c in modo che sia in grado di visualizzare su schermo, per ogni pacchetto TCP acquisito, la dimensione della finestra del controllo di flusso del TCP, tenendo conto della option del TCP "window scale” indicata nel capitolo 2 della RFC 7323, riportato nel seguito, che permette di superare il limite dei 16 bit del campo Window del segmento tcp (chiamato SEG.WND). 9 | Si scarichi anche la RFC793. https://tools.ietf.org/html/rfc793 10 | 11 | Si entri nel server cloud con il comando ssh nome_utente@88.80.187.84 12 | 13 | CONSEGNA 17.10 14 | 15 | 16 | TCP Window Scale Option 17 | 18 | 2.1. Introduction 19 | 20 | The window scale extension expands the definition of the TCP window 21 | to 30 bits and then uses an implicit scale factor to carry this 22 | 30-bit value in the 16-bit window field of the TCP header (SEG.WND in 23 | [RFC0793]). The exponent of the scale factor is carried in a TCP 24 | option, Window Scale. This option is sent only in a segment (a 25 | segment with the SYN bit on), hence the window scale is fixed in each 26 | direction when a connection is opened. 27 | 28 | The maximum receive window, and therefore the scale factor, is 29 | determined by the maximum receive buffer space. In a typical modern 30 | implementation, this maximum buffer space is set by default but can 31 | be overridden by a user program before a TCP connection is opened. 32 | This determines the scale factor, and therefore no new user interface 33 | is needed for window scaling. 34 | 35 | 2.2. Window Scale Option 36 | 37 | The three-byte Window Scale option MAY be sent in a segment by 38 | a TCP. It has two purposes: (1) indicate that the TCP is prepared to 39 | both send and receive window scaling, and (2) communicate the 40 | exponent of a scale factor to be applied to its receive window. 41 | Thus, a TCP that is prepared to scale windows SHOULD send the option, 42 | even if its own scale factor is 1 and the exponent 0. The scale 43 | factor is limited to a power of two and encoded logarithmically, so 44 | it may be implemented by binary shift operations. The maximum scale 45 | exponent is limited to 14 for a maximum permissible receive window 46 | size of 1 GiB (2^(14+16)). 47 | 48 | TCP Window Scale option (WSopt): 49 | 50 | Kind: 3 51 | 52 | Length: 3 bytes 53 | 54 | +---------+---------+---------+ 55 | | Kind=3 |Length=3 |shift.cnt| 56 | +---------+---------+---------+ 57 | 1 1 1 58 | 59 | This option is an offer, not a promise; both sides MUST send Window 60 | Scale options in their segments to enable window scaling in 61 | either direction. If window scaling is enabled, then the TCP that 62 | sent this option will right-shift its true receive-window values by 63 | 'shift.cnt' bits for transmission in SEG.WND. The value 'shift.cnt' 64 | 65 | 66 | 67 | Borman, et al. Standards Track [Page 8] 68 | 69 | RFC 7323 TCP Extensions for High Performance September 2014 70 | 71 | 72 | MAY be zero (offering to scale, while applying a scale factor of 1 to 73 | the receive window). 74 | 75 | This option MAY be sent in an initial segment (i.e., a segment 76 | with the SYN bit on and the ACK bit off). If a Window Scale option 77 | was received in the initial segment, then this option MAY be 78 | sent in the segment. A Window Scale option in a segment 79 | without a SYN bit MUST be ignored. 80 | 81 | The window field in a segment where the SYN bit is set (i.e., a 82 | or ) MUST NOT be scaled. 83 | 84 | 2.3. Using the Window Scale Option 85 | 86 | A model implementation of window scaling is as follows, using the 87 | notation of [RFC0793]: 88 | 89 | o The connection state is augmented by two window shift counters, 90 | Snd.Wind.Shift and Rcv.Wind.Shift, to be applied to the incoming 91 | and outgoing window fields, respectively. 92 | 93 | o If a TCP receives a segment containing a Window Scale 94 | option, it SHOULD send its own Window Scale option in the 95 | segment. 96 | 97 | o The Window Scale option MUST be sent with shift.cnt = R, where R 98 | is the value that the TCP would like to use for its receive 99 | window. 100 | 101 | o Upon receiving a segment with a Window Scale option 102 | containing shift.cnt = S, a TCP MUST set Snd.Wind.Shift to S and 103 | MUST set Rcv.Wind.Shift to R; otherwise, it MUST set both 104 | Snd.Wind.Shift and Rcv.Wind.Shift to zero. 105 | 106 | o The window field (SEG.WND) in the header of every incoming 107 | segment, with the exception of segments, MUST be left- 108 | shifted by Snd.Wind.Shift bits before updating SND.WND: 109 | 110 | SND.WND = SEG.WND << Snd.Wind.Shift 111 | 112 | (assuming the other conditions of [RFC0793] are met, and using the 113 | "C" notation "<<" for left-shift). 114 | 115 | o The window field (SEG.WND) of every outgoing segment, with the 116 | exception of segments, MUST be right-shifted by 117 | Rcv.Wind.Shift bits: 118 | 119 | SEG.WND = RCV.WND >> Rcv.Wind.Shift 120 | 121 | 122 | 123 | Borman, et al. Standards Track [Page 9] 124 | 125 | RFC 7323 TCP Extensions for High Performance September 2014 126 | 127 | 128 | TCP determines if a data segment is "old" or "new" by testing whether 129 | its sequence number is within 2^31 bytes of the left edge of the 130 | window, and if it is not, discarding the data as "old". To insure 131 | that new data is never mistakenly considered old and vice versa, the 132 | left edge of the sender's window has to be at most 2^31 away from the 133 | right edge of the receiver's window. The same is true of the 134 | sender's right edge and receiver's left edge. Since the right and 135 | left edges of either the sender's or receiver's window differ by the 136 | window size, and since the sender and receiver windows can be out of 137 | phase by at most the window size, the above constraints imply that 138 | two times the maximum window size must be less than 2^31, or 139 | 140 | max window < 2^30 141 | 142 | Since the max window is 2^S (where S is the scaling shift count) 143 | times at most 2^16 - 1 (the maximum unscaled window), the maximum 144 | window is guaranteed to be < 2^30 if S <= 14. Thus, the shift count 145 | MUST be limited to 14 (which allows windows of 2^30 = 1 GiB). If a 146 | Window Scale option is received with a shift.cnt value larger than 147 | 14, the TCP SHOULD log the error but MUST use 14 instead of the 148 | specified value. This is safe as a sender can always choose to only 149 | partially use any signaled receive window. If the receiver is 150 | scaling by a factor larger than 14 and the sender is only scaling by 151 | 14, then the receive window used by the sender will appear smaller 152 | than it is in reality. 153 | 154 | The scale factor applies only to the window field as transmitted in 155 | the TCP header; each TCP using extended windows will maintain the 156 | window values locally as 32-bit numbers. For example, the 157 | "congestion window" computed by slow start and congestion avoidance 158 | (see [RFC5681]) is not affected by the scale factor, so window 159 | scaling will not introduce quantization into the congestion window. 160 | 161 | 162 | 163 | -------------------------------------------------------------------------------- /Past exams/20180619-SYNACK.txt: -------------------------------------------------------------------------------- 1 | Università degli Studi di Padova -Dipartimento di Ingegneria Informatica 2 | Esame di Reti di Calcolatori - 19 giugno 2018 3 | Prof. ing. Nicola Zingirian 4 | Il server cloud è configurato in modo tale da non rispondere alle richieste di connessione TCP per i port nel 5 | range da 19000 19999. 6 | Si lavori con il port 19XYZ dove XYZ sono gli ultimi 3 numeri del proprio numero di matricola. 7 | Dal PC locale si effettui tramite il comando 8 | telnet 88.80.187.84 19XYZ 9 | Si vedrà che non si riceve alcuna risposta nè di accettazione nè di rifiuto di connessione. 10 | Si modifichi il programma ​ping sviluppato a lezione in modo tale che ricevendo una richiesta di connessione 11 | TCP (SYN) sul port 19XYZ risponda opportunamente (SYN+ACK) secondo il protocollo TCP ​RFC 793 12 | 13 | CONSEGNA ORE 15:00 14 | 15 | -------------------------------------------------------------------------------- /Past exams/20180620-echo_reply.txt: -------------------------------------------------------------------------------- 1 | Università degli Studi di Padova - Dipartimento di Ingegneria Informatica 2 | Esame di Reti di Calcolatori - 20 Giugno 2018 3 | Prof. ing. Nicola Zingirian 4 | 5 | Il server cloud è ora configurato in modo tale da ​non rispondere​ alle richieste di echo. 6 | Si provi dal ​pc locale del laboratorio​ ad effettuare il comando 7 | ping 88.80.187.84 8 | e si noterà che non risponde 9 | 10 | Si modifichi il programma ​ping.c sviluppato a lezione in modo tale che, quando riceve un echo icmp, risponda 11 | con una echo reply. 12 | Se il programma e’ corretto si notera’ che il comando ping dal PC locale del laboratorio comincia a funzionare 13 | 14 | ATTENZIONE​ per evitare interferenze tra i diversi programmi si verifichi il funzionamento come segue: 15 | 16 | 1) Si effettui il comando sul pc locale del laboratorio: 17 | ping -s ​XYZ 88.80.187.84 18 | Verificandone sul manuale il significato 19 | XYZ ​sono le ultime 3 cifre del numero di matricola con le seguenti eccezioni da 20 | applicare in cascata 21 | ● Eccezione 1 : se ​XYZ ​< 100 usare il numero 1​XYZ​). 22 | ● Eccezione 2 : se ​XYZ ​e’ pari usare il numero successivo (1)​XYZ​+1 23 | 24 | 2) Si faccia in modo che il proprio programma risponda ​solo alle richieste che 25 | hanno lunghezza di payload​ ​XYZ 26 | 27 | CONSEGNA 11.15 28 | 29 | 30 | -------------------------------------------------------------------------------- /Past exams/20180711-NAT.txt: -------------------------------------------------------------------------------- 1 | Università degli Studi di Padova - Dipartimento di Ingegneria Informatica 2 | Esame di Reti di Calcolatori - 11 Luglio 2018 3 | Prof. ing. Nicola Zingirian 4 | 5 | Si modifichi il programma ​ping.c ​in modo che funzioni come un NAT - Network Address Translator. 6 | Quando arriva una richiesta di connessione TCP da un client Web esterno all’indirizzo IP 88.80.187.84 e port 7 | 2XXXX1 il programma inoltra quel pacchetto TCP/IP (e tutti i successivi di quella connessione) verso il server 8 | web di google (216.58.204.68) traducendone opportunamente indirizzi e port, ricalcolando lo pseudo-header, e 9 | ogni volta che un pacchetto TCP/IP di quella connessione torna dal server di Google lo inoltra al client web 10 | esterno ritraducendo in modo opportuno indirizzi e port. 11 | Si faccia riferimento alle ​RFC 791​ e ​RFC 793​. 12 | Il programma deve permettere ad un browser sul PC locale di effettuare l’accesso ​http://88.80.187.84:2XXXX e 13 | di vedere funzionare il servizio di Google. 14 | Si osservi il comportamento del servizio di Google e si veda quali altre trasformazioni siano necessarie per farlo 15 | funzionare in modo trasparente. 16 | 17 | Per evitare conflitti il port locale utilizzato per la connessione verso il server di Google dev’essere 18 | 3XXXX2 19 | 20 | ________ 21 | 22 | CONSEGNA ORE 17:10 23 | 24 | 1 25 | 2 26 | 27 | Si intenda XXXX come le ultime 4 cifre del suo numero di matricola 28 | Si intenda XXXX come le ultime 4 cifre del suo numero di matricola 29 | 30 | -------------------------------------------------------------------------------- /Past exams/20180712-multiple_http_request.txt: -------------------------------------------------------------------------------- 1 | Università degli Studi di Padova - Dipartimento di Ingegneria Informatica 2 | Esame di Reti di Calcolatori - 12 Luglio 2018 3 | Prof. ing. Nicola Zingirian 4 | 5 | Si modifichi il programma ​ws18.c in modo tale che sia in grado di gestire più richieste HTTP/1.1 all’interno della 6 | medesima connessione TCP senza l’uso di chunk. 7 | Si faccia riferimento alla ​RFC2616​. 8 | Si provi con un browser l’accesso a due pagine tra loro linkate verificando che il server risponda a numerose 9 | richieste senza interrompere la connessione. 10 | pag1.html: 11 | Vai a Pagina 2 12 | pag2.html: 13 | Vai a Pagina 1 14 | 15 | Per effettuare il test si utilizzi il port 1XXXX dove XXXX sono le ultime quattro cifre del numero di 16 | matricola 17 | 18 | _______ 19 | CONSEGNA ORE 15.15 20 | 21 | -------------------------------------------------------------------------------- /Past exams/20190201-blacklist.txt: -------------------------------------------------------------------------------- 1 | Università degli Studi di Padova 2 | Dipartimento di Ingegneria dell’Informazione 3 | Esame di Reti di Calcolatori - 1 Febbraio 2019 4 | Prof. ing. Nicola Zingirian 5 | 6 | Si modifichi il programma Web Server in modo che si comporti come segue. 7 | Se l'utente di un client richiede una risorsa provenendo da una pagina configurata come 8 | “cattiva” (blacklisted), il Web Server non permette l’accesso alla risorsa richiesta ma ridireziona 9 | il client alla pagina di provenienza. 10 | Creare prima il meccanismo e, solo successivamente, gestire un file degli URL in black list. 11 | 12 | Si faccia riferimento alla ​RFC 1945 13 | 14 | -------------------------------------------------------------------------------- /Past exams/Esami Teoria/ESAME_DI_RETI_DI_CALCOLATORI-Teoria-2013-07-09-1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nicomazz/ComputerNetworks-unipd2018/ee64f21ccb57208d272c08a81bd8de0d9dd89950/Past exams/Esami Teoria/ESAME_DI_RETI_DI_CALCOLATORI-Teoria-2013-07-09-1.pdf -------------------------------------------------------------------------------- /Past exams/Esami Teoria/ESAME_DI_RETI_DI_CALCOLATORI-Teoria-2013-07-09-2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nicomazz/ComputerNetworks-unipd2018/ee64f21ccb57208d272c08a81bd8de0d9dd89950/Past exams/Esami Teoria/ESAME_DI_RETI_DI_CALCOLATORI-Teoria-2013-07-09-2.pdf -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-midnight --------------------------------------------------------------------------------