简体   繁体   中英

Ethernet packet has trailer instead udp header via socket raw

I'm trying to send udp packet using socket raw with special structure sockaddr_ll, but I'm getting only an ethe.net header with trailer and ip header without udp header. I would like to send a normal udp packet without the trailer and get my message. I checked the package using wireshark. How can I fix this? My packet:

在此处输入图像描述

My code:

int main(int argc, char *argv[])
{
    int sockfd;
    struct ifreq if_idx;
    struct ifreq if_mac;
  struct ifreq ifreq_ip;
    int tx_len = 0;
    unsigned char* sendbuf;
  sendbuf=(unsigned char*)malloc(64); 
    memset(sendbuf,0,64);

    struct ether_header *eh = (struct ether_header *) sendbuf;
    struct iphdr *iph = (struct iphdr *) (sendbuf + sizeof(struct ether_header));
  struct udphdr *uph = (struct udphdr *) (sendbuf + sizeof(struct ether_header) + sizeof(struct iphdr));
    struct sockaddr_ll socket_address;
    char ifName[IFNAMSIZ];
    
    /* Get interface name */
    if (argc > 1)
        strcpy(ifName, argv[1]);
    else
        strcpy(ifName, DEFAULT_IF);

    /* Open RAW socket to send on */
    if ((sockfd = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW)) == -1) {
        perror("socket");
    }

    /* Get the index of the interface to send on */
    memset(&if_idx, 0, sizeof(struct ifreq));
    strncpy(if_idx.ifr_name, ifName, IFNAMSIZ-1);
    if (ioctl(sockfd, SIOCGIFINDEX, &if_idx) < 0)
        perror("SIOCGIFINDEX");
    /* Get the MAC address of the interface to send on */
    memset(&if_mac, 0, sizeof(struct ifreq));
    strncpy(if_mac.ifr_name, ifName, IFNAMSIZ-1);
    if (ioctl(sockfd, SIOCGIFHWADDR, &if_mac) < 0)
        perror("SIOCGIFHWADDR");
  /* get ip */
  memset(&ifreq_ip,0,sizeof(ifreq_ip));
    strncpy(ifreq_ip.ifr_name,ifName,IFNAMSIZ-1);
  if(ioctl(sockfd,SIOCGIFADDR,&ifreq_ip)<0)
    {
        printf("error in SIOCGIFADDR \n");
    }



    /* Construct the Ethernet header */
    /* Ethernet header */
    eh->ether_shost[0] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[0];
    eh->ether_shost[1] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[1];
    eh->ether_shost[2] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[2];
    eh->ether_shost[3] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[3];
    eh->ether_shost[4] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[4];
    eh->ether_shost[5] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[5];
    eh->ether_dhost[0] = MY_DEST_MAC0;
    eh->ether_dhost[1] = MY_DEST_MAC1;
    eh->ether_dhost[2] = MY_DEST_MAC2;
    eh->ether_dhost[3] = MY_DEST_MAC3;
    eh->ether_dhost[4] = MY_DEST_MAC4;
    eh->ether_dhost[5] = MY_DEST_MAC5;
    /* Ethertype field */
    eh->ether_type = htons(ETH_P_IP);
    tx_len += sizeof(struct ether_header);

    /* ip header */
    iph->ihl = 5;
    iph->version = 4;
    iph->tos = 0;
    iph->tot_len = htons(sizeof (struct iphdr));
    iph->id = htonl (54321);    //Id of this packet
    iph->frag_off = 0;
    iph->ttl = 255;
    iph->protocol = IPPROTO_UDP;
    iph->check = 0;     
    iph->saddr = inet_addr(inet_ntoa((((struct sockaddr_in *)&(ifreq_ip.ifr_addr))->sin_addr)));    
    iph->daddr = inet_addr ( "127.0.0.1" );
    
    //Ip checksum
    iph->check = csum ((unsigned short *) sendbuf, iph->tot_len);
  tx_len += sizeof(struct iphdr);

  uph->source   = htons(80);
    uph->dest   = htons(43521);
    uph->check  = 0;

    tx_len+= sizeof(struct udphdr);
    sendbuf[tx_len++]   =   0xAA;
    sendbuf[tx_len++]   =   0xBB;
    sendbuf[tx_len++]   =   0xCC;
    sendbuf[tx_len++]   =   0xDD;
    sendbuf[tx_len++]   =   0xEE;
    uph->len        = htons((tx_len - sizeof(struct iphdr) - sizeof(struct ethhdr)));

    /* Index of the network device */
    socket_address.sll_ifindex = if_idx.ifr_ifindex;
    /* Address length*/
    socket_address.sll_halen = ETH_ALEN;
    /* Destination MAC */
    socket_address.sll_addr[0] = MY_DEST_MAC0;
    socket_address.sll_addr[1] = MY_DEST_MAC1;
    socket_address.sll_addr[2] = MY_DEST_MAC2;
    socket_address.sll_addr[3] = MY_DEST_MAC3;
    socket_address.sll_addr[4] = MY_DEST_MAC4;
    socket_address.sll_addr[5] = MY_DEST_MAC5;

    /* Send packet */
    if (sendto(sockfd, sendbuf, tx_len, 0, (struct sockaddr*)&socket_address, sizeof(struct sockaddr_ll)) < 0)
        printf("Send failed\n");

    return 0;
}

The IP Total Length field is only 20 bytes, which is just the size of the IP Header, so as far as IP is concerned, there is no payload. You need to ensure that the IP Total Length field is set to the size of the IP header plus the size of the entire payload. In particular, this line is wrong:

iph->tot_len = htons(sizeof (struct iphdr));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM