SOCK_RAW发送TCP数据包

1.TCP RAW服务器

/*********************************************************************************************************
**
**                                    中国软件开源组织
**
**                                   嵌入式实时操作系统
**
**                                       SylixOS(TM)
**
**                               Copyright  All Rights Reserved
**
**--------------文件信息----------------------------------------------------------------------------------
**
** 文   件   名: tcp_self_raw_iptcp.c
**
** 创   建   人: zhangyazhong (张亚中)
**
** 文件创建日期: 2018年08月22日
**
** 描        述: TCP RAW 自定义服务器
*********************************************************************************************************/
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
/*********************************************************************************************************
  宏定义
*********************************************************************************************************/
/*
 * ip首部长度
 */
#define IP_HEADER_LEN sizeof(struct ip)
/*
 * tcp首部长度
 */
#define TCP_HEADER_LEN sizeof(struct tcphdr)
/*
 * ip首部 + tcp首部长度
 */
#define IP_TCP_HEADER_LEN IP_HEADER_LEN + TCP_HEADER_LEN
/*
 * 接收数据缓冲大小
 */
#define BUFFER_SIZE 1024
/*
 * ip首部 + tcp首部 + 数据缓冲区大小
 */
#define IP_TCP_BUFF_SIZE IP_TCP_HEADER_LEN + BUFFER_SIZE

/*********************************************************************************************************
** 函数名称: raw_socket_recv
** 功能描述: 原始套接字接收
** 输 入  : NONE
** 输 出  :
** 全局变量:
** 调用模块:
*********************************************************************************************************/
void raw_socket_recv()
{
    struct ip       *ip_header;
    struct tcphdr   *tcp_header;
    int             sock_raw_fd, ret_len;
    char            buf[IP_TCP_BUFF_SIZE];

    if ((sock_raw_fd = socket(PF_INET, SOCK_RAW, IPPROTO_TCP)) == -1)
         err_exit("socket()");

    /*
     * 接收数据
     */
    while (1) {
        bzero(buf, IP_TCP_BUFF_SIZE);
        ret_len = recv(sock_raw_fd, buf, IP_TCP_BUFF_SIZE, 0);
        if (ret_len > 0) {
             /*
              * 取出ip首部
              */
             ip_header = (struct ip *)buf;
             /*
              * 取出tcp首部
              */
            tcp_header = (struct tcphdr *)(buf + IP_HEADER_LEN);

            if (!strcmp(inet_ntoa(ip_header->ip_src), "192.168.7.11") && ntohs(tcp_header->th_sport) == 5566) {
                printf("=======================================\n");
                printf("from ip:%s\n", inet_ntoa(ip_header->ip_src));
                printf("from port:%d\n", ntohs(tcp_header->th_sport));
                /*
                 * 取出数据
                 */
                printf("get data from client:%s\n", buf + IP_TCP_HEADER_LEN);
            }
        }
    }

    close(sock_raw_fd);
}
/*********************************************************************************************************
** 函数名称: tcp_raw_serverHPacket
** 功能描述: TCP RAW服务器主函数
** 输 入  : NONE
** 输 出  :
** 全局变量:
** 调用模块:
*********************************************************************************************************/
int tcp_raw_serverHPacket(void)
{
    printf("TCP RAW Server Start############################\n");
     /*
      * 原始套接字接收
      */
    raw_socket_recv();

    return 0;
}


2.客户端(发送端)

/*********************************************************************************************************
**
**                                    中国软件开源组织
**
**                                   嵌入式实时操作系统
**
**                                       SylixOS(TM)
**
**                               Copyright  All Rights Reserved
**
**--------------文件信息----------------------------------------------------------------------------------
**
** 文   件   名: tcpHeader_Packet_self.c
**
** 创   建   人: zhangyazhong (张亚中)
**
** 文件创建日期: 2018年08月22日
**
** 描        述: TCP RAW自定义发送以太网帧(客户端)
*********************************************************************************************************/
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
/*********************************************************************************************************
  宏定义
*********************************************************************************************************/
 /* ip首部长度 */
#define IP_HEADER_LEN sizeof(struct ip)
 /* tcp首部长度 */
#define TCP_HEADER_LEN sizeof(struct tcphdr)
 /* ip首部 + tcp首部长度 */
#define IP_TCP_HEADER_LEN IP_HEADER_LEN + TCP_HEADER_LEN
/*********************************************************************************************************
  全局变量定义
*********************************************************************************************************/
char Data[256] = "TCP RAW Client!";/*传输内容*/
/*********************************************************************************************************
** 函数名称: err_exit
** 功能描述: 错误处理函数
** 输 入  : NONE
** 输 出  :
** 全局变量:
** 调用模块:
*********************************************************************************************************/
void err_exit(const char *err_msg)
{
    perror(err_msg);
     exit(1);
}
/*********************************************************************************************************
** 函数名称: fill_ip_header
** 功能描述: 填充ip首部
** 输 入  : NONE
** 输 出  :
** 全局变量:
** 调用模块:
*********************************************************************************************************/
struct ip *fill_ip_header(const char *src_ip, const char *dst_ip, int ip_packet_len)
{
     struct ip *ip_header;

