linux基础编程 链路层socket 摆脱winPcap 夸网段socket通信 可夸平台移植
2017-04-10 14:36
543 查看
在linux环境中要从链路层(MAC)直接收发数据帧,可以通过libpcap与libnet两个动态库来分别完成收与发的工作。虽然它已被广泛使用,但在要求进行跨平台移植的软件中使用就很难办到了。。
这是一种更为直接地、无须安装其它库的从MAC层收发数据帧的方式,即通过定义链路层的套接字来完成。
下面的代码也是我做的项目中的代码(夸网段访问网络中的嵌入式设备),去掉了敏感部分,和大家共享!
但是得尊重别人的劳动成果,转载注明出处,谢谢!
[cpp]
view plain
copy
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <lin
4000
ux/if_packet.h>
#include <arpa/inet.h>
/*链路层socket接收端口*/
#define RAW_PROTOCOL 0x0909
#define ETH_NAME "eth0"
#define __DEBUG
#ifdef __DEBUG
#define DBG(fmt,args...) fprintf(stdout, fmt, ##args)
#else
#define DBG(fmt,args...)
#endif
#define ERR(fmt,args...) fprintf(stderr, fmt, ##args)
static int raw_fd;
static int if_index;
static int isSearchQuit = 0;
unsigned char my_mac[6]; /*用于本机保存网卡地址*/
/*接收链路层数据包*/
int GetPacket(unsigned char *buf, int *len)
{
int length = 0;
length = recvfrom( raw_fd, buf, 2000, 0, NULL, NULL );
if ( length < 0 ) {
ERR("failed to receive buf!");
return -1;
}else {
*len = length;
return 0;
}
}
/*发送链路层数据包*/
int SendPacket(unsigned char *buf, int len)
{
struct sockaddr_ll link;
link.sll_ifindex = if_index;
memcpy( link.sll_addr, buf, link.sll_halen );
if ( sendto( raw_fd, buf, len, 0, (struct sockaddr *)&link, sizeof(link) ) < 0 ) {
ERR( "failed to send to RAW socket!\r\n" );
return -1;
}
return 0;
}
void ShowData(unsigned char *d1,int len)
{
int i;
for(i=0;i<len;i++)
printf("%02x ",d1[i]);
printf("\n\r");
}
void *RawSocketThread(void *arg)
{
unsigned char rcvPackage[70];
unsigned char sndPackage[70];
int len;
int curStatus = 0;
while(1){
int ret = 0;
int done = 0;
ret = GetPacket(rcvPackage,&len); //block here
if(ret == -1)
break;
ShowData(rcvPackage,len);
sleep(1);
ret = SendPacket(rcvPackage,len);
if(ret ==-1)
break;
}
pthread_exit(NULL);
close(raw_fd);
}
int RawSocketInit()
{
pthread_t tRawSocketThr;
struct ifreq req;
/*创建链路层socket,注意PF_PACKET,SOCK_RAW,以及RAW_PROTOCOL(自定义的)*/
if ( (raw_fd = socket(PF_PACKET, SOCK_RAW, htons( RAW_PROTOCOL ) ) ) < 0 ) {
ERR( "failed to create raw socket!\n" );
return -1;
}
/*绑定网卡*/
strcpy( req.ifr_name, ETH_NAME );
if ( ioctl( raw_fd, SIOCGIFFLAGS, &req ) < 0 ) {
ERR( "failed to do ioctl!" );
return -1;
}
/*设置工作模式*/
req.ifr_flags |= IFF_PROMISC;
if ( ioctl( raw_fd, SIOCSIFFLAGS, &req ) < 0 ) {
ERR( "failed to set eth0 into promisc mode!" );
return -1;
}
if ( ioctl( raw_fd, SIOCGIFHWADDR, &req ) < 0 ) {
ERR( "failed to get interface hw address!" );
return -1;
}
memcpy( my_mac, req.ifr_hwaddr.sa_data, sizeof(my_mac) );
if ( ioctl( raw_fd, SIOCGIFINDEX, &req ) < 0 ) {
ERR( "failed to get interface index!" );
return -1;
}
if_index = req.ifr_ifindex;
if(pthread_create(&tRawSocketThr,NULL,RawSocketThread,NULL) == -1){
ERR("ERROR in RawSocketThread\n");
return -1;
}
pthread_detach(tIPNCSearchThr);
return 0;
}
#if 1
int main()
{
int count =0;
RawSocketInit();
while(1){
sleep(1);
}
}
#endif
运行结果,接收自网络中的完整数据包:
[cpp]
view plain
copy
[root@localhost src]# ./RawSocket
ff ff ff ff ff ff 1c 6f 65 dc fa fb 09 09 00 00 00 00 06 04 01 00 00 00 00 00 00 00 c0 a8 01 dc ff ff ff ff ff ff c0 a8 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
这是一种更为直接地、无须安装其它库的从MAC层收发数据帧的方式,即通过定义链路层的套接字来完成。
下面的代码也是我做的项目中的代码(夸网段访问网络中的嵌入式设备),去掉了敏感部分,和大家共享!
但是得尊重别人的劳动成果,转载注明出处,谢谢!
[cpp]
view plain
copy
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <lin
4000
ux/if_packet.h>
#include <arpa/inet.h>
/*链路层socket接收端口*/
#define RAW_PROTOCOL 0x0909
#define ETH_NAME "eth0"
#define __DEBUG
#ifdef __DEBUG
#define DBG(fmt,args...) fprintf(stdout, fmt, ##args)
#else
#define DBG(fmt,args...)
#endif
#define ERR(fmt,args...) fprintf(stderr, fmt, ##args)
static int raw_fd;
static int if_index;
static int isSearchQuit = 0;
unsigned char my_mac[6]; /*用于本机保存网卡地址*/
/*接收链路层数据包*/
int GetPacket(unsigned char *buf, int *len)
{
int length = 0;
length = recvfrom( raw_fd, buf, 2000, 0, NULL, NULL );
if ( length < 0 ) {
ERR("failed to receive buf!");
return -1;
}else {
*len = length;
return 0;
}
}
/*发送链路层数据包*/
int SendPacket(unsigned char *buf, int len)
{
struct sockaddr_ll link;
link.sll_ifindex = if_index;
memcpy( link.sll_addr, buf, link.sll_halen );
if ( sendto( raw_fd, buf, len, 0, (struct sockaddr *)&link, sizeof(link) ) < 0 ) {
ERR( "failed to send to RAW socket!\r\n" );
return -1;
}
return 0;
}
void ShowData(unsigned char *d1,int len)
{
int i;
for(i=0;i<len;i++)
printf("%02x ",d1[i]);
printf("\n\r");
}
void *RawSocketThread(void *arg)
{
unsigned char rcvPackage[70];
unsigned char sndPackage[70];
int len;
int curStatus = 0;
while(1){
int ret = 0;
int done = 0;
ret = GetPacket(rcvPackage,&len); //block here
if(ret == -1)
break;
ShowData(rcvPackage,len);
sleep(1);
ret = SendPacket(rcvPackage,len);
if(ret ==-1)
break;
}
pthread_exit(NULL);
close(raw_fd);
}
int RawSocketInit()
{
pthread_t tRawSocketThr;
struct ifreq req;
/*创建链路层socket,注意PF_PACKET,SOCK_RAW,以及RAW_PROTOCOL(自定义的)*/
if ( (raw_fd = socket(PF_PACKET, SOCK_RAW, htons( RAW_PROTOCOL ) ) ) < 0 ) {
ERR( "failed to create raw socket!\n" );
return -1;
}
/*绑定网卡*/
strcpy( req.ifr_name, ETH_NAME );
if ( ioctl( raw_fd, SIOCGIFFLAGS, &req ) < 0 ) {
ERR( "failed to do ioctl!" );
return -1;
}
/*设置工作模式*/
req.ifr_flags |= IFF_PROMISC;
if ( ioctl( raw_fd, SIOCSIFFLAGS, &req ) < 0 ) {
ERR( "failed to set eth0 into promisc mode!" );
return -1;
}
if ( ioctl( raw_fd, SIOCGIFHWADDR, &req ) < 0 ) {
ERR( "failed to get interface hw address!" );
return -1;
}
memcpy( my_mac, req.ifr_hwaddr.sa_data, sizeof(my_mac) );
if ( ioctl( raw_fd, SIOCGIFINDEX, &req ) < 0 ) {
ERR( "failed to get interface index!" );
return -1;
}
if_index = req.ifr_ifindex;
if(pthread_create(&tRawSocketThr,NULL,RawSocketThread,NULL) == -1){
ERR("ERROR in RawSocketThread\n");
return -1;
}
pthread_detach(tIPNCSearchThr);
return 0;
}
#if 1
int main()
{
int count =0;
RawSocketInit();
while(1){
sleep(1);
}
}
#endif
运行结果,接收自网络中的完整数据包:
[cpp]
view plain
copy
[root@localhost src]# ./RawSocket
ff ff ff ff ff ff 1c 6f 65 dc fa fb 09 09 00 00 00 00 06 04 01 00 00 00 00 00 00 00 c0 a8 01 dc ff ff ff ff ff ff c0 a8 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
相关文章推荐
- linux基础编程 链路层socket 摆脱winPcap 夸网段socket通信 可夸平台移植
- linux基础编程 链路层socket 摆脱winPcap 夸网段socket通信 可夸平台移植
- 【原创】《Linux高级程序设计》杨宗德著 - Linux Socket网络编程基础 - BSD Socket网络通信编程 分类: Linux --- 应用程序设计 2014-12-05 16:53 63人阅读 评论(0) 收藏
- 【原创】《Linux高级程序设计》杨宗德著 - Linux Socket网络编程基础 - 网络通信基础 分类: Linux --- 应用程序设计 2014-12-03 22:46 71人阅读 评论(0) 收藏
- Linux socket编程入门及客户端服务器端通信实现 – 基础篇
- 【原创】《Linux高级程序设计》杨宗德著 - Linux Socket网络编程基础 - 网络通信基础
- 【网络编程基础】Linux下进程通信方式(共享内存,管道,消息队列,Socket)
- 【原创】《Linux高级程序设计》杨宗德著 - Linux Socket网络编程基础 - BSD Socket网络通信编程
- linux socket编程基础2
- Socket编程:由Linux向Windows移植问题
- Linux下基于C/C++的Socket编程基础
- Linux下的C编程实战(开发平台搭建,文件系统编程,进程控制与进程通信编程,“线程”控制与“线程”通信编程,驱动程序设计,专家问答)
- Socket 编程 windows到Linux代码移植遇到的问题
- Linux 下Socket编程基础
- Linux Socket 网络编程 基于GTK+ 的多线程实现的局域网通信软件
- Linux 下Socket编程基础(转,当笔记了)
- Linux 下Socket编程基础(转载自http://patton.spaces.eepw.com.cn/articles/article/item/27549)
- Linux socket编程(二) 服务器与客户端的通信
- Linux Socket 网络编程 基于GTK+ 的多线程实现的局域网通信软件
- Linux 下Socket编程基础