SOCK_RAW发送tcp数据包(点对点)

1.server

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>

/* 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

void err_exit(const char *err_msg)
{
     perror(err_msg);
     exit(1);
}

/* 原始套接字接收 */
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 (ntohs(tcp_header->th_sport) != 14692) {
                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:%s\n", buf + IP_TCP_HEADER_LEN);
            }
        }
    }

    close(sock_raw_fd);
}
int main(void)
{
     /* 原始套接字接收 */
    raw_socket_recv();

    return 0;
}

2.client(1)

#include <stdio.h>
#include <ctype.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <netdb.h>
#include <errno.h>
#include <stdlib.h>
#include <time.h>
#include <arpa/inet.h>
#include <netinet/ip.h>
#include <pthread.h>

#define errorlog(msg) do{ \
                        printf(msg); \
                        exit(1);    \
}while(0)
/* 缓冲大小*/
#define BUFSIZE 1024

/*版本信息*/
#define IPVERSION 4

/* 原始套接字 */
int sockfd;

/* 程序活动标志 */


/*目的端口信息*/
#define DEST_PORT 8101

/*源端口信息*/
#define SRC_PORT  5566
/*send buffer */
char sendbuf[BUFSIZE] = {0};
char Data[] = "forever love for you!!";


struct ip{
    unsigned int        hl:4;
    unsigned int        version:4;
    unsigned char       tos;
    unsigned short      total_len;
    unsigned short      id;
    unsigned short      frag_and_flags;
    unsigned char       ttl;
    unsigned char       proto;
    unsigned short      checksum;
    unsigned int        sourceIP;
    unsigned int        destIP;
};

struct tcphdr{
    unsigned short      sport;
    unsigned short      dport;
    unsigned int        seq;
    unsigned int        ack;
    u_char              th_x2:4,                                                /* (unused)                     */
                        th_off:4;
    unsigned char       flag;
    unsigned short      win;
    unsigned short      sum;
    unsigned short      urp;
};

struct pseudohdr
{
    unsigned int        saddr;
    unsigned int        daddr;
    char                zero;
    char                protocol;
    unsigned short      length;
};

/* CRC16校验 */
unsigned short inline
checksum (unsigned short *buffer, unsigned short size)
{

    unsigned long cksum = 0;

    while(size>1){
        cksum += *buffer++;
        size  -= sizeof(unsigned short);
    }

    if(size){
        cksum += *(unsigned char *)buffer;
    }

    cksum = (cksum >> 16) + (cksum & 0xffff);
    cksum += (cksum >> 16);

    return((unsigned short )(~cksum));
}

/* 发送SYN包函数
 * 填写IP头部,TCP头部
 * TCP伪头部仅用于校验和的计算
 */
void
init_header(struct ip *ip, struct tcphdr *tcp, struct pseudohdr *pseudoheader,struct sockaddr_in *dest, char *src)
{
    int len = sizeof(struct ip) + sizeof(struct tcphdr) + strlen(Data);
    // IP头部数据初始化
    ip->hl = 5;
    ip->version = IPVERSION;
    ip->tos = 0;
    ip->total_len = htons(len);
    ip->id = 0;
    ip->frag_and_flags = 0;
    ip->ttl = 255;
    ip->proto = IPPROTO_TCP;
    ip->checksum = 0;
    ip->sourceIP = inet_addr(src);
    ip->destIP = dest->sin_addr.s_addr;

    // TCP头部数据初始化
    tcp->sport = htons( SRC_PORT );
    tcp->dport = htons(DEST_PORT);
//    tcp->seq = htonl( rand()%90000000 + 2345 );
//    tcp->ack = 0;
    tcp->th_off = sizeof(struct tcphdr) / 4;
    tcp->flag = 0x02;
    tcp->win = 4096;
    tcp->sum = 0;
//    tcp->urp = 0;

//    //TCP伪头部
//    pseudoheader->zero = 0;
//    pseudoheader->protocol = IPPROTO_TCP;
//    pseudoheader->length = htons(sizeof(struct tcphdr));
//    pseudoheader->daddr = dest->sin_addr.s_addr;
//    pseudoheader->saddr = inet_addr(src);
////    srand((unsigned) time(NULL));
}

