Beispiel #1
0
/*!
 * Read DSI command and data
 *
 * @param  dsi   (rw) DSI handle
 *
 * @return    DSI function on success, 0 on failure
 */
int dsi_stream_receive(DSI *dsi)
{
  char block[DSI_BLOCKSIZ];

  LOG(log_maxdebug, logtype_dsi, "dsi_stream_receive: START");

  if (dsi->flags & DSI_DISCONNECTED)
      return 0;

  /* read in the header */
  if (dsi_buffered_stream_read(dsi, (uint8_t *)block, sizeof(block)) != sizeof(block)) 
    return 0;

  dsi->header.dsi_flags = block[0];
  dsi->header.dsi_command = block[1];

  if (dsi->header.dsi_command == 0)
      return 0;

  memcpy(&dsi->header.dsi_requestID, block + 2, sizeof(dsi->header.dsi_requestID));
  memcpy(&dsi->header.dsi_code, block + 4, sizeof(dsi->header.dsi_code));
  memcpy(&dsi->header.dsi_len, block + 8, sizeof(dsi->header.dsi_len));
  memcpy(&dsi->header.dsi_reserved, block + 12, sizeof(dsi->header.dsi_reserved));
  dsi->clientID = ntohs(dsi->header.dsi_requestID);
  
  /* make sure we don't over-write our buffers. */
  dsi->cmdlen = MIN(ntohl(dsi->header.dsi_len), dsi->server_quantum);
  if (dsi_stream_read(dsi, dsi->commands, dsi->cmdlen) != dsi->cmdlen) 
    return 0;

  LOG(log_debug, logtype_dsi, "dsi_stream_receive: DSI cmdlen: %zd", dsi->cmdlen);

  return block[1];
}
Beispiel #2
0
/*
 * Get "length" bytes from buffer and/or socket. In order to avoid frequent small reads
 * this tries to read larger chunks (8192 bytes) into a buffer.
 */
static size_t dsi_buffered_stream_read(DSI *dsi, uint8_t *data, const size_t length)
{
  size_t len;
  size_t buflen;

  LOG(log_maxdebug, logtype_dsi, "dsi_buffered_stream_read: %u bytes", length);
  
  len = from_buf(dsi, data, length); /* read from buffer dsi->buffer */
  dsi->read_count += len;
  if (len == length) {          /* got enough bytes from there ? */
      return len;               /* yes */
  }

  /* fill the buffer with 8192 bytes or until buffer is full */
  buflen = MIN(8192, dsi->end - dsi->eof);
  if (buflen > 0) {
      ssize_t ret;
      ret = recv(dsi->socket, dsi->eof, buflen, 0);
      if (ret > 0)
          dsi->eof += ret;
  }

  /* now get the remaining data */
  if ((buflen = dsi_stream_read(dsi, data + len, length - len)) != length - len)
      return 0;
  len += buflen;

  return len;
}
Beispiel #3
0
/* fill up buf and then return. this should be called repeatedly
 * until all the data has been read. i block alarm processing 
 * during the transfer to avoid sending unnecessary tickles. */
size_t dsi_write(DSI *dsi, void *buf, const size_t buflen)
{
  size_t length;

  if (((length = MIN(buflen, dsi->datasize)) > 0) &&
      ((length = dsi_stream_read(dsi, buf, length)) > 0)) {
    dsi->datasize -= length;
    return length;
  }
  return 0;
}
Beispiel #4
0
/* flush any unread buffers. */
void dsi_writeflush(DSI *dsi)
{
  size_t length;

  while (dsi->datasize > 0) { 
    length = dsi_stream_read(dsi, dsi->data,
			     MIN(sizeof(dsi->data), dsi->datasize));
    if (length > 0)
      dsi->datasize -= length;
    else
      break;
  }
}
Beispiel #5
0
/* ---------------------------------------
 * read data. function on success. 0 on failure. data length gets
 * stored in length variable. this should really use size_t's, but
 * that would require changes elsewhere. */
