问题描述
我正在尝试使用具有特殊结构sockaddr_ll的原始套接字发送udp数据包,但是我仅获得带有尾部的以太网头和没有udp头的ip头。我想发送一个没有预告片的普通udp数据包,并得到我的消息。我用wireshark检查了包裹。我怎样才能解决这个问题? 我的包裹:
我的代码:
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,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,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,sizeof(struct ifreq));
strncpy(if_mac.ifr_name,SIocgIFHWADDR,&if_mac) < 0)
perror("SIocgIFHWADDR");
/* get ip */
memset(&ifreq_ip,sizeof(ifreq_ip));
strncpy(ifreq_ip.ifr_name,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,(struct sockaddr*)&socket_address,sizeof(struct sockaddr_ll)) < 0)
printf("Send Failed\n");
return 0;
}
解决方法
“ IP总长度”字段只有20个字节,仅是IP标头的大小,因此就IP而言,没有有效负载。您需要确保IP总长度字段设置为IP标头的大小加上整个有效负载的大小。特别是,这一行是错误的:
iph->tot_len = htons(sizeof (struct iphdr));