我正在测试C中原始套接字的使用,我已将其缩小为一个简单的程序,该程序发送我发送的通用UDP消息(硬编码,始终是相同的消息)。
这是我创建套接字并获取网络接口的MAC地址的方法:
void open_socket(int* sockfd)
{
/* Opens RAW socket to send on */
if ((*sockfd = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW)) == -1) {
perror("socket");
}
}
int get_if_index(const char* interface_name, int sock)
{
struct ifreq if_idx; memset(&if_idx, 0, sizeof(struct ifreq));
strncpy(if_idx.ifr_name, interface_name, IFNAMSIZ-1);
if (ioctl(sock, SIOCGIFINDEX, &if_idx) < 0)
{
perror("SIOCGIFINDEX");
return -1;
}
else
{
return if_idx.ifr_ifru.ifru_ivalue;
}
}
void get_mac_address(char* if_name, int sock, unsigned char* mac_add /*[6]*/, char* formatted_string)
{
struct ifreq if_mac;
memset(&if_mac, 0, sizeof(struct ifreq));
strncpy(if_mac.ifr_name, if_name /*e.g. "eth0"*/, IFNAMSIZ-1);
if (ioctl(sock, SIOCGIFHWADDR, &if_mac) < 0)
perror("SIOCGIFHWADDR - could not get interface address");
memcpy((unsigned char*) mac_add, (unsigned char *)if_mac.ifr_hwaddr.sa_data, 6/*sizeof(*(unsigned char *)ifr.ifr_hwaddr.sa_data)*/);
snprintf (formatted_string, 18, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x", mac_add[0], mac_add[1], mac_add[2], mac_add[3], mac_add[4], mac_add[5]);
}
通过打印格式化的sting,我检查MAC地址实际上是我的网络接口之一。现在,这是我构建以太网头并发送消息的方式:
void construct_ethernet_header(uint8_t* sendbuf /*[1024]*/, int* tx_len /*[1]*/, unsigned char* mac_add/*[6], source mac*/, unsigned char* dest_mac /*[6]*/)
{
*tx_len = 0;
memset(sendbuf, 0, 1024);
/* Ethernet header */
*(sendbuf+6) = (uint8_t) (*mac_add);
*(sendbuf+7) = (uint8_t) (*(++mac_add));
*(sendbuf+8) = (uint8_t) (*(++mac_add));
*(sendbuf+9) = (uint8_t) (*(++mac_add));
*(sendbuf+10) = (uint8_t) (*(++mac_add));
*(sendbuf+11) = (uint8_t) (*(++mac_add));
*(sendbuf+0) = (uint8_t) (*dest_mac);
*(sendbuf+1) = (uint8_t) *(++dest_mac);
*(sendbuf+2) = (uint8_t) *(++dest_mac);
*(sendbuf+3) = (uint8_t) *(++dest_mac);
*(sendbuf+4) = (uint8_t) *(++dest_mac);
*(sendbuf+5) = (uint8_t) *(++dest_mac);
*(sendbuf+12) = 0x08;
*(sendbuf+13) = 0x00;
*tx_len += 16;
}
void send_rsocket(uint8_t* sendbuf /*[1024]*/, int tx_len, int sock, int ifindex, unsigned char* dest_mac /*[6]*/)
{
/* Destination address */
struct sockaddr_ll socket_address;
memset (&socket_address, 0, sizeof(struct sockaddr_ll));
/* Index of the network device */
socket_address.sll_ifindex = ifindex;
/* Address length*/
socket_address.sll_family = AF_PACKET;
socket_address.sll_protocol = htons(ETH_P_IP);
socket_address.sll_halen = ETHER_ADDR_LEN;//ETH_ALEN;
/* Destination MAC */
socket_address.sll_addr[0] = (uint8_t) (*(dest_mac));
socket_address.sll_addr[1] = (uint8_t) (*(++dest_mac));
socket_address.sll_addr[2] = (uint8_t) (*(++dest_mac));
socket_address.sll_addr[3] = (uint8_t) (*(++dest_mac));
socket_address.sll_addr[4] = (uint8_t) (*(++dest_mac));
socket_address.sll_addr[5] = (uint8_t) (*(++dest_mac));
/* Send packet */
if (sendto(sock, sendbuf, tx_len, 0, (struct sockaddr*)&socket_address, sizeof(struct sockaddr_ll)) < 0)
perror("Send failed\n");
}
如果我运行该程序,我可以在wireshark上正确地看到UDP消息,具有正确的校验和,端口和IP源/目的地(因为该部分是硬编码的,所以不会感到惊讶)。但是,如果我运行netcat:
nc -lu (dest IP) (port)
我没有收到任何东西。怎么办?