char* get_mac_addr(int socket, char *interface) { uint8_t *src_mac; char *mac; struct ifreq ifr; memset(&ifr, 0, sizeof (ifr)); bzero(&ifr, sizeof (ifr)); src_mac = allocate_ustrmem(ETHER_ADDR_LEN); mac = allocate_strmem(MAC_ADDR_STRLEN); strncpy((char *) ifr.ifr_name, interface, IFNAMSIZ); if ((ioctl(socket, SIOCGIFHWADDR, &ifr)) == -1) { submit_log("create_raw_socket(): [%s]\n", "Error getting HW ADDR"); exit(EXIT_FAILURE); } memcpy(src_mac, ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN * sizeof (uint8_t)); sprintf(mac, "%02x:%02x:%02x:%02x:%02x:%02x", src_mac[0], src_mac[1], src_mac[2], src_mac[3], src_mac[4], src_mac[5]); submit_log("Interface: %s\n", interface); submit_log("MAC ADDR: %s\n", mac); return mac; }
int main (int argc, char **argv) { int i, sd, status; uint8_t *ether_frame; arp_hdr *arphdr; // Allocate memory for various arrays. ether_frame = allocate_ustrmem (IP_MAXPACKET); // Submit request for a raw socket descriptor. if ((sd = socket (PF_PACKET, SOCK_RAW, htons (ETH_P_ALL))) < 0) { perror ("socket() failed "); exit (EXIT_FAILURE); } // Listen for incoming ethernet frame from socket sd. // We expect an ARP ethernet frame of the form: // MAC (6 bytes) + MAC (6 bytes) + ethernet type (2 bytes) // + ethernet data (ARP header) (28 bytes) // Keep at it until we get an ARP reply. arphdr = (arp_hdr *) (ether_frame + 6 + 6 + 2); while (((((ether_frame[12]) << 8) + ether_frame[13]) != ETH_P_ARP) || (ntohs (arphdr->opcode) != ARPOP_REPLY)) { if ((status = recv (sd, ether_frame, IP_MAXPACKET, 0)) < 0) { if (errno == EINTR) { memset (ether_frame, 0, IP_MAXPACKET * sizeof (uint8_t)); continue; // Something weird happened, but let's try again. } else { perror ("recv() failed:"); exit (EXIT_FAILURE); } } } close (sd); // Print out contents of received ethernet frame. printf ("\nEthernet frame header:\n"); printf ("Destination MAC (this node): "); for (i=0; i<5; i++) { printf ("%02x:", ether_frame[i]); } printf ("%02x\n", ether_frame[5]); printf ("Source MAC: "); for (i=0; i<5; i++) { printf ("%02x:", ether_frame[i+6]); } printf ("%02x\n", ether_frame[11]); // Next is ethernet type code (ETH_P_ARP for ARP). // http://www.iana.org/assignments/ethernet-numbers printf ("Ethernet type code (2054 = ARP): %u\n", ((ether_frame[12]) << 8) + ether_frame[13]); printf ("\nEthernet data (ARP header):\n"); printf ("Hardware type (1 = ethernet (10 Mb)): %u\n", ntohs (arphdr->htype)); printf ("Protocol type (2048 for IPv4 addresses): %u\n", ntohs (arphdr->ptype)); printf ("Hardware (MAC) address length (bytes): %u\n", arphdr->hlen); printf ("Protocol (IPv4) address length (bytes): %u\n", arphdr->plen); printf ("Opcode (2 = ARP reply): %u\n", ntohs (arphdr->opcode)); printf ("Sender hardware (MAC) address: "); for (i=0; i<5; i++) { printf ("%02x:", arphdr->sender_mac[i]); } printf ("%02x\n", arphdr->sender_mac[5]); printf ("Sender protocol (IPv4) address: %u.%u.%u.%u\n", arphdr->sender_ip[0], arphdr->sender_ip[1], arphdr->sender_ip[2], arphdr->sender_ip[3]); printf ("Target (this node) hardware (MAC) address: "); for (i=0; i<5; i++) { printf ("%02x:", arphdr->target_mac[i]); } printf ("%02x\n", arphdr->target_mac[5]); printf ("Target (this node) protocol (IPv4) address: %u.%u.%u.%u\n", arphdr->target_ip[0], arphdr->target_ip[1], arphdr->target_ip[2], arphdr->target_ip[3]); free (ether_frame); return (EXIT_SUCCESS); }
int main (int argc, char **argv) { int i, status, frame_length, sd, bytes; char *interface; uint8_t *src_mac, *dst_mac, *ether_frame; struct sockaddr_in *ipv4; struct sockaddr_ll device; struct ifreq ifr; // Allocate memory for various arrays. src_mac = allocate_ustrmem (6); dst_mac = allocate_ustrmem (6); ether_frame = allocate_ustrmem (ETH_HDRLEN); interface = allocate_strmem (40); // Interface to send packet through. strcpy (interface, argv[1]); // Submit request for a socket descriptor to look up interface. if ((sd = socket (AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) { perror ("socket() failed to get socket descriptor for using ioctl() "); exit (EXIT_FAILURE); } // Use ioctl() to look up interface name and get its MAC address. memset (&ifr, 0, sizeof (ifr)); snprintf (ifr.ifr_name, sizeof (ifr.ifr_name), "%s", interface); if (ioctl (sd, SIOCGIFHWADDR, &ifr) < 0) { perror ("ioctl() failed to get source MAC address "); return (EXIT_FAILURE); } close (sd); // Copy source MAC address. memcpy (src_mac, ifr.ifr_hwaddr.sa_data, 6 * sizeof (uint8_t)); // Report source MAC address to stdout. printf ("MAC address for interface %s is ", interface); for (i=0; i<5; i++) { printf ("%02x:", src_mac[i]); } printf ("%02x\n", src_mac[5]); // Find interface index from interface name and store index in // struct sockaddr_ll device, which will be used as an argument of sendto(). memset (&device, 0, sizeof (device)); if ((device.sll_ifindex = if_nametoindex (interface)) == 0) { perror ("if_nametoindex() failed to obtain interface index "); exit (EXIT_FAILURE); } printf ("Index for interface %s is %i\n", interface, device.sll_ifindex); // Set destination MAC address: broadcast address memset (dst_mac, 0xff, 6 * sizeof (uint8_t)); // Fill out sockaddr_ll. device.sll_family = AF_PACKET; memcpy (device.sll_addr, src_mac, 6 * sizeof (uint8_t)); device.sll_halen = 6; // Fill out ethernet frame header. // Ethernet frame length = ethernet header (MAC + MAC + ethernet type) + ethernet data (ARP header) frame_length = 6 + 6 + 2; // Destination and Source MAC addresses memcpy (ether_frame, dst_mac, 6 * sizeof (uint8_t)); memcpy (ether_frame + 6, src_mac, 6 * sizeof (uint8_t)); // Next is ethernet type code (ETH_P_ARP for ARP). // http://www.iana.org/assignments/ethernet-numbers ether_frame[12] = ETH_HLEN / 256; ether_frame[13] = ETH_HLEN % 256; // Submit request for a raw socket descriptor. if ((sd = socket (PF_PACKET, SOCK_RAW, htons (ETH_P_ALL))) < 0) { perror ("socket() failed "); exit (EXIT_FAILURE); } // Send ethernet frame to socket. if ((bytes = sendto (sd, ether_frame, frame_length, 0, (struct sockaddr *) &device, sizeof (device))) <= 0) { perror ("sendto() failed"); exit (EXIT_FAILURE); } // Close socket descriptor. close (sd); // Free allocated memory. free (src_mac); free (dst_mac); free (ether_frame); free (interface); return (EXIT_SUCCESS); }
int larp_reply_pkt(struct arphdr *ar_hdr, struct sockaddr_ll *recv_addr) { int send_sockfd; int i, send_bytes, frame_length; uint32_t ipaddr_n32; //char ipaddr_p[INET_ADDRSTRLEN]; /* to print IP address in presentation format */ struct sockaddr_ll send_addr; struct arphdr send_arhdr; /* standard ARP header fields */ struct tlv_type_len type_len; /* variable of type-len struct */ struct label_stack *l_stack = (struct label_stack *) malloc(label_count * sizeof(struct label_stack)); /* For label stack */ struct attr_tlv a_tlv; /* For Attributes TLV */ char if_name[IFNAMSIZ]; uint32_t metric_val; unsigned char *s_haddr = allocate_ustrmem (6); /*create a RAW PF_PACKET socket for sending out the reply*/ send_sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ARP)); if (send_sockfd < 0) { /* socket function returns negative value on error */ printf("Sending socket creation failed\n"); exit(1); } uint8_t *buffer = allocate_ustrmem (IP_MAXPACKET); /* Making the buffer all zeros */ memset(buffer, 0, ETH_FRAME_LEN); /* Get the local interface MAC address based on the received interface index*/ get_mac (recv_addr->sll_ifindex, s_haddr); /*zeroing out the struct sockaddr_ll structure*/ memset(&send_addr, 0, sizeof(struct sockaddr_ll)); /* Fill in the values for struct sockaddr_ll structure*/ send_addr.sll_family = PF_PACKET; send_addr.sll_protocol = htons(ETH_P_ARP); send_addr.sll_ifindex = recv_addr->sll_ifindex; send_addr.sll_halen = ETH_ALEN; /*6 bytes for Mac address */ /* filling target MAC address from source MAC field of received LARP req */ send_addr.sll_addr[0] = ar_hdr->ar_sha[0]; send_addr.sll_addr[1] = ar_hdr->ar_sha[1]; send_addr.sll_addr[2] = ar_hdr->ar_sha[2]; send_addr.sll_addr[3] = ar_hdr->ar_sha[3]; send_addr.sll_addr[4] = ar_hdr->ar_sha[4]; send_addr.sll_addr[5] = ar_hdr->ar_sha[5]; /* Not used */ send_addr.sll_addr[6] = 0x00; send_addr.sll_addr[7] = 0x00; #if 0 for (i=0; i<5; i++) printf("%02x:", s_haddr[i]); printf("%02x\n", s_haddr[i]); #endif /* Start filling the buffer starting with Ethernet header */ /* Fill in ethernet header*/ memcpy(buffer, ar_hdr->ar_sha, ETH_ALEN * sizeof(uint8_t)); /* destination MAC*/ memcpy(buffer + ETH_ALEN, s_haddr, ETH_ALEN * sizeof(uint8_t)); /* source MAC */ /* Fill ETH_TYPE = ETH_P_ARP for ARP */ buffer[12] = ETH_P_ARP / 256; buffer[13] = ETH_P_ARP % 256; /*Fill in ARP header fileds */ send_arhdr.ar_htype = htons(ARPHRD_LARP); send_arhdr.ar_ptype = htons(ETH_P_IP); /* code for IPV6 can be added as needed*/ send_arhdr.ar_hln = ETH_ALEN; send_arhdr.ar_pln = IP_ADDR_SIZE; send_arhdr.ar_op = htons(LARP_REPLY_OP); /* LARP reply = 2 */ /* source and destination MAC address */ memcpy(&send_arhdr.ar_sha, s_haddr, ETH_ALEN * sizeof(uint8_t)); memcpy(&send_arhdr.ar_tha, ar_hdr->ar_sha, ETH_ALEN * sizeof(uint8_t)); /* Source and destination IP filled using received LARP request */ memcpy(&send_arhdr.ar_sip, ar_hdr->ar_tip, IP_ADDR_SIZE * sizeof(uint8_t)); memcpy(&send_arhdr.ar_tip, ar_hdr->ar_sip, IP_ADDR_SIZE * sizeof(uint8_t)); /* Copying ARP header to sending packet buffer */ memcpy(buffer + ETH_HDR_SIZE, &send_arhdr, sizeof(struct arphdr)); /*Fill in type, length and label for TLV_LST */ fill_type_label_stack(&type_len, l_stack, ar_hdr->ar_tip); /* copy the tlv TLV_LST struct to sending buffer */ memcpy(buffer + ETH_HDR_SIZE + ARP_HDR_SIZE, &type_len, TYPE_LEN_SIZE); memcpy(buffer + ETH_HDR_SIZE + ARP_HDR_SIZE + TYPE_LEN_SIZE, l_stack, label_count * LABEL_STACK_SIZE); /*Add Attribute TLV to sending buffer only if it is enabled */ if(attr_tlv_flag) { /* zero the type_len struct so that now the new values can be held for attr_tlv*/ memset (&type_len, 0, TYPE_LEN_SIZE); /* Fill in struct values for attributes TLV */ fill_type_attribute_tlv(&type_len, &a_tlv, ar_hdr->ar_tip); /* Copy the ATTR_TLV struct to the sending buffer */ memcpy(buffer + ETH_HDR_SIZE + ARP_HDR_SIZE + TYPE_LEN_SIZE + label_count * LABEL_STACK_SIZE, &type_len, TYPE_LEN_SIZE); memcpy(buffer + ETH_HDR_SIZE + ARP_HDR_SIZE + TYPE_LEN_SIZE + label_count * LABEL_STACK_SIZE + TYPE_LEN_SIZE, &a_tlv, ATTR_TLV_SIZE); } /* Frame length = Ethernet header + ARP header + type_len + label_stack */ frame_length = ETH_HDR_SIZE + ARP_HDR_SIZE + TYPE_LEN_SIZE + label_count * LABEL_STACK_SIZE + attr_tlv_flag * (TYPE_LEN_SIZE + ATTR_TLV_SIZE); /* sending the filled packet buffer using sendto*/ send_bytes = sendto(send_sockfd, buffer, frame_length, 0, (SA *) &send_addr, sizeof(send_addr)); if(send_bytes <= 0) { /* Return value: 0 is no bytes sent and negative is error */ perror("Sendto() for LARP reply failed\n"); exit (1); } get_interface_name (send_addr.sll_ifindex, if_name); printf("Sent LARP reply to %u.%u.%u.%u for target %u.%u.%u.%u on interface: %s with label(s): ", send_arhdr.ar_tip[0], send_arhdr.ar_tip[1], send_arhdr.ar_tip[2], send_arhdr.ar_tip[3], send_arhdr.ar_sip[0], send_arhdr.ar_sip[1], send_arhdr.ar_sip[2], send_arhdr.ar_sip[3],if_name); u32fromu8(send_arhdr.ar_sip, &ipaddr_n32); uint32_t *label_stk = (uint32_t *) calloc (0, label_count * sizeof(uint32_t)); memcpy(label_stk, find_label(ipaddr_n32), label_count * sizeof(uint32_t)); print_label_stack(label_stk); metric_val = find_metric(ipaddr_n32); if (metric_val != 0) printf("and with metric: %u\n", find_metric(ipaddr_n32)); else printf("and with no ATTR_TLV.\n"); if (hex_dump_flag) /* print hex_dump of packet if flag enabled */ hexDump (ntohs(send_arhdr.ar_op), buffer+14 , frame_length - 14); /* freeing dynamically allocated memory */ free (label_stk); free(s_haddr); free(l_stack); }
int main (int argc, char **argv) { int i, offset, sd, status; uint8_t *ether_frame; struct ip *iphdr; ra_hdr *rahdr; char *src_ip, *dst_ip; // Allocate memory for various arrays. ether_frame = allocate_ustrmem (IP_MAXPACKET); src_ip = allocate_strmem (INET_ADDRSTRLEN); dst_ip = allocate_strmem (INET_ADDRSTRLEN); // Submit request for a raw socket descriptor. if ((sd = socket (PF_PACKET, SOCK_RAW, htons (ETH_P_ALL))) < 0) { perror ("socket() failed "); exit (EXIT_FAILURE); } // Listen for incoming ethernet frame from socket sd. // We expect a router advertisment ethernet frame of the form: // MAC (6 bytes) + MAC (6 bytes) + ethernet type (2 bytes) // + ethernet data (IPv4 header + RA header) // Keep at it until we get a router advertisement. iphdr = (struct ip *) (ether_frame + 6 + 6 +2); rahdr = (ra_hdr *) (ether_frame + 6 + 6 + 2 + IP4_HDRLEN); while (((((ether_frame[12]) << 8) + ether_frame[13]) != ETH_P_IP) || (iphdr->ip_p != IPPROTO_ICMP) || (rahdr->icmp_type != ICMP_ROUTERADVERT)) { if ((status = recv (sd, ether_frame, IP_MAXPACKET, 0)) < 0) { if (errno == EINTR) { memset (ether_frame, 0, IP_MAXPACKET * sizeof (uint8_t)); continue; // Something weird happened, but let's try again. } else { perror ("recv() failed:"); exit (EXIT_FAILURE); } } } close (sd); // Print out contents of received ethernet frame. printf ("\nEthernet frame header:\n"); printf ("Destination MAC (this node): "); for (i=0; i<5; i++) { printf ("%02x:", ether_frame[i]); } printf ("%02x\n", ether_frame[5]); printf ("Source MAC: "); for (i=0; i<5; i++) { printf ("%02x:", ether_frame[i+6]); } printf ("%02x\n", ether_frame[11]); // Next is ethernet type code (ETH_P_IP for IPv4 packets). // http://www.iana.org/assignments/ethernet-numbers printf ("Ethernet type code (2048 = IPv4): %u\n", ((ether_frame[12]) << 8) + ether_frame[13]); printf ("\nEthernet data (IPv4 header + Router Advertisement header)\n"); printf ("IPv4 transport layer protocol (1 = ICMP): %u\n", iphdr->ip_p); if (inet_ntop (AF_INET, &(iphdr->ip_src), src_ip, INET_ADDRSTRLEN) == NULL) { status = errno; fprintf (stderr, "inet_ntop() failed.\nError message: %s", strerror (status)); exit (EXIT_FAILURE); } printf ("Source IPv4 address: %s\n", src_ip); if (inet_ntop (AF_INET, &(iphdr->ip_dst), dst_ip, INET_ADDRSTRLEN) == NULL) { status = errno; fprintf (stderr, "inet_ntop() failed.\nError message: %s", strerror (status)); exit (EXIT_FAILURE); } printf ("Destination IPv4 address: %s\n", dst_ip); printf ("ICMP message type (9 = router advertisement): %u\n", rahdr->icmp_type); printf ("ICMP message code: %u\n", rahdr->icmp_code); printf ("Number of IPv4 addresses associated with router: %u\n", rahdr->num_addrs); printf ("Router address entry size (in units of 32 bit words): %u\n", rahdr->entry_size); printf ("Lifetime of validity of router advertisement (seconds): %u\n", ntohs (rahdr->lifetime)); offset = 6 + 6 + 2 + IP4_HDRLEN + ICMP_HDRLEN; // Start of list of addresses and preference levels within ethernet frame for (i=0; i<rahdr->num_addrs; i++) { printf ("Router %i IPv4 address: %u:%u:%u:%u\n", i, ether_frame[offset + (i * rahdr->entry_size * 4) + 0], ether_frame[offset + (i * rahdr->entry_size * 4) + 1], ether_frame[offset + (i * rahdr->entry_size * 4) + 2], ether_frame[offset + (i * rahdr->entry_size * 4) + 3]); printf ("Router %i preference level: %u\n", i, ((ether_frame[offset + (i * rahdr->entry_size * 4) + 4]) << 24) + ((ether_frame[offset + (i * rahdr->entry_size * 4) + 5]) << 16) + ((ether_frame[offset + (i * rahdr->entry_size * 4) + 6]) << 8) + ether_frame[offset + (i * rahdr->entry_size * 4) + 7]); offset += rahdr->entry_size * 4; } free (ether_frame); free (src_ip); free (dst_ip); return (EXIT_SUCCESS); }
int sendRtMsgIntermediate(int sd, void * buf, ssize_t len){ int status, *ip_flags; struct ip iphdr; uint8_t *data, *packet; struct icmp icmphdr; struct sockaddr_in *ipv4, sin; void *tmp; // Allocate memory for various arrays. data = allocate_ustrmem (IP_MAXPACKET); packet = allocate_ustrmem (IP_MAXPACKET); ip_flags = allocate_intmem (4); //Unpack the tourdata struct tourdata * unpack = (struct tourdata *)buf; subscribeToMulticast(unpack); //since we work and change index unpack->index = ntohl(unpack->index); printf("Index:%d, nodes in tour:%d\n", unpack->index, ntohl(unpack->nodes_in_tour)); if((unpack->index + 1) == ntohl(unpack->nodes_in_tour)){ //Tour has ended. Send multicast here to everyone and return actually //you dont send anyting from here endOfTour = 1; free (data); free (packet); free (ip_flags); return 0; } int itemsArrSizeBytes = ntohl(unpack->nodes_in_tour) * sizeof(struct in_addr); int datalen = sizeof(struct tourdata) + itemsArrSizeBytes; // IPv4 header // IPv4 header length (4 bits): Number of 32-bit words in header = 5 iphdr.ip_hl = IP4_HDRLEN / sizeof (uint32_t); iphdr.ip_v = 4;// Internet Protocol version (4 bits): IPv4 iphdr.ip_tos = 0;// Type of service (8 bits) iphdr.ip_len = htons (IP4_HDRLEN + ICMP_HDRLEN + datalen);// Total length of datagram (16 bits): IP header + UDP header + datalen iphdr.ip_id = htons (MY_IP_ID);// ID sequence number (16 bits): unused, since single datagram debug("hey"); // Flags, and Fragmentation offset (3, 13 bits): 0 since single datagram ip_flags[0] = 0; ip_flags[1] = 0;// Do not fragment flag (1 bit) ip_flags[2] = 0;// More fragments following flag (1 bit) ip_flags[3] = 0;// Fragmentation offset (13 bits) iphdr.ip_off = htons ((ip_flags[0] << 15) + (ip_flags[1] << 14) + (ip_flags[2] << 13) + ip_flags[3]); iphdr.ip_ttl = 255;// Time-to-Live (8 bits): default to maximum value iphdr.ip_p = RT_PROTO;// Transport layer protocol (8 bits): 1 for ICMP debug("hey"); void * ptr = buf + sizeof(struct tourdata); ptr = ptr + (sizeof(struct in_addr) * unpack->index); //current node-item iphdr.ip_src = *(struct in_addr *)ptr; unpack->index++; ptr = ptr + sizeof(struct in_addr); //advance the pointer to the next in_addr_t iphdr.ip_dst = *(struct in_addr *)ptr; debug("hey. Src IP :%s\n", printIPHuman(iphdr.ip_src.s_addr)); debug("hey. Dest IP :%s\n", printIPHuman(iphdr.ip_dst.s_addr)); // IPv4 header checksum (16 bits): set to 0 when calculating checksum iphdr.ip_sum = 0; iphdr.ip_sum = checksum ((uint16_t *) &iphdr, IP4_HDRLEN); // ICMP header icmphdr.icmp_type = 0;// Message Type (8 bits): echo request icmphdr.icmp_code = 0;// Message Code (8 bits): echo request icmphdr.icmp_id = htons (RT_ICMPID);// Identifier (16 bits): usually pid of sending process - pick a number icmphdr.icmp_seq = htons (0);// Sequence Number (16 bits): starts at 0 icmphdr.icmp_cksum = 0; icmphdr.icmp_cksum = icmp4_checksum(icmphdr, data, datalen); // Copy tour packet to the new ICMP data payload unpack->index = htonl(unpack->index); memcpy(data, unpack, sizeof(struct tourdata)); memcpy((void*)(data + sizeof(struct tourdata)), (void*)(buf + sizeof(struct tourdata)), itemsArrSizeBytes); debug("hey itemarrsizebytes %d", itemsArrSizeBytes); // Prepare packet. // First part is an IPv4 header. memcpy (packet, &iphdr, IP4_HDRLEN); // Next part of packet is upper layer protocol header. debug("hey"); memcpy ((packet + IP4_HDRLEN), &icmphdr, ICMP_HDRLEN); // Finally, add the ICMP data. debug("hey"); memcpy (packet + IP4_HDRLEN + ICMP_HDRLEN, data, datalen); debug("hey, datalen=%d", datalen); memset (&sin, 0, sizeof (struct sockaddr_in)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = iphdr.ip_dst.s_addr; debug("hey. Dest IP :%s\n", printIPHuman(ntohl(iphdr.ip_dst.s_addr))); printf("Gonna send..."); // Send packet. if (sendto (sd, packet, IP4_HDRLEN + ICMP_HDRLEN + datalen, 0, (struct sockaddr *) &sin, sizeof (struct sockaddr)) < 0) { printFailed(); return 1; } printOK(); // Free allocated memory. free (data); free (packet); free (ip_flags); return 0; }
int sendRtMsg(int sd){ int status, datalen, *ip_flags; char *target, *src_ip, *dst_ip; struct ip iphdr; uint8_t *data, *packet; struct icmp icmphdr; struct addrinfo hints, *res; struct sockaddr_in *ipv4, sin; void *tmp; // Allocate memory for various arrays. data = allocate_ustrmem (IP_MAXPACKET); packet = allocate_ustrmem (IP_MAXPACKET); target = allocate_strmem (40); src_ip = allocate_strmem (INET_ADDRSTRLEN); dst_ip = allocate_strmem (INET_ADDRSTRLEN); ip_flags = allocate_intmem (4); strcpy(src_ip, inet_ntoa(ip_list[0])); strcpy(target, inet_ntoa(ip_list[1])); debug("Source IP %s, targe IP %s", src_ip, target); // Fill out hints for getaddrinfo(). memset (&hints, 0, sizeof (struct addrinfo)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = hints.ai_flags | AI_CANONNAME; // Resolve target using getaddrinfo(). if ((status = getaddrinfo (target, NULL, &hints, &res)) != 0) { fprintf (stderr, "getaddrinfo() failed: %s\n", gai_strerror (status)); exit (EXIT_FAILURE); } ipv4 = (struct sockaddr_in *) res->ai_addr; tmp = &(ipv4->sin_addr); if (inet_ntop (AF_INET, tmp, dst_ip, INET_ADDRSTRLEN) == NULL) { status = errno; fprintf (stderr, "inet_ntop() failed.\nError message: %s", strerror (status)); exit (EXIT_FAILURE); } freeaddrinfo (res); datalen = sizeof(struct tourdata) + (VMcount * 4); struct tourdata td; td.index = htonl(0); td.nodes_in_tour = htonl(VMcount); td.mult_ip = inet_addr(MULTICAST_IP); td.mult_port = htons(MULTICAST_PORT); memcpy(data, &td, sizeof(struct tourdata)); subscribeToMulticast(&td); void * ptr = data; ptr = ptr + sizeof(struct tourdata); int i; //Add the IPs of the VMs to visit for(i = 1; i <=VMcount; i++){ memcpy(ptr, &ip_list[i], 4); struct in_addr * temp2 = (struct in_addr *) ptr; ptr = ptr + 4; } // IPv4 header // IPv4 header length (4 bits): Number of 32-bit words in header = 5 iphdr.ip_hl = IP4_HDRLEN / sizeof (uint32_t); iphdr.ip_v = 4;// Internet Protocol version (4 bits): IPv4 iphdr.ip_tos = 0;// Type of service (8 bits) iphdr.ip_len = htons (IP4_HDRLEN + ICMP_HDRLEN + datalen);// Total length of datagram (16 bits): IP header + UDP header + datalen iphdr.ip_id = htons (MY_IP_ID);// ID sequence number (16 bits): unused, since single datagram // Flags, and Fragmentation offset (3, 13 bits): 0 since single datagram ip_flags[0] = 0; ip_flags[1] = 0;// Do not fragment flag (1 bit) ip_flags[2] = 0;// More fragments following flag (1 bit) ip_flags[3] = 0;// Fragmentation offset (13 bits) iphdr.ip_off = htons ((ip_flags[0] << 15) + (ip_flags[1] << 14) + (ip_flags[2] << 13) + ip_flags[3]); iphdr.ip_ttl = 255;// Time-to-Live (8 bits): default to maximum value iphdr.ip_p = RT_PROTO;// Transport layer protocol (8 bits): 1 for ICMP // Source IPv4 address (32 bits) if ((status = inet_pton (AF_INET, src_ip, &(iphdr.ip_src))) != 1) { fprintf (stderr, "inet_pton() failed.\nError message: %s", strerror (status)); exit (EXIT_FAILURE); } // Destination IPv4 address (32 bits) if ((status = inet_pton (AF_INET, dst_ip, &(iphdr.ip_dst))) != 1) { fprintf (stderr, "inet_pton() failed.\nError message: %s", strerror (status)); exit (EXIT_FAILURE); } // IPv4 header checksum (16 bits): set to 0 when calculating checksum iphdr.ip_sum = 0; iphdr.ip_sum = checksum ((uint16_t *) &iphdr, IP4_HDRLEN); // ICMP header icmphdr.icmp_type = 0;// Message Type (8 bits): echo request icmphdr.icmp_code = 0;// Message Code (8 bits): echo request icmphdr.icmp_id = htons (RT_ICMPID);// Identifier (16 bits): usually pid of sending process - pick a number icmphdr.icmp_seq = htons (0);// Sequence Number (16 bits): starts at 0 icmphdr.icmp_cksum = 0; icmphdr.icmp_cksum = icmp4_checksum(icmphdr, data, datalen); // Prepare packet. // First part is an IPv4 header. memcpy (packet, &iphdr, IP4_HDRLEN); // Next part of packet is upper layer protocol header. memcpy ((packet + IP4_HDRLEN), &icmphdr, ICMP_HDRLEN); // Finally, add the ICMP data. memcpy (packet + IP4_HDRLEN + ICMP_HDRLEN, data, datalen); // Calculate ICMP header checksum //icmphdr.icmp_cksum = 0;//checksum ((uint16_t *) (packet + IP4_HDRLEN), ICMP_HDRLEN + datalen); //memcpy ((packet + IP4_HDRLEN), &icmphdr, ICMP_HDRLEN); // The kernel is going to prepare layer 2 information (ethernet frame header) for us. // For that, we need to specify a destination for the kernel in order for it // to decide where to send the raw datagram. We fill in a struct in_addr with // the desired destination IP address, and pass this structure to the sendto() function. memset (&sin, 0, sizeof (struct sockaddr_in)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = iphdr.ip_dst.s_addr; if (sendto (sd, packet, IP4_HDRLEN + ICMP_HDRLEN + datalen, 0, (struct sockaddr *) &sin, sizeof (struct sockaddr)) < 0) { perror ("sendto() failed "); exit (EXIT_FAILURE); } printOK(); // Free allocated memory. free (data); free (packet); free (target); free (src_ip); free (dst_ip); free (ip_flags); return 0; }