UDP原始套接字程序

时间:2015-05-16 12:47:31

标签: c sockets networking

我正在测试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)

我没有收到任何东西。怎么办?

0 个答案:

没有答案