Raw socket Example

http://www.tenouk.com/Module43a.html

 

http://mixter.void.ru/rawip.html

 

1. 在上面第一个例子的前提下,我做了一个简单的例子。

这个例子特殊的地方,是我将整个wireshark抓到的udp包的ip部分全部写成二进制,放到sendto中发送。成功!

说明这个SOCK_RAW是基于整个ip层的。

/*
 * =====================================================================================
 *
 *       Filename:  raw_copy.c
 *
 *    Description:  This is an test on raw socket.
 *                  In this example, we just copy a whole ip packet captured by wireshark.
 *                  This illstrated the raw socket handle the all ip layer.
 *
 *        Version:  1.0
 *        Created:  01/11/2011 03:59:06 PM
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  YOUR NAME (),
 *        Company: 
 *
 * =====================================================================================
 */

// Must be run by root lol! Just datagram, no payload/data
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
 

// The packet length
#define PCKT_LEN 8192
 
// Source IP, source port, target IP, target port from the command line arguments
int main(int argc, char *argv[])
{
    int sd;
    int one = 1;
    const int *val = &one;
    /* the raw packet captured by wireshark */
    /* This is a udp packet */
    char copy[PCKT_LEN] ={ 0x45, 0x00, 0x00, 0x1e,
                           0x00, 0x00, 0x40, 0x00,
                           0x40, 0x11, 0x3c, 0xcd,
                           0x7f, 0x00, 0x00, 0x01,
                           0x7f, 0x00, 0x00, 0x01,
                           0xe2, 0xb9, 0x13, 0x88,
                           0x00, 0x0a, 0xfe, 0x1d,
                           0x6a, 0x6a,

    };
    // Source addresses: IP and port
    struct sockaddr_in sin, din;
    sin.sin_family = AF_INET;
    // Port numbers
    sin.sin_port = htons(58041);
    // IP addresses
    sin.sin_addr.s_addr = inet_addr("127.0.0.1");

    // Create a raw socket with UDP protocol
    sd = socket(PF_INET, SOCK_RAW, IPPROTO_UDP);
    if(sd < 0)
    {
        perror("socket() error");
        // If something wrong just exit
        exit(-1);
    }
    else
        printf("socket() - Using SOCK_RAW socket and UDP protocol is OK./n");

    // Inform the kernel do not fill up the packet structure. we will build our own...
    if(setsockopt(sd, IPPROTO_IP, IP_HDRINCL, val, sizeof(one)) < 0)
    {
        perror("setsockopt() error");
        exit(-1);
    }
    else
        printf("setsockopt() is OK./n");

    // Send loop, send for every 2 second for 100 count
    printf("Trying.../n");
    printf("Using raw socket and UDP protocol/n");
    printf("Using Source IP: %s port: %u, Target IP: %s port: %u./n", "127.0.0.1", 58041, "127.0.0.1", 5000);

    int count;
    for(count = 1; count <=20; count++)
    {
        if(sendto(sd, copy, 30 , 0, (struct sockaddr *)&sin, sizeof(sin)) < 0)
        { // Verify
            perror("sendto() error");
            exit(-1);
        }
        else
        {
            printf("Count #%u - sendto() is OK./n", count);
            sleep(2);
        }
    }
    close(sd);

    return 0;
}

 

2.也是根据上面的那个网站,里面有个例子是raw socket 的udp,但是例子是有问题的,我改了一下。

有几个要注意的,

1. 定义ipheader时,要注意大小端的问题。

2. 为什么 我将ipheader中的length 转换成网络字节序,反而有问题?

/*
 * =====================================================================================
 *
 *       Filename:  rawudp.c
 *
 *    Description: 
 *
 *        Version:  1.0
 *        Created:  01/11/2011 03:59:06 PM
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  YOUR NAME (),
 *        Company: 
 *
 * =====================================================================================
 */
// Must be run by root lol! Just datagram, no payload/data
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
 
// The packet length
#define PCKT_LEN 8192
    unsigned char copy[PCKT_LEN] ={ 0x45, 0x00, 0x00, 0x1e,
                           0x00, 0x00, 0x40, 0x00,
                           0x40, 0x11, 0x3c, 0xcd,
                           0x7f, 0x00, 0x00, 0x01,
                           0x7f, 0x00, 0x00, 0x01,
                           0xe2, 0xb9, 0x13, 0x88,
                           0x00, 0x0a, 0xfe, 0x1d,
                           0x6a, 0x6a,
    };
// Can create separate header file (.h) for all headers' structure
// The IP header's structure
struct ipheader {

#if     __BYTE_ORDER == __BIG_ENDIAN

    unsigned char     iph_ver:4, iph_ihl:4;

#else

    unsigned char      iph_ihl:4, iph_ver:4;

#endif
    unsigned char      iph_tos;
    unsigned short int iph_len;
    unsigned short int iph_ident;
#if     __BYTE_ORDER == __BIG_ENDIAN
    unsigned short int iph_flag:3;
    unsigned short int iph_offset:13;
#else
    unsigned short int iph_offset:13;
    unsigned short int iph_flag:3;
#endif

    unsigned char      iph_ttl;
    unsigned char      iph_protocol;
    unsigned short int iph_chksum;
    unsigned int       iph_sourceip;
    unsigned int       iph_destip;
};

