This is the mail archive of the cygwin@cygwin.com mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Error compiling code using winsock functions


Hi there, I've recently been trying some programming with sockets in windows, and I obtained the following code from a microsoft book called "Network programming for microsoft windows"...
the code is as follows:


// Module Name: iphdrinc.c
//
#pragma pack(1)

#define WIN32_LEAN_AND_MEAN

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

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

#define MAX_MESSAGE        4068
#define MAX_PACKET         4096
//
// Set up some default values
//
#define DEFAULT_PORT       5150
#define DEFAULT_IP         "10.0.0.1"
#define DEFAULT_COUNT      5
#define DEFAULT_MESSAGE    "This is a test"

//
// Define the IP header. Make the version and length fields one
// character since we can't declare two 4-bit fields without
// the compiler aligning them on at least a 1-byte boundary.
//
typedef struct ip_hdr
{
   unsigned char  ip_verlen;        // IP version & length
   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;      // Destination address
} IP_HDR, *PIP_HDR, FAR* LPIP_HDR;
//
// Define the UDP header
//
typedef struct udp_hdr
{
   unsigned short src_portno;       // Source port number
   unsigned short dst_portno;       // Destination port number
   unsigned short udp_length;       // UDP packet length
   unsigned short udp_checksum;     // UDP checksum (optional)
} UDP_HDR, *PUDP_HDR;

//
// Global variables
//
unsigned long  dwToIP,               // IP to send to
              dwFromIP;             // IP to send from (spoof)
unsigned short iToPort,              // Port to send to
              iFromPort;            // Port to send from (spoof)
DWORD          dwCount;              // Number of times to send
char           strMessage[MAX_MESSAGE]; // Message to send

