⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rawudp.cpp

📁 这个是网络编程
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//
// Sample: Raw IPv4/IPv6 UDP with IP_HDRINCL option
//
// Files:
//      rawudp.cpp    - this file
//      iphdr.h       - IPv4, IPv6, and UDP structure definitions
//      resolve.cpp   - common name resolution routines
//      resolve.h     - header file for common name resolution routines
//
//
// Description:
//    This is a simple app that demonstrates the usage of the 
//    IP_HDRINCL socket option. A raw socket is created of the
//    UDP protocol where we will build our own IP and UDP header
//    that we submit to sendto(). 
//
//    For IPv4 this is fairly simple. Create a raw socket, set the 
//    IP_HDRINCL option, build the IPv4 and UDP headers, and do a
//    sendto. The IPv4 stack will fragment the data as necessary and
//    generally leaves the packet unmodified -- it performs fragmentation
//    and sets the IPv4 ID field.
//
//    For IPv6 its a bit more involved as it does not perform any 
//    fragmentation, you have to do it and build the headers yourself.
//    
//    The IP_HDRINCL option only works on Windows 2000 or greater.
//
// Compile:
//      cl -o rawudp.exe rawudp.cpp resolve.cpp ws2_32.lib
//
// Usage:
//      rawudp.exe [options]
//          -a  4|6    Address family
//          -sa addr   From (sender) port number
//          -sp int    From (sender) IP address
//          -da addr   To (recipient) port number
//          -dp int    To (recipient) IP address
//          -n  int    Number of times to read message
//          -m  str    String message to fill packet data with
//          -p  proto  Protocol value
//          -r  port   Receive raw (SOCK_RAW) datagrams on the given port
//          -rd port   Receive datagram (SOCK_DGRAM) on the given port
//          -t  mtu    MTU size (required for fragmentation)
//          -z  int    Size of message to send
//
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN 
#endif

#include <winsock2.h>
#include <ws2tcpip.h>

#include <stdio.h>
#include <stdlib.h>

#include "resolve.h"

#include "iphdr.h"

//
// Setup some default values 
//
#define DEFAULT_MTU           1496          // default MTU size
#define DEFAULT_TTL           8             // default TTL value

#define MAX_PACKET            65535         // maximum datagram size
#define MAX_PACKET_FRAGMENTS ((MAX_PACKET / DEFAULT_MTU) + 1)

#define DEFAULT_PORT          5150          // default port to send to
#define DEFAULT_COUNT         5             // default number of messages to send
#define DEFAULT_MESSAGE       "This is a test"  // default message

#define FRAGMENT_HEADER_PROTOCOL    44      // protocol value for IPv6 fragmentation header

//
// Global variables
//
char     *gSrcAddress=NULL,          // IP address to send from
         *gDestAddress=NULL,         // IP address to send to
         *gSrcPort=NULL,             // port to send from
         *gDestPort=NULL,            // port to send to
         *gMessage=NULL;             // Message to send as UDP payload
int       gAddressFamily=AF_UNSPEC,
          gSocketType=SOCK_DGRAM,    // Socket type to pass to name resolution routines
          gProtocol=IPPROTO_UDP,     // Protocol value that we're sending
          gSendSize=0,               // Data size of message to send
          gMtuSize=DEFAULT_MTU;      // Maximum transmission unit to use
DWORD     gSendCount;                // number of times to send
BOOL      bSender=TRUE,              // sending or receiving data
          bReadRaw=TRUE;             // Use raw sockets when reading

//
// Function: usage:
//
// Description:
//    Print usage information and exit.
//
void usage(char *progname)
{
    printf("usage: %s [-fp int] [-fi str] [-tp int] [-ti str] [-n int] [-m str]\n"
           "    -a  4|6    Address family\n"
           "    -sa addr   From (sender) port number\n"
           "    -sp int    From (sender) IP address\n"
           "    -da addr   To (recipient) port number\n"
           "    -dp int    To (recipient) IP address\n"
           "    -n  int    Number of times to read message\n"
           "    -m  str    String message to fill packet data with\n"
           "    -p  proto  Protocol value\n"
           "    -r  port   Receive raw (SOCK_RAW) datagrams on the given port\n"
           "    -rd port   Receive datagram (SOCK_DGRAM) on the given port\n"
           "    -t  mtu    MTU size (required for fragmentation)\n"
           "    -z  int    Size of message to send\n",
           progname
           );
    ExitProcess(1);
}

