diff options
Diffstat (limited to 'Semestr 4/sieci/pracownia1/traceroute.c')
-rw-r--r-- | Semestr 4/sieci/pracownia1/traceroute.c | 88 |
1 files changed, 44 insertions, 44 deletions
diff --git a/Semestr 4/sieci/pracownia1/traceroute.c b/Semestr 4/sieci/pracownia1/traceroute.c index 9281e4f..0e51c14 100644 --- a/Semestr 4/sieci/pracownia1/traceroute.c +++ b/Semestr 4/sieci/pracownia1/traceroute.c @@ -1,3 +1,8 @@ +/* Pracownia programistyczna nr 1 - traceroute + * ImiÄ™ i nazwisko: Franciszek Malinka + * Nr indeksu: 316093 + */ + #include <stdio.h> #include <errno.h> #include <netinet/ip.h> @@ -23,6 +28,23 @@ void print_as_bytes (unsigned char* buff, ssize_t length) printf ("%.2x ", *buff); } +void debug_received(uint8_t *buffer, struct sockaddr_in *sender, int packet_len) { + char ip_str[20]; + inet_ntop(AF_INET, &(sender->sin_addr), ip_str, sizeof(ip_str)); + + printf("IP packet with ICMP content from: %s\n", ip_str); + struct ip* ip_header = (struct ip*) buffer; + ssize_t ip_header_len = 4 * ip_header->ip_hl; + + printf ("IP header: "); + print_as_bytes (buffer, ip_header_len); + printf("\n"); + + printf ("IP data: "); + print_as_bytes (buffer + ip_header_len, packet_len - ip_header_len); + printf("\n\n"); +} + struct sockaddr_in get_sockaddr_from_ip(char *ip) { struct sockaddr_in sock; bzero(&sock, sizeof(sock)); @@ -71,7 +93,6 @@ void send_icmp_packet(int sockfd, struct sockaddr_in *destination, int ttl) { struct icmp header = create_icmp_header(ttl); setsockopt(sockfd, IPPROTO_IP, IP_TTL, &ttl, sizeof(int)); - // printf("%u %d\n", destination->sin_addr.s_addr, sockfd); ssize_t bytes_sent = sendto( sockfd, &header, @@ -84,13 +105,11 @@ void send_icmp_packet(int sockfd, struct sockaddr_in *destination, int ttl) { fprintf(stderr, "Error while sending ICMP packet: %s\n", strerror(errno)); exit(EXIT_FAILURE); } - // fprintf(stdout, "Bytes sent: %ld\n", bytes_sent); } /* Return ip address of the sender of recceived package */ ssize_t recv_packet(int sockfd, struct sockaddr_in *sender, uint8_t *buffer) { - socklen_t sender_len = sizeof(*sender); - + socklen_t sender_len = sizeof(*sender); ssize_t packet_len = recvfrom(sockfd, buffer, IP_MAXPACKET, 0, (struct sockaddr*)sender, &sender_len); @@ -114,36 +133,14 @@ int try_select(int sockfd, struct timeval *tv) { return select(sockfd+1, &descriptors, NULL, NULL, tv); } -void in_addr_to_string(struct in_addr *sender, char *ip_str) { - inet_ntop(AF_INET, sender, ip_str, sizeof(ip_str)); -} - -void debug_recieved(uint8_t *buffer, struct sockaddr_in *sender, int packet_len) { - char ip_str[20]; - inet_ntop(AF_INET, &(sender->sin_addr), ip_str, sizeof(ip_str)); - - // in_addr_to_string(&(sender->sin_addr), ip_str); - printf("IP packet with ICMP content from: %s\n", ip_str); - struct ip* ip_header = (struct ip*) buffer; - ssize_t ip_header_len = 4 * ip_header->ip_hl; - - printf ("IP header: "); - print_as_bytes (buffer, ip_header_len); - printf("\n"); - - printf ("IP data: "); - print_as_bytes (buffer + ip_header_len, packet_len - ip_header_len); - printf("\n\n"); -} - -void pretty_print_router(int ttl, struct in_addr *senders, float mean_wait_time, int messages_recieved) { +void pretty_print_router(int ttl, struct in_addr *senders, float mean_wait_time, int messages_received) { char ip_str[20]; printf("%d.\t", ttl); - if (messages_recieved == 0) { + if (messages_received == 0) { printf("*\n"); } else { - for (int i = 0; i < messages_recieved; i++) { + for (int i = 0; i < messages_received; i++) { bool already_printed = false; for (int j = 0; j < i; j++) { if (senders[i].s_addr == senders[j].s_addr) { @@ -153,27 +150,25 @@ void pretty_print_router(int ttl, struct in_addr *senders, float mean_wait_time, } if (already_printed) continue; inet_ntop(AF_INET, senders + i, ip_str, sizeof(ip_str)); - // in_addr_to_string(senders + i, ip_str); printf("%-15s ", ip_str); } - if (messages_recieved < MESSAGES_PER_TTL) printf("\t???\n"); + if (messages_received < MESSAGES_PER_TTL) printf("\t???\n"); else printf("\t%.2fms\n", mean_wait_time); } } +// This function decapsulates important data from the IMCP replies void get_important_data(uint8_t *buffer, uint8_t *code, uint16_t *id, uint16_t *seq) { struct ip* ip_header = (struct ip*) buffer; ssize_t offset = 4 * ip_header->ip_hl; *code = ((struct icmp *)(buffer + offset))->icmp_type; - if (*code == ICMP_TIMXCEED) { + if (*code != ICMP_ECHOREPLY && *code != ICMP_TIMXCEED) { + return; + } else if (*code == ICMP_TIMXCEED) { offset += ICMP_MINLEN; offset += 4 * ((struct ip *)(buffer + offset))->ip_hl; *seq = ((struct icmp *)(buffer + offset))->icmp_seq; *id = ((struct icmp *)(buffer + offset))->icmp_id; - } - else if (*code != ICMP_ECHOREPLY) { - fprintf(stderr, "Something went wrong, recieved ICMP packet with code %d\n.", *code); - exit(EXIT_FAILURE); } else { *seq = ((struct icmp *)(buffer + offset))->icmp_seq; *id = ((struct icmp *)(buffer + offset))->icmp_id; @@ -181,13 +176,13 @@ void get_important_data(uint8_t *buffer, uint8_t *code, uint16_t *id, uint16_t * } // timeout in milliseconds -float get_replies(int sockfd, long timeout, int ttl, int *messages_recieved, struct in_addr *senders) { +float get_replies(int sockfd, long timeout, int ttl, int *messages_received, struct in_addr *senders) { struct sockaddr_in sender; uint8_t buffer[IP_MAXPACKET]; int ready; long mean_wait_time = 0; struct timeval tv; tv.tv_sec = timeout / 1000; tv.tv_usec = 0; - *messages_recieved = 0; + *messages_received = 0; while ((ready = try_select(sockfd, &tv))) { if (ready < 0) { @@ -201,25 +196,29 @@ float get_replies(int sockfd, long timeout, int ttl, int *messages_recieved, str get_important_data(buffer, &icmp_code, &id, &seq); if (seq == ttl) { - senders[(*messages_recieved)++] = sender.sin_addr; + senders[(*messages_received)++] = sender.sin_addr; mean_wait_time += timeout * 1000 - tv.tv_usec; - if (*messages_recieved == MESSAGES_PER_TTL) break; + if (*messages_received == MESSAGES_PER_TTL) break; } } // changing from microseconds to miliseconds return (float)mean_wait_time / 3.0 / 1000.0; } +// Core of the program. void traceroute(struct sockaddr_in *destination) { - int sockfd = create_raw_icmp_socket(), messages_recieved = 0; + int sockfd = create_raw_icmp_socket(), messages_received = 0; struct in_addr senders[MESSAGES_PER_TTL]; for (int ttl = 1; ttl <= MAX_TTL; ++ttl) { send_icmp_requests(sockfd, destination, ttl, MESSAGES_PER_TTL); - float mean_wait_time = get_replies(sockfd, 1000, ttl, &messages_recieved, senders); - pretty_print_router(ttl, senders, mean_wait_time, messages_recieved); - for (int i = 0; i < messages_recieved; i++) { + float mean_wait_time = get_replies(sockfd, 1000, ttl, &messages_received, senders); + pretty_print_router(ttl, senders, mean_wait_time, messages_received); + + // what if our packet branched and we got to the destination faster by some path? + // we gotta make a loop, not an if + for (int i = 0; i < messages_received; i++) { if (senders[i].s_addr == destination->sin_addr.s_addr) { return; } @@ -234,6 +233,7 @@ int main(int argc, char * argv[]) { } struct sockaddr_in destination = get_sockaddr_from_ip(argv[1]); + fprintf(stdout, "traceroute to %s, %d hops max\n", argv[1], MAX_TTL); traceroute(&destination); return 0; |