This chapter focuses on raw sockets
under the windows operating system. A raw socket brings in more flexibility
when creating our own packet.
a.c
#include <windows.h>
#include <stdio.h>
main()
{
printf("%04x\n",MAKEWORD(4,2));
printf("%04x\n",MAKEWORD(2,4));
printf("%04x\n", 4 | 2
<< 8 );
}
Output
0204
0402
0204
In the above example, a macro MAKEWORD
is used to create a short data type. The first parameter 4 to the macro becomes
the low byte and the second the high byte.
The last printf displays the actual
workings of a macro. It takes the second parameter and shifts it 8 to the left
which in effect does a multiplication by 256. This moves the two 8 bits to the
left which is then bitwise ored with
the first parameter which does an addition. Thus, the first parameter to the
MAKEWORD macro becomes the low 8 bits and the second the higher eight bits.
a.c
#include <windows.h>
#include <stdio.h>
int d;WSADATA ws;
main()
{
d = WSAStartup(MAKEWORD(2,1),&ws);
printf("WSAStartup Return
Value=%d\n",d);
printf("wVersion=%x
wHighVersion=%x\n",ws.wVersion,ws.wHighVersion);
d = WSAStartup(MAKEWORD(1,3),&ws);
printf("WSAStartup Return
Value=%d\n",d);
printf("wVersion=%x
wHighVersion=%x\n",ws.wVersion,ws.wHighVersion);
d = WSAStartup(MAKEWORD(0,9),&ws);
printf("WSAStartup Return
Value=%d\n",d);
printf("wVersion=%x
wHighVersion=%x\n",ws.wVersion,ws.wHighVersion);
d = WSAStartup(MAKEWORD(2,3),&ws);
printf("WSAStartup Return
Value=%d\n",d);
printf("wVersion=%x
wHighVersion=%x\n",ws.wVersion,ws.wHighVersion);
d =
WSAStartup(MAKEWORD(12,3),&ws);
printf("WSAStartup Return
Value=%d\n",d);
printf("wVersion=%x wHighVersion=%x\n",ws.wVersion,ws.wHighVersion);
}
>cl a.c ws2_32.lib
Output
WSAStartup Return Value=0
wVersion=102 wHighVersion=202
WSAStartup Return Value=0
wVersion=101 wHighVersion=202
WSAStartup Return Value=10092
wVersion=0 wHighVersion=202
WSAStartup Return Value=0
wVersion=202 wHighVersion=202
WSAStartup Return Value=0
wVersion=202 wHighVersion=202
The function WSAStartup returns 0 on
success, any other value indicates an error. The first parameter is the Winsock
version number that the coder wants to use. The high order byte specifies the
minor version and the low order byte specifies the major version. The MAKEWORD
macro is required here as the version number is written the other way around.
Thus in the first call, MAKEWORD(2,1)
denotes that the version 2.1 of the Sockets API is to be used. The second
parameter, the ws WSADATA structure has two members that reveals the versions
supported. The member wHighVersion gives the highest version supported by this
machine, which is 2.2 whereas wVersion gives the minimum of high version and
version requested.
Thus, irrespective of asking for a low
or a high version, we are given the high version, which is the maximum version
that can be supported. The library used to link is not wsock32.lib but the newer
one, ws2_32.lib.
a.c
#include <winsock2.h>
#include <stdio.h>
int d;WSADATA ws;SOCKET s;
main()
{
d = WSAStartup(MAKEWORD(2,1),&ws);
printf("WSAStartup Return
Value=%d\n",d);
s =
WSASocket(AF_INET,SOCK_RAW,IPPROTO_ICMP,NULL, 0,0);
printf("Socket Return Value=%d\n",s);
}
Output
WSAStartup Return Value=0
Socket Return Value=104
Sockets programming in today’s day and
age shows extensive use of functions beginning with WSA instead of the earlier
Unix socket functions. Therefore, unlike socket, the function used now is
WSASocket. The last parameter is for the newer features, which presently is of
no use, hence it is blank. The WSA functions do what the unix functions do and
much more. However, we can conveniently use some from the WSA family and some
from the unix family.
Also, one of the newer features is the
use of overlapped sockets that make the network world go faster. This function
WSASocket like its socket counterpart returns –1 when in error. The first
parameter is for the major family, in our case not a protocol like Ipx or
NetBios, but the internet family. The second parameter is the major family type
within the internet set of protocols. They are two main types, a stream or
connection oriented protocol or TCP and a connectionless one, UDP. Since we are
creating our own packet, SOCK_RAW representing raw sockets is used.
a.c
#include <winsock2.h>
#include <stdio.h>
int d;WSADATA ws;SOCKET s;struct
hostent * hp;struct sockaddr_in dest;
main(int argc, char **argv)
{
d = WSAStartup(MAKEWORD(2,1),&ws);
printf("WSAStartup Return
Value=%d\n",d);
s =
WSASocket(AF_INET,SOCK_RAW,IPPROTO_ICMP,NULL, 0,0);
printf("Socket Return
Value=%d\n",s);
hp = gethostbyname(argv[1]);
printf("h_name=%s\n",hp->h_name);
printf("Aliases=%s\n",hp->h_aliases[0]);
printf("Length=%d Type=%d
%d\n",hp->h_length,hp->h_addrtype,AF_INET);
//memcpy(&(dest.sin_addr),hp->h_addr,hp->h_length);
memcpy(&(dest.sin_addr),hp->h_addr_list[0],hp->h_length);
dest.sin_family = hp->h_addrtype;
printf("Ip
Address=%s\n",inet_ntoa(dest.sin_addr));
}
Output
A
WSAStartup Return Value=0
Socket Return Value=104
h_name=vmci-354uctxbmk
Aliases=(null)
Length=4 Type=2 2
Ip Address=219.65.17.81
WSAStartup Return Value=0
Socket Return Value=104
h_name=www.vsnl.com
Aliases=(null)
Length=4 Type=2 2
Ip Address=202.54.117.24
A 202.54.117.24
WSAStartup Return Value=0
Socket Return Value=104
h_name=202.54.117.24
Aliases=(null)
Length=4 Type=2 2
Ip Address=202.54.117.24
Function gethostbyname is used in this
program even though the specs consider it to be a depreciated function. The
specs prefer the use of function getaddrinfo instead.
The function gethostbyname takes a
pointer to a char, that can either be in the form of a dotted decimal ip
address or a domain name and returns some data in the form a structure of type
hostent. It is given a null pointer and the
member h_addr gives the ip address of the machine we are running on. In
our case when we connected to our isp we were given an ip address of 219.65.17.81.
In this manner, we can find out the IP address that our machine has been
assigned.
The h_name member is the domain name
our machine is assigned. The aliases or alternative name is null. The length of
each address is 4 and its type is AF_INET or the internet family. The member
h_addr_list is a null terminated list of address and the macro h_addr has a
value h_addr_list[0].
The function inet_ntoa requires a
structure of type sockaddr_in and therefore the long member of the union is
initialized to the ip address. If a
domain like www.vsnl.com
is given, the IP address of this domain name is returned. Likewise, the dotted
decimal address can also be used to obtain the same information.
a.c
#include <winsock2.h>
#include <stdio.h>
int d,dummy,i;WSADATA ws;SOCKET
s;struct hostent * hp;struct sockaddr_in dest;
char databuf[1024];
struct IcmpHeader
*pIcmpHeader,*pIcmpHeader1;
struct IpHeader *pIpHeader;
struct IpHeader
{
unsigned char lenver;
unsigned char tos;
unsigned short totallen;
unsigned short ident;
unsigned short fragandflags;
unsigned char ttl;
unsigned char proto;
unsigned short checksum;
struct in_addr sourceIP;
struct in_addr destIP;
} IpHeader;
struct IcmpHeader
{
char i_type;
char i_code;
unsigned short i_cksum;
unsigned short i_id;
unsigned short i_seq;
unsigned long timestamp;
char data[32];
} ;
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);
}
main(int argc, char **argv)
{
d = WSAStartup (MAKEWORD(2,1),&ws);
printf("WSAStartup Return Value=%d\n",d);
s = WSASocket(AF_INET,SOCK_RAW, IPPROTO_ICMP ,NULL, 0,0);
printf("Socket Return Value=%d\n",s);
hp = gethostbyname(argv[1]);
memcpy(&dest.sin_addr,hp->h_addr,hp->h_length);
dest.sin_family = hp->h_addrtype;
printf("hp=%x Ip Address=%s\n",hp,inet_ntoa(dest.sin_addr));
pIcmpHeader = (IcmpHeader *) malloc(sizeof(IcmpHeader));
pIcmpHeader->i_type = 8;
pIcmpHeader->i_code = 0;
pIcmpHeader->i_id = (USHORT)GetCurrentProcessId();
pIcmpHeader->i_cksum = 0;
pIcmpHeader->i_seq = 326;
memset(pIcmpHeader->data ,'A', 32);
pIcmpHeader->timestamp = GetTickCount();
pIcmpHeader->i_cksum = checksum((USHORT
*)pIcmpHeader,sizeof(IcmpHeader));
d = sendto(s,(char *)pIcmpHeader,sizeof(IcmpHeader),0,(struct
sockaddr*)&dest,sizeof(dest));
printf("Sentto return value=%d\n",d);
dummy = sizeof(dest);
d = recvfrom(s ,databuf,1024,0,(struct
sockaddr*)&dest,&dummy);
printf("recvfrom return value=%d\n",d);
pIpHeader = (struct IpHeader *)databuf;
printf("len=%x TOS=%d Total length %d
%d\n",pIpHeader->lenver,pIpHeader->tos,
pIpHeader->totallen , htons(pIpHeader->totallen));
printf("ident=%d Frag=%d TTL=%d
Protocol=%d\n",pIpHeader->ident,
pIpHeader->fragandflags,pIpHeader->ttl,pIpHeader->proto);
printf("CheckSum=%d %d\n",pIpHeader->checksum ,
checksum((USHORT *)databuf,20+32+12));
printf("Source IP=%s Dest
Ip=%s\n",inet_ntoa(pIpHeader->sourceIP),inet_ntoa(pIpHeader->destIP));
printf("dest=%s\n",inet_ntoa(dest.sin_addr));
pIcmpHeader1= (struct IcmpHeader *)(databuf + 20);
printf("Type=%d
Code=%d\n",pIcmpHeader1->i_type,pIcmpHeader1->i_code);
printf("CheckSum=%d %d\n",pIcmpHeader1->i_cksum ,
checksum((USHORT *)
(databuf+20),32+12));
printf("id ret=%d send=%d
sequence=%d\n",pIcmpHeader1->i_id,pIcmpHeader->i_id ,
pIcmpHeader1->i_seq);
printf("timestamp ret=%d send=%d
Diff=%d\n",pIcmpHeader1->timestamp,
pIcmpHeader->timestamp, GetTickCount() -
pIcmpHeader1->timestamp );
for( i = 0 ; i <= 31 ; i++)
printf("%c",pIcmpHeader1->data[i]);
}
Output
WSAStartup Return Value=0
Socket Return Value=104
hp=158c40 Ip Address=66.102.7.99
Sentto return value=44
recvfrom return value=64
len=45 TOS=0 Total length 16384 64
ident=20299 Frag=0 TTL=242 Protocol=1
CheckSum=50502 0
Source IP=66.102.7.99 Dest
Ip=66.102.7.99
dest=66.102.7.99
Type=0 Code=0
CheckSum=26539 0
id ret=1720 send=1720 sequence=326
timestamp ret=620189515 send=620189515
Diff=1188
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
This example is more a utility that
mimics the ping program. The WSAStartup function asks for Winsock version 2.1.
Though, we have not checked for return values we seriously recommend that you
do. Then a socket is created using the function WSASocket even though the
function socket would suffice. The second parameter is for Raw Sockets and the
third is the actual protocol to be used with IP. All internet packets starts
with IP but then we can use a protocol off our choice.
We normally use TCP or UDP. For those
who want to control the workings of the internet, ICMP is used. Thus, in our
case as we want to control a small part of the net, we use the macro
IPPROTO_ICMP that denotes the ICMP protocol. We want to check whether a machine
on the net has the internet stack or code installed and running. If this is
true, that site must support the ICMP protocol along with IP.
A certain ICMP packet is sent to a
site which will send back a reply. The program takes either the site name or
its IP address. Either way, the function gethostbyname will return a hostent
structure that will contain the ip address in the macro h_addr as shown in the
last example. We also copy this value and the address family AF_INET into the
structure dest.
The ICMP protocol has a certain packet
format. The first 44 bytes are allocated for the ICMP header. In fact, the
first 4 bytes are the bytes defined by the protocol for all ICMP messages. The
field type then decides on the rest of the extra fields. The value of 8 denotes
an Echo message and a value of 0 an echo reply. Thus, whenever a TCP/IP stack
receives a message type of 8 or echo it sends back a Echo Reply message or type
0. The code field is always 0. The checksum field is the normal internet
checksum and its value should be zero before calculating the checksum. The next
two fields id and sequence number share
the same role.
On sending an echo message, an echo
reply is received. However to match the echo reply message with the echo
message, the id and sequence number fields are used which together become a
unique id for the packet. The echo reply message copies the values of these
fields plus more and then returns the packet. The id field is set to the
process id thus making it absolutely unique. However, if more than one echo
request packet is sent, the sequence field is changed to a different value each
time.
Along with these header details, the packet
also has 32 A’s in the array data. In the echo reply, all these extra bytes are
returned back without any change. This helps in validating the packet for any
data corruption. Not really needed.
The timestamp field is set to the
current time and it factors the time taken for the packet to reach and return
back. Not part of the protocol. Once
the packet is ready, the sendto function is used to send this packet over. The
first parameter to this function is the raw socket handle and the second is the
bytes to be sent across. The third is for the number of bytes, whereas the
fourth is for options if any. The fifth is the IP address of the site to be
visited. The IP address and port is always given as a sockaddr_in structure.
The sendto function returns the number of bytes sent.
In our case, the IP header is not
explicitly specified, only the ICMP bytes are given. The IP header is generated
by the system but the ICMP header will be taken from the program.
When the destination site receives a
ICMP packet with type 8, it sends an ICMP echo reply message with type set to
0. First comes the recvfrom function to accept this message. The recvfrom
function returns the number of bytes it has received, which is 64. The ICMP
packet sent was 44 bytes along with the IP header, which is 20 bytes, hence 64
bytes. Thus with raw sockets we can manually look at the IP bytes received. The
parameters for the recvfrom and sendto functions are similar. The only
difference is that the last parameter is the address of a variable that
contains the size of the sockaddr_in structure.
The array databuf now starts with a 20
byte structure that represents the IP header, therefore we set the pointer
pIpHeader to this array databuf and read out the first 20 bytes. We have learnt
earlier the structure of a IP header where the total length is stored in big
endian format, thus the htons function is used which changes it to little
endian.
The protocol field has a value of 1
denoting a follow on of ICMP header. Next is the TTL field which has a very
large number of 242. For some reason, unknown to us both the source and
destination IP addresses are same. The ICMP header follows the IP header so the
the variable pIcmpHeader1 is made to point to 20 bytes from the start of the
array databuf.
As this is an Echo Reply message, both
the Type and Code field will be zero. The process ID is 1720 and the sequence
number has been set to 326 to uniquely identify this packet. The timestamp field
is copied back unaltered, thus, it makes it easier to find out the difference
in time when the packet was sent to when it has been received.
Finally, the contents of the array
data are printed to check for all of them being A’s. The timestamp and the data
following need not be send. Thus, in effect, 8 bytes are all that we need to
send of the ICMP header.
a.c
#include <winsock2.h>
#include <stdio.h>
#include <ws2tcpip.h>
#pragma pack(1)
struct ipopt
{
unsigned char code;
unsigned char len;
unsigned char ptr;
long addr[9];
}ipopt;
int d,dummy,i;WSADATA ws;SOCKET
s;struct hostent * hp;struct sockaddr_in dest;
char databuf[1024];
struct IcmpHeader
*pIcmpHeader,*pIcmpHeader1;struct IpHeader *pIpHeader;
struct IpHeader
{
unsigned char lenver;
unsigned char tos;
unsigned short totallen;
unsigned short ident;
unsigned short fragandflags;
unsigned char ttl;
unsigned char proto;
unsigned short checksum;
struct in_addr sourceIP;
struct in_addr destIP;
long ipaddress[10];
} IpHeader;
struct IcmpHeader
{
char i_type;
char i_code;
unsigned short i_cksum;
unsigned short i_id;
unsigned short i_seq;
unsigned long timestamp;
char data[32];
} ;
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);
}
main(int argc, char **argv)
{
d = WSAStartup(MAKEWORD(2,1),&ws);
printf("WSAStartup Return
Value=%d\n",d);
s = WSASocket(AF_INET,SOCK_RAW,IPPROTO_ICMP,NULL,
0,0);
printf("Socket Return
Value=%d\n",s);
hp = gethostbyname(argv[1]);
memcpy(&dest.sin_addr,hp->h_addr,hp->h_length);
dest.sin_family = hp->h_addrtype;
printf("hp=%x Ip
Address=%s\n",hp,inet_ntoa(dest.sin_addr));
pIcmpHeader = (IcmpHeader *)
malloc(sizeof(IcmpHeader));
pIcmpHeader->i_type = 8;
pIcmpHeader->i_code = 0;
pIcmpHeader->i_id =
(USHORT)GetCurrentProcessId();
pIcmpHeader->i_cksum = 0;
pIcmpHeader->i_seq = 326;
memset(pIcmpHeader->data ,'A', 32);
pIcmpHeader->timestamp =
GetTickCount();
pIcmpHeader->i_cksum =
checksum((USHORT *)pIcmpHeader,sizeof(IcmpHeader));
ipopt.code = 7;
ipopt.ptr = 4;
ipopt.len = 39;
setsockopt (s, IPPROTO_IP,
IP_OPTIONS,(char *)&ipopt, sizeof(ipopt));
d = sendto(s,(char *)pIcmpHeader,sizeof(IcmpHeader),0,(struct
sockaddr*)&dest,sizeof(dest));
printf("Sentto return
value=%d\n",d);
dummy = sizeof(dest);
d = recvfrom(s ,databuf,1024,0,(struct
sockaddr*)&dest,&dummy);
printf("recvfrom return
value=%d\n",d);
pIpHeader = (struct IpHeader
*)databuf;
printf("len=%x TOS=%d Total
length %d
%d\n",pIpHeader->lenver,pIpHeader->tos,pIpHeader->totallen ,
htons(pIpHeader->totallen));
printf("ident=%d Frag=%d TTL=%d
Protocol=%d\n",pIpHeader->ident,
pIpHeader->fragandflags,pIpHeader->ttl,pIpHeader->proto);
printf("CheckSum=%d
%d\n",pIpHeader->checksum , checksum((USHORT *)databuf,20+32+12));
printf("Source IP=%s Dest
Ip=%s\n",inet_ntoa(pIpHeader->sourceIP),inet_ntoa(pIpHeader->destIP));
printf("dest=%s\n",inet_ntoa(dest.sin_addr));
int size = pIpHeader->lenver &
0x0f;
size = size * 4;
size = size - 20;
printf("Size of IP headers
%d\n",size);
if ( size > 0)
{
struct ipopt *pipopt;
pipopt = (struct ipopt *)(databuf +
20);
printf("code=%d len=%d
ptr=%d\n",pipopt->code,pipopt->len,pipopt->ptr);
int noofstr;
noofstr = (pipopt->ptr/4) - 1;
printf("No of
addr's=%d\n",noofstr);
for ( i = 0 ; i < noofstr ; i++)
{
struct in_addr a;
a.S_un.S_addr = pipopt->addr[i];
printf("%s\n",inet_ntoa(a));
}
}
}
Output
WSAStartup Return Value=0
Socket Return Value=104
hp=1581b8 Ip Address=202.54.117.24
Sentto return value=44
recvfrom return value=104
len=4f TOS=0 Total length 26624 104
ident=27551 Frag=0 TTL=61 Protocol=1
CheckSum=56174 33316
Source IP=202.54.117.24 Dest
Ip=202.54.117.24
dest=202.54.117.24
Size of IP headers 40
code=7 len=39 ptr=36
No of addr's=8
202.54.115.154
203.199.24.154
202.54.117.4
202.54.117.24
202.54.117.24
203.199.24.153
202.54.115.152
202.54.115.154
This example is similar to the
traceroute program where we print out all the routers that our packet has seen
along the way. We start as always with the usual WSAStartup, WSASocket and
gethostbyname. Then comes the ICMP header where the type is set to 8 denoting a
Echo Request message to be sent.
Now comes a slight change. The
function setsockopt is brought in to to set a option for the socket. This
function first requires the socket followed by an option that deals with the
family, in our case macro IPPROTO_IP stands for the internet protocol. We then specify that the actual
option deals with IP and not TCP using the macro IP_OPTIONS. Now come the meat.
We need to specify the actual option
using the structure ipopt. This structure starts with a char called code where
the number 7 means record the route the packet takes. This number is not
documented by Microsoft. The ptr option shows where the option will start after
the main IP header and the len field is the total length of the IP options.
Thus, the sendto function sends the same
44 bytes but now the system adds some options data to the IP header. The same
packet in the earlier program returned 64 bytes but now returns 104 bytes, an
extra 40 bytes. These bytes could mean that the IP header has now increased.
The first byte of the IP header gives
a value of 0x0f. This means that the IP header is 60 bytes instead of 20 bytes.
Thus, the size variable denotes the size of the extra IP options, which are 40
bytes. These IP options start with a similar structure where the code field is
7 that tells us what the IP record Route option is and what these extra bytes
represents.
Then the len field gives the number of
bytes these options take up, 36. This value is divided by 4, the size of an IP
addresses and then subtracted by 1 to give the final number of IP addresses
that would be printed out. To print these IP address, function inet_ntoa is
used. This function requires a structure that looks like in_addr where the long
member S_addr is set to the IP address stored in the IP option header. This
member S_addr is part of a unio S_un.
In this manner, all the machines our packet has visited each way can be
printed out.
d.c
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <stdlib.h>
#include <pshpack1.h>
#include <wspiapi.h>
typedef struct ip_hdr
{
unsigned char ip_verlen; // 4-bit IPv4 version
// 4-bit header length (in
32-bit words)
unsigned char ip_tos; // IP type of service
unsigned short ip_totallength;
// Total length
unsigned short ip_id;
// Unique identifier
unsigned short ip_offset;
// Fragment offset field
unsigned char ip_ttl; // Time to live
unsigned char ip_protocol; // Protocol(TCP,UDP etc)
unsigned short ip_checksum;
// IP checksum
unsigned int ip_srcaddr; // Source address
unsigned int ip_destaddr; // Source address
} IPV4_HDR, *PIPV4_HDR, FAR *
LPIPV4_HDR;
typedef struct udp_hdr
{
unsigned short src_portno;
// Source port no.
unsigned short dst_portno;
// Dest. port no.
unsigned short udp_length;
// Udp packet length
unsigned short udp_checksum;
// Udp checksum
} UDP_HDR, *PUDP_HDR;
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);
}
UDP_HDR *udphdr;IPV4_HDR *v4hdr;struct
addrinfo *ressrc,*resdest;
struct addrinfo hints;WSADATA
wsd;SOCKET s;
char *buffer;
int optval=1;
int _cdecl main(int argc, char **argv)
{
WSAStartup(MAKEWORD(2,2), &wsd);
getaddrinfo("1.2.3.4","1234",0,&ressrc
);
hints.ai_flags = 0;
hints.ai_family =
ressrc->ai_family;
hints.ai_socktype =
ressrc->ai_socktype;
hints.ai_protocol =
ressrc->ai_protocol;
getaddrinfo("127.0.0.1","5000",&hints,&resdest);
s=socket(ressrc->ai_family,SOCK_RAW,
ressrc->ai_protocol);
setsockopt(s, IPPROTO_IP, IP_HDRINCL,
(char *)&optval, sizeof(optval));
buffer = (char
*)HeapAlloc(GetProcessHeap(), 0, 128);
v4hdr = (IPV4_HDR *)buffer;
v4hdr->ip_verlen= (4 << 4) |
(sizeof(IPV4_HDR) / sizeof(unsigned long));
v4hdr->ip_tos=0;
v4hdr->ip_totallength=htons(sizeof(IPV4_HDR)+
sizeof(UDP_HDR) + 10);
v4hdr->ip_id=0;
v4hdr->ip_offset= 0;
v4hdr->ip_ttl = (unsigned char)8;
v4hdr->ip_protocol=(unsigned
char)IPPROTO_UDP;
v4hdr->ip_checksum = 0;
v4hdr->ip_srcaddr= ((struct
sockaddr_in *)ressrc->ai_addr)->sin_addr.s_addr;
v4hdr->ip_destaddr= ((struct
sockaddr_in *)resdest->ai_addr)->sin_addr.s_addr;
v4hdr->ip_checksum = checksum((unsigned short *)v4hdr,
sizeof(IPV4_HDR));
udphdr = (UDP_HDR *)(buffer +
sizeof(IPV4_HDR));
udphdr->src_portno = ((struct sockaddr_in
*)ressrc->ai_addr)->sin_port;
udphdr->dst_portno = ((struct
sockaddr_in *)resdest->ai_addr)->sin_port;
udphdr->udp_length =
htons(sizeof(UDP_HDR) + 10);
memcpy(buffer+sizeof(IPV4_HDR) +
sizeof(UDP_HDR),"vijaymukhi",10);
sendto(s,buffer,sizeof(IPV4_HDR)
+ sizeof(UDP_HDR) + 10 ,0,resdest->ai_addr,
resdest->ai_addrlen);
sendto(s,buffer,sizeof(IPV4_HDR) + sizeof(UDP_HDR) + 10
,0,resdest->ai_addr,
resdest->ai_addrlen);
}
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <stdlib.h>
#include <wspiapi.h>
SOCKADDR safrom;
int fromlen,rc;
char *buffer;
struct addrinfo *ressrc,hints;
WSADATA wsd;
SOCKET s;
int _cdecl main()
{
WSAStartup(MAKEWORD(2,2), &wsd);
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_RAW;
//hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_UDP;
getaddrinfo("127.0.0.1","5000",&hints,&ressrc);
s = socket(ressrc->ai_family,
SOCK_RAW, ressrc->ai_protocol);
s = socket(ressrc->ai_family,
SOCK_DGRAM, ressrc->ai_protocol);
buffer = (char *)HeapAlloc(GetProcessHeap(),
0, 128);
bind(s,ressrc->ai_addr,ressrc->ai_addrlen);
while (1)
{
fromlen = sizeof(safrom);
rc = recvfrom(s, buffer, 128, 0,
(SOCKADDR *)&safrom, &fromlen);
printf("Read %d bytes from
\n", rc);
}
}