-
soc = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); in client side, when run, get == -1 error
-
if accept function can only use with UDP and TCP higher protocol, how to accept multiple client with layer 2 communication?
where can find the code of accept function, i would like to rewrite it for layer 2.
Updated :
After tried soc = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
also == -1 , get this error
server side and client side both are the same computer, local one
strange is that running server side, it do not have this error, but running client program got error
//#include "stdafx.h"
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>
#include <net/if.h>
#include <netinet/if_ether.h>
#include <netpacket/packet.h>
#include <net/ethernet.h>
#include <netinet/ether.h>
//#include "sock.h"
#define MAX_MESSAGE 21000
#define FD_NUM 5
#define tcp_port 5009
//#pragma comment(lib, "ws2_32.lib")
//#include <winsock2.h>
char host_ip[16] = "127.0.0.1";
void task()
{
struct sockaddr_in local;
int opt;
int soc;
//soc = socket(AF_INET,SOCK_STREAM,0);
soc = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (soc==-1) {
printf("socket error\n");
}
// determine ethernet number
/*
struct ifreq ifr;
size_t 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) {
printf("determine ethernet number error\n");
}
int ifindex=ifr.ifr_ifindex;
*/
// mac address
/*target address*/
struct sockaddr_ll socket_address;
/*buffer for ethernet frame*/
void* buffer = (void*)malloc(ETH_FRAME_LEN);
/*pointer to ethenet header*/
unsigned char* etherhead = (unsigned char*)buffer;
/*userdata in ethernet frame*/
unsigned char* data = (unsigned char*)buffer + 14;
/*another pointer to ethernet header*/
struct ethhdr *eh = (struct ethhdr *)etherhead;
int send_result = 0;
/*our MAC address*/
//10:78:d2:ad:90:cb
//0x10,0x78,0xD2,0xAD,0x90,0xCB
unsigned char src_mac[6] = {0x10,0x78,0xD2,0xAD,0x90,0xCB};
/*other host MAC address*/
unsigned char dest_mac[6] = {0x10,0x78,0xD2,0xAD,0x90,0xCB};
/*prepare sockaddr_ll*/
/*RAW communication*/
socket_address.sll_family = PF_PACKET;
/*we don't use a protocoll above ethernet layer
->just use anything here*/
socket_address.sll_protocol = htons(ETH_P_IP);
/*index of the network device
see full code later how to retrieve it*/
socket_address.sll_ifindex = 0;
/*ARP hardware identifier is ethernet*/
socket_address.sll_hatype = ARPHRD_ETHER;
/*target is another host*/
socket_address.sll_pkttype = PACKET_OTHERHOST;
/*address length*/
socket_address.sll_halen = ETH_ALEN;
/*MAC - begin*/
socket_address.sll_addr[0] = 0x10;
socket_address.sll_addr[1] = 0x78;
socket_address.sll_addr[2] = 0xD2;
socket_address.sll_addr[3] = 0xAD;
socket_address.sll_addr[4] = 0x90;
socket_address.sll_addr[5] = 0xCB;
/*MAC - end*/
socket_address.sll_addr[6] = 0x00;/*not used*/
socket_address.sll_addr[7] = 0x00;/*not used*/
memcpy((void*)buffer, (void*)dest_mac, ETH_ALEN);
memcpy((void*)(buffer+ETH_ALEN), (void*)src_mac, ETH_ALEN);
eh->h_proto = 0x00;
int j = 0;
for (j = 46; --j; data[j] = (unsigned char)((int) (255.0*rand()/(RAND_MAX+1.0))));
/*
struct sockaddr_in server;
int len = sizeof(server);
server.sin_family=AF_INET;
server.sin_port=htons(5008);
server.sin_addr.s_addr=inet_addr(host_ip);
int CONN_SOCK = InitSocketTcp(tcp_port);
if(connect(CONN_SOCK, (struct sockaddr*)&server, sizeof(server)) == -1)
{
printf("connection failed\n");
}
else
{
printf("connection ok!\n");
}
*/
while(1)
{
char buff[492] = "\0";
printf("input: ");
scanf("%s", buff);
//send(CONN_SOCK,buff,strlen(buff),0);
/*send the packet*/
send_result = sendto(soc, buff, ETH_FRAME_LEN, 0, (struct sockaddr*)&socket_address, sizeof(socket_address));
send_result == -1?printf("send error"):0;
if(buff[0] == 'q')
{
//shutdown(CONN_SOCK, SD_SEND);
//closesocket(CONN_SOCK);
//WSACleanup();
close(soc);
exit(0);
}
}
}
int main()
{
//for(int i=10; i!=0; --i)
//pthread_create();
task();
return 0;
}
Accept() is only used for TCP or UDP (practically it’s main use is in tcp), because it establishes a connection. A connection does 3 way handshake in case of tcp and exchanges information such as sequence numbers etc. and is completely identified by a socket (port plus ip address)
In contrast to that you can simply use sendto and receivefrom api’s as normally used in case of udp, where each packet may follow a different path to reach destination. You do not require an accept in case of udp communication. The same can be extended to link layer (L2) frames i.e. each side can send or receive at will without actually establishing a connection first.
This should be done using root