SOCK_RAW发送UDP数据包

1.client(发送数据包)(需要校验和)

/*********************************************************************************************************
**
**                                    中国软件开源组织
**
**                                   嵌入式实时操作系统
**
**                                SylixOS(TM)  LW : long wing
**
**                               Copyright All Rights Reserved
**
**--------------文件信息--------------------------------------------------------------------------------
**
** 文   件   名: client.c
**
** 创   建   人: zhangyazhong(张亚中)
**
** 文件创建日期: 2018 年 07 月 19日
**
** 描        述: 自定义协议头客户端程序.
*********************************************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <linux/types.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>

#include <net/if_ether.h>
/*********************************************************************************************************
  宏定义
*********************************************************************************************************/
#define BUFSIZE 38
#define TTLSET  255
#define IPVERSION 4
#define DEST_PORT 8101
#define SRC_PORT  880
#define errorlog(msg) do{ \
                        printf(msg);\
                        exit(1);    \
}while(0)
/*********************************************************************************************************
  结构体定义
*********************************************************************************************************/
//typedef struct iphdr{
//       unsigned int ip_length:4; /*little-endian*/
//       unsigned int ip_version:4;
//       unsigned char ip_tos;
//       unsigned short ip_total_length;
//       unsigned short ip_id;
//       unsigned short ip_flags;
//       unsigned char ip_ttl;
//       unsigned char ip_protocol;
//       unsigned short ip_cksum;
//       unsigned int ip_source;
//       unsigned int ip_dest;
//}iphdr;

typedef struct udphdr{
    unsigned short udp_sport;
    unsigned short udp_dport;
    unsigned short udp_ulength;
    unsigned short udp_chksum;
}udphdr;

typedef struct udpvhdr{
    unsigned int    udpv_src;
    unsigned int    udpv_dest;
    unsigned char   udpv_memzero;
    unsigned char   udpv_proto;
    unsigned short  udpv_vlength;
}udpvhdr;
/*********************************************************************************************************
  全局变量定义
*********************************************************************************************************/
char datapacket[BUFSIZE] = {0};
/*********************************************************************************************************
** 函数名称: udp_chsum
** 功能描述:
** 输 入  : NONE
** 输 出  : NONE
** 全局变量:
** 调用模块:
                                           API 函数
*********************************************************************************************************/
unsigned short udpv_hdr_data_chk(unsigned short *addr, int len)
{
    unsigned long chksum = 0;
    while(len > 1){
        chksum += *addr++;
        len -= sizeof(unsigned short);
    }
    if(len){
        chksum = chksum + *(unsigned char *)addr;
    }

    chksum = (chksum >> 16) + (chksum & 0xfffful);

    chksum += (chksum >>16);

    return (unsigned short )(~chksum);
}
/*********************************************************************************************************
** 函数名称: iphdr_fill
** 功能描述: 构造 IP 头
** 输 入  : NONE
** 输 出  : NONE
** 全局变量:
** 调用模块:
                                           API 函数
*********************************************************************************************************/
void iphdr_fill(struct ip *iphdr, struct sockaddr_in  *src, struct sockaddr_in *dest, unsigned short ulen, unsigned char tos, unsigned char id)
{
    iphdr->ip_hl = 5;
    iphdr->ip_v= 4;
    iphdr->ip_tos = tos;
    iphdr->ip_len = htons(sizeof(datapacket));
    iphdr->ip_id = id;
    iphdr->ip_off = 0x40;
    iphdr->ip_ttl = 0x40;
    iphdr->ip_p = 0x11;
    iphdr->ip_sum = 0;
    iphdr->ip_src = src->sin_addr;
    iphdr->ip_dst = dest->sin_addr;
//    iphdr->ip_cksum = udpv_hdr_data_chk((unsigned short*)datapacket, 20);

}
/*********************************************************************************************************
** 函数名称: udphdr_fill
** 功能描述: 构造 UDP 头
** 输 入  : NONE
** 输 出  : NONE
** 全局变量:
** 调用模块:
                                           API 函数
*********************************************************************************************************/
void udphdr_fill(struct udphdr *udph,  struct sockaddr_in *src, struct sockaddr_in *dest, unsigned short ulen)
{
    udph->udp_chksum = 0;
    udph->udp_dport = htons(DEST_PORT);
    udph->udp_sport = htons(8000);
    udph->udp_ulength = htons(ulen);
}
/*********************************************************************************************************
** 函数名称: udp_header_ctor
** 功能描述: 构造 UDP 头
** 输 入  : NONE
** 输 出  : NONE
** 全局变量:
** 调用模块:
                                           API 函数
*********************************************************************************************************/
void udpvhdr_fill(struct udpvhdr *udpv, unsigned int src, unsigned int dest, unsigned char zero, unsigned char proto, unsigned short udphp)
{
    udpv->udpv_dest = dest;
    udpv->udpv_memzero = zero;
    udpv->udpv_src = src;
    udpv->udpv_proto = proto;
    udpv->udpv_vlength = udphp;
}


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

    int tos;
    int tostmp = 0;
    int id = 0;
    int i = 0;

    memset(datapacket, 'a', sizeof(datapacket) - 1);

    for(i = 0; i < 50; i++){
        struct ip *iphdr;
        udphdr *udph;
        udpvhdr udpv;
        tos = tostmp;

        iphdr = (struct ip *)datapacket;
        udph = (struct udphdr *)(datapacket + 20);

        iphdr_fill(iphdr, client, server, sizeof(datapacket), tos, id);
        udphdr_fill(udph, client, server, sizeof(datapacket) - 20);
        udpvhdr_fill(&udpv,client->sin_addr.s_addr, server->sin_addr.s_addr, 0, 0x11, udph->udp_ulength);

        char ckbuf[sizeof(udpv) + ntohs(udph->udp_ulength)];/*new packet for check*/

        memcpy(ckbuf, &udpv, sizeof(udpv));
        memcpy(ckbuf + sizeof(udpv), datapacket + 20, sizeof(datapacket) - 20);

        udph->udp_chksum = udpv_hdr_data_chk((unsigned short *)ckbuf, sizeof(ckbuf));


        sendto(fd, datapacket, sizeof(datapacket), 0, (struct sockaddr *)server, sizeof(struct sockaddr_in));
        sleep(1);
    }

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

    struct sockaddr_in serveraddr, clientaddr;


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

    sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
    if(sockfd <0){
        errorlog("fail to socket\n");
    }