/*********************************************************************************************************
** 函数名称: send_data
** 功能描述:
** 输 入  : NONE
** 输 出  : NONE
** 全局变量:
** 调用模块:
                                           API 函数
*********************************************************************************************************/
void send_data(int fd,  char *client, struct sockaddr_in *server)
{

//    int i = 0;
    int bufsize;
    int send_len = 0;
    bufsize = sizeof(struct ip) + sizeof(struct tcphdr) + strlen(Data) + 1;
//    for(i = 0; i < 50; i++){
    memset(sendbuf, 0, sizeof(sendbuf));

    struct ip *iphdr;
//    iphdr = (struct ip *)malloc(sizeof(struct ip ));
    struct tcphdr *tcph;
//    tcph = (struct tcphdr *)malloc(sizeof(struct tcphdr));
    struct pseudohdr tcpv;


    iphdr = (struct ip *)sendbuf;
    tcph = (struct tcphdr *)(sendbuf + 20);

    init_header(iphdr, tcph, &tcpv, server, client);
//    memset(sendbuf,0,BUFSIZE);
//    memcpy(sendbuf,iphdr,sizeof(struct ip ));
//    memcpy(sendbuf + sizeof(struct ip ), tcph, sizeof(struct tcphdr));
    memcpy(sendbuf + sizeof(struct ip ) + sizeof(struct tcphdr), Data, strlen(Data) + 1);


    /*伪首部校验和*/
//        memcpy(sendbuf, &tcpv, sizeof(tcpv));
//        memcpy(sendbuf + sizeof(tcpv), tcph, sizeof(struct tcphdr));
//        memcpy(sendbuf + sizeof(tcpv) + sizeof(tcph), Data, sizeof(Data));
//        tcph->sum = checksum((unsigned short *)sendbuf, sizeof(sendbuf));


    send_len = sendto(fd, sendbuf, bufsize, 0, (struct sockaddr *)server, sizeof(struct sockaddr_in));
    if(send_len < 0){
        printf("sendto error\n");
        exit(1);
    }
//    free(iphdr);
//    free(tcph);
//    sleep(1);

//    }


}
/*********************************************************************************************************
** 函数名称: main
** 功能描述: 主函数
** 输 入  : NONE
** 输 出  : NONE
** 全局变量:
** 调用模块:
*********************************************************************************************************/
int main (int argc, char **argv)
{
    int sockfd;
    int flag = 1;
//    int timeout=1000;
    struct sockaddr_in serveraddr;
    char  *srcaddr;


    if(argc < 3){
        errorlog("argument too less\n");
    }

    sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
    if(sockfd <0){
        errorlog("fail to socket\n");
    }
    bzero(&serveraddr, sizeof(serveraddr));         /*clear serveraddr*/
    /*server   fill*/
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons(DEST_PORT);
    serveraddr.sin_addr.s_addr = inet_addr(argv[2]);

    setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, (void *)&flag, sizeof(flag)); /*ipheader change*/
//    setsockopt(sockfd,SOL_SOCKET,SO_SNDTIMEO,(char*)&timeout,sizeof(timeout));/*timeout manage*/

    /*client fill*/
    srcaddr = argv[1];
    send_data(sockfd, srcaddr, &serveraddr);
    close(sockfd);

    return  (0);
}

3.client(2)(转)

/**
  2  * @file ip_tcp_send.c
  3  */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>

 /* 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

 void err_exit(const char *err_msg)
 {
    perror(err_msg);
     exit(1);
 }
 /* 填充ip首部 */
 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;
 }

 /* 填充tcp首部 */
 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报文 */
 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);

     /* 发送报文 */
     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");

     close(sockfd);
     free(ip_header);
     free(tcp_header);
 }

 int main(int argc, const char *argv[])
 {
     if (argc != 6)
     {
         printf("usage:%s src_ip src_port dst_ip dst_port data\n", argv[0]);
        exit(1);
     }

     /* 发送ip_tcp报文 */
     ip_tcp_send(argv[1], atoi(argv[2]), argv[3], atoi(argv[4]), argv[5]);

     return 0;
 }

猜你喜欢

转载自blog.csdn.net/weixin_42694291/article/details/81165579