[Search for users] [Overall Top Noters] [List of all Conferences] [Download this site]

Conference smurf::dec_mls_plus

Title:dec_mls_plus
Moderator:SMURF::BAT
Created:Mon Nov 29 1993
Last Modified:Fri Jun 06 1997
Last Successful Update:Fri Jun 06 1997
Number of topics:534
Total number of notes:2544

501.0. "ECONNABORTED destroys tcp socket" by NNTPD::"jm@uvo.dec.com" (John McNulty) Fri May 09 1997 09:31

Folks,

This is happening on a V3.1a system.

Below is a description of a problem from a customer and two source files
which can reproduce the problem.  Apparently, the socket is only destroyed
with tcp, but the same scenario (and error) doesn't destroy the socket
when using udp.   

Can someone explain this behaviour please?  Is this a bug?

Regards,

John

       ------------------------------------------------------------

Attached are two source files, 'server.c' and 'client.c'.  See the
comments at the top of the files for compilation/privilege stuff.

In a window, run 'server', you'll get:

	about to call select()...

In another window, run 'client `uname -n`', you'll get:

	connecting to matelot...
	about to write...
	about to read...
	read() failed with 53			*****
	Software caused connection abort	*****
	about to write...
	Broken pipe				*****

in 'server' window, you'll get:

	read on fd 3
	handle_client_connect()...
	about to call select()...
	read on fd 4
	handle_client_message() on 4
	read 64 bytes
	about to call select()...
	read on fd 4
	handle_client_message() on 4
	read() failed
	about to call select()...
	read on fd 4
	handle_client_message() on 4
	handle_client_disconnect() on 4
	about to call select()...

The receipt of a message from the server whose sensitivity label
dominates that of the client causes the client's read() to fail with
ECONNABORTED and the connection to be destroyed - if the client attempts
to use the connection again, it fails with 'Broken pipe'.

Is this behaviour correct?  What I'd _like_ to happen is that the
client's read() fails but the connection itself is left intact so that
the client can carry on using it to communicate with the server. 

Hope this is clear.

       ------------------------------------------------------------

/*
 * server.c
 *
 * compile with 'cc -o server server.c -lsecurity -lnet'
 *
 * Needs allowmacaccess potential priv
 *
 */
#include <cmw.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <tnet_attrs.h>
#include <mandatory.h>
#include <prot.h>

/* Stuff that appears to be missing from any DEC MLS+ header files! */
int setslabel(mand_ir_t *ir);
int sec_push_proc_attr(ilb_ir_t *inf, mand_ir_t *sen, priv_t *add,
		       priv_t *sub);
int sec_pop_proc_attr(void);
int select(int, fd_set *, fd_set *, fd_set *, struct timeval *);

#define PORT 9000

struct {
  void (*rfn)(int);
  void (*efn)(int);
} dispatch_table[10];

fd_set rset;

static void handle_client_disconnect(int fd) {
  fprintf(stderr, "handle_client_disconnect() on %d\n", fd);
  
  close(fd);
  FD_CLR(fd, &rset);
}

static void handle_client_message(int fd) {
  char buff[1024];
  int bytesread;
  
  fprintf(stderr, "handle_client_message() on %d\n", fd);

  switch (bytesread = read(fd, buff, sizeof(buff))) {
    case -1:
      fprintf(stderr, "read() failed\n");
      break;
    case 0:
      handle_client_disconnect(fd);
      break;
    default:
      fprintf(stderr, "read %d bytes\n", bytesread);
      /* Send a response */
      {
	char buff[64];
	/* Do a normal send, sensitivity label will match process's */
	if (send(fd, buff, sizeof(buff), 0) == -1)
	  fprintf(stderr, "send() failed\n");
      }
      break;
  }
}

static void handle_client_connect(int fd) {
  int act_fd;
  struct sockaddr_in sact_addr;  /* active socket */
  int sact_len = sizeof(sact_addr);

  fprintf(stderr, "handle_client_connect()...\n");
  
  /* set up a new socket to the client */
  if ((act_fd = accept(fd, (struct sockaddr *)&sact_addr, &sact_len)) < 0)
    fprintf(stderr, "accept() failed\n");
  else {
    FD_SET(act_fd, &rset);
    dispatch_table[act_fd].rfn = handle_client_message;
    dispatch_table[act_fd].efn = handle_client_disconnect;
  }
}

