*BSD News Article 4739


Return to BSD News archive

Xref: sserve comp.unix.ultrix:13601 comp.unix.bsd:4787
Newsgroups: comp.unix.ultrix,comp.unix.bsd
Path: sserve!manuel!munnari.oz.au!uunet!ftpbox!mothost!lmpsbbs!supra!rittle
From: rittle@supra (Loren James Rittle)
Subject: A major BSD socket bug?
Organization: Land Mobile Products Sector, Motorola Inc.
Date: Wed, 9 Sep 1992 05:31:47 GMT
Message-ID: <1992Sep9.053147.411@lmpsbbs.comm.mot.com>
Followup-To: comp.unix.ultrix
Summary: sockets in non-blocking mode appear to have problems
Sender: Loren J. Rittle <rittle@comm.mot.com>
Nntp-Posting-Host: 145.1.80.40
Lines: 82

I have reproduced this bug (be it in my code or the BSD OS) under
both ULTRIX 4.2A and SunOS 4.1.2.  As I don't read any sun groups, I didn't
know where to crosspost there.  The example below is under 20 lines of code.
If you are a BSD hacker, please take a look.

Thanks,
Loren

/* It appears that whenever recvfrom() doesn't block and yet doesn't
   return a packet (due to being in non-blocking mode), it hoses the
   socket in some way.  Any later call to recvfrom() that returns a
   valid packet fails to write the sender's network address in the
   sockaddr stucture that was passed to recvfrom().  Any number of
   correctly matched SEND() - RECV pairs (i.e. SEND() comes before RECV)
   can be inserted above the extra RECV with the same results
   occurring.  I have cut this example to the bone in the hopes that
   people will look at it.  Thanks to you if you do take the time. */

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/ioctl.h>

struct sockaddr_in a = {AF_INET, 0xf1f1};
struct sockaddr_in rcv = {AF_INET, 0xf1f1};
int s, rcvsize = sizeof rcv, one = 1;
char m[80];

#define ERROR(a) do { perror (a); exit (1); } while (0)
#define SEND(m) if (sendto (s,m,sizeof m,0,&a,sizeof a)==-1) ERROR ("sendto");
#define RECV rcv.sin_addr.S_un.S_addr = 0; m[0] = '\0'; \
		recvfrom (s, m, sizeof m, 0, &rcv, &rcvsize); \
		printf ("%d %s\n", rcv.sin_addr.S_un.S_addr, m)

int main ()
{
  if ((s = socket (AF_INET, SOCK_DGRAM, 0)) == -1) ERROR ("socket");

  if (bind (s, &a, sizeof a) == -1) ERROR ("bind");

  if (ioctl (s, FIONBIO, (char *) &one) == -1) ERROR ("ioctl");

  SEND ("hello1"); 
  RECV; /* AND PRINT NETWORK ADDRESS OF SENDER AND MESSAGE */
  RECV; /* THIS RECV DOESN'T FIND ANYTHING BUT DOESN'T BLOCK */
  SEND ("hello2"); /* QUEUE UP ONE MORE MESSAGE ON OUR SOCKET */
  RECV; /* BOGUS NETWORK ADDRESS OF SENDER IS PRINTED! */

  return 0;
}

/* Output from a DECstation 5100 running Ultrix 4.2A:

   rittle@supra 631> uname -a
   ULTRIX supra 4.2 0 RISC
   rittle@supra 632> gcc test2.c   # c89 and cc output session similar.
   rittle@supra 633> a.out
   676331921 hello1
   0
   0 hello2

  Output from a Sun running SunOS 4.1.2 looked similar:

  56> uname -a
  SunOS asun 4.1.2 1 sun4c
  57> cc test2.c -ldl
  58> a.out
  2130706433 hello1
  0
  0 hello2

  It seems to me that the correct output (for my machine) should be:
  676331921 hello1   # 676331921 is 145.1.80.40 - my machine's IP address BTW...
  0
  676331921 hello2

  Anyone have a clue as to what is going on?  Did I find a bug that afflicts
  many versions of BSD UNIX, or is my code or thought process buggy? */
--
"I really doubt it," he said, "it's far more likely he was bumped off by
 someone on the net." - The rumors of Mark's death are greatly exaggerated.