Linux-Rawsoket通信
为了满足能够从2层直接读取相应数据编写了raw通讯接口, 直接代码。
1. server
#include pthread.h
#include sys/socket.h
#include sys/ioctl.h
#include sys/time.h
#include asm/types.h
#include math.h
#include string.h
#include stdlib.h
#include unistd.h
#include signal.h
#include linux/if.h
#include linux/if_packet.h
#include linux/if_ether.h
#include linux/if_arp.h
#include arpa/inet.h
#include stdio.h
#include "rawsend.h"
#include "MessageFrame.h"
#include "ber_decoder.h"
int sock_fd = 0;
char *ifname;
int running = 1;
struct raw_result server_result;
int open_socket(const char *ifname)
{
struct ifreq ifr;
int sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_WSMP));
if (sock < 0){
exit(EXIT_FAILURE);
}
strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
ioctl(sock, SIOCGIFFLAGS, &ifr);
ifr.ifr_flags |= IFF_PROMISC;
ioctl(sock, SIOCGIFFLAGS, &ifr);
return sock;
}
void close_socket(int sock)
{
struct ifreq ifr;
/* reset promiscuous mode */
strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
ioctl(sock_fd, SIOCGIFFLAGS, &ifr);
ifr.ifr_flags &= ~IFF_PROMISC;
ioctl(sock_fd, SIOCSIFFLAGS, &ifr);
shutdown(sock_fd, SHUT_RD);
close(sock_fd);
}
void print_mac(const char *addr)
{
int i;
for (i = 0; i < ETH_ALEN - 1; i++){
printf("%02hhx:", addr[i]);
}
printf("%02hhx\n", addr[ETH_ALEN - 1]);
}
int interface_index(int sock, char *ifname)
{
struct ifreq ifr;
int i;
/* retrieve source ethernet interface index */
strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
if (ioctl(sock_fd, SIOCGIFINDEX, &ifr) < 0)
return -EXIT_FAILURE;
return ifr.ifr_ifindex;
}
int interface_addr(int sock, char *ifname, char *addr)
{
struct ifreq ifr;
/* retrieve corresponding source MAC */
strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
if (ioctl(sock_fd, SIOCGIFHWADDR, &ifr) < 0){
return -EXIT_FAILURE;
}
memcpy(addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
return EXIT_SUCCESS;
}
void sigint(int signum)
{
if (!running){
exit(EXIT_FAILURE);
}
running = 0;
}
double timeval_subtract(struct timeval *result, struct timeval *t2, struct timeval *t1)
{
double ret;
long int diff;
diff = (t2->tv_usec + 1000000 * t2->tv_sec) - (t1->tv_usec + 1000000 * t1->tv_sec);
result->tv_sec = diff / 1000000;
result->tv_usec = diff % 1000000;
ret = diff;
ret /= 1000000.0;
return ret;
}
int main(int argc, char *argv[])
{
unsigned char *buff = (void *)malloc(PACKET_SIZE);
unsigned char *data_ptr = buff + ETH_HLEN;
unsigned char src_mac[ETH_ALEN];
struct ethhdr *eth_hdr = (struct ethhdr *)buff;
struct sockaddr_ll s_addr;
struct timeval begin, end, elapsed;
struct raw_result *result = (struct raw_result *)(data_ptr + sizeof(END_OF_STREAM));
double diff;
int if_index = 0, recv, i, seq;
if (argc < 2)
{
printf("Missing arguments.\n"
"%s [ifname] \n",argv[0]);
exit(EXIT_FAILURE);
}
ifname = argv[1];
/* open socket */
if ((sock_fd = open_socket(ifname)) < 0){
exit(EXIT_FAILURE);
}
/* get ethernet interface index */
if ((if_index = interface_index(sock_fd, ifname)) < 0){
exit(EXIT_FAILURE);
}
/* get ethernet interface address */
if (interface_addr(sock_fd, ifname, src_mac) < 0){
exit(EXIT_FAILURE);
}
/* prepare sockaddr_ll */
memset(&s_addr, 0, sizeof(s_addr));
s_addr.sll_family = AF_PACKET;
s_addr.sll_protocol = htons(ETH_P_WSMP);
s_addr.sll_ifindex = if_index;
/* bind to interface */
if (bind(sock_fd, (struct sockaddr *) &s_addr, sizeof(s_addr)) == -1){
exit(EXIT_FAILURE);
}
/* enable signal */
signal(SIGINT, sigint);
printf("listening on ");
print_mac(src_mac);
while (running) {
recv = recvfrom(sock_fd, buff, PACKET_SIZE, 0, NULL, NULL);
if (recv <= 0){
continue;
}else{
print_string_hex(buff, recv);
}
}
return EXIT_SUCCESS;
}
2. client
#include pthread.h
#include sys/socket.h
#include sys/ioctl.h
#include sys/time.h
#include asm/types.h
#include math.h
#include string.h
#include stdlib.h
#include unistd.h
#include signal.h
#include linux/if.h
#include linux/if_packet.h
#include linux/if_ether.h
#include linux/if_arp.h
#include arpa/inet.h
#include stdio.h
#include "rawsend.h"
struct raw_result client_result;
int sock_fd = 0;
unsigned char* out_buff = NULL;
unsigned char* in_buff = NULL;
unsigned char snd_mac[6];
char *src_ifname;
char *dst_ifname;
long total_sent_packets = 0;
long total_recv_packets = 0;
long total_sent_bytes = 0;
int running = 1, waiting = 1;
int open_socket(const char *ifname)
{
struct ifreq ifr;
int sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_WSMP));
if (sock < 0){
exit(EXIT_FAILURE);
}
/* set promiscuous mode */
strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
ioctl(sock, SIOCGIFFLAGS, &ifr);
ifr.ifr_flags |= IFF_PROMISC;
ioctl(sock, SIOCGIFFLAGS, &ifr);
return sock;
}
void close_socket(int sock)
{
struct ifreq ifr;
/* reset promiscuous mode */
strncpy(ifr.ifr_name, src_ifname, IFNAMSIZ);
ioctl(sock_fd, SIOCGIFFLAGS, &ifr);
ifr.ifr_flags &= ~IFF_PROMISC;
ioctl(sock_fd, SIOCSIFFLAGS, &ifr);
shutdown(sock_fd, SHUT_RD);
close(sock_fd);
}
void print_mac(const char *addr)
{
int i;
for (i = 0; i < ETH_ALEN - 1; i++){
printf("%02hhx:", addr[i]);
}
printf("%02hhx\n", addr[ETH_ALEN - 1]);
}
int interface_index(int sock, char *ifname)
{
struct ifreq ifr;
int i;
/* retrieve source ethernet interface index */
strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
if (ioctl(sock_fd, SIOCGIFINDEX, &ifr) < 0){
return -EXIT_FAILURE;
}
return ifr.ifr_ifindex;
}
int interface_addr(int sock, char *ifname, char *addr)
{
struct ifreq ifr;
/* retrieve corresponding source MAC */
strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
if (ioctl(sock_fd, SIOCGIFHWADDR, &ifr) < 0){
return -EXIT_FAILURE;
}
memcpy(addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
return EXIT_SUCCESS;
}
void sigint(int signum)
{
if (!running){
exit(EXIT_FAILURE);
}
running = 0;
}
void sigalarm(int signum)
{
if (!running){
exit(EXIT_FAILURE);
}
running = 0;
}
int main(int argc, char *argv[])
{
pthread_t thread;
out_buff = (void*)malloc(PACKET_SIZE);
unsigned char *data_ptr = out_buff + ETH_HLEN;
unsigned char src_addr[ETH_HLEN], dst_addr[ETH_HLEN];
struct ethhdr *out_hdr = (struct ethhdr *)out_buff;
struct sockaddr_ll s_addr;
struct timeval begin, end, elapsed;
double diff;
int i, sent, rate, interval, timeout = 0, src_idx, dst_idx;
src_ifname = argv[1];
/* open raw socket */
if ((sock_fd = open_socket(src_ifname)) < 0){
exit(EXIT_FAILURE);
}
/* prepare source interface */
if ((src_idx = interface_index(sock_fd, src_ifname)) < 0){
exit(EXIT_FAILURE);
}
if (interface_addr(sock_fd, src_ifname, src_addr) < 0){
exit(EXIT_FAILURE);
}
memset(dst_addr, 0xff, ETH_HLEN);
/* prepare sockaddr_ll */
memset(&s_addr, 0, sizeof(s_addr));
s_addr.sll_family = AF_PACKET;
s_addr.sll_protocol = htons(ETH_P_ALL);
s_addr.sll_ifindex = src_idx;
if (bind(sock_fd, (struct sockaddr *)&s_addr, sizeof(s_addr)) < 0){
exit(EXIT_FAILURE);
}
/* enable signals */
signal(SIGINT, sigint);
signal(SIGALRM, sigalarm);
if (timeout){
alarm(timeout);
}
/* prepare ethernet header */
memcpy(out_hdr->h_dest, dst_addr, ETH_ALEN);
memcpy(out_hdr->h_source, src_addr, ETH_ALEN);
out_hdr->h_proto= htons(ETH_P_WSMP);
/* fill ethernet payload with some data */
for (i = 0; i < PACKET_SIZE - ETH_HLEN; i++){
data_ptr[i] = (unsigned char)(1);
}
printf("sending packets\n");
memcpy(s_addr.sll_addr, dst_addr, ETH_ALEN);
while (running) {
*(int *)data_ptr = htonl(client_result.sequence++);
sent = sendto(sock_fd, out_buff, PACKET_SIZE, 0, (struct sockaddr *)&s_addr, sizeof(s_addr));
if(sent){
printf("sending packets sucess\n");
print_string_hex(out_buff, sent);
}
sleep(5);
}
close_socket(sock_fd);
return EXIT_SUCCESS;
}
3 头文件
#define PACKET_SIZE 1000
#ifndef ETH_P_WSMP
#define ETH_P_WSMP 0x88DC
#endif
void print_string_hex(char *buf, unsigned short length)
{
int i =0;
printf("\n\t\t");
for( i = 0; i < length; i++){
printf(" %02X", (buf[i]&0xFF));
if( (i + 1) % 16 == 0 )
{
printf("\n\t\t");
}
}
printf("\n\n");
}