//    char *src, *dest;
//    src = argv[1];
//    dest = argv[2];


    bzero(&serveraddr, sizeof(serveraddr));         /*clear serveraddr*/


    /*server   fill*/
    serveraddr.sin_family = AF_INET;
//    serveraddr.sin_len = socklen;
    serveraddr.sin_port = htons(DEST_PORT);
//    serveraddr.sin_addr.s_addr = inet_addr(dest);
    serveraddr.sin_addr.s_addr = inet_addr(argv[2]);




    /*client fill*/


    clientaddr.sin_addr.s_addr = inet_addr(argv[1]);


    setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, (void *)&flag, sizeof(flag)); /*ipheader change*/

    send_data(sockfd, &clientaddr, &serveraddr);
    close(sockfd);
    return  (0);
}

2.server(需绑定)

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/udp.h>
#include <time.h>
#include <sys/time.h>

#define __BUF_SIZE 1024
#define LocalPort 8101
#define errorlog(msg) do{            \
                        perror(msg); \
                        exit(1);     \
}while(0)

int main (int argc, char **argv)
{
    int sockFd;
    int iRet;
    int getRet;
    struct sockaddr_in  localaddr;
    socklen_t           socklen = sizeof(localaddr);
    char   localbuf[__BUF_SIZE] = {0};
    struct timeval   start, end, result;

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

    sockFd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (sockFd < 0) {
        errorlog("socket failed\n");
    }

    localaddr.sin_family = AF_INET;
    localaddr.sin_port = htons(LocalPort);

    if (argv[1]) {
        if (inet_aton(argv[1], &localaddr.sin_addr) == 0) {
            errorlog("arguments error\n");
        }
    } else {
        errorlog("can not found addr\n");
    }
    localaddr.sin_len = socklen;

    iRet = bind(sockFd, (struct sockaddr *)&localaddr, socklen);
    if (iRet < 0) {
        errorlog("bind error\n");
    }

    while (1) {

        bzero(localbuf, sizeof(localbuf));
        gettimeofday(&start, NULL);
        getRet = recvfrom(sockFd, localbuf, __BUF_SIZE, 0, (struct sockaddr *)&localaddr, &socklen);
        gettimeofday(&end, NULL);
        if (getRet < 0) {
            errorlog("recvfrom failed\n");
        } else if(getRet == 0) {
            printf("NO DATA get\n");
        } else {
            timersub(&end, &start, &result);
            printf("localbuf = %s (time: %lld.%ld)\n", localbuf, result.tv_sec, result.tv_usec);
        }
    }

    close(sockFd);

    return  (0);
}

猜你喜欢

转载自blog.csdn.net/weixin_42694291/article/details/81165619
今日推荐