void dump_ipheader(struct ipheader *iph)
{
    printf("version: %d, Header length %d/n", iph->iph_ver, iph->iph_ihl);
    printf("Tos:     %d, Total length  %d/n", iph->iph_tos, ntohs(iph->iph_len));
    printf("Identification: %04x/n", iph->iph_ident);
    printf("Flags:   %01x, Frag Offset: %d/n", iph->iph_flag,  iph->iph_offset);
    printf("TTL:    %d, Protocal: %d/n",     iph->iph_ttl, iph->iph_protocol);
    printf("Checksum:%d/n", iph->iph_chksum);
    printf("Source IP: %s/n", (char*)inet_ntoa(iph->iph_sourceip));
    printf("Destin IP: %s/n", (char*)inet_ntoa(iph->iph_destip));
    return;
}

// UDP header's structure
struct udpheader {
    unsigned short int udph_srcport;
    unsigned short int udph_destport;
    unsigned short int udph_len;
    unsigned short int udph_chksum;
};

// total udp header length: 8 bytes (=64 bits)
// Function for checksum calculation. From the RFC,
// the checksum algorithm is:
//  "The checksum field is the 16 bit one's complement of the one's
//  complement sum of all 16 bit words in the header.  For purposes of
//  computing the checksum, the value of the checksum field is zero."
unsigned short csum(unsigned short *buf, int nwords)
{       //
    unsigned long sum;
    for(sum=0; nwords>0; nwords--)
            sum += *buf++;
    sum = (sum >> 16) + (sum &0xffff);
    sum += (sum >> 16);
    return (unsigned short)(~sum);
}

// Source IP, source port, target IP, target port from the command line arguments
int main(int argc, char *argv[])
{
    int                sd;
    int                count;
    unsigned char      buffer[PCKT_LEN];
    // Source and destination addresses: IP and port
    int                one = 1;
    const int          *val = &one;
    struct sockaddr_in sin ;

    if(argc != 5)
    {
        printf("- Invalid parameters!!!/n");
        printf("- Usage %s <source hostname/IP> <source port> <target hostname/IP> <target port>/n", argv[0]);
        exit(-1);
    }
    // Our own headers' structures
    memset(buffer, 0, PCKT_LEN);
    struct ipheader  *ip  = (struct ipheader *) buffer;
    struct udpheader *udp = (struct udpheader*) (buffer + sizeof(struct ipheader));

    // Create a raw socket with UDP protocol
    sd = socket(PF_INET, SOCK_RAW, IPPROTO_UDP);
    if(sd < 0)
    { // If something wrong just exit
        perror("socket() error");
        exit(-1);
    }
    else
        printf("socket() - Using SOCK_RAW socket and UDP protocol is OK./n");

    // The source is redundant, may be used later if needed
    // The address family
    sin.sin_family = AF_INET;
    // IP addresses // Port numbers
    sin.sin_addr.s_addr = inet_addr(argv[1]);
    sin.sin_port = htons(atoi(argv[2]));

    // Fabricate the IP header or we can use the
    // standard header structures but assign our own values.
    {
        ip->iph_ihl      = 5;
        ip->iph_ver      = 4;
        ip->iph_tos      = 0; // Low delay
        ip->iph_ident    = htons(0);
        ip->iph_flag     = 0x00;
        ip->iph_offset   = 0;
        ip->iph_ttl      = 64; // hops
        ip->iph_protocol = 17; // UDP
        // Source IP address, can use spoofed address here!!!
        ip->iph_sourceip = inet_addr(argv[1]);
        // The destination IP address
        ip->iph_destip   = inet_addr(argv[3]);
//        ip->iph_len = htons(sizeof(struct ipheader) + sizeof(struct udpheader) + 2);
        ip->iph_len      = sizeof(struct ipheader) + sizeof(struct udpheader) + 2;

        printf("%d/n", ip->iph_len);
    }

    // Fabricate the UDP header. Source port number, redundant
    {
        udp->udph_srcport  = htons(atoi(argv[2]));
        udp->udph_destport = htons(atoi(argv[4]));
        udp->udph_len      = htons(sizeof(struct udpheader) + 2);
    }

    /* personal data ...., hard coded */
    buffer[28] = 'j';
    buffer[29] = 'j';

    // Calculate the checksum for integrity
    ip->iph_chksum = csum((unsigned short *)buffer,
            sizeof(struct ipheader) + sizeof(struct udpheader) + 2);
    // Inform the kernel do not fill up the packet structure. we will build our own...
    if(setsockopt(sd, IPPROTO_IP, IP_HDRINCL, val, sizeof(one)) < 0)
    {
        perror("setsockopt() error");
        exit(-1);
    }
    else
        printf("setsockopt() is OK./n");

    dump_ipheader(ip);
    printf("--------------------------------/n");
    dump_ipheader((struct ipheader*)copy);
//    return 0;
   
    // Send loop, send for every 2 second for 100 count
    printf("Trying.../nUsing raw socket and UDP protocol/n");
    printf("Using Source IP: %s port: %u, Target IP: %s port: %u./n",
            argv[1], atoi(argv[2]), argv[3], atoi(argv[4]));

    for(count = 1; count <=20; count++)
    {
        //if(sendto(sd, copy, 30, 0, (struct sockaddr *)&sin, sizeof(sin)) < 0)
        if(sendto(sd, buffer, ip->iph_len, 0, (struct sockaddr *)&sin, sizeof(sin)) < 0)
        // Verify
        {
            perror("sendto() error");
            exit(-1);
        }
        else
        {
            printf("Count #%u - sendto() is OK./n", count);
            sleep(2);
        }
    }
    close(sd);

    return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值