     ip_header         = (struct ip *)malloc(IP_HEADER_LEN);
     ip_header->ip_v   = IPVERSION;
     ip_header->ip_hl  = sizeof(struct ip) / 4;                                    /* 这里注意,ip首部长度
                                                                                      是指占多个32位的数量,
                                                                                      4字节=32位,所以除以4*/
     ip_header->ip_tos = 0;
     ip_header->ip_len = htons(ip_packet_len);                                     /* 整个IP数据报长度,包
                                                                                      括普通数据 */
     ip_header->ip_id  = 0;                                                        /* 让内核自己填充标识位 */
     ip_header->ip_off = 0;
     ip_header->ip_ttl = MAXTTL;
     ip_header->ip_p   = IPPROTO_TCP;                                              /* ip包封装的协议类型 */
     ip_header->ip_sum = 0;                                                        /* 让内核自己计算校验和 */
     ip_header->ip_src.s_addr = inet_addr(src_ip);                                 /* 源IP地址 */
     ip_header->ip_dst.s_addr = inet_addr(dst_ip);                                 /* 目标IP地址 */

     return ip_header;
}
/*********************************************************************************************************
** 函数名称: fill_tcp_header
** 功能描述: 填充tcp首部
** 输 入  : NONE
** 输 出  :
** 全局变量:
** 调用模块:
*********************************************************************************************************/
 struct tcphdr *fill_tcp_header(int src_port, int dst_port)
 {
     struct tcphdr *tcp_header;

     tcp_header = (struct tcphdr *)malloc(TCP_HEADER_LEN);
     tcp_header->th_sport = htons(src_port);
     tcp_header->th_dport = htons(dst_port);
     /*
      * 同IP首部一样,这里是占32位的字节多少个
      */
     tcp_header->th_off = sizeof(struct tcphdr) / 4;
     /*
      * 发起连接
      */
     tcp_header->th_flags = TH_SYN;
     tcp_header->th_win = 4096;
     tcp_header->th_sum = 0;

     return tcp_header;
 }
 /*********************************************************************************************************
 ** 函数名称: ip_tcp_send
 ** 功能描述: 发送ip_tcp报文
 ** 输 入  : NONE
 ** 输 出  :
 ** 全局变量:
 ** 调用模块:
 *********************************************************************************************************/
 void ip_tcp_send(const char *src_ip, int src_port, const char *dst_ip, int dst_port, const char *data)
 {
     struct ip           *ip_header;
     struct tcphdr       *tcp_header;
     struct sockaddr_in  dst_addr;
     socklen_t           sock_addrlen = sizeof(struct sockaddr_in);
     int                 data_len = strlen(data);
     int                 ip_packet_len = IP_TCP_HEADER_LEN + data_len;
     char                buf[ip_packet_len];
     int                 sockfd, ret_len, on = 1;

     bzero(&dst_addr, sock_addrlen);
     dst_addr.sin_family = PF_INET;
     dst_addr.sin_addr.s_addr = inet_addr(dst_ip);
     dst_addr.sin_port = htons(dst_port);

     /*
      * 创建tcp原始套接字
      */
     if ((sockfd = socket(PF_INET, SOCK_RAW, IPPROTO_TCP)) == -1)
         err_exit("socket()");

     if (setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) == -1)
         err_exit("setsockopt()");


     ip_header = fill_ip_header(src_ip, dst_ip, ip_packet_len);

     tcp_header = fill_tcp_header(src_port, dst_port);

     bzero(buf, ip_packet_len);
     memcpy(buf, ip_header, IP_HEADER_LEN);
     memcpy(buf + IP_HEADER_LEN, tcp_header, TCP_HEADER_LEN);
     memcpy(buf + IP_TCP_HEADER_LEN, data, data_len);
     while (1) {
         ret_len = sendto(sockfd, buf, ip_packet_len, 0, (struct sockaddr *)&dst_addr, sock_addrlen);
         if (ret_len > 0){
             printf("sendto() ok!!!\n");
         } else {
             printf("sendto() failed\n");
         }
         sleep(2);

     }
     /*
      * 发送报文
      */

     close(sockfd);
     free(ip_header);
     free(tcp_header);
 }
 /*********************************************************************************************************
 ** 函数名称: tcpHPacket
 ** 功能描述: 发送ip_tcp报文入口函数
 ** 输 入  : NONE
 ** 输 出  :
 ** 全局变量:
 ** 调用模块:
 *********************************************************************************************************/
 int tcpHPacket(int argc, char *argv[])
 {
     printf("TCP RAW Client Start###########(by yourself)\n");
     printf("srcPort:5566\n "
            "srcAddr:192.168.7.11\n"
            "dstPort:8444\n"
            "dstAddr:192.168.7.33\n"
            "data is %s\n", Data);
     /*
      * 发送ip_tcp报文
      */
     ip_tcp_send(SRC_ADDR, SRC_PORT, TCP_SERVER_ADDR, TCP_SERVER_PORT, Data);

     return 0;
 }

 

你可能感兴趣的:(c,网络)