Как перенести фрейм Ethernet?
Я хочу отправить данные моему другу. Я не знаю его IP-адрес. Но я знаю его MAC-адрес. Поэтому я должен отправить данные, используя фреймы Ethernet.
Я написал программу, но она не работает. Я не понял, в чем проблема? Где я сделал ошибку?
отправка кадра на стороне клиента:
main()
{
int size ;
char req[10];
printf("enter to send\n");
gets(req);
int fd=socket(PF_PACKET,SOCK_RAW,htons(ETH_P_IP));
if (fd==-1)
{
perror("socket");
}
struct ifreq ifr;
char if_name[5]="eth0";
int if_name_len=strlen(if_name);
if (if_name_len<sizeof(ifr.ifr_name))
{
memcpy(ifr.ifr_name,if_name,if_name_len);
ifr.ifr_name[if_name_len]=0;
}
else
{
printf("interface name is too long");
}
if (ioctl(fd,SIOCGIFINDEX,&ifr)==-1)
{
perror("ioctl");
}
int ifindex=ifr.ifr_ifindex;
printf("ethernet interface id:%x\n",ifindex);
const unsigned char ether_broadcast_addr[]={0x00,0x1d,0x09,0x7a,0xDf,0x5e};
struct sockaddr_ll addr={0};
addr.sll_family=PF_PACKET;
addr.sll_ifindex=ifindex;
addr.sll_halen=ETHER_ADDR_LEN;
//addr.sll_protocol=htons(ETH_P_IP);
memcpy(&addr.sll_addr,ether_broadcast_addr,ETHER_ADDR_LEN);
addr.sll_hatype=772;
addr.sll_pkttype=PACKET_OUTGOING;
printf("size=%d\n",size);
if (size=sendto(fd,req,sizeof(req),0,(struct sockaddr*)&addr,sizeof(addr))==-1)
{
perror("sendto");
}
printf("send size=%d\n",size);
}
фрейм получить код на стороне сервера:
main()
{
int size;
char req[20];
int fd=socket(PF_PACKET,SOCK_RAW,htons(ETH_P_ALL));
if (fd==-1)
{
perror("socket");
}
struct ifreq ifr;
char if_name[5]="eth0";
int if_name_len=strlen(if_name);
if (if_name_len<sizeof(ifr.ifr_name))
{
memcpy(ifr.ifr_name,if_name,if_name_len);
ifr.ifr_name[if_name_len]=0;
}
else
{
printf("interface name is too long");
}
if (ioctl(fd,SIOCGIFINDEX,&ifr)==-1)
{
perror("ioctl");
}
int ifindex=ifr.ifr_ifindex;
printf("ethernet interface id:%x\n",ifindex);
const unsigned char ether_broadcast_addr[]={0x00,0x1d,0x09,0x7a,0xDf,0x5e};
struct sockaddr_ll addr={0};
addr.sll_family=PF_PACKET;
addr.sll_ifindex=ifindex;
addr.sll_halen=ETHER_ADDR_LEN;
addr.sll_protocol=htons(ETH_P_ALL);
memcpy(&addr.sll_addr,ether_broadcast_addr,ETHER_ADDR_LEN);
addr.sll_pkttype=PACKET_OUTGOING;
addr.sll_hatype=772;
bind (fd, (struct sockaddr*)&addr, sizeof(addr));
printf("size=%d\n",size);
socklen_t a=sizeof(addr);
size=recvfrom(fd,req,sizeof(req),0,(struct sockaddr*)&addr,&a);
if(size==-1)
{
perror("recvfrom");
}
printf("size=%d\n",size);
printf("recv msg=%s\n",req);
}
1 ответ
Хотя ваша программа может работать с отправкой фрейма данных в сеть, оттуда она никуда не денется. Адреса МАС не являются иерархическими, что означает, что адресное пространство плоское. Знание MAC-адреса ничего не говорит вам о том, как достичь этого адреса.
Наличие чьего-либо MAC-адреса совпадает с чьим-либо именем. Вы можете знать их имя, но не можете позвонить им по нашему номеру телефона. Теперь, если у вас есть их полное имя, вы можете посмотреть их номер телефона. Сеть похожа.
Сетевые данные (пакеты) отправляются с вашего компьютера на ваш шлюз по умолчанию, который представляет собой DSL или кабельный модем, который подключается к вашему провайдеру. Когда он получает пакет, он смотрит на IP-адрес, чтобы решить, куда его отправить. Поскольку ваш фрейм (данные без IP-адреса называются фреймом) не имеет IP-адреса, шлюз просто удалит его. Чтобы быть более точным, поскольку у него нет IP-адреса назначения или источника, он никогда не достигает шлюза. Он передается по сети и с этим ничего не делается.