int main(int argc, char *argv[]) {
  int fd;

  sec_push_proc_attr(0, 0, privvec(SEC_ALLOWMACACCESS, -1), 0);
  {
    /* Wind our sensitivity label up to System High */
    mand_init();
    if (setslabel(mand_syshi) == -1)
      fprintf(stderr, "setslabel() failed\n");
  }
  sec_pop_proc_attr();
  
  /* create socket */
  if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
    fprintf(stderr, "socket() failed\n");
    abort();
  }

  /* bind to the server's port */
  {
    struct sockaddr_in sin;
    memset(&sin, 0, sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = htonl(INADDR_ANY);
    sin.sin_port = htons(PORT);
    if (bind(fd, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
      fprintf(stderr, "bind() failed\n");
      abort();
    }   
  }

  if (listen(fd, 5) < 0) {
    fprintf(stderr, "listen() failed\n");
    abort();
  }

  dispatch_table[fd].rfn = handle_client_connect;
  
  FD_ZERO(&rset);
  FD_SET(fd, &rset);

  while (1) {
    fd_set rset1 = rset;
    fd_set eset = rset;
      
    fprintf(stderr, "about to call select()...\n");
    switch (select(10, &rset1, 0, &eset, 0)) {
      case -1:
	fprintf(stderr, "select() failed\n");
	break;
      case 0:
	fprintf(stderr, "select() timed out\n");
	break;
      default:
	{
	  int i;
	  for (i = 0; i < 10; i++) {
	    if (FD_ISSET(i, &eset)) {
	      fprintf(stderr, "error on fd %d\n", i);
	      dispatch_table[i].efn(i);
	    }
	    if (FD_ISSET(i, &rset1)) {
	      fprintf(stderr, "read on fd %d\n", i);
	      dispatch_table[i].rfn(i);
	    }
	  }
	}
	break;
    }	  
  }
  
  return (0);
}

       ------------------------------------------------------------

/*
 * client.c
 *
 * compile with 'cc -o client client.c'
 *
 */
#include <cmw.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <tnet_attrs.h>
#include <sys/secnet.h>
#include <sys/sec_sockopts.h>

#define PORT 9000

static int connect_to_server(const char *machine) {
  int fd;

  fprintf(stderr, "connecting to %s...\n", machine);
  
  /* create socket */
  if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
    fprintf(stderr, "socket() failed\n");
    abort();
  }
  
  /* connect to the server */
  {
    struct sockaddr_in sin;
    struct hostent *host;
    if (!(host = gethostbyname(machine))) {
      fprintf(stderr, "gethostbyname() failed for '%s'\n", machine);
      abort();
    }
    memset(&sin, 0, sizeof(sin));
    sin.sin_family = host->h_addrtype;
    memcpy(&sin.sin_addr, host->h_addr, host->h_length);
    sin.sin_port = htons(PORT);

    if (connect(fd, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
      fprintf(stderr, "connect() failed\n");
      abort();
    }
  }

  return (fd);
}

int main(int argc, char *argv[]) {
  int fd;

  if (argc < 2) {
    fprintf(stderr, "usage: %s <host_name>\n", argv[0]);
    exit(1);
  }

  fd = connect_to_server(argv[1]);
  
  while (1) {
    fprintf(stderr, "about to write...\n");
    {
      char buff[64];
      int written;

      written = write(fd, buff, sizeof(buff));
      
      if (written == -1)
	fprintf(stderr, "write() failed\n");
      else {
	fprintf(stderr, "about to read...\n");
	{
	  char buff[64];
	  int bytesread;
  
	  switch (bytesread = read(fd, buff, sizeof(buff))) {
	    case -1:
	      fprintf(stderr, "read() failed with %d\n", errno);
	      perror("");
	      break;
	    case 0:
	      fprintf(stderr, "parent closed pipe?\n");
	      break;
	    default:
	      fprintf(stderr, "read %d bytes\n", bytesread);
	      break;
	  }
	}
      }
    }
  }
  
  return (0);
}

[Posted by WWW Notes gateway]
T.RTitleUserPersonal
Name
DateLines
501.1quick guess--not guaranteedSMURF::BATSegui la tua beatitudineMon May 12 1997 16:0514
    My quick guess is because of the send on a file descriptor,
    but I've not studied it (see submit request 6255 in
    ~cmosf/Mail/Approve)
    
    They could rewrite the send call to not use a file descriptor to see if
    that is the problem.
    
    If your customer is not running the latest patch level, then I'm not
    sure if they selectively put on those modules from the latest patch
    kit, that it will be "healthy".  It would take some time to investigate
    (as I recall they are running only to patch level 6?); I could put it
    on my queue, but I won't be getting to it for a while.... if you want
    to volunteer...