#include <stdlib.h> #include <string.h> #include <unistd.h> #include <errno.h> #include <sys/socket.h> #include <sys/ioctl.h> //#include <linux/if_ether.h> //#include <linux/if_packet.h> //#include <linux/if_arp.h> #include <net/if.h> #include <netpacket/packet.h> //#include <netinet/in.h> #include "ethernet_drv.h" #include "display.h" // Some projects can not use stdio.h. #ifndef LABCOMM_NO_STDIO #include <stdio.h> #endif /** LOCAL FUNCTIONS **/ /* local type for the ethernet interface */ struct eth_int_t { struct ether_addr mac_adr; /* MAC address */ int socket_id; /* socket file descriptor */ int index; /* index of the eth interface */ unsigned char validity; }; /*** Open an Ethernet Raw packet connection ***/ struct eth_int_t* eth_open(const char* eth_int_name) { struct eth_int_t* tmp_eth = NULL; /* pointer to ethernet interface struct */ struct ifreq ifr; /* struct used by ioctl function */ /* TO-DO: check if a ethernet socket has already been created for eth_int_name interface */ /* Ethernet interface name pointer valid ? */ if (NULL == eth_int_name) { errno = EINVAL; DISPLAY_ERR("Input parameter NULL"); } else { /* allocate memory for the Ethernet Interface */ tmp_eth = (struct eth_int_t*)malloc(sizeof(struct eth_int_t)); if (NULL == tmp_eth) { DISPLAY_ERR("Error allocating memory!"); } else { /* creates a Packet Socket, raw delivery, accept all protocol */ tmp_eth->socket_id = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); if (-1 == tmp_eth->socket_id) /* error occurred during socket creation ? */ { free(tmp_eth); /* deallocate the memory */ tmp_eth = NULL; DISPLAY_ERR("Error in creating socket"); } else { /* retrieve the Ethernet card MAC address */ strcpy(ifr.ifr_name, eth_int_name); if (ioctl(tmp_eth->socket_id, SIOCGIFHWADDR, &ifr) == -1) /* error during the retrieve of MAC address ? */ { close(tmp_eth->socket_id); /* close the socket */ free(tmp_eth); /* deallocate the memory */ tmp_eth = NULL; DISPLAY_ERR("ioctl error SIOCGIFHWADDR"); } else { /* copy the MAC address into the eth interface struct */ memcpy(tmp_eth->mac_adr.ether_addr_octet, ifr.ifr_hwaddr.sa_data, ETH_ALEN); /*retrieve the Ethernet interface index*/ if (ioctl(tmp_eth->socket_id, SIOCGIFINDEX, &ifr) == -1)/* error during the retrieve of index */ { close(tmp_eth->socket_id); /* close the socket */ free(tmp_eth); /* deallocate the memory */ tmp_eth = NULL; DISPLAY_ERR("ioctl error SIOCGIFINDEX"); } else { /* copy the interface index into the eth interface struct */ tmp_eth->index = ifr.ifr_ifindex; printf("Successfully got our MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n", tmp_eth->mac_adr.ether_addr_octet[0],tmp_eth->mac_adr.ether_addr_octet[1],tmp_eth->mac_adr.ether_addr_octet[2],tmp_eth->mac_adr.ether_addr_octet[3],tmp_eth->mac_adr.ether_addr_octet[4],tmp_eth->mac_adr.ether_addr_octet[5]); printf("Successfully got interface index for %s: %i\n",eth_int_name, tmp_eth->index); } } } } } return(tmp_eth); } /*** Close the Ethernet Raw packet connection ***/ int eth_close(struct eth_int_t* eth_int) { int ret = 0; /* Ethernet interface pointer valid ? */ if (NULL == eth_int) { ret = -1; errno = EINVAL; DISPLAY_ERR("Input parameter NULL"); } else { if (-1 == close(eth_int->socket_id)) /* error during the closure of the socket ? */ { ret = -1; DISPLAY_ERR("Socket closure error"); } else { free(eth_int); /* deallocate the memory */ eth_int = NULL; } } return(ret); } /*** Returns the MAC address of the Ethernet Interface ***/ int eth_getMACadr(const struct eth_int_t* eth_int, struct ether_addr * mac_adr) { int ret = 0; if ((NULL == eth_int) || (NULL == mac_adr)) /* Input parameters valid ? */ { ret = -1; errno = EINVAL; DISPLAY_ERR("Input parameter(s) NULL"); } else { /* TO-DO: introduce a validity flag to be check before accessing to eth_int (better a crc) */ memcpy(mac_adr, ð_int->mac_adr, sizeof(mac_adr)); } return(ret); } /*** send a complete Ethernet Raw Packet ***/ int eth_send(const struct eth_int_t* eth_int, const unsigned char* eth_frame, unsigned short length) { struct ethhdr *eth_header = NULL; /* Pointer to Ethernet frame header (Dest,Source,Type) */ struct sockaddr_ll socket_address; int ret; if ((NULL == eth_int) || (NULL == eth_frame)) { ret = -1; errno = EINVAL; DISPLAY_ERR("Input parameter(s) Null!"); } else { eth_header = (struct ethhdr*)eth_frame; /*prepare sockaddr_ll (address structure for PACKET_SOCKET) */ socket_address.sll_family = AF_PACKET; socket_address.sll_addr[0] = eth_header->h_dest[0]; socket_address.sll_addr[1] = eth_header->h_dest[1]; socket_address.sll_addr[2] = eth_header->h_dest[2]; socket_address.sll_addr[3] = eth_header->h_dest[3]; socket_address.sll_addr[4] = eth_header->h_dest[4]; socket_address.sll_addr[5] = eth_header->h_dest[5]; socket_address.sll_addr[6] = 0x00; /* not used */ socket_address.sll_addr[7] = 0x00; /* not used */ socket_address.sll_halen = ETH_ALEN; /* Length of the MAC address */ socket_address.sll_ifindex = eth_int->index; /* Ethernet Interface index */ // The rest should be zero for sending, and are set by the system for receiving. socket_address.sll_hatype = 0; socket_address.sll_protocol = 0; socket_address.sll_pkttype = 0; //socket_address.sll_protocol = htons(ETH_P_IP); /* Physical layer protocol */ //socket_address.sll_hatype = ARPHRD_ETHER; /* ARP hardware identifier: Ethernet */ //socket_address.sll_pkttype = PACKET_OTHERHOST; /* Packet type: Another host */ /*send the Ethernet frame */ ret = sendto(eth_int->socket_id, eth_frame, length, 0, (struct sockaddr*)&socket_address, sizeof(socket_address)); if (ret == -1) /* error during the trasmission of the Ethernet frame ? */ { DISPLAY_ERR("sendto error!"); } } return(ret); } /*** receive a complete Ethernet Raw Packet ***/ int eth_receive (const struct eth_int_t* eth_int, unsigned char* eth_frame, unsigned short length) { int ret; if ((NULL == eth_int) || (NULL == eth_frame)) { ret = -1; errno = EINVAL; DISPLAY_ERR("Input parameter(s) Null!"); } else { /*Wait for incoming packet...*/ ret = recvfrom(eth_int->socket_id, (void*)eth_frame, length, 0, NULL, NULL); if (ret == -1) /* error during the reception of the Ethernet frame ? */ { DISPLAY_ERR("recvfrom error!"); } } return(ret); }