linux原始套接字实战

本文的主线是一个使用原始套接字发送数据的程序,工作在数据链路层,采用自定义以太网帧协议,靠MAC地址识别目标主机。所以不涉及到IP地址和端口号。程序主要用于互联的两台机器之间进行丢帧率计算。以下部分都是围绕它而展开说明的。内容分为以下几部分:

  1. 原始套接字概述
  2. 原始套接字的创建
  3. 自定义协议
  4. 发送端程序流程、实现
  5. 接收端程序的开发

一、原始套接字概述

先来看看socket函数原型:

int socket(int domain, int type, int protocol);

我们知道,当进行网络编程的时候,通常会用到socket函数。而且主要有两种,一种是第二个参数为SOCK_STREAM,面向连接的 Socket,针对于面向连接的TCP 服务应用,另外一种是第二个参数为SOCK_DGRAM,面向无连接的 Socket,针对于无连接的 UDP 服务应用。对于TCP或UDP,我们不能修改其头部的格式,只能依照系统开放给我们定义好的头部进行编程开发。而今天,介绍的原始套接字却跟前面两种大不相同。原始套接字可以提供普通的TCP和UDP套接字不支持的能力。比如:

  1. 发送一个自定义的以太网帧。(这将是本节实现的重点
  2. 发送一个 ICMP 协议包。
  3. 发送一个自定义的 IP 包。
  4. 分析所有经过网络的包,而不管这样包是否是发给自己的。
  5. 伪装本地的 IP 地址。

注意:原始套接字需要在root权限下使用!

二、原始套接字的创建

创建原始套接字有如下步骤:
这里把socket函数第一个参数指定为PF_PACKET,因为本文程序利用PF_PACKET接口操作链路层的数据。
第二个参数指定为SOCK_RAW。第三个参数指定为一个字符串”0x980A”来标识自定义协议。

    int sock;
    //这里把protocol自定义为0x980A
    if((sock = socket(PF_PACKET, SOCK_RAW, htons(protocol))) < 0)
    {
        perror("socket");
        return -1;
    }

创建完成之后就可以利用函数sendto函数和recvfrom函数来发送和接收数据链路层的数据包了。

三、自定义协议

自定义数据包格式:

typedef struct {
    unsigned char  tmac[6];     //目的主机mac地址
    unsigned char  smac[6];     //本机mac地址
    unsigned short type;        //自定义为0x980A
    unsigned short  len;        //暂定为46
    unsigned char   reserve[3]; //保留,暂填写为00
    unsigned char   opcode;     //探测请求 = 0x08;响应 = 0x00
    unsigned short  seqnum;     //报文序号,从0-65535
    unsigned int    datetime;   //填充当前发送测试包时间,精确到毫秒
    unsigned char   content[34];//填充,以0123456798ABCDEF0123456……模式循环
} __attribute__((packed)) stbtest_packet_t ;

其中,attribute ((packed)) 的作用就是告诉编译器取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐。

四、发送端程序流程、实现

先来看下程序的主函数:

int main(int argc, char **argv){
    stbtest_packet_t packet;
    struct sockaddr_ll addrSrc;
    u_int nLen = 0;
    int ret = -1,i = 0;
    int fd = -1;
    char pidstr[20] = {
  0};
    struct sockaddr_ll socketAddrReply;
    //解析程序输入参数,采用./stb_test 50 30 00:00:00:00:00:00  11:11:11:11:11:11格式
    //50 表示发送频率,30表示发送周期,00:00:00:00:00:00表示本机的mac地址,11:11:11:11:11:11表示目的mac
    for(i=0; i<argc; i++)  
    {
        printf("%d ",i);
        printf("=%s\n",argv[i]);
    }
    if(argc < 4)
    {
      printf("usage:%s <freqency> <send-period> <src-mac> <dst-mac>\r\n", argv[0]);
      printf("eg: ./stb_test 50 30 dc:0e:a1:68:6a:98  dc:0e:a1:68:6a:98\r\n");
      exit(1);
    }

    stbTestCfg.freqency = atoi(argv[1]);
    stbTestCfg.send_period = atoi(argv[
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值