Raw Sockets

 

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

 

A www.vsnl.com

 

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

a www.google.com

 

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);

}

}

 

Back to the main page