c 原始套接字和 64 位问题
我仍在努力让我的示例代码在 64 位机器上运行。由于标头/库丢失/过时,我之前的问题得到了解决。
我编译此代码如下: gcc -Wall -g -o server server.c 和 gcc -Wall -g -o client client.c 我在两台 linux 机器(都是 32 位)上运行它们,并且运行良好。当我在 64 位机器上重新编译此代码时,似乎没有数据包从客户端传输到服务器。将 tcpdump 放在客户端上,似乎它正在发送格式错误的标头,并且始终被拒绝。有人可以启发我吗?
#include "client.h"
#include "util.h"
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <asm/types.h>
#include <math.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>
#define BUF_SIZE ETH_FRAME_TOTALLEN
#define NUMBER_OF_MESUREMENTS_PER_AMOUNT_OF_DATA 100000 /*how often to measure travelling time with one certain amount of data*/
int s = 0; /*Socketdescriptor*/
void* buffer = NULL;
long total_sent_packets = 0;
int main(int argc, char* argv[])
{
buffer = (void*)malloc(BUF_SIZE); /*Buffer for ethernet frame*/
unsigned char* etherhead = buffer; /*Pointer to ethenet header*/
unsigned char* data = buffer + 14; /*Userdata in ethernet frame*/
struct ethhdr *eh = (struct ethhdr *)etherhead; /*Another pointer to ethernet header*/
unsigned char src_mac[6]; /*our MAC address */
unsigned char dest_mac[6] = {0x00, 0x1E, 0x4F, 0xB1, 0xCB, 0x43}; /*MAC address, hardcoded...... :-(*/
struct ifreq ifr;
struct sockaddr_ll socket_address;
int ifindex = 0; /*Ethernet Interface index*/
int i,j,k;
int length; /*length of received packet*/
int sent; /*length of sent packet*/
/*stuff for time measuring: */
struct timeval begin;
struct timeval end;
struct timeval result;
unsigned long long allovertime;
printf("Client started, entering initialiation phase...\n");
/*open socket*/
s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (s == -1) {
perror("socket():");
exit(1);
}
printf("Successfully opened socket: %i\n", s);
/*retrieve ethernet interface index*/
strncpy(ifr.ifr_name, ETH0, IFNAMSIZ);
if (ioctl(s, SIOCGIFINDEX, &ifr) == -1) {
perror("SIOCGIFINDEX");
exit(1);
}
ifindex = ifr.ifr_ifindex;
printf("Successfully got interface index: %i\n", ifindex);
/*retrieve corresponding MAC*/
if (ioctl(s, SIOCGIFHWADDR, &ifr) == -1) {
perror("SIOCGIFINDEX");
exit(1);
}
for (i = 0; i < 6; i++) {
src_mac[i] = ifr.ifr_hwaddr.sa_data[i];
}
printf("Successfully got our MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n",
src_mac[0],src_mac[1],src_mac[2],src_mac[3],src_mac[4],src_mac[5]);
/*prepare sockaddr_ll*/
socket_address.sll_family = PF_PACKET;
socket_address.sll_protocol = htons(ETH_P_IP);
socket_address.sll_ifindex = ifindex;
socket_address.sll_hatype = ARPHRD_ETHER;
socket_address.sll_pkttype = PACKET_OTHERHOST;
socket_address.sll_halen = ETH_ALEN;
socket_address.sll_addr[0] = dest_mac[0];
socket_address.sll_addr[1] = dest_mac[1];
socket_address.sll_addr[2] = dest_mac[2];
socket_address.sll_addr[3] = dest_mac[3];
socket_address.sll_addr[4] = dest_mac[4];
socket_address.sll_addr[5] = dest_mac[5];
socket_address.sll_addr[6] = 0x00;
socket_address.sll_addr[7] = 0x00;
/*establish signal handler*/
signal(SIGINT, sigint);
printf("Successfully established signal handler for SIGINT\n");
/*init random number generator*/
srand(time(NULL));
printf("We are in production state, sending packets to: %02X:%02X:%02X:%02X:%02X:%02X\n",
dest_mac[0],dest_mac[1],dest_mac[2],dest_mac[3],dest_mac[4],dest_mac[5]);
for (i = 50; i <= 1500; i += 50) {
allovertime = 0;
for (k = 0; k < NUMBER_OF_MESUREMENTS_PER_AMOUNT_OF_DATA; k++) {
/*prepare buffer*/
memcpy((void*)buffer, (void*)dest_mac, ETH_MAC_LEN);
memcpy((void*)(buffer+ETH_MAC_LEN), (void*)src_mac, ETH_MAC_LEN);
eh->h_proto = ETH_P_NULL;
/*fill it with random data....*/
for (j = 0; j < i; j++) {
data[j] = (unsigned char)((int) (256.0*rand()/(RAND_MAX+1.0)));
}
/*clear the timers:*/
timerclear(&begin);
timerclear(&end);
/*get time before sending.....*/
gettimeofday(&begin,NULL);
/*send packet*/
sent = sendto(s, buffer, i+ETH_HEADER_LEN, 0, (struct sockaddr*)&socket_address, sizeof(socket_address));
if (sent == -1) {
perror("sendto():");
exit(1);
}
/*Wait for incoming packet...*/
length = recvfrom(s, buffer, BUF_SIZE, 0, NULL, NULL);
if (length == -1) {
perror("recvfrom():");
exit(1);
}
/*get time after sending.....*/
gettimeofday(&end,NULL);
/*...and calculate difference.........*/
timersub(&end,&begin,&result);
allovertime += ((result.tv_sec * 1000000 ) + result.tv_usec );
total_sent_packets++;
}
printf("Sending %i bytes takes %lld microseconds in average\n",i ,allovertime/NUMBER_OF_MESUREMENTS_PER_AMOUNT_OF_DATA);
}
return (0);
}
void sigint(int signum) {
/*Clean up.......*/
struct ifreq ifr;
if (s == -1)
return;
strncpy(ifr.ifr_name, ETH0, IFNAMSIZ);
ioctl(s, SIOCGIFFLAGS, &ifr);
ifr.ifr_flags &= ~IFF_PROMISC;
ioctl(s, SIOCSIFFLAGS, &ifr);
close(s);
free(buffer);
printf("Client terminating....\n");
printf("Totally sent: %ld packets\n", total_sent_packets);
exit(0);
}
------------------server.c---------------------
#include "server.h"
#include "util.h"
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <asm/types.h>
#include <math.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>
#define BUF_SIZE ETH_FRAME_TOTALLEN
int s = 0; /*Socketdescriptor*/
void* buffer = NULL;
long total_packets = 0;
long answered_packets = 0;
int main(int argc, char* argv[])
{
buffer = (void*)malloc(BUF_SIZE); /*Buffer for Ethernet Frame*/
unsigned char* etherhead = buffer; /*Pointer to Ethenet Header*/
struct ethhdr *eh = (struct ethhdr *)etherhead; /*Another pointer to ethernet header*/
unsigned char src_mac[6]; /*our MAC address*/
struct ifreq ifr;
struct sockaddr_ll socket_address;
int ifindex = 0; /*Ethernet Interface index*/
int i;
int length; /*length of received packet*/
int sent;
printf("Server started, entering initialiation phase...\n");
/*open socket*/
s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (s == -1) {
perror("socket():");
exit(1);
}
printf("Successfully opened socket: %i\n", s);
/*retrieve ethernet interface index*/
strncpy(ifr.ifr_name, ETH0, IFNAMSIZ);
if (ioctl(s, SIOCGIFINDEX, &ifr) == -1) {
perror("SIOCGIFINDEX");
exit(1);
}
ifindex = ifr.ifr_ifindex;
printf("Successfully got interface index: %i\n", ifindex);
/*retrieve corresponding MAC*/
if (ioctl(s, SIOCGIFHWADDR, &ifr) == -1) {
perror("SIOCGIFINDEX");
exit(1);
}
for (i = 0; i < 6; i++) {
src_mac[i] = ifr.ifr_hwaddr.sa_data[i];
}
printf("Successfully got our MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n",
src_mac[0],src_mac[1],src_mac[2],src_mac[3],src_mac[4],src_mac[5]);
/*prepare sockaddr_ll*/
socket_address.sll_family = PF_PACKET;
socket_address.sll_protocol = htons(ETH_P_IP);
socket_address.sll_ifindex = ifindex;
socket_address.sll_hatype = ARPHRD_ETHER;
socket_address.sll_pkttype = PACKET_OTHERHOST;
socket_address.sll_halen = ETH_ALEN;
socket_address.sll_addr[6] = 0x00;
socket_address.sll_addr[7] = 0x00;
/*establish signal handler (keyboard)*/
signal(SIGINT, sigint);
printf("Successfully established signal handler for SIGINT\n");
printf("We are in production state, waiting for incoming packets....\n");
while (1) {
/*Wait for incoming packet...*/
length = recvfrom(s, buffer, BUF_SIZE, 0, NULL, NULL);
if (length == -1) {
perror("recvfrom():");
exit(1);
}
/*See if we should answer (Ethertype == 0x0 && destination address == our MAC)*/
if (eh->h_proto == ETH_P_NULL && memcmp( (const void*)eh->h_dest, (const void*)src_mac, ETH_MAC_LEN) == 1 )
{
/*exchange addresses in buffer*/
memcpy( (void*)etherhead, (const void*)(etherhead+ETH_MAC_LEN), ETH_MAC_LEN);
memcpy( (void*)(etherhead+ETH_MAC_LEN), (const void*)src_mac, ETH_MAC_LEN);
/*prepare sockaddr_ll*/
socket_address.sll_addr[0] = eh->h_dest[0];
socket_address.sll_addr[1] = eh->h_dest[1];
socket_address.sll_addr[2] = eh->h_dest[2];
socket_address.sll_addr[3] = eh->h_dest[3];
socket_address.sll_addr[4] = eh->h_dest[4];
socket_address.sll_addr[5] = eh->h_dest[5];
/*send answer*/
sent = sendto(s, buffer, length-4, 0, (struct sockaddr*)&socket_address, sizeof(socket_address));
if (sent == -1) {
perror("sendto():");
exit(1);
}
answered_packets++;
}
total_packets++;
}
}
void sigint(int signum) {
/*Clean up.......*/
struct ifreq ifr;
if (s == -1)
return;
strncpy(ifr.ifr_name, ETH0, IFNAMSIZ);
ioctl(s, SIOCGIFFLAGS, &ifr);
ifr.ifr_flags &= ~IFF_PROMISC;
ioctl(s, SIOCSIFFLAGS, &ifr);
close(s);
free(buffer);
printf("Server terminating....\n");
printf("Totally received: %ld packets\n", total_packets);
printf("Answered %ld packets\n", answered_packets);
exit(0);
}
I'm still struggling to get my sample code working on a 64 bit machine. My previous problem was solved because of missing/outdated headers/libraries.
I compile this code as follow: gcc -Wall -g -o server server.c and gcc -Wall -g -o client client.c
I run them on 2 linux machines(both 32bit) and it works fine. When I recompile this code on 64 bit machines then it seems that no packets go through from the client to the server. Putting tcpdump on the client it seems that it is sending malformed headers that gets rejected all the time. Can anybody enlighten me?
#include "client.h"
#include "util.h"
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <asm/types.h>
#include <math.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>
#define BUF_SIZE ETH_FRAME_TOTALLEN
#define NUMBER_OF_MESUREMENTS_PER_AMOUNT_OF_DATA 100000 /*how often to measure travelling time with one certain amount of data*/
int s = 0; /*Socketdescriptor*/
void* buffer = NULL;
long total_sent_packets = 0;
int main(int argc, char* argv[])
{
buffer = (void*)malloc(BUF_SIZE); /*Buffer for ethernet frame*/
unsigned char* etherhead = buffer; /*Pointer to ethenet header*/
unsigned char* data = buffer + 14; /*Userdata in ethernet frame*/
struct ethhdr *eh = (struct ethhdr *)etherhead; /*Another pointer to ethernet header*/
unsigned char src_mac[6]; /*our MAC address */
unsigned char dest_mac[6] = {0x00, 0x1E, 0x4F, 0xB1, 0xCB, 0x43}; /*MAC address, hardcoded...... :-(*/
struct ifreq ifr;
struct sockaddr_ll socket_address;
int ifindex = 0; /*Ethernet Interface index*/
int i,j,k;
int length; /*length of received packet*/
int sent; /*length of sent packet*/
/*stuff for time measuring: */
struct timeval begin;
struct timeval end;
struct timeval result;
unsigned long long allovertime;
printf("Client started, entering initialiation phase...\n");
/*open socket*/
s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (s == -1) {
perror("socket():");
exit(1);
}
printf("Successfully opened socket: %i\n", s);
/*retrieve ethernet interface index*/
strncpy(ifr.ifr_name, ETH0, IFNAMSIZ);
if (ioctl(s, SIOCGIFINDEX, &ifr) == -1) {
perror("SIOCGIFINDEX");
exit(1);
}
ifindex = ifr.ifr_ifindex;
printf("Successfully got interface index: %i\n", ifindex);
/*retrieve corresponding MAC*/
if (ioctl(s, SIOCGIFHWADDR, &ifr) == -1) {
perror("SIOCGIFINDEX");
exit(1);
}
for (i = 0; i < 6; i++) {
src_mac[i] = ifr.ifr_hwaddr.sa_data[i];
}
printf("Successfully got our MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n",
src_mac[0],src_mac[1],src_mac[2],src_mac[3],src_mac[4],src_mac[5]);
/*prepare sockaddr_ll*/
socket_address.sll_family = PF_PACKET;
socket_address.sll_protocol = htons(ETH_P_IP);
socket_address.sll_ifindex = ifindex;
socket_address.sll_hatype = ARPHRD_ETHER;
socket_address.sll_pkttype = PACKET_OTHERHOST;
socket_address.sll_halen = ETH_ALEN;
socket_address.sll_addr[0] = dest_mac[0];
socket_address.sll_addr[1] = dest_mac[1];
socket_address.sll_addr[2] = dest_mac[2];
socket_address.sll_addr[3] = dest_mac[3];
socket_address.sll_addr[4] = dest_mac[4];
socket_address.sll_addr[5] = dest_mac[5];
socket_address.sll_addr[6] = 0x00;
socket_address.sll_addr[7] = 0x00;
/*establish signal handler*/
signal(SIGINT, sigint);
printf("Successfully established signal handler for SIGINT\n");
/*init random number generator*/
srand(time(NULL));
printf("We are in production state, sending packets to: %02X:%02X:%02X:%02X:%02X:%02X\n",
dest_mac[0],dest_mac[1],dest_mac[2],dest_mac[3],dest_mac[4],dest_mac[5]);
for (i = 50; i <= 1500; i += 50) {
allovertime = 0;
for (k = 0; k < NUMBER_OF_MESUREMENTS_PER_AMOUNT_OF_DATA; k++) {
/*prepare buffer*/
memcpy((void*)buffer, (void*)dest_mac, ETH_MAC_LEN);
memcpy((void*)(buffer+ETH_MAC_LEN), (void*)src_mac, ETH_MAC_LEN);
eh->h_proto = ETH_P_NULL;
/*fill it with random data....*/
for (j = 0; j < i; j++) {
data[j] = (unsigned char)((int) (256.0*rand()/(RAND_MAX+1.0)));
}
/*clear the timers:*/
timerclear(&begin);
timerclear(&end);
/*get time before sending.....*/
gettimeofday(&begin,NULL);
/*send packet*/
sent = sendto(s, buffer, i+ETH_HEADER_LEN, 0, (struct sockaddr*)&socket_address, sizeof(socket_address));
if (sent == -1) {
perror("sendto():");
exit(1);
}
/*Wait for incoming packet...*/
length = recvfrom(s, buffer, BUF_SIZE, 0, NULL, NULL);
if (length == -1) {
perror("recvfrom():");
exit(1);
}
/*get time after sending.....*/
gettimeofday(&end,NULL);
/*...and calculate difference.........*/
timersub(&end,&begin,&result);
allovertime += ((result.tv_sec * 1000000 ) + result.tv_usec );
total_sent_packets++;
}
printf("Sending %i bytes takes %lld microseconds in average\n",i ,allovertime/NUMBER_OF_MESUREMENTS_PER_AMOUNT_OF_DATA);
}
return (0);
}
void sigint(int signum) {
/*Clean up.......*/
struct ifreq ifr;
if (s == -1)
return;
strncpy(ifr.ifr_name, ETH0, IFNAMSIZ);
ioctl(s, SIOCGIFFLAGS, &ifr);
ifr.ifr_flags &= ~IFF_PROMISC;
ioctl(s, SIOCSIFFLAGS, &ifr);
close(s);
free(buffer);
printf("Client terminating....\n");
printf("Totally sent: %ld packets\n", total_sent_packets);
exit(0);
}
------------------server.c---------------------
#include "server.h"
#include "util.h"
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <asm/types.h>
#include <math.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>
#define BUF_SIZE ETH_FRAME_TOTALLEN
int s = 0; /*Socketdescriptor*/
void* buffer = NULL;
long total_packets = 0;
long answered_packets = 0;
int main(int argc, char* argv[])
{
buffer = (void*)malloc(BUF_SIZE); /*Buffer for Ethernet Frame*/
unsigned char* etherhead = buffer; /*Pointer to Ethenet Header*/
struct ethhdr *eh = (struct ethhdr *)etherhead; /*Another pointer to ethernet header*/
unsigned char src_mac[6]; /*our MAC address*/
struct ifreq ifr;
struct sockaddr_ll socket_address;
int ifindex = 0; /*Ethernet Interface index*/
int i;
int length; /*length of received packet*/
int sent;
printf("Server started, entering initialiation phase...\n");
/*open socket*/
s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (s == -1) {
perror("socket():");
exit(1);
}
printf("Successfully opened socket: %i\n", s);
/*retrieve ethernet interface index*/
strncpy(ifr.ifr_name, ETH0, IFNAMSIZ);
if (ioctl(s, SIOCGIFINDEX, &ifr) == -1) {
perror("SIOCGIFINDEX");
exit(1);
}
ifindex = ifr.ifr_ifindex;
printf("Successfully got interface index: %i\n", ifindex);
/*retrieve corresponding MAC*/
if (ioctl(s, SIOCGIFHWADDR, &ifr) == -1) {
perror("SIOCGIFINDEX");
exit(1);
}
for (i = 0; i < 6; i++) {
src_mac[i] = ifr.ifr_hwaddr.sa_data[i];
}
printf("Successfully got our MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n",
src_mac[0],src_mac[1],src_mac[2],src_mac[3],src_mac[4],src_mac[5]);
/*prepare sockaddr_ll*/
socket_address.sll_family = PF_PACKET;
socket_address.sll_protocol = htons(ETH_P_IP);
socket_address.sll_ifindex = ifindex;
socket_address.sll_hatype = ARPHRD_ETHER;
socket_address.sll_pkttype = PACKET_OTHERHOST;
socket_address.sll_halen = ETH_ALEN;
socket_address.sll_addr[6] = 0x00;
socket_address.sll_addr[7] = 0x00;
/*establish signal handler (keyboard)*/
signal(SIGINT, sigint);
printf("Successfully established signal handler for SIGINT\n");
printf("We are in production state, waiting for incoming packets....\n");
while (1) {
/*Wait for incoming packet...*/
length = recvfrom(s, buffer, BUF_SIZE, 0, NULL, NULL);
if (length == -1) {
perror("recvfrom():");
exit(1);
}
/*See if we should answer (Ethertype == 0x0 && destination address == our MAC)*/
if (eh->h_proto == ETH_P_NULL && memcmp( (const void*)eh->h_dest, (const void*)src_mac, ETH_MAC_LEN) == 1 )
{
/*exchange addresses in buffer*/
memcpy( (void*)etherhead, (const void*)(etherhead+ETH_MAC_LEN), ETH_MAC_LEN);
memcpy( (void*)(etherhead+ETH_MAC_LEN), (const void*)src_mac, ETH_MAC_LEN);
/*prepare sockaddr_ll*/
socket_address.sll_addr[0] = eh->h_dest[0];
socket_address.sll_addr[1] = eh->h_dest[1];
socket_address.sll_addr[2] = eh->h_dest[2];
socket_address.sll_addr[3] = eh->h_dest[3];
socket_address.sll_addr[4] = eh->h_dest[4];
socket_address.sll_addr[5] = eh->h_dest[5];
/*send answer*/
sent = sendto(s, buffer, length-4, 0, (struct sockaddr*)&socket_address, sizeof(socket_address));
if (sent == -1) {
perror("sendto():");
exit(1);
}
answered_packets++;
}
total_packets++;
}
}
void sigint(int signum) {
/*Clean up.......*/
struct ifreq ifr;
if (s == -1)
return;
strncpy(ifr.ifr_name, ETH0, IFNAMSIZ);
ioctl(s, SIOCGIFFLAGS, &ifr);
ifr.ifr_flags &= ~IFF_PROMISC;
ioctl(s, SIOCSIFFLAGS, &ifr);
close(s);
free(buffer);
printf("Server terminating....\n");
printf("Totally received: %ld packets\n", total_packets);
printf("Answered %ld packets\n", answered_packets);
exit(0);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
对所有代码感到抱歉,但我不知道如何缩短它,因为我不确定错误在哪里。不管怎样,我发现了这个问题,所以对“代码墙”的家伙们表示歉意!
事实证明问题出在我们的交换机的配置方式上。当我在同一子网上找到两台机器后,代码运行得非常好!
Sorry for all the code, but I didn't know how to make it shorter as i wasn't sure where the error was. Anyway, I found the problem, so apologies for the "wall of code" guys!
It turns out the problem was how our switches are configured. After I got 2 machines on the same subnet the code worked beautiful!