//
// Function: ValidateArgs
//
// Description:
//    Parse the command line arguments and set some global flags to
//    indicate what actions to perform.
//
void ValidateArgs(int argc, char **argv)
{
    int                i;

    gMessage = DEFAULT_MESSAGE;
    for(i=1; i < argc ;i++)
    {
        if ((argv[i][0] == '-') || (argv[i][0] == '/'))
        {
            switch (tolower(argv[i][1]))
            {
                case 'a':                   // Address family
                    if (i+1 > argc)
                        usage(argv[0]);
                    if (argv[i+1][0] == '4')
                        gAddressFamily = AF_INET;
                    else if (argv[i+1][0] == '6')
                        gAddressFamily = AF_INET6;
                    else
                        usage(argv[0]);
                    i++;
                    break;
                case 's':                   // source address
                    if (i+1 > argc)
                        usage(argv[0]);
                    if (tolower(argv[i][2]) == 'a')
                    {
                        gSrcAddress = argv[++i];
                    }
                    else if (tolower(argv[i][2]) == 'p')
                    {
                        gSrcPort = argv[++i];
                    }
                    else
                    {
                        usage(argv[0]);
                        break;
                    }    
                    break;
                case 'd':                   // destination address
                    if (i+1 > argc)
                        usage(argv[0]);
                    if (tolower(argv[i][2]) == 'a')
                    {
                        gDestAddress = argv[++i];
                    }
                    else if (tolower(argv[i][2]) == 'p')
                    {
                        gDestPort = argv[++i];
                    }
                    else
                    {
                        usage(argv[0]);
                        break;
                    }
                    break;
                case 'n':                   // number of times to send message
                    if (i+1 >= argc)
                        usage(argv[0]);
                    gSendCount = atol(argv[++i]);
                    break;                  // String message to copy into payload
                case 'm':
                    if (i+1 >= argc)
                        usage(argv[0]);
                    gMessage = argv[++i];
                    break;
                case 'p':                   // Protocol value
                    if (i+1 >= argc)
                        usage(argv[0]);
                    gProtocol = atoi(argv[++i]);
                    break;
                case 'r':                   // Port to receive data on
                    if (i+1 >= argc)
                        usage(argv[0]);
                    if (strlen(argv[i]) == 3)
                        bReadRaw = FALSE;
                    gSrcPort = argv[++i];
                    bSender = FALSE;
                    break;
                case 't':                   // MTU size
                    if (i+1 >= argc)
                        usage(argv[0]);
                    gMtuSize = atoi(argv[++i]);
                    break;
                case 'z':                   // Send size
                    if (i+1 >= argc)
                        usage(argv[0]);
                    gSendSize = atoi(argv[++i]);
                    break;
                default:
                    usage(argv[0]);
                    break;
            }
        }
    }

    // If no data size was given, initialize it to the message supplied
    if (gSendSize == 0)
    {
        gSendSize = strlen(gMessage);
    }

    return;
}

// 
// Function: checksum
//
// Description:
//    This function calculates the 16-bit one's complement sum
//    for the supplied buffer.
//
USHORT checksum(USHORT *buffer, int size)
{
    unsigned long cksum=0;

    while (size > 1)
    {
        cksum += *buffer++;
        size  -= sizeof(USHORT);   
    }
    if (size)
    {
        cksum += *(UCHAR*)buffer;   
    }
    cksum = (cksum >> 16) + (cksum & 0xffff);
    cksum += (cksum >>16); 

    return (USHORT)(~cksum); 
}

//
// Function: InitIpv4Header
//
// Description:
//    Initialize the IPv4 header with the version, header length,
//    total length, ttl, protocol value, and source and destination
//    addresses.
//
int InitIpv4Header(
    char *buf, 
    SOCKADDR *src, 
    SOCKADDR *dest, 
    int ttl,
    int proto,
    int payloadlen
    )
{
    IPV4_HDR    *v4hdr=NULL;

    v4hdr = (IPV4_HDR *)buf;

    v4hdr->ip_verlen      = (4 << 4) | (sizeof(IPV4_HDR) / sizeof(unsigned long));
    v4hdr->ip_tos         = 0;
    v4hdr->ip_totallength = htons(sizeof(IPV4_HDR) + payloadlen);
    v4hdr->ip_id          = 0;
    v4hdr->ip_offset      = 0;
    v4hdr->ip_ttl         = (unsigned char)ttl;
    v4hdr->ip_protocol    = (unsigned char)proto;
    v4hdr->ip_checksum    = 0;
    v4hdr->ip_srcaddr     = ((SOCKADDR_IN *)src)->sin_addr.s_addr;
    v4hdr->ip_destaddr    = ((SOCKADDR_IN *)dest)->sin_addr.s_addr;

    v4hdr->ip_checksum    = checksum((unsigned short *)v4hdr, sizeof(IPV4_HDR));
    
    return sizeof(IPV4_HDR);
}

//
// Function: InitIpv6Header
//
// Description:
//    Initialize the IPv6 header with the version, payload length, next
//    hop protocol, TTL, and source and destination addresses.
//
int InitIpv6Header(
    char *buf, 
    SOCKADDR *src, 
    SOCKADDR *dest, 
    int ttl,
    int proto,
    int payloadlen
    )
{
    IPV6_HDR    *v6hdr=NULL;

	v6hdr = (IPV6_HDR *)buf;

    // We don't explicitly set the traffic class or flow label fields
    v6hdr->ipv6_vertcflow    = htonl(6 << 28);
    v6hdr->ipv6_payloadlen   = htons((unsigned short)payloadlen);
    v6hdr->ipv6_nexthdr      = (unsigned char)proto;
    v6hdr->ipv6_hoplimit     = (unsigned char)ttl;
    v6hdr->ipv6_srcaddr      = ((SOCKADDR_IN6 *)src)->sin6_addr;
    v6hdr->ipv6_destaddr     = ((SOCKADDR_IN6 *)dest)->sin6_addr;

    return sizeof(IPV6_HDR);
}

//
// Function: InitIpv6FragmentHeader
//
// Description:
//    Initialize the IPv6 fragmentation header. The offset is the offset
//    from the start of the IPv6 total payload (which includes the UDP
//    header along with the data) which is why we add the length of
//    the UDP header if this fragment is not the first fragment. Also,
//    the lastfragment parameter is a boolean value (0 == not the last
//    fragment while 1 == this is the last fragment) which is the opposite
//    value thats supposed to be indicated in the header (i.e. 0 indicates
//    that this fragment is the last fragment).
//
int InitIpv6FragmentHeader(
    char *buf,
    unsigned long offset,
    int nextproto,
    int id,
    int lastfragment
    )
{
    IPV6_FRAGMENT_HDR *frag=NULL;

    frag = (IPV6_FRAGMENT_HDR *)buf;

    // Swap the value of this field
    lastfragment = (lastfragment ? 0 : 1);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -