📄 rawudp.cpp
字号:
// Account for the size of the UDP header
if (offset != 0)
offset += sizeof(UDP_HDR);
frag->ipv6_frag_nexthdr = (unsigned char)nextproto;
frag->ipv6_frag_offset = htons( (unsigned short)(((offset/8) << 3) | lastfragment));
frag->ipv6_frag_id = htonl(id);
return sizeof(IPV6_FRAGMENT_HDR);
}
//
// Function: InitUdpHeader
//
// Description:
// Setup the UDP header which is fairly simple. Grab the ports and
// stick in the total payload length.
//
int InitUdpHeader(
char *buf,
SOCKADDR *src,
SOCKADDR *dest,
int payloadlen
)
{
UDP_HDR *udphdr=NULL;
udphdr = (UDP_HDR *)buf;
// Port numbers are already in network byte order
if (src->sa_family == AF_INET)
{
udphdr->src_portno = ((SOCKADDR_IN *)src)->sin_port;
udphdr->dst_portno = ((SOCKADDR_IN *)dest)->sin_port;
}
else if (src->sa_family == AF_INET6)
{
udphdr->src_portno = ((SOCKADDR_IN6 *)src)->sin6_port;
udphdr->dst_portno = ((SOCKADDR_IN6 *)dest)->sin6_port;
}
udphdr->udp_length = htons(sizeof(UDP_HDR) + payloadlen);
return sizeof(UDP_HDR);
}
//
// Function: ComputeUdpPseudoHeaderChecksumV4
//
// Description:
// Compute the UDP pseudo header checksum. The UDP checksum is based
// on the following fields:
// o source IP address
// o destination IP address
// o 8-bit zero field
// o 8-bit protocol field
// o 16-bit UDP length
// o 16-bit source port
// o 16-bit destination port
// o 16-bit UDP packet length
// o 16-bit UDP checksum (zero)
// o UDP payload (padded to the next 16-bit boundary)
// This routine copies these fields to a temporary buffer and computes
// the checksum from that.
//
void ComputeUdpPseudoHeaderChecksumV4(
void *iphdr,
UDP_HDR *udphdr,
char *payload,
int payloadlen
)
{
IPV4_HDR *v4hdr=NULL;
unsigned long zero=0;
char buf[MAX_PACKET],
*ptr=NULL;
int chksumlen=0,
i;
ptr = buf;
v4hdr = (IPV4_HDR *)iphdr;
// Include the source and destination IP addresses
memcpy(ptr, &v4hdr->ip_srcaddr, sizeof(v4hdr->ip_srcaddr));
ptr += sizeof(v4hdr->ip_srcaddr);
chksumlen += sizeof(v4hdr->ip_srcaddr);
memcpy(ptr, &v4hdr->ip_destaddr, sizeof(v4hdr->ip_destaddr));
ptr += sizeof(v4hdr->ip_destaddr);
chksumlen += sizeof(v4hdr->ip_destaddr);
// Include the 8 bit zero field
memcpy(ptr, &zero, 1);
ptr++;
chksumlen += 1;
// Protocol
memcpy(ptr, &v4hdr->ip_protocol, sizeof(v4hdr->ip_protocol));
ptr += sizeof(v4hdr->ip_protocol);
chksumlen += sizeof(v4hdr->ip_protocol);
// UDP length
memcpy(ptr, &udphdr->udp_length, sizeof(udphdr->udp_length));
ptr += sizeof(udphdr->udp_length);
chksumlen += sizeof(udphdr->udp_length);
// UDP source port
memcpy(ptr, &udphdr->src_portno, sizeof(udphdr->src_portno));
ptr += sizeof(udphdr->src_portno);
chksumlen += sizeof(udphdr->src_portno);
// UDP destination port
memcpy(ptr, &udphdr->dst_portno, sizeof(udphdr->dst_portno));
ptr += sizeof(udphdr->dst_portno);
chksumlen += sizeof(udphdr->dst_portno);
// UDP length again
memcpy(ptr, &udphdr->udp_length, sizeof(udphdr->udp_length));
ptr += sizeof(udphdr->udp_length);
chksumlen += sizeof(udphdr->udp_length);
// 16-bit UDP checksum, zero
memcpy(ptr, &zero, sizeof(unsigned short));
ptr += sizeof(unsigned short);
chksumlen += sizeof(unsigned short);
// payload
memcpy(ptr, payload, payloadlen);
ptr += payloadlen;
chksumlen += payloadlen;
// pad to next 16-bit boundary
for(i=0 ; i < payloadlen%2 ; i++, ptr++)
{
printf("pad one byte\n");
*ptr = 0;
ptr++;
chksumlen++;
}
// Compute the checksum and put it in the UDP header
udphdr->udp_checksum = checksum((USHORT *)buf, chksumlen);
return;
}
void ComputeUdpPseudoHeaderChecksumV6(
void *iphdr,
UDP_HDR *udphdr,
char *payload,
int payloadlen
)
{
IPV6_HDR *v6hdr=NULL;
unsigned long length=0;
char buf[MAX_PACKET],
proto,
*ptr=NULL;
int chksumlen=0,
i;
ptr = buf;
v6hdr = (IPV6_HDR *)iphdr;
memcpy(ptr, &v6hdr->ipv6_srcaddr, sizeof(v6hdr->ipv6_srcaddr));
ptr += sizeof(v6hdr->ipv6_srcaddr);
chksumlen += sizeof(v6hdr->ipv6_srcaddr);
memcpy(ptr, &v6hdr->ipv6_destaddr, sizeof(v6hdr->ipv6_destaddr));
ptr += sizeof(v6hdr->ipv6_destaddr);
chksumlen += sizeof(v6hdr->ipv6_destaddr);
printf("payload length = %d\n", payloadlen);
length = htonl(payloadlen + sizeof(UDP_HDR));
memcpy(ptr, &length, sizeof(length));
ptr += sizeof(length);
chksumlen += sizeof(length);
memset(ptr, 0, 3);
ptr += 3;
chksumlen +=3;
proto = IPPROTO_UDP;
memcpy(ptr, &proto, sizeof(proto));
ptr += sizeof(proto);
chksumlen += sizeof(proto);
// UDP source port
memcpy(ptr, &udphdr->src_portno, sizeof(udphdr->src_portno));
ptr += sizeof(udphdr->src_portno);
chksumlen += sizeof(udphdr->src_portno);
// UDP destination port
memcpy(ptr, &udphdr->dst_portno, sizeof(udphdr->dst_portno));
ptr += sizeof(udphdr->dst_portno);
chksumlen += sizeof(udphdr->dst_portno);
// UDP length again
memcpy(ptr, &udphdr->udp_length, sizeof(udphdr->udp_length));
ptr += sizeof(udphdr->udp_length);
chksumlen += sizeof(udphdr->udp_length);
// 16-bit UDP checksum, zero
memset(ptr, 0, sizeof(unsigned short));
ptr += sizeof(unsigned short);
chksumlen += sizeof(unsigned short);
// payload
memcpy(ptr, payload, payloadlen);
ptr += payloadlen;
chksumlen += payloadlen;
// pad to next 16-bit boundary
for(i=0 ; i < payloadlen%2 ; i++, ptr++)
{
printf("pad one byte\n");
*ptr = 0;
ptr++;
chksumlen++;
}
// Compute the checksum and put it in the UDP header
udphdr->udp_checksum = checksum((USHORT *)buf, chksumlen);
return;
}
//
// Function: memfill
//
// Description:
// Fills a block of memory with a given string pattern.
//
void memfill(
char *dest,
int destlen,
char *data,
int datalen
)
{
char *ptr=NULL;
int copylen;
ptr = dest;
while (destlen > 0)
{
copylen = ((destlen > datalen) ? datalen : destlen);
memcpy(ptr, data, copylen);
destlen -= copylen;
ptr += copylen;
}
return;
}
//
// Function: PacketizeIpv4
//
// Description:
// This routine takes the data buffer and packetizes it for IPv4.
// Since the IPv4 stack takes care of fragmentation for us, this
// routine simply initializes the IPv4 and UDP headers. The data
// is returned in an array of WSABUF structures.
//
WSABUF *PacketizeIpv4(
struct addrinfo *src,
struct addrinfo *dest,
char *payload,
int payloadlen
)
{
static WSABUF Packets[MAX_PACKET_FRAGMENTS];
int iphdrlen,
udphdrlen;
// Allocate memory for the packet
Packets[0].buf = (char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IPV4_HDR) + sizeof(UDP_HDR) + payloadlen);
if (Packets[0].buf == NULL)
{
fprintf(stderr, "PacetizeV4: HeapAlloc failed: %d\n", GetLastError());
ExitProcess(-1);
}
Packets[0].len = sizeof(IPV4_HDR) + sizeof(UDP_HDR) + payloadlen;
// Initialize the v4 header
iphdrlen = InitIpv4Header(
Packets[0].buf,
src->ai_addr,
dest->ai_addr,
DEFAULT_TTL,
gProtocol,
payloadlen
);
// Initialize the UDP header
udphdrlen = InitUdpHeader(
&Packets[0].buf[iphdrlen],
src->ai_addr,
dest->ai_addr,
payloadlen
);
// Compute the UDP checksum
ComputeUdpPseudoHeaderChecksumV4(
Packets[0].buf,
(UDP_HDR *)&Packets[0].buf[iphdrlen],
payload,
payloadlen
);
// Copy the payload to the end of the header
memcpy(&Packets[0].buf[iphdrlen + udphdrlen], payload, payloadlen);
// Zero out the next WSABUF structure which indicates the end of
// the packets -- caller must free the buffers
Packets[1].buf = NULL;
Packets[1].len = 0;
return Packets;
}
//
// Function: PacketizeIpv6
//
// Description:
// This routine fragments data payload with the appropriate IPv6
// headers. The individual fragments are returned via an array of
// WSABUF structures. Each structure is a separate fragment of the
// whole message. The end of the fragments is indicated by a WSABUF
// entry with a NULL buffer pointer.
//
WSABUF *PacketizeIpv6(
struct addrinfo *src,
struct addrinfo *dest,
char *payload,
int payloadlen
)
{
static WSABUF Packets[MAX_PACKET_FRAGMENTS];
static ULONG fragid=1;
int offset=0, // offset into payload
datalen, // length of the payload
hdrlen, // length of the header(s)
fragment, // is this a fragment?
lastfragment, // is this the last fragment?
iphdrlen, // length of ip header
udphdrlen, // length of the udp header
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -