📄 rawudp.cpp
字号:
plushdrs, // IPv6 length field includes encapsulated headers
numpackets=0, // number of fragments
originalpayload;
originalpayload = payloadlen;
do
{
// Compute the size of this fragment
lastfragment = 0;
fragment = 0;
if ((payloadlen > gMtuSize) && (numpackets == 0))
{
// Data needs to be fragmented, this is the first packet
hdrlen = sizeof(IPV6_HDR) + sizeof(UDP_HDR) + sizeof(IPV6_FRAGMENT_HDR);
datalen = gMtuSize - hdrlen;
plushdrs = sizeof(UDP_HDR) + sizeof(IPV6_FRAGMENT_HDR);
fragment = 1;
printf("Require fragmentation: FIRST packet\n");
}
else if ((payloadlen > gMtuSize) && (numpackets > 0))
{
// Data needs to be fragmented, this is packet number > 0
hdrlen = sizeof(IPV6_HDR) + sizeof(IPV6_FRAGMENT_HDR);
datalen = gMtuSize - hdrlen;
fragment = 1;
plushdrs = sizeof(IPV6_FRAGMENT_HDR);
printf("Require fragmentation: packet number > 0\n");
}
else if (numpackets == 0)
{
// Data doesn't need to be fragmented
hdrlen = sizeof(IPV6_HDR) + sizeof(UDP_HDR);
datalen = payloadlen;
fragment = 0;
plushdrs = sizeof(UDP_HDR);
printf("No fragmentation required\n");
}
else
{
// This is the last fragment
hdrlen = sizeof(IPV6_HDR) + sizeof(IPV6_FRAGMENT_HDR);
datalen = payloadlen;
fragment = 1;
plushdrs = sizeof(IPV6_FRAGMENT_HDR);
lastfragment = 1;
printf("Require fragmentation: Last packet\n");
}
// Build packet
// Allocate buffer for this fragment
Packets[numpackets].buf = (char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, hdrlen + datalen);
if (Packets[numpackets].buf == NULL)
{
fprintf(stderr, "PacketizeV6: HeapAlloc failed: %d\n", GetLastError());
ExitProcess(-1);
}
Packets[numpackets].len = hdrlen + datalen;
// Initialize the V6 header, if we have to fragment the next header field of
// the v6 header is that of the fragmentation header. Also the payload
// length includes the headers (UDP + fragmentation) and the payload itself.
iphdrlen = InitIpv6Header(
Packets[numpackets].buf,
src->ai_addr,
dest->ai_addr,
DEFAULT_TTL,
(fragment ? FRAGMENT_HEADER_PROTOCOL : gProtocol),
datalen + plushdrs
);
// Build the fragmentation header if necessary
if (fragment)
{
iphdrlen += InitIpv6FragmentHeader(
&Packets[numpackets].buf[iphdrlen],
offset, // offset from start of packet
gProtocol,
fragid,
lastfragment
);
}
// The first fragment includes the UDP header, subsequent fragments don't
if (numpackets == 0)
{
udphdrlen = InitUdpHeader(
&Packets[numpackets].buf[iphdrlen],
src->ai_addr,
dest->ai_addr,
originalpayload //payloadlen
);
// Compute the checksum
ComputeUdpPseudoHeaderChecksumV6(
Packets[numpackets].buf,
(UDP_HDR *)&Packets[numpackets].buf[iphdrlen],
payload,
payloadlen);
}
else
{
udphdrlen = 0;
}
// Copy the payload into this fragment
memcpy(&Packets[numpackets].buf[iphdrlen + udphdrlen], &payload[offset], datalen);
// Adjust our counters
payloadlen = payloadlen - datalen;
offset += datalen;
numpackets++;
} while (payloadlen > 0);
fragid++;
// Mark the next WSABUF entry with NULL and zero to indicate end of fragments
Packets[numpackets].buf = NULL;
Packets[numpackets].len = 0;
return Packets;
}
//
// Function: main
//
// Description:
// First, parse command line arguments and load Winsock. Then
// create the raw socket and then set the IP_HDRINCL option.
// Following this assemble the IP and UDP packet headers by
// assigning the correct values and calculating the checksums.
// Then fill in the data and send to its destination.
//
int _cdecl main(int argc, char **argv)
{
WSADATA wsd;
SOCKET s;
DWORD bytes;
WSABUF *wbuf=NULL;
struct addrinfo *ressrc=NULL,
*resdest=NULL,
*resbind=NULL;
int packets,
rc,
i, j;
// Parse command line arguments and print them out
ValidateArgs(argc, argv);
srand(GetTickCount());
if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
{
printf("WSAStartup() failed: %d\n", GetLastError());
return -1;
}
// Convert the source and destination addresses/ports
ressrc = ResolveAddress(gSrcAddress, gSrcPort, gAddressFamily, gSocketType, gProtocol);
if (ressrc == NULL)
{
fprintf(stderr, "Unable to resolve address '%s' and port '%s'\n",
gSrcAddress, gSrcPort);
return -1;
}
if (bSender)
{
resdest = ResolveAddress(gDestAddress, gDestPort, ressrc->ai_family, ressrc->ai_socktype, ressrc->ai_protocol);
if (resdest == NULL)
{
fprintf(stderr, "Unable to resolve address '%s' and port '%s'\n",
gDestAddress, gDestPort);
return -1;
}
}
// Creating a raw socket
// BUG - For IPv6 if we create the raw socket with IPPROTO_UDP then the Ipv6
// stack will thow away our IPv6 and UDP headers and put "valid" ones in their
// place. As a workaround, create the socket with a protocol value of an
// unhandled protocol. Of course the IPv6 header should still indicate that
// the encapsulated protocol is UDP.
if (bSender)
s = socket(ressrc->ai_family, SOCK_RAW, ((ressrc->ai_family == AF_INET6) ? 3 : ressrc->ai_protocol));
else if (!bSender && bReadRaw)
s = socket(ressrc->ai_family, SOCK_RAW, ressrc->ai_protocol);
else
s = socket(ressrc->ai_family, SOCK_DGRAM, ressrc->ai_protocol);
if (s == INVALID_SOCKET)
{
fprintf(stderr, "socket failed: %d\n", WSAGetLastError());
return -1;
}
if (bSender)
{
char *payload=NULL;
int optlevel,
option,
optval;
payload = (char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, gSendSize);
if (payload == NULL)
{
fprintf(stderr, "HeapAlloc failed: %d\n", GetLastError());
return -1;
}
memfill(payload, gSendSize, gMessage, strlen(gMessage));
// Enable the IP header include option
optval = 1;
if (ressrc->ai_family == AF_INET)
{
optlevel = IPPROTO_IP;
option = IP_HDRINCL;
}
else if (ressrc->ai_family == AF_INET6)
{
optlevel = IPPROTO_IPV6;
option = IPV6_HDRINCL;
}
rc = setsockopt(s, optlevel, option, (char *)&optval, sizeof(optval));
if (rc == SOCKET_ERROR)
{
fprintf(stderr, "setsockopt: IP_HDRINCL failed: %d\n", WSAGetLastError());
return -1;
}
// Packetize and/or perform necessary fragmentation on data
if (ressrc->ai_family == AF_INET)
{
wbuf = PacketizeIpv4(
ressrc,
resdest,
payload,
gSendSize
);
}
else if (ressrc->ai_family == AF_INET6)
{
wbuf = PacketizeIpv6(
ressrc,
resdest,
payload,
gSendSize
);
}
// Count how many packets there are
i=0;
packets=0;
while (wbuf[i].buf)
{
printf("packet %d buf 0x%p len %d\n",
i, wbuf[i].buf, wbuf[i].len);
packets++;
i++;
}
// Apparently, this SOCKADDR_IN structure makes no difference.
// Whatever we put as the destination IP addr in the IP
// header is what goes. Specifying a different dest in remote
// will be ignored.
for(i=0; i < (int)gSendCount ;i++)
{
for(j=0; j < packets ;j++)
{
rc = sendto(
s,
wbuf[j].buf,
wbuf[j].len,
0,
resdest->ai_addr,
resdest->ai_addrlen
);
bytes = rc;
if (rc == SOCKET_ERROR)
{
printf("sendto() failed: %d\n", WSAGetLastError());
break;
}
else
{
printf("sent %d bytes\n", bytes);
}
}
}
// Free the packet buffers
for(i=0; i < packets ;i++)
{
HeapFree(GetProcessHeap(), 0, wbuf[i].buf);
}
}
else
{
SOCKADDR_STORAGE safrom;
char buf[MAX_PACKET];
int fromlen;
rc = bind(
s,
ressrc->ai_addr,
ressrc->ai_addrlen
);
if (rc == SOCKET_ERROR)
{
fprintf(stderr, "bind failed: %d\n", WSAGetLastError());
return -1;
}
printf("binding to: ");
PrintAddress(ressrc->ai_addr, ressrc->ai_addrlen);
printf("\n");
while (1)
{
fromlen = sizeof(safrom);
rc = recvfrom(
s,
buf,
MAX_PACKET,
0,
(SOCKADDR *)&safrom,
&fromlen
);
if (rc == SOCKET_ERROR)
{
fprintf(stderr, "recvfrom failed: %d\n", WSAGetLastError());
break;
}
printf("Read %d bytes from ", rc);
PrintAddress((SOCKADDR *)&safrom, fromlen);
printf("\n");
}
}
closesocket(s) ;
WSACleanup() ;
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -