본문 바로가기

OS/vxworks

Raw Socket :: 패킷을 구성하여 전송하자.

Vxworks 6.x에서 Raw Socket을 사용하여, IP/UDP 헤더를 조작하여 해당 패킷을 전송하는 예제이다.

UDP 체크섬은 0을 채워 전송하였다.

#include <stdio.h>
#include "vxLib.h"
#include "ipProto.h"
#include "netinet/in.h"
#include "netinet/in_systm.h"
#include "netinet/if_ether.h"
#include "netinet/ip.h"
#include "netinet/ip_icmp.h"
#include "netinet/udp.h"
#include "sys/socket.h"
#include "sockLib.h"
#include "inetLib.h"

static int s_iIpId = 0;

#pragma pack(1)
struct ps_udph
{
    struct    in_addr srcip;
    struct    in_addr dstip;
    u_char    zero;
    u_char    prto;
    u_short    ulen;   
};
#pragma pack()

u_short udp_cksum(struct ps_udph * pUdpPh, char* buf, int n) {
    //#[ operation udp_cksum(struct ps_udph *,char*,int)
    u_long         sum = 0;
    u_short *        tmp = NULL;
    u_short        result;
    FAST int         i = 0;
    unsigned char     pad[2];
   
    tmp = (u_short *) pUdpPh;
    for (i = 0; i > 6; i++)
        {
        sum += *tmp++;
        }     
   
    tmp = (u_short *)buf;
    while (n > 1)
        {
        sum += *tmp++;
        n -= sizeof (u_short);
        }
   
    if (n == 1)        /* n % 2 == 1, so padding is needed */
        {
        pad [0] = *(u_char *)tmp;
        pad [1] = 0;
        tmp = (u_short *)pad;
        sum += *tmp;
        }
   
    sum = (sum >> 16) + (sum & 0xffff);
    sum += (sum >> 16);
    result = (u_short) ~sum;
    if (result == 0)
        result = 0xffff;
   
    return (result);
    //#]
}

unsigned short crcUdpHdr(struct ip * pIph, struct udphdr * pUdph) {
    //#[ operation crcUdpHdr(struct ip *,struct udphdr *)
        struct ps_udph UdpPh;
       
        bzero ( (char *)&UdpPh, sizeof (UdpPh));
       
        UdpPh.srcip.s_addr = pIph->ip_src.s_addr;
        UdpPh.dstip.s_addr = pIph->ip_dst.s_addr;
        UdpPh.zero = 0;
        UdpPh.prto = IPPROTO_UDP;
        UdpPh.ulen = pUdph->uh_ulen;
        pUdph->uh_sum = 0;
       
        return (udp_cksum (&UdpPh, (char *)pUdph, ntohs (UdpPh.ulen)));
    //#]
}

unsigned short crcIpHdr(struct ip * pIph) {
    //#[ operation crcIpHdr(struct ip *)
    pIph->ip_sum = 0;
    return (checksum( (u_short *)pIph, pIph->ip_hl << 2) );
    //#]
}

STATUS raw_sock()
{
    int m_hRawSocket;
    struct ip *pIpHdr;
    struct udphdr *pUdpHdr;
    int iSize = 0;
   
    iSize = 64;
       
    if ( ( m_hRawSocket = socket(AF_INET, SOCK_RAW, 0) ) < 0 )
    {
        perror("socket");
        return ERROR;
    }
       
    int tmp = 1;
    int *val = &tmp;

    if ( setsockopt(m_hRawSocket, IPPROTO_IP, IP_HDRINCL, reinterpret_cast<char *>(val), sizeof(tmp)) < 0 )
    {
        perror("setsockopt");
        return ERROR;
    }

    char *buf;
    char *p;
    int iPkgLen = iSize + sizeof(ip) + sizeof(udphdr);
   
    buf = new char[iPkgLen];
    memset(buf, 0x0, iPkgLen);
   
    pIpHdr = (ip *)buf;
    pUdpHdr = (udphdr *)(buf + sizeof(ip));
    p = buf + sizeof(ip) + sizeof(udphdr);
   
    memcpy(p, "Hello World", strlen("Hello World"));
   
    pIpHdr->ip_dst.s_addr = inet_addr("10.100.10.90");    // Destination Address
    pIpHdr->ip_src.s_addr = inet_addr("10.100.10.1");    // Source Address
    pIpHdr->ip_len = iSize + sizeof(ip) + sizeof(udphdr);            // Total Length
    pIpHdr->ip_v = 0x4;                            // IPv4
    pIpHdr->ip_hl = 0x5;                        // Header Length
    pIpHdr->ip_p = 17;                            // UDP Protocol
    pIpHdr->ip_ttl = 60;                        // TTL
    pIpHdr->ip_id = s_iIpId ++;                    // Identification
    pIpHdr->ip_sum = crcIpHdr(pIpHdr);
   
    pUdpHdr->uh_sport = 8888;
    pUdpHdr->uh_dport = 8889;
    pUdpHdr->uh_ulen = htons(iSize + sizeof(udphdr));
    //pUdpHdr->uh_sum = crcUdpHdr(pIpHdr, pUdpHdr);
    pUdpHdr->uh_sum = 0;
   
    int ret = 0;
    struct sockaddr_in sin;
   
    memset(&sin, 0x0, sizeof(struct sockaddr_in));
    sin.sin_family = AF_INET;
    sin.sin_port = pUdpHdr->uh_dport;
    sin.sin_addr = pIpHdr->ip_dst;
   
    ret = sendto(m_hRawSocket, buf, iPkgLen, 0, (struct sockaddr *)&sin, sizeof(sin));
   
    if ( ret < 0 )
    {
        perror("sendto");
        delete [] buf;
        return ERROR;
    }
   
    for ( int i = 0; i < iPkgLen; i ++ )
    {
        printf("0x%02X ", buf[i]);
    }
   
    delete [] buf;
   
    return OK;
}