int dsi_stream_receive(DSI *dsi, void *buf, const size_t ilength,
		       size_t *rlength)
{
  char block[DSI_BLOCKSIZ];

  LOG(log_maxdebug, logtype_dsi, "dsi_stream_receive: %u bytes", ilength);

  if (dsi->flags & DSI_DISCONNECTED)
      return 0;

  /* read in the header */
  if (dsi_buffered_stream_read(dsi, (u_int8_t *)block, sizeof(block)) != sizeof(block)) 
    return 0;

  dsi->header.dsi_flags = block[0];
  dsi->header.dsi_command = block[1];
  /* FIXME, not the right place, 
     but we get a server disconnect without reason in the log
  */
  if (!block[1]) {
      LOG(log_error, logtype_dsi, "dsi_stream_receive: invalid packet, fatal");
      return 0;
  }

  memcpy(&dsi->header.dsi_requestID, block + 2, 
	 sizeof(dsi->header.dsi_requestID));
  memcpy(&dsi->header.dsi_code, block + 4, sizeof(dsi->header.dsi_code));
  memcpy(&dsi->header.dsi_len, block + 8, sizeof(dsi->header.dsi_len));
  memcpy(&dsi->header.dsi_reserved, block + 12,
	 sizeof(dsi->header.dsi_reserved));
  dsi->clientID = ntohs(dsi->header.dsi_requestID);
  
  /* make sure we don't over-write our buffers. */
  *rlength = min(ntohl(dsi->header.dsi_len), ilength);
  if (dsi_stream_read(dsi, buf, *rlength) != *rlength) 
    return 0;

  return block[1];
}
Beispiel #6
0
/* accept the socket and do a little sanity checking */
static int dsi_tcp_open(DSI *dsi)
{
    pid_t pid;
    SOCKLEN_T len;

    len = sizeof(dsi->client);
    dsi->socket = accept(dsi->serversock, (struct sockaddr *) &dsi->client, &len);

#ifdef TCPWRAP
    {
        struct request_info req;
        request_init(&req, RQ_DAEMON, dsi->program, RQ_FILE, dsi->socket, NULL);
        fromhost(&req);
        if (!hosts_access(&req)) {
            LOG(deny_severity, logtype_dsi, "refused connect from %s", eval_client(&req));
            close(dsi->socket);
            errno = ECONNREFUSED;
            dsi->socket = -1;
        }
    }
#endif /* TCPWRAP */

    if (dsi->socket < 0)
        return -1;

    getitimer(ITIMER_PROF, &itimer);
    if (0 == (pid = fork()) ) { /* child */
        static struct itimerval timer = {{0, 0}, {DSI_TCPTIMEOUT, 0}};
        struct sigaction newact, oldact;
        u_int8_t block[DSI_BLOCKSIZ];
        size_t stored;

        /* Immediateyl mark globally that we're a child now */
        parent_or_child = 1;

        /* reset signals */
        server_reset_signal();

#ifndef DEBUGGING
        /* install an alarm to deal with non-responsive connections */
        newact.sa_handler = timeout_handler;
        sigemptyset(&newact.sa_mask);
        newact.sa_flags = 0;
        sigemptyset(&oldact.sa_mask);
        oldact.sa_flags = 0;
        setitimer(ITIMER_PROF, &itimer, NULL);

        if ((sigaction(SIGALRM, &newact, &oldact) < 0) ||
            (setitimer(ITIMER_REAL, &timer, NULL) < 0)) {
            LOG(log_error, logtype_dsi, "dsi_tcp_open: %s", strerror(errno));
            exit(EXITERR_SYS);
        }
#endif

        /* read in commands. this is similar to dsi_receive except
         * for the fact that we do some sanity checking to prevent
         * delinquent connections from causing mischief. */

        /* read in the first two bytes */
        len = dsi_stream_read(dsi, block, 2);
        if (!len ) {
            /* connection already closed, don't log it (normal OSX 10.3 behaviour) */
            exit(EXITERR_CLNT);
        }
        if (len < 2 || (block[0] > DSIFL_MAX) || (block[1] > DSIFUNC_MAX)) {
            LOG(log_error, logtype_dsi, "dsi_tcp_open: invalid header");
            exit(EXITERR_CLNT);
        }

        /* read in the rest of the header */
        stored = 2;
        while (stored < DSI_BLOCKSIZ) {
            len = dsi_stream_read(dsi, block + stored, sizeof(block) - stored);
            if (len > 0)
                stored += len;
            else {
                LOG(log_error, logtype_dsi, "dsi_tcp_open: stream_read: %s", strerror(errno));
                exit(EXITERR_CLNT);
            }
        }

        dsi->header.dsi_flags = block[0];
        dsi->header.dsi_command = block[1];
        memcpy(&dsi->header.dsi_requestID, block + 2,
               sizeof(dsi->header.dsi_requestID));
        memcpy(&dsi->header.dsi_code, block + 4, sizeof(dsi->header.dsi_code));
        memcpy(&dsi->header.dsi_len, block + 8, sizeof(dsi->header.dsi_len));
        memcpy(&dsi->header.dsi_reserved, block + 12,
               sizeof(dsi->header.dsi_reserved));
        dsi->clientID = ntohs(dsi->header.dsi_requestID);

        /* make sure we don't over-write our buffers. */
        dsi->cmdlen = min(ntohl(dsi->header.dsi_len), DSI_CMDSIZ);

        stored = 0;
        while (stored < dsi->cmdlen) {
            len = dsi_stream_read(dsi, dsi->commands + stored, dsi->cmdlen - stored);
            if (len > 0)
                stored += len;
            else {
                LOG(log_error, logtype_dsi, "dsi_tcp_open: stream_read: %s", strerror(errno));
                exit(EXITERR_CLNT);
            }
        }

        /* stop timer and restore signal handler */
#ifndef DEBUGGING
        memset(&timer, 0, sizeof(timer));
        setitimer(ITIMER_REAL, &timer, NULL);
        sigaction(SIGALRM, &oldact, NULL);
#endif

        LOG(log_info, logtype_dsi, "AFP/TCP session from %s:%u",
            getip_string((struct sockaddr *)&dsi->client),
            getip_port((struct sockaddr *)&dsi->client));
    }

    /* send back our pid */
    return pid;
}