//
// 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", progname);
   printf("       -fp:int   From (sender) port number\n");
   printf("       -fi:IP    From (sender) IP address\n");
   printf("       -fp:int   To (recipient) port number\n");
   printf("       -fi:IP    To (recipient) IP address\n");
   printf("       -n:int    Number of times to read message\n");
   printf("       -m:str    Size of buffer to read\n\n");
   ExitProcess(1);
}
//
// Function: ValidateArgs
//
// Description:
//    Parse the command line arguments, and set some global flags to
//    indicate the actions to perform
//
void ValidateArgs(int argc, char **argv)
{
   int                i;

   iToPort = DEFAULT_PORT;
   iFromPort = DEFAULT_PORT;
   dwToIP = inet_addr(DEFAULT_IP);
   dwFromIP = inet_addr(DEFAULT_IP);
   dwCount = DEFAULT_COUNT;
   strcpy(strMessage, DEFAULT_MESSAGE);

   for(i = 1; i < argc; i++)
   {
       if ((argv[i][0] == '-') || (argv[i][0] == '/'))
       {
           switch (tolower(argv[i][1]))
           {
               case 'f':        // From address
                   switch (tolower(argv[i][2]))
                   {
                       case 'p':
                           if (strlen(argv[i]) > 4)
                               iFromPort = atoi(&argv[i][4]);
                           break;
                       case 'i':
                           if (strlen(argv[i]) > 4)
                               dwFromIP = inet_addr(&argv[i][4]);
                           break;
                       default:
                           usage(argv[0]);
                           break;
                   }
                   break;
               case 't':        // To address
                   switch (tolower(argv[i][2]))
                   {
                       case 'p':
                           if (strlen(argv[i]) > 4)
                               iToPort = atoi(&argv[i][4]);
                           break;
                       case 'i':
                           if (strlen(argv[i]) > 4)
                               dwToIP = inet_addr(&argv[i][4]);
                           break;
                       default:
                           usage(argv[0]);
                           break;
                   }
                   break;
               case 'n':        // Number of times to send message
                   if (strlen(argv[i]) > 3)
                       dwCount = atol(&argv[i][3]);
                   break;
               case 'm':
                   if (strlen(argv[i]) > 3)
                       strcpy(strMessage, &argv[i][3]);
                   break;
               default:
                   usage(argv[0]);
                   break;
           }
       }
   }
   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: main
//
// Description:
//    First parse command line arguments and load Winsock. Then
//    create the raw socket and 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 main(int argc, char **argv)
{
   WSADATA            wsd;
   SOCKET             s;
   BOOL               bOpt;
   struct sockaddr_in remote;       // IP addressing structures
   IP_HDR             ipHdr;
   UDP_HDR            udpHdr;
   int                ret;
   DWORD              i;
   unsigned short     iTotalSize,   // Lots of sizes needed to fill
                      iUdpSize,     // the various headers with
                      iUdpChecksumSize,
                      iIPVersion,
                      iIPSize,
                      cksum = 0;
   char               buf[MAX_PACKET],
                     *ptr = NULL;
   IN_ADDR            addr;

   // Parse command line arguments, and print them out
   //
   ValidateArgs(argc, argv);
   addr.S_un.S_addr = dwFromIP;
   printf("From IP: <%s>\n     Port: %d\n", inet_ntoa(addr),
       iFromPort);
   addr.S_un.S_addr = dwToIP;
   printf("To   IP: <%s>\n     Port: %d\n", inet_ntoa(addr),
       iToPort);
   printf("Message: [%s]\n", strMessage);
   printf("Count:   %d\n", dwCount);

   if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
   {
       printf("WSAStartup() failed: %d\n", GetLastError());
       return -1;
   }
   //  Creating a raw socket
   //
   s = WSASocket(AF_INET, SOCK_RAW, IPPROTO_UDP, NULL, 0,0);
   if (s == INVALID_SOCKET)
   {
       printf("WSASocket() failed: %d\n", WSAGetLastError());
       return -1;
   }

   // Enable the IP header include option
   //
   bOpt = TRUE;
   ret = setsockopt(s, IPPROTO_IP, IP_HDRINCL, (char *)&bOpt,
      sizeof(bOpt));
   if (ret == SOCKET_ERROR)
   {
       printf("setsockopt(IP_HDRINCL) failed: %d\n", WSAGetLastError());
       return -1;
   }
   // Initalize the IP header
   //
   iTotalSize = sizeof(ipHdr) + sizeof(udpHdr) + strlen(strMessage);

   iIPVersion = 4;
   iIPSize = sizeof(ipHdr) / sizeof(unsigned long);
   //
   // IP version goes in the high-order 4 bits of ip_verlen. The
   // IP header length (in 32-bit words) goes in the lower 4 bits.
   //
   ipHdr.ip_verlen = (iIPVersion << 4) | iIPSize;
   ipHdr.ip_tos = 0;                         // IP type of service
   ipHdr.ip_totallength = htons(iTotalSize); // Total packet len
   ipHdr.ip_id = 0;                 // Unique identifier: set to 0
   ipHdr.ip_offset = 0;             // Fragment offset field
   ipHdr.ip_ttl = 128;              // Time to live
   ipHdr.ip_protocol = 0x11;        // Protocol(UDP)
   ipHdr.ip_checksum = 0 ;          // IP checksum
   ipHdr.ip_srcaddr = dwFromIP;     // Source address
   ipHdr.ip_destaddr = dwToIP;      // Destination address
   //
   // Initalize the UDP header
   //
   iUdpSize = sizeof(udpHdr) + strlen(strMessage);

   udpHdr.src_portno = htons(iFromPort) ;
   udpHdr.dst_portno = htons(iToPort) ;
   udpHdr.udp_length = htons(iUdpSize) ;
   udpHdr.udp_checksum = 0 ;
   //
   // Build the UDP pseudo-header for calculating the UDP checksum.
   // The pseudo-header consists of the 32-bit source IP address,
   // the 32-bit destination IP address, a zero byte, the 8-bit
   // IP protocol field, the 16-bit UDP length, and the UDP
   // header itself along with its data (padded with a 0 if
   // the data is odd length).
   //
   iUdpChecksumSize = 0;
   ptr = buf;
   ZeroMemory(buf, MAX_PACKET);

   memcpy(ptr, &ipHdr.ip_srcaddr,  sizeof(ipHdr.ip_srcaddr));
   ptr += sizeof(ipHdr.ip_srcaddr);
   iUdpChecksumSize += sizeof(ipHdr.ip_srcaddr);

   memcpy(ptr, &ipHdr.ip_destaddr, sizeof(ipHdr.ip_destaddr));
   ptr += sizeof(ipHdr.ip_destaddr);
   iUdpChecksumSize += sizeof(ipHdr.ip_destaddr);

   ptr++;
   iUdpChecksumSize += 1;

   memcpy(ptr, &ipHdr.ip_protocol, sizeof(ipHdr.ip_protocol));
   ptr += sizeof(ipHdr.ip_protocol);
   iUdpChecksumSize += sizeof(ipHdr.ip_protocol);

   memcpy(ptr, &udpHdr.udp_length, sizeof(udpHdr.udp_length));
   ptr += sizeof(udpHdr.udp_length);
   iUdpChecksumSize += sizeof(udpHdr.udp_length);

   memcpy(ptr, &udpHdr, sizeof(udpHdr));
   ptr += sizeof(udpHdr);
   iUdpChecksumSize += sizeof(udpHdr);

   for(i = 0; i < strlen(strMessage); i++, ptr++)
       *ptr = strMessage[i];
   iUdpChecksumSize += strlen(strMessage);

   cksum = checksum((USHORT *)buf, iUdpChecksumSize);
   udpHdr.udp_checksum = cksum;
   //
   // Now assemble the IP and UDP headers along with the data
   // so we can send it
   //
   ZeroMemory(buf, MAX_PACKET);
   ptr = buf;

   memcpy(ptr, &ipHdr, sizeof(ipHdr));   ptr += sizeof(ipHdr);
   memcpy(ptr, &udpHdr, sizeof(udpHdr)); ptr += sizeof(udpHdr);
   memcpy(ptr, strMessage, strlen(strMessage));

   // 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 destination in remote
   // will be ignored.
   //
   remote.sin_family = AF_INET;
   remote.sin_port = htons(iToPort);
   remote.sin_addr.s_addr = dwToIP;

   for(i = 0; i < dwCount; i++)
   {
       ret = sendto(s, buf, iTotalSize, 0, (SOCKADDR *)&remote,
           sizeof(remote));
       if (ret == SOCKET_ERROR)
       {
           printf("sendto() failed: %d\n", WSAGetLastError());
           break;
       }
       else
           printf("sent %d bytes\n", ret);
   }
   closesocket(s) ;
   WSACleanup() ;

   return 0;
}


------- END CODE -----------


Basically, when compiling with cygwin with the following command:
gcc iphdrinc.c -o iphdrinc.exe -lwsock32

I get the following error:
"iphdrinc.o(.text+0x820):iphdrinc.c: undefined reference to '_WSASocketA@24' collect2: ld returned 1 exit status"


and if I dont use -lwsock32, i get even more errors of the same form ("undefined reference to XXX", where XXX is some function in winsock2.h)..
and I've noticed that the WSASocketA function is stated in the winsock2.h header file as follows:
SOCKET WINAPI WSASocketA(int, int, int, LPWSAPROTOCOL_INFOA, GROUP, DWORD);


(if that helps)

anyways, Im running windows XP, and the latest version of cygwin... so hopefully someone can give me some help =)

thanks in advance !
regards,
David.

_________________________________________________________________
The new MSN 8: advanced junk mail protection and 2 months FREE* http://join.msn.com/?page=features/junkmail



-- Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple Problem reports: http://cygwin.com/problems.html Documentation: http://cygwin.com/docs.html FAQ: http://cygwin.com/faq/


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]