int get_source_ipv4(int protocol, struct sockaddr_in * address) { /* Voir la section NOTES du man(2) de gethostname pour la taille * du buffer. */ char buffer[HOST_NAME_MAX+1]; gethostname(buffer, HOST_NAME_MAX+1); int success = get_ipv4(buffer, protocol, address); /* Workaround pour obtenir une adresse de la machine. * * Sur certaines machines getaddrinfo retourne pour unique adresse 127.0.0.1 * lorsqu'on donne le hostname de la machine... * Sur d'autres elle retourne bien les adresses des interfaces * de la machine. * * De même avec les « vrais » ping et traceroute: * `ping localhost` et `ping <hostname de la machine>` vont tous deux se faire sur * 127.0.0.1, mais sur d'autres machines se feront sur deux adresses différentes. * Configuration des machines ? Versions des logiciels ? ...? * * Avec ça, ça fonctionne partout : */ const in_addr_t REFUSED_IPV4 = inet_addr("127.0.0.1"); if (address->sin_addr.s_addr == REFUSED_IPV4) success = get_interface_ipv4(address); return success; }
int anna(const char * hostname) { int success; struct sockaddr_in address; struct timeval wait_time = { 1, 0 }; succeed_or_die(success, 0, get_ipv4(hostname, IPPROTO_ICMP, &address)); int sockfd; succeed_or_die(success, 0, create_raw_socket(AF_INET, SOCK_RAW, IPPROTO_ICMP, &sockfd)); set_handler(); int i; for (i = 0; fin_des_temps == 1; i++) { printf("Discovering new route:\n"); printf("----------------------\n"); succeed_or_die(success, 0, traceroute_icmp_v4(hostname, 64, 3, 64, &wait_time)); printf("\n"); printf("Pinging:\n"); printf("--------\n"); ping_v4(hostname); printf("\n"); } printf("traceroute and pinging done %d time(s).\n", i); close(sockfd); return success; }
void set_interface(interface *inter, struct ifaddrs *ifa) { get_name(inter,ifa->ifa_name); get_status(inter,ifa); if (ifa->ifa_addr->sa_family == AF_INET) { get_ipv4(inter,ifa); get_mask(inter,ifa); } if (ifa->ifa_addr->sa_family == AF_INET6) get_ipv6(inter,ifa); if (ifa->ifa_addr->sa_family == AF_PACKET) get_hwaddr(inter,ifa); }
int main(int argc, char **argv) { int raw_mode = 0; struct GlobalHeader ghead; // parameter check if(argc == 1) { raw_mode = 0; } else if(argc == 2) { if(0 != strcmp(argv[1], "-r")) { usage(); return 0; } raw_mode = 1; } else { usage(); return 0; } // read global header if(!raw_mode) { // XXX Should check link type and record snapshot length. fread(&ghead, sizeof(unsigned char), sizeof(struct GlobalHeader), stdin); if(ghead.magic != MAGIC_NUMBER) { printf("invalid file format\n"); return 0; } printf("PCAP format v%d.%d, ", ghead.majorver, ghead.minorver); if(ghead.linklayertype != 1) { printf("unsupported link layer type\n"); return 0; } printf("link layer type: Ethernet.\n"); } // read each packet while (1) { int i; struct PacketHeader phead; struct EthernetHeader ehead; printf("\n"); // packet header if (!raw_mode) { // XXX Should use length information in decoding below. if(sizeof(struct PacketHeader) != fread(&phead, sizeof(unsigned char), sizeof(struct PacketHeader), stdin)) break; if(phead.packetsize > ghead.snapshotlength) { printf("wrong packet at 0x%08x\n", (int)ftell(stdin)); return 0; } printf("<<<PCAP packet\n"); printf(" packet size: %d\n", phead.packetsize); printf(" payload size: %d\n", phead.payloadsize); } // data captured from wire get_ether(&ehead); print_ether(&ehead); if (ehead.length_type <= 1500) { // old style packet printf("Old style packet, length = %d\n", ehead.length_type); printf("We don't support this packet now\n"); if (!raw_mode) { dump(phead.packetsize-sizeof(ehead), 1); } } else if (ehead.length_type == 0x0800) { // ASSIGNMENT: MODIFY THIS TO PRINT INFORMATION ABOUT ENCAPSULATED PAYLOAD. struct IPv4Header ipv4head; get_ipv4(&ipv4head); print_ipv4(&ipv4head); if(ipv4head.protocol == 4) { printf("IP packet\n"); printf("Wedon't support this packet now\n"); dump(ipv4head.datalen-sizeof(ipv4head), 1); } else if(ipv4head.protocol == 6) { struct TCPHeader tcphead; get_tcp(&tcphead); print_tcp(&tcphead); // get payload in TCP packet //dump(ipv4head.datalen-sizeof(ipv4head)-sizeof(tcphead), 2); if(phead.packetsize >= sizeof(ehead)+ipv4head.datalen) { dump(ipv4head.datalen-sizeof(ipv4head)-sizeof(tcphead), 0); } else { dump((ipv4head.datalen-sizeof(ipv4head)-sizeof(tcphead))-(sizeof(ehead)+ipv4head.datalen-phead.packetsize), 0); } } else if(ipv4head.protocol == 17) { struct UDPHeader udphead; get_udp(&udphead); assert(udphead.size == ipv4head.datalen-sizeof(ipv4head)); print_udp(&udphead); // get payload in UDP packet if(phead.packetsize >= sizeof(ehead)+ipv4head.datalen) { dump(udphead.size-sizeof(udphead), 0); } else { dump((udphead.size-sizeof(udphead))-(sizeof(ehead)+ipv4head.datalen-phead.packetsize), 0); } } else { printf("Unexpected IP packet\n"); dump(ipv4head.datalen-sizeof(ipv4head), 1); } if(!raw_mode) { if(phead.packetsize > sizeof(ehead)+ipv4head.datalen) { printf("pad:\n"); dump(phead.packetsize-sizeof(ehead)-ipv4head.datalen, 1); } } } else if(ehead.length_type == 0x0806) { printf("ARP packet\n"); printf("We don't support this packet now\n"); if (!raw_mode) { dump(phead.packetsize-sizeof(ehead), 1); } } else if(ehead.length_type == 0x86DD) { printf("IPv6 packet\n"); printf("We don't support this packet now\n"); if (!raw_mode) { dump(phead.packetsize-sizeof(ehead), 1); } } else { printf("Unexpected Ethernet packet\n"); if (!raw_mode) { dump(phead.packetsize-sizeof(ehead), 1); } } } return 0; }
int do_recv (const char *answer) { if (get_ipv4 () < 0) { fprintf (stderr, "ERROR on getting IPv4 address, exiting...\n"); return -1; } struct sockaddr_in my_addr, peer_addr; unsigned int file_size = 0, total_bytes_read = 0, tmp_file_size; ssize_t nread = 0, tx = 0; size_t socket_len = 0; void *filebuffer = NULL; char *filename = NULL; char yes_or_no[2], hash[33]; /* Info sul server locale */ my_addr.sin_family = AF_INET; my_addr.sin_port = 15000; my_addr.sin_addr.s_addr = INADDR_ANY; init_signals (); if ((fsd.sockd = socket (AF_INET, SOCK_STREAM, 0)) < 0) { fprintf (stderr, "Error on socket creation\n"); return -1; } if (bind (fsd.sockd, (struct sockaddr *) &my_addr, sizeof (struct sockaddr_in)) < 0) { fprintf (stderr, "Bind error\n"); return -1; } if (listen (fsd.sockd, 10) < 0) { fprintf (stderr, "Error on listen"); return -1; } new_conn: socket_len = sizeof (peer_addr); if ((fsd.newsockd = accept (fsd.sockd, (struct sockaddr *) &peer_addr, (socklen_t *) &socket_len)) < 0) { fprintf (stderr, "Connection error (accept)\n"); return -1; } file_size = total_bytes_read = nread = 0; memset( yes_or_no, 0, sizeof (yes_or_no)); if (recv (fsd.newsockd, &file_size, sizeof (file_size), 0) < 0) { fprintf(stderr, "Error on receiving the file name length\n"); return -1; } filename = (char *) malloc (file_size); if (filename == NULL) { fprintf(stderr, "Error during filename memory allocation\n"); return -1; } if (recv (fsd.newsockd, filename, file_size, 0) < 0) { fprintf(stderr, "Error on receiving the file name\n"); free(filename); return -1; } file_size = 0; if (recv (fsd.newsockd, &file_size, sizeof(file_size), 0) < 0) { fprintf (stderr, "Error on receiving the file size\n"); free (filename); return -1; } if (strcmp (answer, "y") == 0) { strcpy (yes_or_no, "Y"); goto auto_accept; } printf ("Do you want to receive the file '%s' which size is '%"PRIu32"' bytes? (Y or N)\n", filename, file_size); another_yorn: if(scanf("%1s", yes_or_no) == EOF) { fprintf (stderr, "Scanf error\n"); free (filename); return -1; } yes_or_no[0] = toupper (yes_or_no[0]); if (strcmp (yes_or_no, "Y") != 0) { if (strcmp (yes_or_no, "N") != 0) { printf ("You have to write Y or N, try again: "); memset (yes_or_no, 0, sizeof (yes_or_no)); goto another_yorn; } } auto_accept: if (strcmp (yes_or_no, "N") == 0) { printf ("Transfer aborted\n"); if (send (fsd.newsockd, yes_or_no, 2, 0) < 0) { printf ("Error on sending N\n"); free (filename); return -1; } close (fsd.newsockd); free (filename); goto new_conn; } else { if (send (fsd.newsockd, yes_or_no, 2, 0) < 0) { fprintf (stderr, "Error on sending Y\n"); free (filename); return -1; } } tmp_file_size = file_size; filebuffer = malloc (file_size); if (filebuffer == NULL) { fprintf (stderr, "Error during filebuffer memory allocation\n"); free (filename); return -1; } fsd.fd = open (filename, O_CREAT | O_WRONLY, 0644); if (fsd.fd < 0) { fprintf (stderr, "Error during file opening\n"); free (filename); free (filebuffer); return -1; } tx = 0; while((total_bytes_read != file_size) && ((nread = read(fsd.newsockd, filebuffer, tmp_file_size)) > 0)) { tx += nread; printf ("\r%zd%%", (tx * 100 / file_size)); if (write (fsd.fd, filebuffer, nread) != nread) { fprintf (stderr, "Write error\n"); free (filename); free (filebuffer); return -1; } total_bytes_read += nread; tmp_file_size -= nread; } char *file_md5 = check_md5 (filename); if (recv (fsd.newsockd, hash, 33, 0) < 0) { fprintf (stderr, "Error on receiving file md5\n"); free (filename); free (file_md5); return -1; } if (strcmp (file_md5, hash) == 0) { memset (yes_or_no, 0, sizeof(yes_or_no)); strcpy (yes_or_no, "Y"); if (send (fsd.newsockd, yes_or_no, 2, 0) < 0) { free (filename); free (file_md5); return -1; } printf ("\n--> File successfully received\n"); } else { memset (yes_or_no, 0, sizeof (yes_or_no)); strcpy (yes_or_no, "N"); if (send (fsd.newsockd, yes_or_no, 2, 0) < 0) { close (fsd.newsockd); close (fsd.fd); free (filename); free (file_md5); goto new_conn; } printf ("\n--> File transfer FAILED, md5sum doesn't match\n"); } free (file_md5); close (fsd.fd); free (filename); free (filebuffer); close (fsd.newsockd); goto new_conn; }
static inline int ping_v4(const char * hostname) { int sockfd; struct sockaddr_in address; icmp4_packet packet; int success = get_ipv4(hostname, IPPROTO_ICMP, &address); printf("ping "); print_host_v4(&address); printf("\n"); succeed_or_die(success, 0, create_raw_socket(AF_INET, SOCK_RAW, IPPROTO_ICMP, &sockfd)); succeed_or_die(success, 0, icmp4_packet_init(&packet, extract_ipv4(&address))); succeed_or_die(success, 0, icmp4_packet_set_length(&packet, sizeof packet)); int sent = 0; int i = 0; int gotten = 0; struct timeval wait_time = { 1, 0 }; long double min = 0.; long double max = 0.; long double sum = .0; struct timeval ping_start = { 0, 0 }; struct timeval ping_end = { 0, 0 }; gettimeofday(&ping_start, NULL); while (success == 0 && fin_des_temps == 1) { struct timeval start = { 0, 0 }; struct timeval end = { 0, 0 }; succeed_or_die(success, 0, icmp4_packet_set_echo_seq(&packet, i)); gettimeofday(&start, NULL); if (sendto(sockfd, &packet, sizeof packet, 0, (struct sockaddr *) &address, sizeof address) == sizeof packet) { sent++; icmp4_packet received; memset(&received, 0, sizeof received); int before = gotten; if (receive_icmp_v4(sockfd, &address, &wait_time, &received) == 0) { if (received.icmp_header.type == ICMP_ECHOREPLY && received.icmp_header.un.echo.sequence == i && received.icmp_header.un.echo.id == packet.icmp_header.un.echo.id ) { gotten++; gettimeofday(&end, NULL); struct timeval diff = diff_timeval(start, end); long double rtt = extract_time(diff); update_statistics(&min, &max, &sum, rtt, gotten, before); print_received(&received, &address, rtt); if (rtt > sum / gotten * 2 || rtt < sum / gotten / 2) success = -1; } } if ((float) gotten / sent < 0.7) success = -1; } i++; sleep(1); } gettimeofday(&ping_end, NULL); struct timeval total = diff_timeval(ping_start, ping_end); print_ping_statistics(sent, gotten, min, max, sum, total, &address); return success; }