Example #1
0
/*! Receive message from queue (global or from own thread message queue) */
int sys__msg_recv ( void *p )
{
	/* parameters on thread stack */
	int src_type;	/* MSG_QUEUE or MSG_THREAD 		*/
	void *src;	/* (msg_q *) or (thread_t *)		*/
	msg_t *msg;	/* { type, size, data[0..size-1] }	*/
	int type;	/* message type (identifier) */
	size_t size;	/* size of 'data' member */
	uint flags;
	/* local variables */
	kthread_t *kthr;
	kthrmsg_qs *thrmsg;
	kgmsg_q *kgmsgq;
	kmsg_q *kmsgq;
	msg_q *msgq;
	kmsg_t *kmsg;

	src_type = *( (int *) p );	p += sizeof (int);
	src = *( (void **) p );		p += sizeof (void *);
	msg = *( (msg_t **) p );	p += sizeof (msg_t *);
	type = *( (int *) p );		p += sizeof (int);
	size = *( (size_t *) p );	p += sizeof (size_t);
	flags = *( (uint *) p );

	ASSERT_ERRNO_AND_EXIT ( src && msg, E_INVALID_HANDLE );

	ASSERT_ERRNO_AND_EXIT ( src_type == MSG_THREAD || src_type == MSG_QUEUE,
				E_INVALID_TYPE );

	if ( src_type == MSG_THREAD )
	{
		kthr = k_get_active_thread ();
		thrmsg = k_get_thrmsg ( kthr );
		kmsgq = &thrmsg->msgq;
	}
	else { /* src_type == MSG_QUEUE */
		msgq = src;
		kgmsgq = msgq->handle;
		ASSERT_ERRNO_AND_EXIT ( kgmsgq && kgmsgq->id == msgq->id,
					E_INVALID_HANDLE );
		kmsgq = &kgmsgq->mq;
	}

	/* get first message from queue */
	kmsg = list_get ( &kmsgq->msgs, FIRST );

	if ( type != 0 ) /* type != 0 => search for first message 'type' */
		while ( kmsg && kmsg->msg.type != type )
			kmsg = list_get_next ( &kmsg->list );

	if ( kmsg ) /* have message */
	{
		if ( size < kmsg->msg.size )
		{
			msg->size = 0;
			EXIT ( E_TOO_BIG );
		}

		msg->type = kmsg->msg.type;
		msg->size = kmsg->msg.size;
		memcpy ( msg->data, kmsg->msg.data, msg->size );

		kmsg = list_remove ( &kmsgq->msgs, FIRST, &kmsg->list );
		ASSERT ( kmsg );
		kfree ( kmsg );

		EXIT ( SUCCESS );
	}
	else { /* queue empty! */
		if ( !( flags & IPC_WAIT ) )
			EXIT ( E_EMPTY );

		SET_ERRNO ( E_RETRY );
		/* block thread */
		k_enqueue_thread ( NULL, &kmsgq->thrq );

		k_schedule_threads ();

		RETURN ( E_RETRY );
	}
}
Example #2
0
File: pap_read.c Project: OTiZ/osx
int
pap_read(int fd, u_char *data, int len)
{
	SET_ERRNO(ENXIO);
	return (-1);
}
Example #3
0
int
assemble_rmcp_pkt (fiid_obj_t obj_rmcp_hdr,
                   fiid_obj_t obj_cmd,
                   void *pkt,
                   unsigned int pkt_len,
		   unsigned int flags)
{
  int obj_cmd_len, obj_rmcp_hdr_len;
  unsigned int flags_mask = 0;

  if (!fiid_obj_valid (obj_rmcp_hdr)
      || !fiid_obj_valid (obj_cmd)
      || !pkt
      || !pkt_len
      || (flags & ~flags_mask))
    {
      SET_ERRNO (EINVAL);
      return (-1);
    }

  if (FIID_OBJ_TEMPLATE_COMPARE (obj_rmcp_hdr, tmpl_rmcp_hdr) < 0)
    {
      ERRNO_TRACE (errno);
      return (-1);
    }

  if (FIID_OBJ_PACKET_VALID (obj_rmcp_hdr) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_rmcp_hdr);
      return (-1);
    }
  if (FIID_OBJ_PACKET_VALID (obj_cmd) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd);
      return (-1);
    }

  if ((obj_rmcp_hdr_len = fiid_obj_len_bytes (obj_rmcp_hdr)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_rmcp_hdr);
      return (-1);
    }
  if ((obj_cmd_len = fiid_obj_len_bytes (obj_cmd)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd);
      return (-1);
    }

  if (pkt_len < (obj_rmcp_hdr_len + obj_cmd_len))
    {
      SET_ERRNO (EMSGSIZE);
      return (-1);
    }

  memset (pkt, '\0', pkt_len);
  if ((obj_rmcp_hdr_len = fiid_obj_get_all (obj_rmcp_hdr,
                                            pkt,
                                            pkt_len)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_rmcp_hdr);
      return (-1);
    }
  if ((obj_cmd_len = fiid_obj_get_all (obj_cmd,
                                       pkt + obj_rmcp_hdr_len,
                                       pkt_len - obj_rmcp_hdr_len)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd);
      return (-1);
    }

  return (obj_rmcp_hdr_len + obj_cmd_len);
}
Example #4
0
static int fuse_operations_mount_open(struct MountsPublicInterface* this_, const char* path, int oflag, uint32_t mode) {
    int ret=-1;
    int fd=-1;
    struct FuseOperationsMount* fs = (struct FuseOperationsMount*)this_;
    struct stat st;
    struct stat st_parent;
    int file_exist;

    CHECK_FUNC_ENSURE_EXIST(fs, open);

    file_exist=fs->fuse_operations->getattr(path, &st);

    /*file exist, do checks of O_CREAT, O_EXCL flags*/
    if ( !file_exist && CHECK_FLAG(oflag, O_CREAT) && CHECK_FLAG(oflag, O_EXCL) ) {
        SET_ERRNO(EEXIST);
        return -1;
    }
    /*truncate existing writable file*/
    if ( !file_exist && CHECK_FLAG(oflag, O_TRUNC) &&
            (CHECK_FLAG(oflag, O_WRONLY) || CHECK_FLAG(oflag, O_RDWR)) ) {
        CHECK_FUNC_ENSURE_EXIST(fs, truncate);
        if ( (ret=fs->fuse_operations->truncate(path, 0)) <0 ) {
            /*truncate error*/
            SET_ERRNO(-ret);
            return -1;
        }
    }

    /*create fuse object, it must be attached into ofd entry or be
      destroyed if zrt would not be able to return file handle*/
    struct fuse_file_info *finfo = calloc(1, sizeof(struct fuse_file_info));
    /*reset flags that should not be passed to fuse's open*/
    finfo->flags = oflag & ~(O_CREAT|O_TRUNC|O_EXCL);

    /*is file exist?*/
    if (!file_exist) {
        if ( (ret=fs->fuse_operations->open(path, finfo)) <0 ) {
            SET_ERRNO(-ret);
        }
    }
    else {
        /*file does not exist, create & open it*/
        if ( CHECK_FLAG(oflag, O_CREAT) ) {
            CHECK_FUNC_ENSURE_EXIST(fs, create);
            if ( (ret=fs->fuse_operations->create(path, mode, finfo)) <0 ) {
                SET_ERRNO(-ret);
            }
        }
    }

    /*if path open/create success*/
    if ( ! ret ) {
        int open_file_description_id;
        if ( fs->proxy_mode == EFuseProxyModeDisabled ) {
            /*in case if fs works in generic mode it use own handles
              stored in finfo->fh, so we need to issue a global fd
              visible across system*/
            open_file_description_id = get_open_files_pool()->getnew_ofd(oflag);
            fd = fs->handle_allocator->allocate_handle(this_,
                    st.st_ino, st_parent.st_ino,
                    open_file_description_id);
            if ( fd < 0 ) {
                /*it's hipotetical but possible case if amount of open files
                  are exceeded an maximum value.*/
                fs->open_files_pool->release_ofd(open_file_description_id);
                SET_ERRNO(ENFILE);
            }
        }
        else if ( fs->proxy_mode == EFuseProxyModeEnabled) {
            /*proxy mode is enabled, so open already returned actual
              fd, therefore do not issue a new one and use returned*/
            fd = finfo->fh;
            const struct HandleItem *hentry = fs->handle_allocator->entry(finfo->fh);
            if (hentry!=NULL)
                open_file_description_id = hentry->open_file_description_id;
            else {
                ZRT_LOG(L_ERROR,
                        "can't open '%s' due to handle=%lld returned from fuse fs has no HandleEntry",
                        path, finfo->fh );
                SET_ERRNO(EINVAL);
            }
        }
        else {
            assert(0);
        }

        /*successfully opened, save fuse data*/
        struct FuseFileOptionalData *fdata = malloc( sizeof(struct FuseFileOptionalData) );
        fs->open_files_pool->set_optional_data( open_file_description_id, (intptr_t)fdata );
        fdata->path = strdup(path);
        fdata->finfo = finfo;

        return fd;
    }
    else {
        free(finfo);
        return -1;
    }
}
Example #5
0
asmlinkage int pthread_create_sys (pthread_t *thread, 
				   const pthread_attr_t *attr,
                                   void *(*startup)(void *),
				   void *(*start_routine)(void *), 
				   void *args) {
  int flags;

  hw_save_flags_and_cli (flags);


  // Check policy & prio
  if (attr) {
    if (attr->policy != SCHED_FIFO) {
      SET_ERRNO(EINVAL);
      return -1;
    } else {

      if (attr -> sched_param.sched_priority > MIN_SCHED_PRIORITY ||
	  attr -> sched_param.sched_priority < MAX_SCHED_PRIORITY) {
	SET_ERRNO(EINVAL);
	return -1;
      }
    }
  }

  // Creating the pthread structure
  if (!(*thread = create_pthread_struct ())) {
    SET_ERRNO (EAGAIN);
    hw_restore_flags (flags);
    return -1;
  }
  
  /* 
   * Configuring the new thread either with attr (if not NULL)
   * or with the default values
   */
  if (attr) {
    (*thread) -> sched_param = attr -> sched_param;    
    (*thread) -> stack_info.stack_size = attr -> stack_size;
    (*thread) -> stack_info.stack_bottom = attr -> stack_addr;
    SET_THREAD_DETACH_STATE((*thread), attr -> detachstate);
    SET_THREAD_POLICY ((*thread), attr -> policy);
  } else {
    (*thread) -> sched_param.sched_priority = MIN_SCHED_PRIORITY;
    (*thread) -> stack_info.stack_size = STACK_SIZE;
    (*thread) -> stack_info.stack_bottom = 0;
    SET_THREAD_DETACH_STATE((*thread), 0);
    SET_THREAD_POLICY ((*thread), SCHED_FIFO);
  }

  if (!((*thread) -> stack_info.stack_bottom)) {
    // Creating the thread stack
    if (alloc_stack (&(*thread) -> stack_info) < 0) {
      SET_ERRNO (EAGAIN);
      hw_restore_flags (flags);
      return -1;
    }
  }

  // This is arhictecture dependent
  (*thread) -> stack = setup_stack ((*thread)->stack_info.stack_bottom +
				    (*thread)->stack_info.stack_size 
				    / sizeof (int),
                                    startup,
                                    start_routine, args);

  activate_thread (*thread);
  pthread_t tmp = *thread;
  printf("pthred_create_sys thread 0x%x state:%d\n", (unsigned long)tmp, GET_THREAD_STATE(tmp));

  // no error at all
  hw_restore_flags (flags);

  // Calling the scheduler
  scheduling ();
  return 0;
}
Example #6
0
int
unassemble_ipmi_lan_pkt (const void *pkt,
                         unsigned int pkt_len,
                         fiid_obj_t obj_rmcp_hdr,
                         fiid_obj_t obj_lan_session_hdr,
                         fiid_obj_t obj_lan_msg_hdr,
                         fiid_obj_t obj_cmd,
                         fiid_obj_t obj_lan_msg_trlr,
			 unsigned int flags)
{
  uint8_t authentication_type;
  unsigned int indx = 0;
  unsigned int obj_cmd_len;
  int obj_lan_msg_trlr_len, len;
  uint64_t val;
  unsigned int flags_mask = (IPMI_INTERFACE_FLAGS_NO_LEGAL_CHECK);

  if (!pkt
      || !fiid_obj_valid (obj_rmcp_hdr)
      || !fiid_obj_valid (obj_lan_session_hdr)
      || !fiid_obj_valid (obj_lan_msg_hdr)
      || !fiid_obj_valid (obj_cmd)
      || !fiid_obj_valid (obj_lan_msg_trlr)
      || (flags & ~flags_mask))
    {
      SET_ERRNO (EINVAL);
      return (-1);
    }

  if (FIID_OBJ_TEMPLATE_COMPARE (obj_rmcp_hdr, tmpl_rmcp_hdr) < 0)
    {
      ERRNO_TRACE (errno);
      return (-1);
    }
  if (FIID_OBJ_TEMPLATE_COMPARE (obj_lan_session_hdr, tmpl_lan_session_hdr) < 0)
    {
      ERRNO_TRACE (errno);
      return (-1);
    }
  if (FIID_OBJ_TEMPLATE_COMPARE (obj_lan_msg_hdr, tmpl_lan_msg_hdr_rs) < 0)
    {
      ERRNO_TRACE (errno);
      return (-1);
    }
  if (FIID_OBJ_TEMPLATE_COMPARE (obj_lan_msg_trlr, tmpl_lan_msg_trlr) < 0)
    {
      ERRNO_TRACE (errno);
      return (-1);
    }

  indx = 0;
  if (fiid_obj_clear (obj_rmcp_hdr) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_rmcp_hdr);
      return (-1);
    }

  if (fiid_obj_clear (obj_lan_session_hdr) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_session_hdr);
      return (-1);
    }

  if (fiid_obj_clear (obj_lan_msg_hdr) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_msg_hdr);
      return (-1);
    }
  
  if (fiid_obj_clear (obj_cmd) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd);
      return (-1);
    }

  if (fiid_obj_clear (obj_lan_msg_trlr) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_msg_trlr);
      return (-1);
    }

  if ((len = fiid_obj_set_all (obj_rmcp_hdr, pkt + indx, pkt_len - indx)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_rmcp_hdr);
      return (-1);
    }
  indx += len;

  if (pkt_len <= indx)
    {
      /* cannot parse packet */
      ERR_TRACE ("malformed packet", EINVAL);
      return (0);
    }

  if ((len = fiid_obj_set_block (obj_lan_session_hdr,
                                 "authentication_type",
                                 "session_id",
                                 pkt + indx,
                                 pkt_len - indx)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_session_hdr);
      return (-1);
    }
  indx += len;

  if (FIID_OBJ_GET (obj_lan_session_hdr,
                    "authentication_type",
                    &val) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_session_hdr);
      return (-1);
    }
  authentication_type = val;

  if (!IPMI_1_5_AUTHENTICATION_TYPE_VALID (authentication_type))
    {
      /* cannot parse packet */
      ERR_TRACE ("malformed packet", EINVAL);
      return (0);
    }

  if (authentication_type != IPMI_AUTHENTICATION_TYPE_NONE)
    {
      if ((len = fiid_obj_set_data (obj_lan_session_hdr,
                                    "authentication_code",
                                    pkt + indx,
                                    pkt_len - indx)) < 0)
        {
          FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_session_hdr);
          return (-1);
        }
      indx += len;

      if (pkt_len <= indx)
        {
          /* cannot parse packet */
          ERR_TRACE ("malformed packet", EINVAL);
          return (0);
        }
    }

  if ((len = fiid_obj_set_data (obj_lan_session_hdr,
                                "ipmi_msg_len",
                                pkt + indx,
                                pkt_len - indx)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_session_hdr);
      return (-1);
    }
  indx += len;

  if (pkt_len <= indx)
    {
      /* cannot parse packet */
      ERR_TRACE ("malformed packet", EINVAL);
      return (0);
    }

  if ((len = fiid_obj_set_all (obj_lan_msg_hdr, pkt + indx, pkt_len - indx)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_msg_hdr);
      return (-1);
    }
  indx += len;

  if (pkt_len <= indx)
    {
      /* cannot parse packet */
      ERR_TRACE ("malformed packet", EINVAL);
      return (0);
    }

  if ((obj_lan_msg_trlr_len = fiid_template_len_bytes (tmpl_lan_msg_trlr)) < 0)
    {
      ERRNO_TRACE (errno);
      return (-1);
    }

  if ((pkt_len - indx) <= obj_lan_msg_trlr_len)
    {
      /* cannot parse packet */
      ERR_TRACE ("malformed packet", EINVAL);
      return (0);
    }

  obj_cmd_len = (pkt_len - indx) - obj_lan_msg_trlr_len;

  if ((len = fiid_obj_set_all (obj_cmd, pkt + indx, obj_cmd_len)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd);
      return (-1);
    }
  indx += len;

  if (pkt_len <= indx)
    {
      /* cannot parse packet */
      ERR_TRACE ("malformed packet", EINVAL);
      return (0);
    }

  if ((len = fiid_obj_set_all (obj_lan_msg_trlr, pkt + indx, pkt_len - indx)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_msg_trlr);
      return (-1);
    }
  indx += len;
  
  if (FIID_OBJ_PACKET_VALID (obj_rmcp_hdr) == 1
      && FIID_OBJ_PACKET_VALID (obj_lan_session_hdr) == 1
      && FIID_OBJ_PACKET_VALID (obj_lan_msg_hdr) == 1
      && ((flags & IPMI_INTERFACE_FLAGS_NO_LEGAL_CHECK) || FIID_OBJ_PACKET_SUFFICIENT (obj_cmd) == 1)
      && FIID_OBJ_PACKET_VALID (obj_lan_msg_trlr) == 1)
    return (1);

  return (0);
}
int
ipmi_algorithms_to_cipher_suite_id (uint8_t authentication_algorithm,
                                    uint8_t integrity_algorithm,
                                    uint8_t confidentiality_algorithm,
                                    uint8_t *cipher_suite_id)
{
  if (!IPMI_AUTHENTICATION_ALGORITHM_SUPPORTED (authentication_algorithm)
      || !IPMI_INTEGRITY_ALGORITHM_SUPPORTED (integrity_algorithm)
      || !IPMI_CONFIDENTIALITY_ALGORITHM_SUPPORTED (confidentiality_algorithm)
      || !IPMI_CIPHER_SUITE_COMBINATION_VALID (authentication_algorithm,
                                               integrity_algorithm,
                                               confidentiality_algorithm)
      || !cipher_suite_id)
    {
      SET_ERRNO (EINVAL);
      return (-1);
    }

  if (authentication_algorithm == IPMI_AUTHENTICATION_ALGORITHM_RAKP_NONE
      && integrity_algorithm == IPMI_INTEGRITY_ALGORITHM_NONE
      && confidentiality_algorithm == IPMI_CONFIDENTIALITY_ALGORITHM_NONE)
    *cipher_suite_id = 0;
  else if (authentication_algorithm == IPMI_AUTHENTICATION_ALGORITHM_RAKP_HMAC_SHA1)
    {
      if (integrity_algorithm == IPMI_INTEGRITY_ALGORITHM_NONE
          && confidentiality_algorithm == IPMI_CONFIDENTIALITY_ALGORITHM_NONE)
        *cipher_suite_id = 1;
      else /* integrity_algorithm == IPMI_INTEGRITY_ALGORITHM_HMAC_SHA1_96) */
        {
          if (confidentiality_algorithm == IPMI_CONFIDENTIALITY_ALGORITHM_NONE)
            *cipher_suite_id = 2;
          else if (confidentiality_algorithm == IPMI_CONFIDENTIALITY_ALGORITHM_AES_CBC_128)
            *cipher_suite_id = 3;
          else if (confidentiality_algorithm == IPMI_CONFIDENTIALITY_ALGORITHM_XRC4_128)
            *cipher_suite_id = 4;
          else /* confidentiality_algorithm == IPMI_CONFIDENTIALITY_ALGORITHM_XRC4_40 */
            *cipher_suite_id = 5;
        }
    }
  else if (authentication_algorithm == IPMI_INTEGRITY_ALGORITHM_HMAC_MD5_128)
    {
      if (integrity_algorithm == IPMI_INTEGRITY_ALGORITHM_NONE
          && confidentiality_algorithm == IPMI_CONFIDENTIALITY_ALGORITHM_NONE)
        *cipher_suite_id = 6;
      else if (integrity_algorithm == IPMI_INTEGRITY_ALGORITHM_HMAC_MD5_128)
        {
          if (confidentiality_algorithm == IPMI_CONFIDENTIALITY_ALGORITHM_NONE)
            *cipher_suite_id = 7;
          else if (confidentiality_algorithm == IPMI_CONFIDENTIALITY_ALGORITHM_AES_CBC_128)
            *cipher_suite_id = 8;
          else if (confidentiality_algorithm == IPMI_CONFIDENTIALITY_ALGORITHM_XRC4_128)
            *cipher_suite_id = 9;
          else /* confidentiality_algorithm == IPMI_CONFIDENTIALITY_ALGORITHM_XRC4_40 */
            *cipher_suite_id = 10;
        }
      else /* integrity_algorithm == IPMI_INTEGRITY_ALGORITHM_MD5_128 */
        {
          if (confidentiality_algorithm == IPMI_CONFIDENTIALITY_ALGORITHM_NONE)
            *cipher_suite_id = 11;
          else if (confidentiality_algorithm == IPMI_CONFIDENTIALITY_ALGORITHM_AES_CBC_128)
            *cipher_suite_id = 12;
          else if (confidentiality_algorithm == IPMI_CONFIDENTIALITY_ALGORITHM_XRC4_128)
            *cipher_suite_id = 13;
          else /* confidentiality_algorithm == IPMI_CONFIDENTIALITY_ALGORITHM_XRC4_40 */
            *cipher_suite_id = 14;
        }
    }
  else if (authentication_algorithm == IPMI_AUTHENTICATION_ALGORITHM_RAKP_HMAC_SHA256)
    {
      if (integrity_algorithm == IPMI_INTEGRITY_ALGORITHM_NONE
	  && confidentiality_algorithm == IPMI_CONFIDENTIALITY_ALGORITHM_NONE)
	*cipher_suite_id = 15;
      else /* integrity_algorithm == IPMI_INTEGRITY_ALGORITHM_HMAC_SHA256_128 */
	{
          if (confidentiality_algorithm == IPMI_CONFIDENTIALITY_ALGORITHM_NONE)
            *cipher_suite_id = 16;
          else if (confidentiality_algorithm == IPMI_CONFIDENTIALITY_ALGORITHM_AES_CBC_128)
            *cipher_suite_id = 17;
          else if (confidentiality_algorithm == IPMI_CONFIDENTIALITY_ALGORITHM_XRC4_128)
            *cipher_suite_id = 18;
          else /* confidentiality_algorithm == IPMI_CONFIDENTIALITY_ALGORITHM_XRC4_40 */
            *cipher_suite_id = 19;
	}
    }

  return (0);
}
/*!
 * Receive message from queue (global or from own thread message queue)
 */
int sys__msg_recv ( int src_type, void *src, msg_t *msg, int type, size_t size,
		    uint flags )
{
	kthread_t *kthr;
	kthrmsg_qs *thrmsg;
	kgmsg_q *kgmsgq;
	kmsg_q *kmsgq;
	msg_q *msgq;
	kmsg_t *kmsg;

	ASSERT_ERRNO_AND_EXIT ( src && msg, E_INVALID_HANDLE );
	ASSERT_ERRNO_AND_EXIT ( src_type == MSG_THREAD || src_type == MSG_QUEUE,
				E_INVALID_TYPE );

	if ( src_type == MSG_THREAD )
	{
		kthr = k_get_active_thread ();
		thrmsg = k_get_thrmsg ( kthr );
		kmsgq = &thrmsg->msgq;
	}
	else { /* src_type == MSG_QUEUE */
		msgq = src;
		kgmsgq = msgq->handle;
		ASSERT_ERRNO_AND_EXIT ( kgmsgq && kgmsgq->id == msgq->id,
					E_INVALID_HANDLE );
		kmsgq = &kgmsgq->mq;
	}

	/* get first message from queue */
	kmsg = list_get ( &kmsgq->msgs, FIRST );

	if ( type != 0 ) /* type != 0 => search for first message 'type' */
		while ( kmsg && kmsg->msg.type != type )
			kmsg = list_get_next ( &kmsg->list );

	if ( kmsg ) /* have message */
	{
		if ( size < kmsg->msg.size )
		{
			msg->size = 0;
			EXIT ( E_TOO_BIG );
		}

		msg->type = kmsg->msg.type;
		msg->size = kmsg->msg.size;
		memcpy ( msg->data, kmsg->msg.data, msg->size );

		kmsg = list_remove ( &kmsgq->msgs, FIRST, &kmsg->list );
		ASSERT ( kmsg );
		kfree ( kmsg );

		EXIT ( SUCCESS );
	}
	else { /* queue empty! */
		if ( !( flags & IPC_WAIT ) )
			EXIT ( E_EMPTY );

		SET_ERRNO ( E_RETRY );
		/* block thread */
		k_enqueue_thread ( NULL, &kmsgq->thrq );

		k_schedule_threads ();

		RETURN ( E_RETRY );
	}
}
Example #9
0
/*!
 * Start new process
 * \param prog_name Program name (as given with module)
 * \param thr_desc Pointer to thread descriptor (user) for starting thread
 * \param param Command line arguments for starting thread (if not NULL)
 * \param prio Priority for starting thread
 */
int sys__start_program ( void *p )
{
	char *prog_name;
	void *param;
	int prio;
	thread_t *thr_desc;
	kthread_t *kthr, *cur = active_thread;
	char *arg, *karg, **args, **kargs = NULL;
	int argnum, argsize;

	prog_name = *( (void **) p ); p += sizeof (void *);
	ASSERT_ERRNO_AND_EXIT ( prog_name, E_INVALID_HANDLE );

	prog_name = U2K_GET_ADR ( prog_name, cur->proc );

	thr_desc = *( (void **) p ); p += sizeof (void *);

	param = *( (void **) p ); p += sizeof (void *);

	prio = *( (int *) p );

	if ( param ) /* copy parameters from one process space to another */
	{
		/* copy parameters to new process address space */
		/* first copy them to kernel */
		argnum = 0;
		argsize = 0;
		args = U2K_GET_ADR ( param, cur->proc );
		while ( args[argnum] )
		{
			arg = U2K_GET_ADR ( args[argnum++], cur->proc );
			argsize += strlen ( arg ) + 1;
		}
		if ( argnum > 0 )
		{
			kargs = kmalloc ( (argnum + 1) * sizeof (void *) +
					      argsize );
			karg = (void *) kargs + (argnum + 1) * sizeof (void *);
			argnum = 0;
			while ( args[argnum] )
			{
				arg = U2K_GET_ADR ( args[argnum], cur->proc );
				strcpy ( karg, arg );
				kargs[argnum++] = karg;
				karg += strlen ( karg ) + 1;
			}
			kargs[argnum] = NULL;
		}
	}

	SET_ERRNO ( SUCCESS );

	kthr = k_proc_start ( prog_name, kargs, prio );

	if ( !kthr )
		EXIT ( E_NO_MEMORY );

	if ( thr_desc ) /* save thread descriptor */
	{
		thr_desc = U2K_GET_ADR ( thr_desc, cur->proc );
		thr_desc->thread = kthr;
		thr_desc->thr_id = kthr->id;
	}

	RETURN ( SUCCESS );
}
Example #10
0
int
ipmi_dump_rmcp_packet (int fd,
                       const char *prefix,
                       const char *hdr,
                       const char *trlr,
                       const void *pkt,
                       unsigned int pkt_len,
                       fiid_template_t tmpl_cmd)
{
  unsigned int indx = 0;
  char prefix_buf[IPMI_DEBUG_MAX_PREFIX_LEN];
  char *rmcp_hdr =
    "RMCP Header:\n"
    "------------";
  char *rmcp_cmd =
    "RMCP Command Data:\n"
    "------------------";
  char *unexpected_hdr =
    "Unexpected Data:\n"
    "----------------";
  fiid_obj_t obj_rmcp_hdr = NULL;
  fiid_obj_t obj_cmd = NULL;
  fiid_obj_t obj_unexpected_data = NULL;
  int len, rv = -1;

  if (!pkt || !tmpl_cmd)
    {
      SET_ERRNO (EINVAL);
      return (-1);
    }

  if (debug_set_prefix (prefix_buf, IPMI_DEBUG_MAX_PREFIX_LEN, prefix) < 0)
    {
      ERRNO_TRACE (errno);
      return (-1);
    }

  if (debug_output_str (fd, prefix_buf, hdr) < 0)
    {
      ERRNO_TRACE (errno);
      return (-1);
    }

  /* Dump rmcp header */

  if (!(obj_rmcp_hdr = fiid_obj_create (tmpl_rmcp_hdr)))
    {
      ERRNO_TRACE (errno);
      goto cleanup;
    }

  if ((len = fiid_obj_set_all (obj_rmcp_hdr, pkt + indx, pkt_len - indx)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_rmcp_hdr);
      goto cleanup;
    }
  indx += len;

  if (ipmi_obj_dump (fd, prefix, rmcp_hdr, NULL, obj_rmcp_hdr) < 0)
    {
      ERRNO_TRACE (errno);
      goto cleanup;
    }

  if (pkt_len <= indx)
    {
      rv = 0;
      goto cleanup;
    }

  /* Dump command data */

  if (!(obj_cmd = fiid_obj_create (tmpl_cmd)))
    {
      ERRNO_TRACE (errno);
      goto cleanup;
    }

  if ((len = fiid_obj_set_all (obj_cmd, pkt + indx, pkt_len - indx)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd);
      goto cleanup;
    }
  indx += len;

  if (ipmi_obj_dump (fd, prefix, rmcp_cmd, NULL, obj_cmd) < 0)
    {
      ERRNO_TRACE (errno);
      goto cleanup;
    }

  /* Dump unexpected stuff */

  if ((pkt_len - indx) > 0)
    {
      if (!(obj_unexpected_data = fiid_obj_create (tmpl_unexpected_data)))
        {
          ERRNO_TRACE (errno);
          goto cleanup;
        }
      
      if ((len = fiid_obj_set_all (obj_unexpected_data, pkt + indx, pkt_len - indx)) < 0)
        {
          FIID_OBJECT_ERROR_TO_ERRNO (obj_unexpected_data);
          goto cleanup;
        }
      indx += len;
      
      if (ipmi_obj_dump (fd, prefix, unexpected_hdr, NULL, obj_unexpected_data) < 0)
        {
          ERRNO_TRACE (errno);
          goto cleanup;
        }
    }

  if (debug_output_str (fd, prefix_buf, trlr) < 0)
    {
      ERRNO_TRACE (errno);
      goto cleanup;
    }


#if WITH_RAWDUMPS
  /* For those vendors that get confused when they see the nice output
   * and want the hex output
   */
  if (ipmi_dump_hex (fd,
                     prefix,
                     hdr,
		     trlr,
		     pkt,
		     pkt_len) < 0)
    {
      ERRNO_TRACE (errno);
      goto cleanup;
    }
#endif
  
  rv = 0;
 cleanup:
  fiid_obj_destroy (obj_rmcp_hdr);
  fiid_obj_destroy (obj_cmd);
  fiid_obj_destroy (obj_unexpected_data);
  return (rv);
}
/*!
 * Send message to queue or signal to thread
 */
int sys__msg_post ( int dest_type, void *dest, msg_t *msg, uint flags )
{
	thread_t *thr;
	kthread_t *kthr, *new_kthr;
	kthrmsg_qs *thrmsg;
	kgmsg_q *kgmsgq;
	kmsg_q *kmsgq;
	msg_q *msgq;
	kmsg_t *kmsg;
	msg_t *cmsg;

	ASSERT_ERRNO_AND_EXIT ( dest && msg, E_INVALID_HANDLE );

	if ( dest_type == MSG_THREAD || dest_type == MSG_SIGNAL )
	{
		thr = dest;
		kthr = k_get_kthread ( thr );
		ASSERT_ERRNO_AND_EXIT ( kthr, E_DONT_EXIST );
		thrmsg = k_get_thrmsg ( kthr );
		kmsgq = &thrmsg->msgq;
	}
	else if ( dest_type == MSG_QUEUE )
	{
		msgq = dest;
		kgmsgq = msgq->handle;
		ASSERT_ERRNO_AND_EXIT ( kgmsgq && kgmsgq->id == msgq->id,
					E_INVALID_HANDLE );
		kmsgq = &kgmsgq->mq;
	}
	else {
		EXIT ( E_INVALID_TYPE );
	}

	if ( dest_type == MSG_THREAD || dest_type == MSG_QUEUE )
	{
		/* send message to queue */
		if ( kmsgq->min_prio <= msg->type ) /* msg has required prio. */
		{
			kmsg = kmalloc ( sizeof (kmsg_t) + msg->size );
			ASSERT_ERRNO_AND_EXIT ( kmsg, E_NO_MEMORY );

			kmsg->msg.type = msg->type;
			kmsg->msg.size = msg->size;
			memcpy ( kmsg->msg.data, msg->data, msg->size );

			list_append ( &kmsgq->msgs, kmsg, &kmsg->list );

			/* is thread waiting for message? */
			if ( k_release_thread ( &kmsgq->thrq ) )
				k_schedule_threads ();

			EXIT ( SUCCESS );
		}
		else { /* ignore message */
			EXIT ( E_IGNORED );
		}
	}

	/* must be MSG_SIGNAL */
	if ( thrmsg->sig_prio <= msg->type )
	{
		/* create thread that will service this signal */

		cmsg = k_create_thread_private_storage ( kthr,
				sizeof (msg_t) + msg->size );
		cmsg->type = msg->type;
		cmsg->size = msg->size;
		memcpy ( cmsg->data, msg->data, msg->size );

		new_kthr = k_create_thread (
			thrmsg->signal_handler, cmsg, pi.exit,
			k_get_thread_prio ( kthr ) + 1, NULL, 0, 1
		);
		ASSERT_ERRNO_AND_EXIT ( new_kthr, k_get_errno() );

		k_set_thread_private_storage ( new_kthr, cmsg );

		SET_ERRNO ( SUCCESS );

		k_schedule_threads ();

		RETURN ( SUCCESS );
	}
	else { /* ignore signal */
		EXIT ( E_IGNORED );
	}
}
Example #12
0
const char *Curl_sspi_strerror (struct connectdata *conn, int err)
{
#ifndef CURL_DISABLE_VERBOSE_STRINGS
  char txtbuf[80];
  char msgbuf[sizeof(conn->syserr_buf)];
  char *p, *str, *msg = NULL;
  bool msg_formatted = FALSE;
  int old_errno;
#endif
  const char *txt;
  char *outbuf;
  size_t outmax;

  DEBUGASSERT(conn);

  outbuf = conn->syserr_buf;
  outmax = sizeof(conn->syserr_buf)-1;
  *outbuf = '\0';

#ifndef CURL_DISABLE_VERBOSE_STRINGS

  old_errno = ERRNO;

  switch (err) {
    case SEC_E_OK:
      txt = "No error";
      break;
    case SEC_E_ALGORITHM_MISMATCH:
      txt = "SEC_E_ALGORITHM_MISMATCH";
      break;
    case SEC_E_BAD_BINDINGS:
      txt = "SEC_E_BAD_BINDINGS";
      break;
    case SEC_E_BAD_PKGID:
      txt = "SEC_E_BAD_PKGID";
      break;
    case SEC_E_BUFFER_TOO_SMALL:
      txt = "SEC_E_BUFFER_TOO_SMALL";
      break;
    case SEC_E_CANNOT_INSTALL:
      txt = "SEC_E_CANNOT_INSTALL";
      break;
    case SEC_E_CANNOT_PACK:
      txt = "SEC_E_CANNOT_PACK";
      break;
    case SEC_E_CERT_EXPIRED:
      txt = "SEC_E_CERT_EXPIRED";
      break;
    case SEC_E_CERT_UNKNOWN:
      txt = "SEC_E_CERT_UNKNOWN";
      break;
    case SEC_E_CERT_WRONG_USAGE:
      txt = "SEC_E_CERT_WRONG_USAGE";
      break;
    case SEC_E_CONTEXT_EXPIRED:
      txt = "SEC_E_CONTEXT_EXPIRED";
      break;
    case SEC_E_CROSSREALM_DELEGATION_FAILURE:
      txt = "SEC_E_CROSSREALM_DELEGATION_FAILURE";
      break;
    case SEC_E_CRYPTO_SYSTEM_INVALID:
      txt = "SEC_E_CRYPTO_SYSTEM_INVALID";
      break;
    case SEC_E_DECRYPT_FAILURE:
      txt = "SEC_E_DECRYPT_FAILURE";
      break;
    case SEC_E_DELEGATION_POLICY:
      txt = "SEC_E_DELEGATION_POLICY";
      break;
    case SEC_E_DELEGATION_REQUIRED:
      txt = "SEC_E_DELEGATION_REQUIRED";
      break;
    case SEC_E_DOWNGRADE_DETECTED:
      txt = "SEC_E_DOWNGRADE_DETECTED";
      break;
    case SEC_E_ENCRYPT_FAILURE:
      txt = "SEC_E_ENCRYPT_FAILURE";
      break;
    case SEC_E_ILLEGAL_MESSAGE:
      txt = "SEC_E_ILLEGAL_MESSAGE";
      break;
    case SEC_E_INCOMPLETE_CREDENTIALS:
      txt = "SEC_E_INCOMPLETE_CREDENTIALS";
      break;
    case SEC_E_INCOMPLETE_MESSAGE:
      txt = "SEC_E_INCOMPLETE_MESSAGE";
      break;
    case SEC_E_INSUFFICIENT_MEMORY:
      txt = "SEC_E_INSUFFICIENT_MEMORY";
      break;
    case SEC_E_INTERNAL_ERROR:
      txt = "SEC_E_INTERNAL_ERROR";
      break;
    case SEC_E_INVALID_HANDLE:
      txt = "SEC_E_INVALID_HANDLE";
      break;
    case SEC_E_INVALID_PARAMETER:
      txt = "SEC_E_INVALID_PARAMETER";
      break;
    case SEC_E_INVALID_TOKEN:
      txt = "SEC_E_INVALID_TOKEN";
      break;
    case SEC_E_ISSUING_CA_UNTRUSTED:
      txt = "SEC_E_ISSUING_CA_UNTRUSTED";
      break;
    case SEC_E_ISSUING_CA_UNTRUSTED_KDC:
      txt = "SEC_E_ISSUING_CA_UNTRUSTED_KDC";
      break;
    case SEC_E_KDC_CERT_EXPIRED:
      txt = "SEC_E_KDC_CERT_EXPIRED";
      break;
    case SEC_E_KDC_CERT_REVOKED:
      txt = "SEC_E_KDC_CERT_REVOKED";
      break;
    case SEC_E_KDC_INVALID_REQUEST:
      txt = "SEC_E_KDC_INVALID_REQUEST";
      break;
    case SEC_E_KDC_UNABLE_TO_REFER:
      txt = "SEC_E_KDC_UNABLE_TO_REFER";
      break;
    case SEC_E_KDC_UNKNOWN_ETYPE:
      txt = "SEC_E_KDC_UNKNOWN_ETYPE";
      break;
    case SEC_E_LOGON_DENIED:
      txt = "SEC_E_LOGON_DENIED";
      break;
    case SEC_E_MAX_REFERRALS_EXCEEDED:
      txt = "SEC_E_MAX_REFERRALS_EXCEEDED";
      break;
    case SEC_E_MESSAGE_ALTERED:
      txt = "SEC_E_MESSAGE_ALTERED";
      break;
    case SEC_E_MULTIPLE_ACCOUNTS:
      txt = "SEC_E_MULTIPLE_ACCOUNTS";
      break;
    case SEC_E_MUST_BE_KDC:
      txt = "SEC_E_MUST_BE_KDC";
      break;
    case SEC_E_NOT_OWNER:
      txt = "SEC_E_NOT_OWNER";
      break;
    case SEC_E_NO_AUTHENTICATING_AUTHORITY:
      txt = "SEC_E_NO_AUTHENTICATING_AUTHORITY";
      break;
    case SEC_E_NO_CREDENTIALS:
      txt = "SEC_E_NO_CREDENTIALS";
      break;
    case SEC_E_NO_IMPERSONATION:
      txt = "SEC_E_NO_IMPERSONATION";
      break;
    case SEC_E_NO_IP_ADDRESSES:
      txt = "SEC_E_NO_IP_ADDRESSES";
      break;
    case SEC_E_NO_KERB_KEY:
      txt = "SEC_E_NO_KERB_KEY";
      break;
    case SEC_E_NO_PA_DATA:
      txt = "SEC_E_NO_PA_DATA";
      break;
    case SEC_E_NO_S4U_PROT_SUPPORT:
      txt = "SEC_E_NO_S4U_PROT_SUPPORT";
      break;
    case SEC_E_NO_TGT_REPLY:
      txt = "SEC_E_NO_TGT_REPLY";
      break;
    case SEC_E_OUT_OF_SEQUENCE:
      txt = "SEC_E_OUT_OF_SEQUENCE";
      break;
    case SEC_E_PKINIT_CLIENT_FAILURE:
      txt = "SEC_E_PKINIT_CLIENT_FAILURE";
      break;
    case SEC_E_PKINIT_NAME_MISMATCH:
      txt = "SEC_E_PKINIT_NAME_MISMATCH";
      break;
    case SEC_E_POLICY_NLTM_ONLY:
      txt = "SEC_E_POLICY_NLTM_ONLY";
      break;
    case SEC_E_QOP_NOT_SUPPORTED:
      txt = "SEC_E_QOP_NOT_SUPPORTED";
      break;
    case SEC_E_REVOCATION_OFFLINE_C:
      txt = "SEC_E_REVOCATION_OFFLINE_C";
      break;
    case SEC_E_REVOCATION_OFFLINE_KDC:
      txt = "SEC_E_REVOCATION_OFFLINE_KDC";
      break;
    case SEC_E_SECPKG_NOT_FOUND:
      txt = "SEC_E_SECPKG_NOT_FOUND";
      break;
    case SEC_E_SECURITY_QOS_FAILED:
      txt = "SEC_E_SECURITY_QOS_FAILED";
      break;
    case SEC_E_SHUTDOWN_IN_PROGRESS:
      txt = "SEC_E_SHUTDOWN_IN_PROGRESS";
      break;
    case SEC_E_SMARTCARD_CERT_EXPIRED:
      txt = "SEC_E_SMARTCARD_CERT_EXPIRED";
      break;
    case SEC_E_SMARTCARD_CERT_REVOKED:
      txt = "SEC_E_SMARTCARD_CERT_REVOKED";
      break;
    case SEC_E_SMARTCARD_LOGON_REQUIRED:
      txt = "SEC_E_SMARTCARD_LOGON_REQUIRED";
      break;
    case SEC_E_STRONG_CRYPTO_NOT_SUPPORTED:
      txt = "SEC_E_STRONG_CRYPTO_NOT_SUPPORTED";
      break;
    case SEC_E_TARGET_UNKNOWN:
      txt = "SEC_E_TARGET_UNKNOWN";
      break;
    case SEC_E_TIME_SKEW:
      txt = "SEC_E_TIME_SKEW";
      break;
    case SEC_E_TOO_MANY_PRINCIPALS:
      txt = "SEC_E_TOO_MANY_PRINCIPALS";
      break;
    case SEC_E_UNFINISHED_CONTEXT_DELETED:
      txt = "SEC_E_UNFINISHED_CONTEXT_DELETED";
      break;
    case SEC_E_UNKNOWN_CREDENTIALS:
      txt = "SEC_E_UNKNOWN_CREDENTIALS";
      break;
    case SEC_E_UNSUPPORTED_FUNCTION:
      txt = "SEC_E_UNSUPPORTED_FUNCTION";
      break;
    case SEC_E_UNSUPPORTED_PREAUTH:
      txt = "SEC_E_UNSUPPORTED_PREAUTH";
      break;
    case SEC_E_UNTRUSTED_ROOT:
      txt = "SEC_E_UNTRUSTED_ROOT";
      break;
    case SEC_E_WRONG_CREDENTIAL_HANDLE:
      txt = "SEC_E_WRONG_CREDENTIAL_HANDLE";
      break;
    case SEC_E_WRONG_PRINCIPAL:
      txt = "SEC_E_WRONG_PRINCIPAL";
      break;
    case SEC_I_COMPLETE_AND_CONTINUE:
      txt = "SEC_I_COMPLETE_AND_CONTINUE";
      break;
    case SEC_I_COMPLETE_NEEDED:
      txt = "SEC_I_COMPLETE_NEEDED";
      break;
    case SEC_I_CONTEXT_EXPIRED:
      txt = "SEC_I_CONTEXT_EXPIRED";
      break;
    case SEC_I_CONTINUE_NEEDED:
      txt = "SEC_I_CONTINUE_NEEDED";
      break;
    case SEC_I_INCOMPLETE_CREDENTIALS:
      txt = "SEC_I_INCOMPLETE_CREDENTIALS";
      break;
    case SEC_I_LOCAL_LOGON:
      txt = "SEC_I_LOCAL_LOGON";
      break;
    case SEC_I_NO_LSA_CONTEXT:
      txt = "SEC_I_NO_LSA_CONTEXT";
      break;
    case SEC_I_RENEGOTIATE:
      txt = "SEC_I_RENEGOTIATE";
      break;
    case SEC_I_SIGNATURE_NEEDED:
      txt = "SEC_I_SIGNATURE_NEEDED";
      break;
    default:
      txt = "Unknown error";
  }

  if(err == SEC_E_OK)
    strncpy(outbuf, txt, outmax);
  else {
    str = txtbuf;
    snprintf(txtbuf, sizeof(txtbuf), "%s (0x%04X%04X)",
             txt, (err >> 16) & 0xffff, err & 0xffff);
    txtbuf[sizeof(txtbuf)-1] = '\0';

#ifdef _WIN32_WCE
    {
      wchar_t wbuf[256];
      wbuf[0] = L'\0';

      if(FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
                       FORMAT_MESSAGE_IGNORE_INSERTS,
                       NULL, err, LANG_NEUTRAL,
                       wbuf, sizeof(wbuf)/sizeof(wchar_t), NULL)) {
        wcstombs(msgbuf,wbuf,sizeof(msgbuf)-1);
        msg_formatted = TRUE;
      }
    }
#else
    if(FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM |
                      FORMAT_MESSAGE_IGNORE_INSERTS,
                      NULL, err, LANG_NEUTRAL,
                      msgbuf, sizeof(msgbuf)-1, NULL)) {
      msg_formatted = TRUE;
    }
#endif
    if(msg_formatted) {
      msgbuf[sizeof(msgbuf)-1] = '\0';
      /* strip trailing '\r\n' or '\n' */
      if((p = strrchr(msgbuf,'\n')) != NULL && (p - msgbuf) >= 2)
         *p = '\0';
      if((p = strrchr(msgbuf,'\r')) != NULL && (p - msgbuf) >= 1)
         *p = '\0';
      msg = msgbuf;
    }
    if(msg)
      snprintf(outbuf, outmax, "%s - %s", str, msg);
    else
      strncpy(outbuf, str, outmax);
  }

  if(old_errno != ERRNO)
    SET_ERRNO(old_errno);

#else

  if(err == SEC_E_OK)
    txt = "No error";
  else
    txt = "Error";

  strncpy(outbuf, txt, outmax);

#endif

  outbuf[outmax] = '\0';

  return outbuf;
}
Example #13
0
/*
 * init_resolve_thread() starts a new thread that performs the actual
 * resolve. This function returns before the resolve is done.
 *
 * Returns FALSE in case of failure, otherwise TRUE.
 */
static bool init_resolve_thread (struct connectdata *conn,
								 const char *hostname, int port,
								 const struct addrinfo *hints)
{
	struct thread_data *td = calloc(sizeof(*td), 1);
	HANDLE thread_and_event[2] = {0};

	if (!td)
	{
		SET_ERRNO(ENOMEM);
		return FALSE;
	}

	Curl_safefree(conn->async.hostname);
	conn->async.hostname = strdup(hostname);
	if (!conn->async.hostname)
	{
		free(td);
		SET_ERRNO(ENOMEM);
		return FALSE;
	}

	conn->async.port = port;
	conn->async.done = FALSE;
	conn->async.status = 0;
	conn->async.dns = NULL;
	conn->async.os_specific = (void*) td;
	td->dummy_sock = CURL_SOCKET_BAD;

	/* Create the mutex used to inform the resolver thread that we're
	 * still waiting, and take initial ownership.
	 */
	td->mutex_waiting = CreateMutex(NULL, TRUE, NULL);
	if (td->mutex_waiting == NULL)
	{
		Curl_destroy_thread_data(&conn->async);
		SET_ERRNO(EAGAIN);
		return FALSE;
	}

	/* Create the event that the thread uses to inform us that it's
	 * done resolving. Do not signal it.
	 */
	td->event_resolved = CreateEvent(NULL, TRUE, FALSE, NULL);
	if (td->event_resolved == NULL)
	{
		Curl_destroy_thread_data(&conn->async);
		SET_ERRNO(EAGAIN);
		return FALSE;
	}
	/* Create the mutex used to serialize access to event_terminated
	 * between us and resolver thread.
	 */
	td->mutex_terminate = CreateMutex(NULL, FALSE, NULL);
	if (td->mutex_terminate == NULL)
	{
		Curl_destroy_thread_data(&conn->async);
		SET_ERRNO(EAGAIN);
		return FALSE;
	}
	/* Create the event used to signal thread that it should terminate.
	 */
	td->event_terminate = CreateEvent(NULL, TRUE, FALSE, NULL);
	if (td->event_terminate == NULL)
	{
		Curl_destroy_thread_data(&conn->async);
		SET_ERRNO(EAGAIN);
		return FALSE;
	}
	/* Create the event used by thread to inform it has initialized its own data.
	 */
	td->event_thread_started = CreateEvent(NULL, TRUE, FALSE, NULL);
	if (td->event_thread_started == NULL)
	{
		Curl_destroy_thread_data(&conn->async);
		SET_ERRNO(EAGAIN);
		return FALSE;
	}

#ifdef _WIN32_WCE
	td->thread_hnd = (HANDLE) CreateThread(NULL, 0,
										   (LPTHREAD_START_ROUTINE) THREAD_FUNC,
										   conn, 0, &td->thread_id);
#else
	td->thread_hnd = (HANDLE) _beginthreadex(NULL, 0, THREAD_FUNC,
					 conn, 0, &td->thread_id);
#endif

#ifdef CURLRES_IPV6
	DEBUGASSERT(hints);
	td->hints = *hints;
#else
	(void) hints;
#endif

	if (!td->thread_hnd)
	{
#ifndef _WIN32_WCE
		SET_ERRNO(errno);
#endif
		Curl_destroy_thread_data(&conn->async);
		return FALSE;
	}
	/* Waiting until the thread will initialize its data or it will exit due errors.
	 */
	thread_and_event[0] = td->thread_hnd;
	thread_and_event[1] = td->event_thread_started;
	if (WaitForMultipleObjects(sizeof(thread_and_event) /
							   sizeof(thread_and_event[0]),
							   (const HANDLE*)thread_and_event, FALSE,
							   INFINITE) == WAIT_FAILED)
	{
		/* The resolver thread has been created,
		 * most probably it works now - ignoring this "minor" error
		 */
	}
	/* This socket is only to keep Curl_resolv_fdset() and select() happy;
	 * should never become signalled for read/write since it's unbound but
	 * Windows needs atleast 1 socket in select().
	 */
	td->dummy_sock = socket(AF_INET, SOCK_DGRAM, 0);
	return TRUE;
}
int
assemble_ipmi_kcs_pkt (fiid_obj_t obj_kcs_hdr,
                       fiid_obj_t obj_cmd,
                       void *pkt,
                       unsigned int pkt_len,
		       unsigned int flags)
{
  int obj_cmd_len, obj_kcs_hdr_len;
  unsigned int utmp;
  unsigned int flags_mask = 0;

  if (!fiid_obj_valid (obj_kcs_hdr)
      || !fiid_obj_valid (obj_cmd)
      || !pkt
      || (flags & ~flags_mask))
    {
      SET_ERRNO (EINVAL);
      return (-1);
    }

  if (FIID_OBJ_TEMPLATE_COMPARE (obj_kcs_hdr, tmpl_hdr_kcs) < 0)
    {
      ERRNO_TRACE (errno);
      return (-1);
    }

  if (FIID_OBJ_PACKET_VALID (obj_kcs_hdr) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_kcs_hdr);
      return (-1);
    }
  if (FIID_OBJ_PACKET_VALID (obj_cmd) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd);
      return (-1);
    }

  if ((obj_kcs_hdr_len = fiid_obj_len_bytes (obj_kcs_hdr)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_kcs_hdr);
      return (-1);
    }
  if ((obj_cmd_len = fiid_obj_len_bytes (obj_cmd)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd);
      return (-1);
    }

  /* int overflow not possible here */
  if (pkt_len < (obj_kcs_hdr_len + obj_cmd_len))
    {
      SET_ERRNO (EMSGSIZE);
      return (-1);
    }

  memset (pkt, 0, pkt_len);
  if ((obj_kcs_hdr_len = fiid_obj_get_all (obj_kcs_hdr,
                                           pkt,
                                           pkt_len)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_kcs_hdr);
      return (-1);
    }
  if ((obj_cmd_len = fiid_obj_get_all (obj_cmd,
                                       pkt + obj_kcs_hdr_len,
                                       pkt_len - obj_kcs_hdr_len)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd);
      return (-1);
    }

  utmp = obj_kcs_hdr_len + obj_cmd_len;
  if (utmp > INT_MAX)
    {
      SET_ERRNO (EMSGSIZE);
      return (-1);
    }

  return (obj_kcs_hdr_len + obj_cmd_len);
}
Example #15
0
void	*MIONet_Open (char *pmOpenString)
{
    NetRecord	*myNetRecord;
    char	myNetAddr[256];
    char	myDoc [256];
    int		myPort;

    if (!stMDNetInitialized)
    {
	ABORT_WITH_ERRNO (E_NET_INIT_FAILED);
	// Never reaches here
    }

    // Allocate the NetRecord
    myNetRecord = (NetRecord *) malloc (sizeof (NetRecord));
    if (myNetRecord == NULL) 
    {
	SET_ERRNO (E_INSUFFICIENT_MEMORY);
	return NULL;
    }

    // Initialize the entire record to zeroes
    memset (myNetRecord, 0, sizeof (NetRecord));

    // Allocate the socket
    myNetRecord -> socket = MDIONet_CreateSocket ();
    if (myNetRecord -> socket == NULL) 
    {
	free (myNetRecord);
	return NULL;
    }

    // Allocate the socket address
    myNetRecord -> sockAddr = MDIO_AllocateSockAddr ();
    if (myNetRecord -> sockAddr == NULL)
    {
	free (myNetRecord);
	return NULL;
    }

    // Allocate the buffer
    myNetRecord -> buf = (BYTE *) malloc(BUFFER_SIZE);
    if (myNetRecord -> buf == NULL) 
    {
	MDIONet_CloseSocket (myNetRecord -> socket);
	free (myNetRecord);
	SET_ERRNO (E_INSUFFICIENT_MEMORY);
	return NULL;
    }
    memset (myNetRecord -> buf, 128, BUFFER_SIZE);

    switch (pmOpenString[0])
    {
	case 'C':
	    // Connect to arbitrary port
	    if (MyDoConnect (myNetRecord, pmOpenString + 2, &myPort, 
			     myNetAddr)) 
	    {
		MDIO_sprintf (stLastOpenDescription,
		    "Connect to port %d on %s", &myPort, myNetAddr);
		stLastStreamOpened = myNetRecord;
		return myNetRecord;
	    }
	    break;
	
	case 'A':
	    // Open for accepting a connection on a port
	    if (MyDoOpenForAccept (myNetRecord, pmOpenString + 2, &myPort)) 
	    {
		MDIO_sprintf (stLastOpenDescription,
		    "Accepted connection on port %d", &myPort);
		stLastStreamOpened = myNetRecord;
		return myNetRecord;
	    }
	    break;

	case 'U':
	    // Open a URL for read
	    {
		if (MyGetURLAddressAndDocument (myNetAddr, myDoc, 
					        pmOpenString + 2)) 
		{
		    if (MyDoConnect (myNetRecord, myNetAddr, &myPort, NULL)) 
		    {
			MySendURLGet (myNetRecord, myDoc);
			if (myPort == 80)
			{
			    MDIO_sprintf (stLastOpenDescription,
				"Connect to URL %s", myNetAddr);
			}
			else
			{
			    MDIO_sprintf (stLastOpenDescription,
				"Connect to URL %s (port %d)", myNetAddr, 
				myPort);
			}
			stLastStreamOpened = myNetRecord;
			return myNetRecord;
		    }
		}
	    }
	    break;
    }

    MDIONet_CloseSocket (myNetRecord -> socket);
    if (myNetRecord -> sockAddr != NULL)
    {
	free (myNetRecord -> sockAddr);
    }
    free (myNetRecord -> buf);
    free (myNetRecord);
    stLastStreamOpened = NULL;
    return NULL;
} // MIONet_Open
Example #16
0
/**
 * Emulated version of the strtoll function.  This extracts a long long
 * value from the given input string and returns it.
 */
curl_off_t
curlx_strtoll(const char *nptr, char **endptr, int base)
{
    char       *end;
    int        is_negative = 0;
    int        overflow;
    int        i;
    curl_off_t value = 0;
    curl_off_t newval;

    /* Skip leading whitespace. */
    end = (char*)nptr;

    while (ISSPACE(end[0]))
    {
        end++;
    }

    /* Handle the sign, if any. */
    if (end[0] == '-')
    {
        is_negative = 1;
        end++;
    }
    else if (end[0] == '+')
    {
        end++;
    }
    else if (end[0] == '\0')
    {
        /* We had nothing but perhaps some whitespace -- there was no number. */
        if (endptr)
        {
            *endptr = end;
        }

        return 0;
    }

    /* Handle special beginnings, if present and allowed. */
    if (end[0] == '0' && end[1] == 'x')
    {
        if (base == 16 || base == 0)
        {
            end += 2;
            base = 16;
        }
    }
    else if (end[0] == '0')
    {
        if (base == 8 || base == 0)
        {
            end++;
            base = 8;
        }
    }

    /* Matching strtol, if the base is 0 and it doesn't look like
     * the number is octal or hex, we assume it's base 10.
     */
    if (base == 0)
    {
        base = 10;
    }

    /* Loop handling digits. */
    value    = 0;
    overflow = 0;

    for (i = get_char(end[0], base);
         i != -1;
         end++, i = get_char(end[0], base))
    {
        newval = base * value + i;
        if (newval < value)
        {
            /* We've overflowed. */
            overflow = 1;
            break;
        }
        else
            value = newval;
    }

    if (!overflow)
    {
        if (is_negative)
        {
            /* Fix the sign. */
            value *= -1;
        }
    }
    else
    {
        if (is_negative)
            value = CURL_LLONG_MIN;
        else
            value = CURL_LLONG_MAX;

        SET_ERRNO(ERANGE);
    }

    if (endptr)
        *endptr = end;

    return value;
}
Example #17
0
int
assemble_ipmi_lan_pkt (fiid_obj_t obj_rmcp_hdr,
                       fiid_obj_t obj_lan_session_hdr,
                       fiid_obj_t obj_lan_msg_hdr,
                       fiid_obj_t obj_cmd,
                       const void *authentication_code_data,
                       unsigned int authentication_code_data_len,
                       void *pkt,
                       unsigned int pkt_len,
		       unsigned int flags)
{
  uint8_t authentication_type;
  uint64_t val;
  unsigned int indx = 0;
  int required_len;
  void *authentication_code_field_ptr = NULL;
  void *checksum_data_ptr = NULL;
  void *msg_data_ptr = NULL;
  void *ipmi_msg_len_ptr = NULL;
  unsigned int msg_data_count = 0;
  unsigned int checksum_data_count = 0;
  uint8_t ipmi_msg_len;
  fiid_obj_t obj_lan_msg_trlr = NULL;
  uint8_t pwbuf[IPMI_1_5_MAX_PASSWORD_LENGTH];
  uint8_t checksum;
  int len, rv = -1;
  unsigned int flags_mask = 0;

  if (!fiid_obj_valid (obj_rmcp_hdr)
      || !fiid_obj_valid (obj_lan_session_hdr)
      || !fiid_obj_valid (obj_lan_msg_hdr)
      || !fiid_obj_valid (obj_cmd)
      || (authentication_code_data && authentication_code_data_len > IPMI_1_5_MAX_PASSWORD_LENGTH)
      || !pkt
      || (flags & ~flags_mask))
    {
      SET_ERRNO (EINVAL);
      return (-1);
    }

  if (FIID_OBJ_TEMPLATE_COMPARE (obj_rmcp_hdr, tmpl_rmcp_hdr) < 0)
    {
      ERRNO_TRACE (errno);
      return (-1);
    }
  if (FIID_OBJ_TEMPLATE_COMPARE (obj_lan_session_hdr, tmpl_lan_session_hdr) < 0)
    {
      ERRNO_TRACE (errno);
      return (-1);
    }
  if (FIID_OBJ_TEMPLATE_COMPARE (obj_lan_msg_hdr, tmpl_lan_msg_hdr_rq) < 0)
    {
      ERRNO_TRACE (errno);
      return (-1);
    }

  if (FIID_OBJ_PACKET_VALID (obj_rmcp_hdr) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_rmcp_hdr);
      return (-1);
    }

  /*
   * ipmi_msg_len is calculated in this function, so we can't use
   * fiid_obj_packet_valid() on obj_lan_session_hdr b/c ipmi_msg_len
   * is probably not set yet.
   */

  if (FIID_OBJ_PACKET_VALID (obj_lan_msg_hdr) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_msg_hdr);
      return (-1);
    }
  if (FIID_OBJ_PACKET_VALID (obj_cmd) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd);
      return (-1);
    }

  if (FIID_OBJ_GET (obj_lan_session_hdr,
                    "authentication_type",
                    &val) < 0)
    {
      ERRNO_TRACE (errno);
      return (-1);
    }
  authentication_type = val;

  if (authentication_type != IPMI_AUTHENTICATION_TYPE_NONE
      && authentication_type != IPMI_AUTHENTICATION_TYPE_MD2
      && authentication_type != IPMI_AUTHENTICATION_TYPE_MD5
      && authentication_type != IPMI_AUTHENTICATION_TYPE_STRAIGHT_PASSWORD_KEY)
    {
      SET_ERRNO (EINVAL);
      return (-1);
    }

  /* no need for overflow checks, handled w/ _ipmi_lan_pkt_rq_min_size check */

  required_len = _ipmi_lan_pkt_rq_min_size (authentication_type, obj_cmd);
  if (pkt_len < required_len)
    {
      SET_ERRNO (EMSGSIZE);
      return (-1);
    }

  memset (pkt, 0, pkt_len);

  if ((len = fiid_obj_get_all (obj_rmcp_hdr, pkt + indx, pkt_len - indx)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_rmcp_hdr);
      goto cleanup;
    }
  indx += len;

  if ((len = fiid_obj_get_block (obj_lan_session_hdr,
                                 "authentication_type",
                                 "session_id",
                                 pkt + indx,
                                 pkt_len - indx)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_session_hdr);
      goto cleanup;
    }

  indx += len;

  /* authentication_code generated last.  Save pointers for later calculation */
  if (authentication_type != IPMI_AUTHENTICATION_TYPE_NONE)
    {
      authentication_code_field_ptr = (pkt + indx);
      indx += IPMI_1_5_MAX_PASSWORD_LENGTH;
    }

  ipmi_msg_len_ptr = (pkt + indx);
  if ((len = fiid_template_field_len_bytes (tmpl_lan_session_hdr, "ipmi_msg_len")) < 0)
    {
      ERRNO_TRACE (errno);
      goto cleanup;
    }
  if (len != 1)
    {
      SET_ERRNO (EINVAL);
      goto cleanup;
    }
  indx += len;

  msg_data_ptr = (pkt + indx);

  if ((len = fiid_obj_get_block (obj_lan_msg_hdr,
                                 "rs_addr",
                                 "checksum1",
                                 pkt + indx,
                                 pkt_len - indx)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_msg_hdr);
      goto cleanup;
    }
  indx += len;
  msg_data_count += len;

  checksum_data_ptr = (pkt + indx);

  if ((len = fiid_obj_get_block (obj_lan_msg_hdr,
                                 "rq_addr",
                                 "rq_seq",
                                 pkt + indx,
                                 pkt_len - indx)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_msg_hdr);
      goto cleanup;
    }
  indx += len;
  msg_data_count += len;
  checksum_data_count += len;

  if ((len = fiid_obj_get_all (obj_cmd, pkt + indx, pkt_len - indx)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd);
      goto cleanup;
    }
  indx += len;
  msg_data_count += len;
  checksum_data_count += len;

  if (!(obj_lan_msg_trlr = fiid_obj_create (tmpl_lan_msg_trlr)))
    {
      ERRNO_TRACE (errno);
      goto cleanup;
    }

  checksum = ipmi_checksum (checksum_data_ptr, checksum_data_count);

  if (fiid_obj_set_all (obj_lan_msg_trlr, &checksum, sizeof (checksum)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_msg_trlr);
      goto cleanup;
    }

  if ((len = fiid_obj_get_all (obj_lan_msg_trlr, pkt + indx, pkt_len - indx)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_msg_trlr);
      goto cleanup;
    }
  indx += len;
  msg_data_count += len;

  /* ipmi_msg_len done after message length is computed */
  ipmi_msg_len = msg_data_count;
  memcpy (ipmi_msg_len_ptr,
          &ipmi_msg_len,
          sizeof (ipmi_msg_len));

  /* Auth code must be done last, some authentication like md2 and md5
   * require all fields, including checksums, to be calculated
   * beforehand
   */
  if (authentication_type != IPMI_AUTHENTICATION_TYPE_NONE)
    {
      int authentication_len;

      memset (pwbuf, '\0', IPMI_1_5_MAX_PASSWORD_LENGTH);

      if ((authentication_len = fiid_obj_field_len_bytes (obj_lan_session_hdr,
                                                          "authentication_code")) < 0)
        {
          FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_session_hdr);
          goto cleanup;
        }

      if (authentication_len)
        {
          if (fiid_obj_get_data (obj_lan_session_hdr,
                                 "authentication_code",
                                 pwbuf,
                                 IPMI_1_5_MAX_PASSWORD_LENGTH) < 0)
            {
              FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_session_hdr);
              goto cleanup;
            }

          memcpy (authentication_code_field_ptr,
                  pwbuf,
                  IPMI_1_5_MAX_PASSWORD_LENGTH);
        }
      else
        {
          if (authentication_code_data)
            memcpy (pwbuf,
                    authentication_code_data,
                    authentication_code_data_len);

          if (authentication_type == IPMI_AUTHENTICATION_TYPE_STRAIGHT_PASSWORD_KEY)
            {
              memcpy (authentication_code_field_ptr,
                      pwbuf,
                      IPMI_1_5_MAX_PASSWORD_LENGTH);
            }
          else /* IPMI_AUTHENTICATION_TYPE_MD2 || IPMI_AUTHENTICATION_TYPE_MD5 */
            {
              uint8_t session_id_buf[1024];
              uint8_t session_sequence_number_buf[1024];
              int session_id_len, session_sequence_number_len;

              if ((session_id_len = fiid_obj_get_data (obj_lan_session_hdr,
                                                       "session_id",
                                                       session_id_buf,
                                                       1024)) < 0)
                {
                  FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_session_hdr);
                  goto cleanup;
                }

              if ((session_sequence_number_len = fiid_obj_get_data (obj_lan_session_hdr,
                                                                    "session_sequence_number",
                                                                    session_sequence_number_buf,
                                                                    1024)) < 0)
                {
                  FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_session_hdr);
                  goto cleanup;
                }

              if (authentication_type == IPMI_AUTHENTICATION_TYPE_MD2)
                {
                  md2_t ctx;
                  uint8_t digest[MD2_DIGEST_LENGTH];

                  assert (IPMI_1_5_MAX_PASSWORD_LENGTH == MD2_DIGEST_LENGTH);

                  md2_init (&ctx);
                  md2_update_data (&ctx, pwbuf, IPMI_1_5_MAX_PASSWORD_LENGTH);
                  md2_update_data (&ctx, session_id_buf, session_id_len);
                  md2_update_data (&ctx, msg_data_ptr, msg_data_count);
                  md2_update_data (&ctx, session_sequence_number_buf, session_sequence_number_len);
                  md2_update_data (&ctx, pwbuf, IPMI_1_5_MAX_PASSWORD_LENGTH);
                  md2_finish (&ctx, digest, MD2_DIGEST_LENGTH);
                  md2_init (&ctx);

                  memcpy (authentication_code_field_ptr, digest, IPMI_1_5_MAX_PASSWORD_LENGTH);
                  secure_memset (digest, '\0', MD2_DIGEST_LENGTH);
                }
              else if (authentication_type == IPMI_AUTHENTICATION_TYPE_MD5)
                {
                  md5_t ctx;
                  uint8_t digest[MD5_DIGEST_LENGTH];

                  assert (IPMI_1_5_MAX_PASSWORD_LENGTH == MD5_DIGEST_LENGTH);

                  md5_init (&ctx);
                  md5_update_data (&ctx, pwbuf, IPMI_1_5_MAX_PASSWORD_LENGTH);
                  md5_update_data (&ctx, session_id_buf, session_id_len);
                  md5_update_data (&ctx, msg_data_ptr, msg_data_count);
                  md5_update_data (&ctx, session_sequence_number_buf, session_sequence_number_len);
                  md5_update_data (&ctx, pwbuf, IPMI_1_5_MAX_PASSWORD_LENGTH);
                  md5_finish (&ctx, digest, MD5_DIGEST_LENGTH);
                  md5_init (&ctx);

                  memcpy (authentication_code_field_ptr, digest, IPMI_1_5_MAX_PASSWORD_LENGTH);
                  secure_memset (digest, '\0', MD5_DIGEST_LENGTH);
                }
            }
        }
    }

  if (indx > INT_MAX)
    {
      SET_ERRNO (EMSGSIZE);
      goto cleanup;
    }

  rv = indx;
 cleanup:
  if (rv < 0)
    secure_memset (pkt, '\0', pkt_len);
  fiid_obj_destroy (obj_lan_msg_trlr);
  secure_memset (pwbuf, '\0', IPMI_1_5_MAX_PASSWORD_LENGTH);
  return (rv);
}
Example #18
0
size_t http_parser_execute (http_parser *parser,
                            const http_parser_settings *settings,
                            const char *data,
                            size_t len)
{
  char c, ch;
  int8_t unhex_val;
  const char *p = data, *pe;
  int64_t to_read;
  enum state state;
  enum header_states header_state;
  uint64_t index = parser->index;
  uint64_t nread = parser->nread;

  /* technically we could combine all of these (except for url_mark) into one
     variable, saving stack space, but it seems more clear to have them
     separated. */
  const char *header_field_mark = 0;
  const char *header_value_mark = 0;
  const char *url_mark = 0;

  /* We're in an error state. Don't bother doing anything. */
  if (HTTP_PARSER_ERRNO(parser) != HPE_OK) {
    return 0;
  }

  state = (enum state) parser->state;
  header_state = (enum header_states) parser->header_state;

  if (len == 0) {
    switch (state) {
      case s_body_identity_eof:
        CALLBACK2(message_complete);
        return 0;

      case s_dead:
      case s_start_req_or_res:
      case s_start_res:
      case s_start_req:
        return 0;

      default:
        SET_ERRNO(HPE_INVALID_EOF_STATE);
        return 1;
    }
  }


  if (state == s_header_field)
    header_field_mark = data;
  if (state == s_header_value)
    header_value_mark = data;
  if (state == s_req_path || state == s_req_schema || state == s_req_schema_slash
      || state == s_req_schema_slash_slash || state == s_req_port
      || state == s_req_query_string_start || state == s_req_query_string
      || state == s_req_host
      || state == s_req_fragment_start || state == s_req_fragment)
    url_mark = data;

  for (p=data, pe=data+len; p != pe; p++) {
    ch = *p;

    if (PARSING_HEADER(state)) {
      ++nread;
      /* Buffer overflow attack */
      if (nread > HTTP_MAX_HEADER_SIZE) {
        SET_ERRNO(HPE_HEADER_OVERFLOW);
        goto error;
      }
    }

    switch (state) {

      case s_dead:
        /* this state is used after a 'Connection: close' message
         * the parser will error out if it reads another message
         */
        SET_ERRNO(HPE_CLOSED_CONNECTION);
        goto error;

      case s_start_req_or_res:
      {
        if (ch == CR || ch == LF)
          break;
        parser->flags = 0;
        parser->content_length = -1;

        CALLBACK2(message_begin);

        if (ch == 'H')
          state = s_res_or_resp_H;
        else {
          parser->type = HTTP_REQUEST;
          goto start_req_method_assign;
        }
        break;
      }

      case s_res_or_resp_H:
        if (ch == 'T') {
          parser->type = HTTP_RESPONSE;
          state = s_res_HT;
        } else {
          if (ch != 'E') {
            SET_ERRNO(HPE_INVALID_CONSTANT);
            goto error;
          }

          parser->type = HTTP_REQUEST;
          parser->method = HTTP_HEAD;
          index = 2;
          state = s_req_method;
        }
        break;

      case s_start_res:
      {
        parser->flags = 0;
        parser->content_length = -1;

        CALLBACK2(message_begin);

        switch (ch) {
          case 'H':
            state = s_res_H;
            break;

          case CR:
          case LF:
            break;

          default:
            SET_ERRNO(HPE_INVALID_CONSTANT);
            goto error;
        }
        break;
      }

      case s_res_H:
        STRICT_CHECK(ch != 'T');
        state = s_res_HT;
        break;

      case s_res_HT:
        STRICT_CHECK(ch != 'T');
        state = s_res_HTT;
        break;

      case s_res_HTT:
        STRICT_CHECK(ch != 'P');
        state = s_res_HTTP;
        break;

      case s_res_HTTP:
        STRICT_CHECK(ch != '/');
        state = s_res_first_http_major;
        break;

      case s_res_first_http_major:
        if (ch < '0' || ch > '9') {
          SET_ERRNO(HPE_INVALID_VERSION);
          goto error;
        }

        parser->http_major = ch - '0';
        state = s_res_http_major;
        break;

      /* major HTTP version or dot */
      case s_res_http_major:
      {
        if (ch == '.') {
          state = s_res_first_http_minor;
          break;
        }

        if (!IS_NUM(ch)) {
          SET_ERRNO(HPE_INVALID_VERSION);
          goto error;
        }

        parser->http_major *= 10;
        parser->http_major += ch - '0';

        if (parser->http_major > 999) {
          SET_ERRNO(HPE_INVALID_VERSION);
          goto error;
        }

        break;
      }

      /* first digit of minor HTTP version */
      case s_res_first_http_minor:
        if (!IS_NUM(ch)) {
          SET_ERRNO(HPE_INVALID_VERSION);
          goto error;
        }

        parser->http_minor = ch - '0';
        state = s_res_http_minor;
        break;

      /* minor HTTP version or end of request line */
      case s_res_http_minor:
      {
        if (ch == ' ') {
          state = s_res_first_status_code;
          break;
        }

        if (!IS_NUM(ch)) {
          SET_ERRNO(HPE_INVALID_VERSION);
          goto error;
        }

        parser->http_minor *= 10;
        parser->http_minor += ch - '0';

        if (parser->http_minor > 999) {
          SET_ERRNO(HPE_INVALID_VERSION);
          goto error;
        }

        break;
      }

      case s_res_first_status_code:
      {
        if (!IS_NUM(ch)) {
          if (ch == ' ') {
            break;
          }

          SET_ERRNO(HPE_INVALID_STATUS);
          goto error;
        }
        parser->status_code = ch - '0';
        state = s_res_status_code;
        break;
      }

      case s_res_status_code:
      {
        if (!IS_NUM(ch)) {
          switch (ch) {
            case ' ':
              state = s_res_status;
              break;
            case CR:
              state = s_res_line_almost_done;
              break;
            case LF:
              state = s_header_field_start;
              break;
            default:
              SET_ERRNO(HPE_INVALID_STATUS);
              goto error;
          }
          break;
        }

        parser->status_code *= 10;
        parser->status_code += ch - '0';

        if (parser->status_code > 999) {
          SET_ERRNO(HPE_INVALID_STATUS);
          goto error;
        }

        break;
      }

      case s_res_status:
        /* the human readable status. e.g. "NOT FOUND"
         * we are not humans so just ignore this */
        if (ch == CR) {
          state = s_res_line_almost_done;
          break;
        }

        if (ch == LF) {
          state = s_header_field_start;
          break;
        }
        break;

      case s_res_line_almost_done:
        STRICT_CHECK(ch != LF);
        state = s_header_field_start;
        break;

      case s_start_req:
      {
        if (ch == CR || ch == LF)
          break;
        parser->flags = 0;
        parser->content_length = -1;

        CALLBACK2(message_begin);

        if (!IS_ALPHA(ch)) {
          SET_ERRNO(HPE_INVALID_METHOD);
          goto error;
        }

      start_req_method_assign:
        parser->method = (enum http_method) 0;
        index = 1;
        switch (ch) {
          case 'C': parser->method = HTTP_CONNECT; /* or COPY, CHECKOUT */ break;
          case 'D': parser->method = HTTP_DELETE; break;
          case 'G': parser->method = HTTP_GET; break;
          case 'H': parser->method = HTTP_HEAD; break;
          case 'L': parser->method = HTTP_LOCK; break;
          case 'M': parser->method = HTTP_MKCOL; /* or MOVE, MKACTIVITY, MERGE, M-SEARCH */ break;
          case 'N': parser->method = HTTP_NOTIFY; break;
          case 'O': parser->method = HTTP_OPTIONS; break;
          case 'P': parser->method = HTTP_POST;
            /* or PROPFIND or PROPPATCH or PUT or PATCH */
            break;
          case 'R': parser->method = HTTP_REPORT; break;
          case 'S': parser->method = HTTP_SUBSCRIBE; break;
          case 'T': parser->method = HTTP_TRACE; break;
          case 'U': parser->method = HTTP_UNLOCK; /* or UNSUBSCRIBE */ break;
          default:
            SET_ERRNO(HPE_INVALID_METHOD);
            goto error;
        }
        state = s_req_method;
        break;
      }

      case s_req_method:
      {
        const char *matcher;
        if (ch == '\0') {
          SET_ERRNO(HPE_INVALID_METHOD);
          goto error;
        }

        matcher = method_strings[parser->method];
        if (ch == ' ' && matcher[index] == '\0') {
          state = s_req_spaces_before_url;
        } else if (ch == matcher[index]) {
          ; /* nada */
        } else if (parser->method == HTTP_CONNECT) {
          if (index == 1 && ch == 'H') {
            parser->method = HTTP_CHECKOUT;
          } else if (index == 2  && ch == 'P') {
            parser->method = HTTP_COPY;
          } else {
            goto error;
          }
        } else if (parser->method == HTTP_MKCOL) {
          if (index == 1 && ch == 'O') {
            parser->method = HTTP_MOVE;
          } else if (index == 1 && ch == 'E') {
            parser->method = HTTP_MERGE;
          } else if (index == 1 && ch == '-') {
            parser->method = HTTP_MSEARCH;
          } else if (index == 2 && ch == 'A') {
            parser->method = HTTP_MKACTIVITY;
          } else {
            goto error;
          }
        } else if (index == 1 && parser->method == HTTP_POST) {
          if (ch == 'R') {
            parser->method = HTTP_PROPFIND; /* or HTTP_PROPPATCH */
          } else if (ch == 'U') {
            parser->method = HTTP_PUT;
          } else if (ch == 'A') {
            parser->method = HTTP_PATCH;
          } else {
            goto error;
          }
        } else if (index == 2 && parser->method == HTTP_UNLOCK && ch == 'S') {
          parser->method = HTTP_UNSUBSCRIBE;
        } else if (index == 4 && parser->method == HTTP_PROPFIND && ch == 'P') {
          parser->method = HTTP_PROPPATCH;
        } else {
          SET_ERRNO(HPE_INVALID_METHOD);
          goto error;
        }

        ++index;
        break;
      }
      case s_req_spaces_before_url:
      {
        if (ch == ' ') break;

        if (ch == '/' || ch == '*') {
          MARK(url);
          state = s_req_path;
          break;
        }

        /* Proxied requests are followed by scheme of an absolute URI (alpha).
         * CONNECT is followed by a hostname, which begins with alphanum.
         * All other methods are followed by '/' or '*' (handled above).
         */
        if (IS_ALPHA(ch) || (parser->method == HTTP_CONNECT && IS_NUM(ch))) {
          MARK(url);
          state = (parser->method == HTTP_CONNECT) ? s_req_host : s_req_schema;
          break;
        }

        SET_ERRNO(HPE_INVALID_URL);
        goto error;
      }

      case s_req_schema:
      {
        if (IS_ALPHA(ch)) break;

        if (ch == ':') {
          state = s_req_schema_slash;
          break;
        }

        SET_ERRNO(HPE_INVALID_URL);
        goto error;
      }

      case s_req_schema_slash:
        STRICT_CHECK(ch != '/');
        state = s_req_schema_slash_slash;
        break;

      case s_req_schema_slash_slash:
        STRICT_CHECK(ch != '/');
        state = s_req_host;
        break;

      case s_req_host:
      {
        if (IS_HOST_CHAR(ch)) break;
        switch (ch) {
          case ':':
            state = s_req_port;
            break;
          case '/':
            state = s_req_path;
            break;
          case ' ':
            /* The request line looks like:
             *   "GET http://foo.bar.com HTTP/1.1"
             * That is, there is no path.
             */
            CALLBACK(url);
            state = s_req_http_start;
            break;
          case '?':
            state = s_req_query_string_start;
            break;
          default:
            SET_ERRNO(HPE_INVALID_HOST);
            goto error;
        }
        break;
      }

      case s_req_port:
      {
        if (IS_NUM(ch)) break;
        switch (ch) {
          case '/':
            state = s_req_path;
            break;
          case ' ':
            /* The request line looks like:
             *   "GET http://foo.bar.com:1234 HTTP/1.1"
             * That is, there is no path.
             */
            CALLBACK(url);
            state = s_req_http_start;
            break;
          case '?':
            state = s_req_query_string_start;
            break;
          default:
            SET_ERRNO(HPE_INVALID_PORT);
            goto error;
        }
        break;
      }

      case s_req_path:
      {
        if (IS_URL_CHAR(ch)) break;

        switch (ch) {
          case ' ':
            CALLBACK(url);
            state = s_req_http_start;
            break;
          case CR:
            CALLBACK(url);
            parser->http_major = 0;
            parser->http_minor = 9;
            state = s_req_line_almost_done;
            break;
          case LF:
            CALLBACK(url);
            parser->http_major = 0;
            parser->http_minor = 9;
            state = s_header_field_start;
            break;
          case '?':
            state = s_req_query_string_start;
            break;
          case '#':
            state = s_req_fragment_start;
            break;
          default:
            SET_ERRNO(HPE_INVALID_PATH);
            goto error;
        }
        break;
      }

      case s_req_query_string_start:
      {
        if (IS_URL_CHAR(ch)) {
          state = s_req_query_string;
          break;
        }

        switch (ch) {
          case '?':
            break; /* XXX ignore extra '?' ... is this right? */
          case ' ':
            CALLBACK(url);
            state = s_req_http_start;
            break;
          case CR:
            CALLBACK(url);
            parser->http_major = 0;
            parser->http_minor = 9;
            state = s_req_line_almost_done;
            break;
          case LF:
            CALLBACK(url);
            parser->http_major = 0;
            parser->http_minor = 9;
            state = s_header_field_start;
            break;
          case '#':
            state = s_req_fragment_start;
            break;
          default:
            SET_ERRNO(HPE_INVALID_QUERY_STRING);
            goto error;
        }
        break;
      }

      case s_req_query_string:
      {
        if (IS_URL_CHAR(ch)) break;

        switch (ch) {
          case '?':
            /* allow extra '?' in query string */
            break;
          case ' ':
            CALLBACK(url);
            state = s_req_http_start;
            break;
          case CR:
            CALLBACK(url);
            parser->http_major = 0;
            parser->http_minor = 9;
            state = s_req_line_almost_done;
            break;
          case LF:
            CALLBACK(url);
            parser->http_major = 0;
            parser->http_minor = 9;
            state = s_header_field_start;
            break;
          case '#':
            state = s_req_fragment_start;
            break;
          default:
            SET_ERRNO(HPE_INVALID_QUERY_STRING);
            goto error;
        }
        break;
      }

      case s_req_fragment_start:
      {
        if (IS_URL_CHAR(ch)) {
          state = s_req_fragment;
          break;
        }

        switch (ch) {
          case ' ':
            CALLBACK(url);
            state = s_req_http_start;
            break;
          case CR:
            CALLBACK(url);
            parser->http_major = 0;
            parser->http_minor = 9;
            state = s_req_line_almost_done;
            break;
          case LF:
            CALLBACK(url);
            parser->http_major = 0;
            parser->http_minor = 9;
            state = s_header_field_start;
            break;
          case '?':
            state = s_req_fragment;
            break;
          case '#':
            break;
          default:
            SET_ERRNO(HPE_INVALID_FRAGMENT);
            goto error;
        }
        break;
      }

      case s_req_fragment:
      {
        if (IS_URL_CHAR(ch)) break;

        switch (ch) {
          case ' ':
            CALLBACK(url);
            state = s_req_http_start;
            break;
          case CR:
            CALLBACK(url);
            parser->http_major = 0;
            parser->http_minor = 9;
            state = s_req_line_almost_done;
            break;
          case LF:
            CALLBACK(url);
            parser->http_major = 0;
            parser->http_minor = 9;
            state = s_header_field_start;
            break;
          case '?':
          case '#':
            break;
          default:
            SET_ERRNO(HPE_INVALID_FRAGMENT);
            goto error;
        }
        break;
      }

      case s_req_http_start:
        switch (ch) {
          case 'H':
            state = s_req_http_H;
            break;
          case ' ':
            break;
          default:
            SET_ERRNO(HPE_INVALID_CONSTANT);
            goto error;
        }
        break;

      case s_req_http_H:
        STRICT_CHECK(ch != 'T');
        state = s_req_http_HT;
        break;

      case s_req_http_HT:
        STRICT_CHECK(ch != 'T');
        state = s_req_http_HTT;
        break;

      case s_req_http_HTT:
        STRICT_CHECK(ch != 'P');
        state = s_req_http_HTTP;
        break;

      case s_req_http_HTTP:
        STRICT_CHECK(ch != '/');
        state = s_req_first_http_major;
        break;

      /* first digit of major HTTP version */
      case s_req_first_http_major:
        if (ch < '1' || ch > '9') {
          SET_ERRNO(HPE_INVALID_VERSION);
          goto error;
        }

        parser->http_major = ch - '0';
        state = s_req_http_major;
        break;

      /* major HTTP version or dot */
      case s_req_http_major:
      {
        if (ch == '.') {
          state = s_req_first_http_minor;
          break;
        }

        if (!IS_NUM(ch)) {
          SET_ERRNO(HPE_INVALID_VERSION);
          goto error;
        }

        parser->http_major *= 10;
        parser->http_major += ch - '0';

        if (parser->http_major > 999) {
          SET_ERRNO(HPE_INVALID_VERSION);
          goto error;
        }

        break;
      }

      /* first digit of minor HTTP version */
      case s_req_first_http_minor:
        if (!IS_NUM(ch)) {
          SET_ERRNO(HPE_INVALID_VERSION);
          goto error;
        }

        parser->http_minor = ch - '0';
        state = s_req_http_minor;
        break;

      /* minor HTTP version or end of request line */
      case s_req_http_minor:
      {
        if (ch == CR) {
          state = s_req_line_almost_done;
          break;
        }

        if (ch == LF) {
          state = s_header_field_start;
          break;
        }

        /* XXX allow spaces after digit? */

        if (!IS_NUM(ch)) {
          SET_ERRNO(HPE_INVALID_VERSION);
          goto error;
        }

        parser->http_minor *= 10;
        parser->http_minor += ch - '0';

        if (parser->http_minor > 999) {
          SET_ERRNO(HPE_INVALID_VERSION);
          goto error;
        }

        break;
      }

      /* end of request line */
      case s_req_line_almost_done:
      {
        if (ch != LF) {
          SET_ERRNO(HPE_LF_EXPECTED);
          goto error;
        }

        state = s_header_field_start;
        break;
      }

      case s_header_field_start:
      header_field_start:
      {
        if (ch == CR) {
          state = s_headers_almost_done;
          break;
        }

        if (ch == LF) {
          /* they might be just sending \n instead of \r\n so this would be
           * the second \n to denote the end of headers*/
          state = s_headers_almost_done;
          goto headers_almost_done;
        }

        c = TOKEN(ch);

        if (!c) {
          SET_ERRNO(HPE_INVALID_HEADER_TOKEN);
          goto error;
        }

        MARK(header_field);

        index = 0;
        state = s_header_field;

        switch (c) {
          case 'c':
            header_state = h_C;
            break;

          case 'p':
            header_state = h_matching_proxy_connection;
            break;

          case 't':
            header_state = h_matching_transfer_encoding;
            break;

          case 'u':
            header_state = h_matching_upgrade;
            break;

          default:
            header_state = h_general;
            break;
        }
        break;
      }

      case s_header_field:
      {
        c = TOKEN(ch);

        if (c) {
          switch (header_state) {
            case h_general:
              break;

            case h_C:
              index++;
              header_state = (c == 'o' ? h_CO : h_general);
              break;

            case h_CO:
              index++;
              header_state = (c == 'n' ? h_CON : h_general);
              break;

            case h_CON:
              index++;
              switch (c) {
                case 'n':
                  header_state = h_matching_connection;
                  break;
                case 't':
                  header_state = h_matching_content_length;
                  break;
                default:
                  header_state = h_general;
                  break;
              }
              break;

            /* connection */

            case h_matching_connection:
              index++;
              if (index > sizeof(CONNECTION)-1
                  || c != CONNECTION[index]) {
                header_state = h_general;
              } else if (index == sizeof(CONNECTION)-2) {
                header_state = h_connection;
              }
              break;

            /* proxy-connection */

            case h_matching_proxy_connection:
              index++;
              if (index > sizeof(PROXY_CONNECTION)-1
                  || c != PROXY_CONNECTION[index]) {
                header_state = h_general;
              } else if (index == sizeof(PROXY_CONNECTION)-2) {
                header_state = h_connection;
              }
              break;

            /* content-length */

            case h_matching_content_length:
              index++;
              if (index > sizeof(CONTENT_LENGTH)-1
                  || c != CONTENT_LENGTH[index]) {
                header_state = h_general;
              } else if (index == sizeof(CONTENT_LENGTH)-2) {
                header_state = h_content_length;
              }
              break;

            /* transfer-encoding */

            case h_matching_transfer_encoding:
              index++;
              if (index > sizeof(TRANSFER_ENCODING)-1
                  || c != TRANSFER_ENCODING[index]) {
                header_state = h_general;
              } else if (index == sizeof(TRANSFER_ENCODING)-2) {
                header_state = h_transfer_encoding;
              }
              break;

            /* upgrade */

            case h_matching_upgrade:
              index++;
              if (index > sizeof(UPGRADE)-1
                  || c != UPGRADE[index]) {
                header_state = h_general;
              } else if (index == sizeof(UPGRADE)-2) {
                header_state = h_upgrade;
              }
              break;

            case h_connection:
            case h_content_length:
            case h_transfer_encoding:
            case h_upgrade:
              if (ch != ' ') header_state = h_general;
              break;

            default:
              assert(0 && "Unknown header_state");
              break;
          }
          break;
        }

        if (ch == ':') {
          CALLBACK(header_field);
          state = s_header_value_start;
          break;
        }

        if (ch == CR) {
          state = s_header_almost_done;
          CALLBACK(header_field);
          break;
        }

        if (ch == LF) {
          CALLBACK(header_field);
          state = s_header_field_start;
          break;
        }

        SET_ERRNO(HPE_INVALID_HEADER_TOKEN);
        goto error;
      }

      case s_header_value_start:
      {
        if (ch == ' ' || ch == '\t') break;

        MARK(header_value);

        state = s_header_value;
        index = 0;

        if (ch == CR) {
          CALLBACK(header_value);
          header_state = h_general;
          state = s_header_almost_done;
          break;
        }

        if (ch == LF) {
          CALLBACK(header_value);
          state = s_header_field_start;
          break;
        }

        c = LOWER(ch);

        switch (header_state) {
          case h_upgrade:
            parser->flags |= F_UPGRADE;
            header_state = h_general;
            break;

          case h_transfer_encoding:
            /* looking for 'Transfer-Encoding: chunked' */
            if ('c' == c) {
              header_state = h_matching_transfer_encoding_chunked;
            } else {
              header_state = h_general;
            }
            break;

          case h_content_length:
            if (!IS_NUM(ch)) {
              SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
              goto error;
            }

            parser->content_length = ch - '0';
            break;

          case h_connection:
            /* looking for 'Connection: keep-alive' */
            if (c == 'k') {
              header_state = h_matching_connection_keep_alive;
            /* looking for 'Connection: close' */
            } else if (c == 'c') {
              header_state = h_matching_connection_close;
            } else {
              header_state = h_general;
            }
            break;

          default:
            header_state = h_general;
            break;
        }
        break;
      }

      case s_header_value:
      {

        if (ch == CR) {
          CALLBACK(header_value);
          state = s_header_almost_done;
          break;
        }

        if (ch == LF) {
          CALLBACK(header_value);
          goto header_almost_done;
        }

        c = LOWER(ch);

        switch (header_state) {
          case h_general:
            break;

          case h_connection:
          case h_transfer_encoding:
            assert(0 && "Shouldn't get here.");
            break;

          case h_content_length:
            if (ch == ' ') break;
            if (!IS_NUM(ch)) {
              SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
              goto error;
            }

            parser->content_length *= 10;
            parser->content_length += ch - '0';
            break;

          /* Transfer-Encoding: chunked */
          case h_matching_transfer_encoding_chunked:
            index++;
            if (index > sizeof(CHUNKED)-1
                || c != CHUNKED[index]) {
              header_state = h_general;
            } else if (index == sizeof(CHUNKED)-2) {
              header_state = h_transfer_encoding_chunked;
            }
            break;

          /* looking for 'Connection: keep-alive' */
          case h_matching_connection_keep_alive:
            index++;
            if (index > sizeof(KEEP_ALIVE)-1
                || c != KEEP_ALIVE[index]) {
              header_state = h_general;
            } else if (index == sizeof(KEEP_ALIVE)-2) {
              header_state = h_connection_keep_alive;
            }
            break;

          /* looking for 'Connection: close' */
          case h_matching_connection_close:
            index++;
            if (index > sizeof(CLOSE)-1 || c != CLOSE[index]) {
              header_state = h_general;
            } else if (index == sizeof(CLOSE)-2) {
              header_state = h_connection_close;
            }
            break;

          case h_transfer_encoding_chunked:
          case h_connection_keep_alive:
          case h_connection_close:
            if (ch != ' ') header_state = h_general;
            break;

          default:
            state = s_header_value;
            header_state = h_general;
            break;
        }
        break;
      }

      case s_header_almost_done:
      header_almost_done:
      {
        STRICT_CHECK(ch != LF);

        state = s_header_value_lws;

        switch (header_state) {
          case h_connection_keep_alive:
            parser->flags |= F_CONNECTION_KEEP_ALIVE;
            break;
          case h_connection_close:
            parser->flags |= F_CONNECTION_CLOSE;
            break;
          case h_transfer_encoding_chunked:
            parser->flags |= F_CHUNKED;
            break;
          default:
            break;
        }
        break;
      }

      case s_header_value_lws:
      {
        if (ch == ' ' || ch == '\t')
          state = s_header_value_start;
        else
        {
          state = s_header_field_start;
          goto header_field_start;
        }
        break;
      }

      case s_headers_almost_done:
      headers_almost_done:
      {
        STRICT_CHECK(ch != LF);

        if (parser->flags & F_TRAILING) {
          /* End of a chunked request */
          CALLBACK2(message_complete);
          state = NEW_MESSAGE();
          break;
        }

        nread = 0;

        if (parser->flags & F_UPGRADE || parser->method == HTTP_CONNECT) {
          parser->upgrade = 1;
        }

        /* Here we call the headers_complete callback. This is somewhat
         * different than other callbacks because if the user returns 1, we
         * will interpret that as saying that this message has no body. This
         * is needed for the annoying case of recieving a response to a HEAD
         * request.
         */
        if (settings->on_headers_complete) {
          switch (settings->on_headers_complete(parser)) {
            case 0:
              break;

            case 1:
              parser->flags |= F_SKIPBODY;
              break;

            default:
              parser->state = state;
              SET_ERRNO(HPE_CB_headers_complete);
              return p - data; /* Error */
          }
        }

        /* Exit, the rest of the connect is in a different protocol. */
        if (parser->upgrade) {
          CALLBACK2(message_complete);
          return (p - data) + 1;
        }

        if (parser->flags & F_SKIPBODY) {
          CALLBACK2(message_complete);
          state = NEW_MESSAGE();
        } else if (parser->flags & F_CHUNKED) {
          /* chunked encoding - ignore Content-Length header */
          state = s_chunk_size_start;
        } else {
          if (parser->content_length == 0) {
            /* Content-Length header given but zero: Content-Length: 0\r\n */
            CALLBACK2(message_complete);
            state = NEW_MESSAGE();
          } else if (parser->content_length > 0) {
            /* Content-Length header given and non-zero */
            state = s_body_identity;
          } else {
            if (parser->type == HTTP_REQUEST || http_should_keep_alive(parser)) {
              /* Assume content-length 0 - read the next */
              CALLBACK2(message_complete);
              state = NEW_MESSAGE();
            } else {
              /* Read body until EOF */
              state = s_body_identity_eof;
            }
          }
        }

        break;
      }

      case s_body_identity:
        to_read = MIN(pe - p, (int64_t)parser->content_length);
        if (to_read > 0) {
          if (settings->on_body) settings->on_body(parser, p, to_read);
          p += to_read - 1;
          parser->content_length -= to_read;
          if (parser->content_length == 0) {
            CALLBACK2(message_complete);
            state = NEW_MESSAGE();
          }
        }
        break;

      /* read until EOF */
      case s_body_identity_eof:
        to_read = pe - p;
        if (to_read > 0) {
          if (settings->on_body) settings->on_body(parser, p, to_read);
          p += to_read - 1;
        }
        break;

      case s_chunk_size_start:
      {
        assert(nread == 1);
        assert(parser->flags & F_CHUNKED);

        unhex_val = unhex[(unsigned char)ch];
        if (unhex_val == -1) {
          SET_ERRNO(HPE_INVALID_CHUNK_SIZE);
          goto error;
        }

        parser->content_length = unhex_val;
        state = s_chunk_size;
        break;
      }

      case s_chunk_size:
      {
        assert(parser->flags & F_CHUNKED);

        if (ch == CR) {
          state = s_chunk_size_almost_done;
          break;
        }

        unhex_val = unhex[(unsigned char)ch];

        if (unhex_val == -1) {
          if (ch == ';' || ch == ' ') {
            state = s_chunk_parameters;
            break;
          }

          SET_ERRNO(HPE_INVALID_CHUNK_SIZE);
          goto error;
        }

        parser->content_length *= 16;
        parser->content_length += unhex_val;
        break;
      }

      case s_chunk_parameters:
      {
        assert(parser->flags & F_CHUNKED);
        /* just ignore this shit. TODO check for overflow */
        if (ch == CR) {
          state = s_chunk_size_almost_done;
          break;
        }
        break;
      }

      case s_chunk_size_almost_done:
      {
        assert(parser->flags & F_CHUNKED);
        STRICT_CHECK(ch != LF);

        nread = 0;

        if (parser->content_length == 0) {
          parser->flags |= F_TRAILING;
          state = s_header_field_start;
        } else {
          state = s_chunk_data;
        }
        break;
      }

      case s_chunk_data:
      {
        assert(parser->flags & F_CHUNKED);

        to_read = MIN(pe - p, (int64_t)(parser->content_length));

        if (to_read > 0) {
          if (settings->on_body) settings->on_body(parser, p, to_read);
          p += to_read - 1;
        }

        if (to_read == parser->content_length) {
          state = s_chunk_data_almost_done;
        }

        parser->content_length -= to_read;
        break;
      }

      case s_chunk_data_almost_done:
        assert(parser->flags & F_CHUNKED);
        STRICT_CHECK(ch != CR);
        state = s_chunk_data_done;
        break;

      case s_chunk_data_done:
        assert(parser->flags & F_CHUNKED);
        STRICT_CHECK(ch != LF);
        state = s_chunk_size_start;
        break;

      default:
        assert(0 && "unhandled state");
        SET_ERRNO(HPE_INVALID_INTERNAL_STATE);
        goto error;
    }
  }

#if defined(HTTP_PARSER_USE_RESTART)
  if (url_mark) return (url_mark - data);
  if (header_field_mark) return (header_field_mark - data);
  if (header_value_mark) return (header_value_mark - data);
#else
  CALLBACK(header_field);
  CALLBACK(header_value);
  CALLBACK(url);
#endif

  parser->state = state;
  parser->header_state = header_state;
  parser->index = index;
  parser->nread = nread;

  return len;

error:
  if (HTTP_PARSER_ERRNO(parser) == HPE_OK) {
    SET_ERRNO(HPE_UNKNOWN);
  }

  return (p - data);
}
Example #19
0
int execlp(const char *file, const char *arg0,
		... /*, (char *)0 */) {
	printk(">>> %s %s %s\n", __func__, file, arg0);
	return SET_ERRNO(ENOSYS);
}
Example #20
0
static int ProcessRequest(struct httprequest *req)
{
  char *line=&req->reqbuf[req->checkindex];
  bool chunked = FALSE;
  static char request[REQUEST_KEYWORD_SIZE];
  static char doc[MAXDOCNAMELEN];
  char logbuf[256];
  int prot_major, prot_minor;
  char *end;
  int error;
  end = strstr(line, end_of_headers);

  logmsg("ProcessRequest() called");

  /* try to figure out the request characteristics as soon as possible, but
     only once! */

  if(use_gopher &&
     (req->testno == DOCNUMBER_NOTHING) &&
     !strncmp("/verifiedserver", line, 15)) {
    logmsg("Are-we-friendly question received");
    req->testno = DOCNUMBER_WERULEZ;
    return 1; /* done */
  }

  else if((req->testno == DOCNUMBER_NOTHING) &&
     sscanf(line,
            "%" REQUEST_KEYWORD_SIZE_TXT"s %" MAXDOCNAMELEN_TXT "s HTTP/%d.%d",
            request,
            doc,
            &prot_major,
            &prot_minor) == 4) {
    char *ptr;

    req->prot_version = prot_major*10 + prot_minor;

    /* find the last slash */
    ptr = strrchr(doc, '/');

    /* get the number after it */
    if(ptr) {
      FILE *stream;
      char *filename;

      if((strlen(doc) + strlen(request)) < 200)
        sprintf(logbuf, "Got request: %s %s HTTP/%d.%d",
                request, doc, prot_major, prot_minor);
      else
        sprintf(logbuf, "Got a *HUGE* request HTTP/%d.%d",
                prot_major, prot_minor);
      logmsg("%s", logbuf);

      if(!strncmp("/verifiedserver", ptr, 15)) {
        logmsg("Are-we-friendly question received");
        req->testno = DOCNUMBER_WERULEZ;
        return 1; /* done */
      }

      if(!strncmp("/quit", ptr, 5)) {
        logmsg("Request-to-quit received");
        req->testno = DOCNUMBER_QUIT;
        return 1; /* done */
      }

      ptr++; /* skip the slash */

      /* skip all non-numericals following the slash */
      while(*ptr && !ISDIGIT(*ptr))
        ptr++;

      req->testno = strtol(ptr, &ptr, 10);

      if(req->testno > 10000) {
        req->partno = req->testno % 10000;
        req->testno /= 10000;
      }
      else
        req->partno = 0;

      sprintf(logbuf, "Requested test number %ld part %ld",
              req->testno, req->partno);
      logmsg("%s", logbuf);

      filename = test2file(req->testno);

      stream=fopen(filename, "rb");
      if(!stream) {
        error = ERRNO;
        logmsg("fopen() failed with error: %d %s", error, strerror(error));
        logmsg("Error opening file: %s", filename);
        logmsg("Couldn't open test file %ld", req->testno);
        req->open = FALSE; /* closes connection */
        return 1; /* done */
      }
      else {
        char *orgcmd = NULL;
        char *cmd = NULL;
        size_t cmdsize = 0;
        int num=0;

        /* get the custom server control "commands" */
        error = getpart(&orgcmd, &cmdsize, "reply", "servercmd", stream);
        fclose(stream);
        if(error) {
          logmsg("getpart() failed with error: %d", error);
          req->open = FALSE; /* closes connection */
          return 1; /* done */
        }

        cmd = orgcmd;
        while(cmd && cmdsize) {
          char *check;

          if(!strncmp(CMD_AUTH_REQUIRED, cmd, strlen(CMD_AUTH_REQUIRED))) {
            logmsg("instructed to require authorization header");
            req->auth_req = TRUE;
          }
          else if(!strncmp(CMD_IDLE, cmd, strlen(CMD_IDLE))) {
            logmsg("instructed to idle");
            req->rcmd = RCMD_IDLE;
            req->open = TRUE;
          }
          else if(!strncmp(CMD_STREAM, cmd, strlen(CMD_STREAM))) {
            logmsg("instructed to stream");
            req->rcmd = RCMD_STREAM;
          }
          else if(1 == sscanf(cmd, "pipe: %d", &num)) {
            logmsg("instructed to allow a pipe size of %d", num);
            if(num < 0)
              logmsg("negative pipe size ignored");
            else if(num > 0)
              req->pipe = num-1; /* decrease by one since we don't count the
                                    first request in this number */
          }
          else if(1 == sscanf(cmd, "skip: %d", &num)) {
            logmsg("instructed to skip this number of bytes %d", num);
            req->skip = num;
          }
          else if(1 == sscanf(cmd, "writedelay: %d", &num)) {
            logmsg("instructed to delay %d secs between packets", num);
            req->writedelay = num;
          }
          else {
            logmsg("funny instruction found: %s", cmd);
          }
          /* try to deal with CRLF or just LF */
          check = strchr(cmd, '\r');
          if(!check)
            check = strchr(cmd, '\n');

          if(check) {
            /* get to the letter following the newline */
            while((*check == '\r') || (*check == '\n'))
              check++;

            if(!*check)
              /* if we reached a zero, get out */
              break;
            cmd = check;
          }
          else
            break;
        }
        if(orgcmd)
          free(orgcmd);
      }
    }
    else {
      if(sscanf(req->reqbuf, "CONNECT %" MAXDOCNAMELEN_TXT "s HTTP/%d.%d",
                doc, &prot_major, &prot_minor) == 3) {
        sprintf(logbuf, "Received a CONNECT %s HTTP/%d.%d request",
                doc, prot_major, prot_minor);
        logmsg("%s", logbuf);

        if(req->prot_version == 10)
          req->open = FALSE; /* HTTP 1.0 closes connection by default */

        if(!strncmp(doc, "bad", 3))
          /* if the host name starts with bad, we fake an error here */
          req->testno = DOCNUMBER_BADCONNECT;
        else if(!strncmp(doc, "test", 4)) {
          /* if the host name starts with test, the port number used in the
             CONNECT line will be used as test number! */
          char *portp = strchr(doc, ':');
          if(portp && (*(portp+1) != '\0') && ISDIGIT(*(portp+1)))
            req->testno = strtol(portp+1, NULL, 10);
          else
            req->testno = DOCNUMBER_CONNECT;
        }
        else
          req->testno = DOCNUMBER_CONNECT;
      }
      else {
        logmsg("Did not find test number in PATH");
        req->testno = DOCNUMBER_404;
      }
    }
  }

  if(!end) {
    /* we don't have a complete request yet! */
    logmsg("ProcessRequest returned without a complete request");
    return 0; /* not complete yet */
  }
  logmsg("ProcessRequest found a complete request");

  if(use_gopher) {
    /* when using gopher we cannot check the request until the entire
       thing has been received */
    char *ptr;

    /* find the last slash in the line */
    ptr = strrchr(line, '/');

    if(ptr) {
      ptr++; /* skip the slash */

      /* skip all non-numericals following the slash */
      while(*ptr && !ISDIGIT(*ptr))
        ptr++;

      req->testno = strtol(ptr, &ptr, 10);

      if(req->testno > 10000) {
        req->partno = req->testno % 10000;
        req->testno /= 10000;
      }
      else
        req->partno = 0;

      sprintf(logbuf, "Requested GOPHER test number %ld part %ld",
              req->testno, req->partno);
      logmsg("%s", logbuf);
    }
  }

  if(req->pipe)
    /* we do have a full set, advance the checkindex to after the end of the
       headers, for the pipelining case mostly */
    req->checkindex += (end - line) + strlen(end_of_headers);

  /* **** Persistence ****
   *
   * If the request is a HTTP/1.0 one, we close the connection unconditionally
   * when we're done.
   *
   * If the request is a HTTP/1.1 one, we MUST check for a "Connection:"
   * header that might say "close". If it does, we close a connection when
   * this request is processed. Otherwise, we keep the connection alive for X
   * seconds.
   */

  do {
    if(got_exit_signal)
      return 1; /* done */

    if((req->cl==0) && curlx_strnequal("Content-Length:", line, 15)) {
      /* If we don't ignore content-length, we read it and we read the whole
         request including the body before we return. If we've been told to
         ignore the content-length, we will return as soon as all headers
         have been received */
      char *endptr;
      char *ptr = line + 15;
      unsigned long clen = 0;
      while(*ptr && ISSPACE(*ptr))
        ptr++;
      endptr = ptr;
      SET_ERRNO(0);
      clen = strtoul(ptr, &endptr, 10);
      if((ptr == endptr) || !ISSPACE(*endptr) || (ERANGE == ERRNO)) {
        /* this assumes that a zero Content-Length is valid */
        logmsg("Found invalid Content-Length: (%s) in the request", ptr);
        req->open = FALSE; /* closes connection */
        return 1; /* done */
      }
      req->cl = clen - req->skip;

      logmsg("Found Content-Length: %lu in the request", clen);
      if(req->skip)
        logmsg("... but will abort after %zu bytes", req->cl);
      break;
    }
    else if(curlx_strnequal("Transfer-Encoding: chunked", line,
                            strlen("Transfer-Encoding: chunked"))) {
      /* chunked data coming in */
      chunked = TRUE;
    }

    if(chunked) {
      if(strstr(req->reqbuf, "\r\n0\r\n\r\n"))
        /* end of chunks reached */
        return 1; /* done */
      else
        return 0; /* not done */
    }

    line = strchr(line, '\n');
    if(line)
      line++;

  } while(line);

  if(!req->auth && strstr(req->reqbuf, "Authorization:")) {
    req->auth = TRUE; /* Authorization: header present! */
    if(req->auth_req)
      logmsg("Authorization header found, as required");
  }

  if(!req->digest && strstr(req->reqbuf, "Authorization: Digest")) {
    /* If the client is passing this Digest-header, we set the part number
       to 1000. Not only to spice up the complexity of this, but to make
       Digest stuff to work in the test suite. */
    req->partno += 1000;
    req->digest = TRUE; /* header found */
    logmsg("Received Digest request, sending back data %ld", req->partno);
  }
  else if(!req->ntlm &&
          strstr(req->reqbuf, "Authorization: NTLM TlRMTVNTUAAD")) {
    /* If the client is passing this type-3 NTLM header */
    req->partno += 1002;
    req->ntlm = TRUE; /* NTLM found */
    logmsg("Received NTLM type-3, sending back data %ld", req->partno);
    if(req->cl) {
      logmsg("  Expecting %zu POSTed bytes", req->cl);
    }
  }
  else if(!req->ntlm &&
          strstr(req->reqbuf, "Authorization: NTLM TlRMTVNTUAAB")) {
    /* If the client is passing this type-1 NTLM header */
    req->partno += 1001;
    req->ntlm = TRUE; /* NTLM found */
    logmsg("Received NTLM type-1, sending back data %ld", req->partno);
  }
  else if((req->partno >= 1000) && strstr(req->reqbuf, "Authorization: Basic")) {
    /* If the client is passing this Basic-header and the part number is already
       >=1000, we add 1 to the part number.  This allows simple Basic authentication
       negotiation to work in the test suite. */
    req->partno += 1;
    logmsg("Received Basic request, sending back data %ld", req->partno);
  }
  if(strstr(req->reqbuf, "Connection: close"))
    req->open = FALSE; /* close connection after this request */

  if(!req->pipe &&
     req->open &&
     req->prot_version >= 11 &&
     end &&
     req->reqbuf + req->offset > end + strlen(end_of_headers) &&
     (!strncmp(req->reqbuf, "GET", strlen("GET")) ||
      !strncmp(req->reqbuf, "HEAD", strlen("HEAD")))) {
    /* If we have a persistent connection, HTTP version >= 1.1
       and GET/HEAD request, enable pipelining. */
    req->checkindex = (end - req->reqbuf) + strlen(end_of_headers);
    req->pipelining = TRUE;
  }

  while(req->pipe) {
    if(got_exit_signal)
      return 1; /* done */
    /* scan for more header ends within this chunk */
    line = &req->reqbuf[req->checkindex];
    end = strstr(line, end_of_headers);
    if(!end)
      break;
    req->checkindex += (end - line) + strlen(end_of_headers);
    req->pipe--;
  }

  /* If authentication is required and no auth was provided, end now. This
     makes the server NOT wait for PUT/POST data and you can then make the
     test case send a rejection before any such data has been sent. Test case
     154 uses this.*/
  if(req->auth_req && !req->auth)
    return 1; /* done */

  if(req->cl > 0) {
    if(req->cl <= req->offset - (end - req->reqbuf) - strlen(end_of_headers))
      return 1; /* done */
    else
      return 0; /* not complete yet */
  }

  return 1; /* done */
}
int
ipmi_cipher_suite_id_to_algorithms (uint8_t cipher_suite_id,
                                    uint8_t *authentication_algorithm,
                                    uint8_t *integrity_algorithm,
                                    uint8_t *confidentiality_algorithm)
{
  uint8_t a, i, c;

  /* To avoid gcc warnings, add +1 to comparison */
  if (!((cipher_suite_id + 1) >= 1
	&& cipher_suite_id <= 19))
    {
      SET_ERRNO (EINVAL);
      return (-1);
    }

  if (cipher_suite_id == 0)
    a = IPMI_AUTHENTICATION_ALGORITHM_RAKP_NONE;
  else if (cipher_suite_id >= 1 && cipher_suite_id <= 5)
    a = IPMI_AUTHENTICATION_ALGORITHM_RAKP_HMAC_SHA1;
  else if (cipher_suite_id >= 6 && cipher_suite_id <= 14)
    a = IPMI_AUTHENTICATION_ALGORITHM_RAKP_HMAC_MD5;
  else /* cipher_suite_id >= 15 && cipher_suite_id <= 19 */
    a = IPMI_AUTHENTICATION_ALGORITHM_RAKP_HMAC_SHA256;

  if (cipher_suite_id == 0
      || cipher_suite_id == 1
      || cipher_suite_id == 6
      || cipher_suite_id == 15)
    i = IPMI_INTEGRITY_ALGORITHM_NONE;
  else if (cipher_suite_id >= 2 && cipher_suite_id <= 5)
    i = IPMI_INTEGRITY_ALGORITHM_HMAC_SHA1_96;
  else if (cipher_suite_id >= 7 && cipher_suite_id <= 10)
    i = IPMI_INTEGRITY_ALGORITHM_HMAC_MD5_128;
  else if (cipher_suite_id >= 11 && cipher_suite_id <= 14)
    i = IPMI_INTEGRITY_ALGORITHM_MD5_128;
  else /* cipher_suite_id >= 16 && cipher_suite_id <= 19 */
    i = IPMI_INTEGRITY_ALGORITHM_HMAC_SHA256_128;

  if (cipher_suite_id == 0
      || cipher_suite_id == 1
      || cipher_suite_id == 2
      || cipher_suite_id == 6
      || cipher_suite_id == 7
      || cipher_suite_id == 11
      || cipher_suite_id == 15
      || cipher_suite_id == 16)
    c = IPMI_CONFIDENTIALITY_ALGORITHM_NONE;
  else if (cipher_suite_id == 3
           || cipher_suite_id == 8
           || cipher_suite_id == 12
           || cipher_suite_id == 17)
    c = IPMI_CONFIDENTIALITY_ALGORITHM_AES_CBC_128;
  else if (cipher_suite_id == 4
           || cipher_suite_id == 9
           || cipher_suite_id == 13
           || cipher_suite_id == 18)
    c = IPMI_CONFIDENTIALITY_ALGORITHM_XRC4_128;
  else /* cipher_suite_id == 5
          || cipher_suite_id == 10
          || cipher_suite_id == 14
          || cipher_suite_id == 19 */
    c = IPMI_CONFIDENTIALITY_ALGORITHM_XRC4_40;

  if (authentication_algorithm)
    *authentication_algorithm = a;
  if (integrity_algorithm)
    *integrity_algorithm = i;
  if (confidentiality_algorithm)
    *confidentiality_algorithm = c;

  return (0);
}
Example #22
0
BOOL	MIOMusic_PlayFile (EventDescriptor *pmEvent, OOTstring pmPath)
{
    char	myFilePath[4096];
    int		myKind;
    int		mySoundID;
    Sound	*mySound;
    PreLoadFile	*myPtr = stPreLoadHead;
    
    if (!stAllowSound)
    {
        SET_ERRNO(E_MUSIC_DISABLED);
        return FALSE;
    }

    /* File name is "CD" or "CD:<track>" */
    if ((strlen (pmPath) >= 2) &&
        (((pmPath [0] == 'c') || (pmPath [0] == 'C')) &&
	 ((pmPath [1] == 'd') || (pmPath [1] == 'D')) &&
	 ((pmPath [2] == 0) || (pmPath [2] == ':'))))
    {
	if (MDIOMusic_FileCDPlay (&pmPath [2], &myKind, &mySoundID)) 
	{
	    mySound = (Sound *) malloc (sizeof (Sound));
	    mySound -> fileKind = myKind;
	    mySound -> soundID = mySoundID;
	    
	    pmEvent -> mode  = EventMode_PlayFileDone;
	    pmEvent -> count = (int) mySound;
	    return TRUE;
	}
    }

    if (!MIOFile_ConvertPath (pmPath, NULL, myFilePath, NO_TRAILING_SLASH))
    {
	return FALSE;
    }

    while (myPtr != NULL)
    {
    	if (stricmp (myPtr -> pathName, myFilePath) == 0)
    	{
    	    if (MDIOMusic_PreLoadPlay (myPtr -> mdInfo, &myKind, &mySoundID))
    	    {
		mySound = (Sound *) malloc (sizeof (Sound));
		mySound -> fileKind = myKind;
		mySound -> soundID = mySoundID;
		
		pmEvent -> mode  = EventMode_PlayFileDone;
		pmEvent -> count = (int) mySound;
	    	return TRUE;
    	    }
	    return FALSE;
	}
	myPtr = myPtr -> next;
    } // while
    
    /* File name is <pmPath>.wav */
    if (stricmp (".wav", &myFilePath [strlen (myFilePath) - 4]) == 0)
    {
	if (MDIOMusic_FileWAVEPlay (myFilePath, &myKind, &mySoundID))
	{
	    mySound = (Sound *) malloc (sizeof (Sound));
	    mySound -> fileKind = myKind;
	    mySound -> soundID = mySoundID;
	    
	    pmEvent -> mode  = EventMode_PlayFileDone;
	    pmEvent -> count = (int) mySound;
	    return TRUE;
	}
	return FALSE;
    }

    /* File name is <pmPath>.mp3 */
    if (stricmp (".mp3", &myFilePath [strlen (myFilePath) - 4]) == 0)
    {
	if (MDIOMusic_FileMP3Play (myFilePath, &myKind, &mySoundID))
	{
	    mySound = (Sound *) malloc (sizeof (Sound));
	    mySound -> fileKind = myKind;
	    mySound -> soundID = mySoundID;
	    
	    pmEvent -> mode  = EventMode_PlayFileDone;
	    pmEvent -> count = (int) mySound;
	    return TRUE;
	}
	return FALSE;
    }

    /* File name is <pmPath>.mid */
    if ((stricmp (".mid", &myFilePath [strlen (myFilePath) - 4]) == 0) ||
        (stricmp (".midi", &myFilePath [strlen (myFilePath) - 5]) == 0))
    {
	if (MDIOMusic_FileMIDIPlay (myFilePath, &myKind, &mySoundID))
	{
	    mySound = (Sound *) malloc (sizeof (Sound));
	    mySound -> fileKind = myKind;
	    mySound -> soundID = mySoundID;
	    
	    pmEvent -> mode  = EventMode_PlayFileDone;
	    pmEvent -> count = (int) mySound;
	    return TRUE;
	}
	return FALSE;
    }

    SET_ERRNO(E_MUSIC_UNKNOWN_FILE_TYPE);
    
    return FALSE;
} // MIOMusic_PlayFile
Example #23
0
static int fuse_operations_mount_fcntl(struct MountsPublicInterface* this_, int fd, int cmd, ...) {
    ZRT_LOG(L_INFO, "cmd=%s", STR_FCNTL_CMD(cmd));
    SET_ERRNO(ENOSYS);
    return -1;
}
Example #24
0
static void	MyParsePlayString (const OOTstring pmPlayStr,
				   TONE_RECORD pmToneList [],
				   int *pmNumTones)
{
    #define NUM_NOTE_TYPES	6

    char    	*myPtr = pmPlayStr;
    char    	myChar;
    int	    	myNoteInd, myNote;
    int		cnt;
    static char stMyNoteCode [NUM_NOTE_TYPES] = 
			    { '1', '2', '4', '8', '6', '3' };

    *pmNumTones = 0;

    while (*myPtr != 0) 
    {
	myChar = tolower (*myPtr);

	if (isdigit (myChar)) 
	{
            cnt = 0;

	    while ((cnt < NUM_NOTE_TYPES) && (myChar != stMyNoteCode [cnt]))
	    {
		cnt++;
	    }

	    if (cnt == NUM_NOTE_TYPES) 
	    {
		SET_ERRNO(E_MUSIC_BAD_PLAY_CHAR);
	    }
	    else 
	    {
		stNoteDiv = (1 << cnt);
	    }
	}
	else if (('a' <= myChar) && (myChar <= 'g'))
	{
	    myNoteInd = 
		((( myChar < 'c' ) ? (myChar - 'a' + 5) : (myChar - 'c')));
	    myNote = stToneBase [myNoteInd];

	    // Check for flat or sharp
	    if (*(myPtr + 1) == '-') 
	    {
		myNote--;
		myPtr++;
	    }
	    else if (*(myPtr + 1) == '+') 
	    {
		myNote++;
		myPtr++;
	    }

	    // Fill in a tone record

	    pmToneList [*pmNumTones].midiTone = (myNote - 1) + stOctave * 12;
	    pmToneList [*pmNumTones].freq =
		FREQ_FACTOR / (stToneDivisor [myNote] / ( 1 << stOctave ));
	    pmToneList [*pmNumTones].duration = stWholeNoteDuration / stNoteDiv;
	    pmToneList [*pmNumTones].volume = stVolume;
	    (*pmNumTones)++;
	}
	else if (myChar == 'p') 
	{
	    // Fill in a tone record
	    pmToneList [*pmNumTones].midiTone = -1;
	    pmToneList [*pmNumTones].freq = 0;
	    pmToneList [*pmNumTones].duration = stWholeNoteDuration / stNoteDiv;
	    pmToneList [*pmNumTones].volume = 0;
	    (*pmNumTones)++;
	}
	else if (myChar == '<') 
	{
	    // Down one octave
	    if (stOctave > 1)
	    {
	        stOctave--;
	    }
	}
	else if (myChar == '>') 
	{
	    // Up one octave
	    if (stOctave < 8)
	    {
	        stOctave++;
	    }
	}
	else 
	{
	    SET_ERRNO (E_MUSIC_BAD_PLAY_CHAR);
	}
	myPtr++;
    }
    #undef NUM_NOTE_TYPES
} // MyParsePlayString
Example #25
0
/*
 * Our thread-safe and smart strerror() replacement.
 *
 * The 'err' argument passed in to this function MUST be a true errno number
 * as reported on this system. We do no range checking on the number before
 * we pass it to the "number-to-message" conversion function and there might
 * be systems that don't do proper range checking in there themselves.
 *
 * We don't do range checking (on systems other than Windows) since there is
 * no good reliable and portable way to do it.
 */
const char *Curl_strerror(struct connectdata *conn, int err)
{
  char *buf, *p;
  size_t max;
  int old_errno = ERRNO;

  DEBUGASSERT(conn);
  DEBUGASSERT(err >= 0);

  buf = conn->syserr_buf;
  max = sizeof(conn->syserr_buf)-1;
  *buf = '\0';

#ifdef USE_WINSOCK

#ifdef _WIN32_WCE
  {
    wchar_t wbuf[256];
    wbuf[0] = L'\0';

    FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err,
                  LANG_NEUTRAL, wbuf, sizeof(wbuf)/sizeof(wchar_t), NULL);
    wcstombs(buf,wbuf,max);
  }
#else
  /* 'sys_nerr' is the maximum errno number, it is not widely portable */
  if(err >= 0 && err < sys_nerr)
    strncpy(buf, strerror(err), max);
  else {
    if(!get_winsock_error(err, buf, max) &&
        !FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err,
                       LANG_NEUTRAL, buf, (DWORD)max, NULL))
      snprintf(buf, max, "Unknown error %d (%#x)", err, err);
  }
#endif

#else /* not USE_WINSOCK coming up */

#if defined(HAVE_STRERROR_R) && defined(HAVE_POSIX_STRERROR_R)
 /*
  * The POSIX-style strerror_r() may set errno to ERANGE if insufficient
  * storage is supplied via 'strerrbuf' and 'buflen' to hold the generated
  * message string, or EINVAL if 'errnum' is not a valid error number.
  */
  if(0 != strerror_r(err, buf, max)) {
    if('\0' == buf[0])
      snprintf(buf, max, "Unknown error %d", err);
  }
#elif defined(HAVE_STRERROR_R) && defined(HAVE_GLIBC_STRERROR_R)
 /*
  * The glibc-style strerror_r() only *might* use the buffer we pass to
  * the function, but it always returns the error message as a pointer,
  * so we must copy that string unconditionally (if non-NULL).
  */
  {
    char buffer[256];
    char *msg = strerror_r(err, buffer, sizeof(buffer));
    if(msg)
      strncpy(buf, msg, max);
    else
      snprintf(buf, max, "Unknown error %d", err);
  }
#elif defined(HAVE_STRERROR_R) && defined(HAVE_VXWORKS_STRERROR_R)
 /*
  * The vxworks-style strerror_r() does use the buffer we pass to the function.
  * The buffer size should be at least MAXERRSTR_SIZE (150) defined in rtsold.h
  */
  {
    char buffer[256];
    if(OK == strerror_r(err, buffer))
      strncpy(buf, buffer, max);
    else
      snprintf(buf, max, "Unknown error %d", err);
  }
#else
  {
    char *msg = strerror(err);
    if(msg)
      strncpy(buf, msg, max);
    else
      snprintf(buf, max, "Unknown error %d", err);
  }
#endif

#endif /* end of ! USE_WINSOCK */

  buf[max] = '\0'; /* make sure the string is zero terminated */

  /* strip trailing '\r\n' or '\n'. */
  if((p = strrchr(buf,'\n')) != NULL && (p - buf) >= 2)
     *p = '\0';
  if((p = strrchr(buf,'\r')) != NULL && (p - buf) >= 1)
     *p = '\0';

  if(old_errno != ERRNO)
    SET_ERRNO(old_errno);

  return buf;
}
Example #26
0
/* ==========================================================================
 * select() 
 */
int select(int numfds, fd_set *readfds, fd_set *writefds,
           fd_set *exceptfds, struct timeval *timeout)
{
  fd_set real_exceptfds, real_readfds, real_writefds; /* mapped fd_sets */
  fd_set * real_readfds_p, * real_writefds_p, * real_exceptfds_p;
  fd_set read_locks, write_locks, rdwr_locks;
  struct timespec timeout_time, current_time;
  int i, j, ret = 0, got_all_locks = 1;
  struct pthread_select_data data;

  if (numfds > dtablesize) {
    numfds = dtablesize;
  }

  data.nfds = 0;
  FD_ZERO(&data.readfds);
  FD_ZERO(&data.writefds);
  FD_ZERO(&data.exceptfds);

  /* Do this first */
  if (timeout) {
    machdep_gettimeofday(&current_time);
    timeout_time.tv_sec = current_time.tv_sec + timeout->tv_sec;
    if ((timeout_time.tv_nsec = current_time.tv_nsec + 
	 (timeout->tv_usec * 1000)) > 1000000000) {
      timeout_time.tv_nsec -= 1000000000;
      timeout_time.tv_sec++;
    }
  }

  FD_ZERO(&read_locks);
  FD_ZERO(&write_locks);
  FD_ZERO(&rdwr_locks);
  FD_ZERO(&real_readfds);
  FD_ZERO(&real_writefds);
  FD_ZERO(&real_exceptfds);

  /* lock readfds */
  if (readfds || writefds || exceptfds) {
    for (i = 0; i < numfds; i++) {
      if ((readfds && (FD_ISSET(i, readfds))) || 
	  (exceptfds && FD_ISSET(i, exceptfds))) {
	if (writefds && FD_ISSET(i ,writefds)) {
	  if ((ret = fd_lock(i, FD_RDWR, NULL)) != OK) {
	    got_all_locks = 0;
	    break;
	  }
	  FD_SET(i, &rdwr_locks);
	  FD_SET(fd_table[i]->fd.i,&real_writefds);
	} else {
	  if ((ret = fd_lock(i, FD_READ, NULL)) != OK) {
	    got_all_locks = 0;
	    break;
	  }
	  FD_SET(i, &read_locks);
	}
	if (readfds && FD_ISSET(i,readfds)) {
	  FD_SET(fd_table[i]->fd.i, &real_readfds);
	}
	if (exceptfds && FD_ISSET(i,exceptfds)) {
	  FD_SET(fd_table[i]->fd.i, &real_exceptfds);
	}
	if (fd_table[i]->fd.i >= data.nfds) {
	  data.nfds = fd_table[i]->fd.i + 1;
	}
      } else {
	if (writefds && FD_ISSET(i, writefds)) {
	  if ((ret = fd_lock(i, FD_WRITE, NULL)) != OK) {
	    got_all_locks = 0;
	    break;
	  }
	  FD_SET(i, &write_locks);
	  FD_SET(fd_table[i]->fd.i,&real_writefds);
	  if (fd_table[i]->fd.i >= data.nfds) {
	    data.nfds = fd_table[i]->fd.i + 1;
	  }
	}
      }
    }
  }

  if (got_all_locks)
  {
    memcpy(&data.readfds,&real_readfds,sizeof(fd_set));
    memcpy(&data.writefds,&real_writefds,sizeof(fd_set));
    memcpy(&data.exceptfds,&real_exceptfds,sizeof(fd_set));

    real_readfds_p = (readfds == NULL) ? NULL : &real_readfds;
    real_writefds_p = (writefds == NULL) ? NULL : &real_writefds;
    real_exceptfds_p = (exceptfds == NULL) ? NULL : &real_exceptfds;

    pthread_run->sighandled=0;
    if ((ret = machdep_sys_select(data.nfds, real_readfds_p,
				  real_writefds_p, real_exceptfds_p,
				  &zero_timeout)) == OK) {
      pthread_sched_prevent();

      real_exceptfds_p = (exceptfds == NULL) ? NULL : &data.exceptfds;
      real_writefds_p = (writefds == NULL) ? NULL : &data.writefds;
      real_readfds_p = (readfds == NULL) ? NULL : &data.readfds;

      pthread_queue_enq(&fd_wait_select, pthread_run);
      pthread_run->data.select_data = &data;
      SET_PF_WAIT_EVENT(pthread_run);

      if (timeout) {
	machdep_gettimeofday(&current_time);
	sleep_schedule(&current_time, &timeout_time);

	SET_PF_AT_CANCEL_POINT(pthread_run);
	pthread_resched_resume(PS_SELECT_WAIT);
	CLEAR_PF_AT_CANCEL_POINT(pthread_run);

	/* We're awake */
	if (sleep_cancel(pthread_run) == NOTOK) {
	  ret = OK;
	}
	else
	{
	  int count = 0;
	  for (i = 0; i < numfds; i++)
	  {
	    if (real_readfds_p && (FD_ISSET(i, real_readfds_p)))
	      count++;
	  if (real_writefds_p && (FD_ISSET(i, real_writefds_p)))
	    count++;
	  if (real_exceptfds_p && (FD_ISSET(i, real_exceptfds_p)))
	    count++;
	  }
	  ret = count;
	}
      /* Moving this after the sleep_cancel() seemed
       * to fix intermittent crashes during heavy
       * socket use. (mevans)
       */
      CLEAR_PF_DONE_EVENT(pthread_run);
    } else {
      int count = 0;
      SET_PF_AT_CANCEL_POINT(pthread_run);
      pthread_resched_resume(PS_SELECT_WAIT);
      CLEAR_PF_AT_CANCEL_POINT(pthread_run);
      CLEAR_PF_DONE_EVENT(pthread_run);
      for (i = 0; i < numfds; i++)
      {
	if (real_readfds_p && (FD_ISSET(i, real_readfds_p)))
	  count++;
	if (real_writefds_p && (FD_ISSET(i, real_writefds_p)))
	  count++;
	if (real_exceptfds_p && (FD_ISSET(i, real_exceptfds_p)))
	  count++;
      }
      ret = count;
    }
    if (pthread_run->sighandled) /* Added by monty */
    {			/* We where aborted */
      ret= NOTOK;
      SET_ERRNO(EINTR);
    }
  } else if (ret < 0) {
      SET_ERRNO(-ret);
      ret = NOTOK;
    }
  }

  /* clean up the locks */
  for (i = 0; i < numfds; i++)
  {					/* Changed by monty */
    if (FD_ISSET(i,&read_locks)) fd_unlock(i,FD_READ);
    if (FD_ISSET(i,&rdwr_locks)) fd_unlock(i,FD_RDWR);
    if (FD_ISSET(i,&write_locks)) fd_unlock(i,FD_WRITE);
  }
  if (ret > 0) {
    if (readfds != NULL) {
      for (i = 0; i < numfds; i++) {
	if (! (FD_ISSET(i,readfds) &&
	       FD_ISSET(fd_table[i]->fd.i,real_readfds_p)))
	  FD_CLR(i,readfds);
      }
    }
    if (writefds != NULL) {
      for (i = 0; i < numfds; i++)
	if (! (FD_ISSET(i,writefds) &&
	       FD_ISSET(fd_table[i]->fd.i,real_writefds_p)))
	  FD_CLR(i,writefds);
    }
    if (exceptfds != NULL) {
      for (i = 0; i < numfds; i++)
	if (! (FD_ISSET(i,exceptfds) &&
	       FD_ISSET(fd_table[i]->fd.i,real_exceptfds_p)))
	  FD_CLR(i,exceptfds);
    }
  } else {
    if (exceptfds != NULL) FD_ZERO(exceptfds);
    if (writefds != NULL) FD_ZERO(writefds);
    if (readfds != NULL) FD_ZERO(readfds);
  }

  return(ret);
}
Example #27
0
int
unassemble_rmcp_pkt (const void *pkt,
                     unsigned int pkt_len,
                     fiid_obj_t obj_rmcp_hdr,
                     fiid_obj_t obj_cmd,
		     unsigned int flags)
{
  unsigned int indx = 0;
  int len;
  unsigned int flags_mask = (IPMI_INTERFACE_FLAGS_NO_LEGAL_CHECK);

  if (!pkt
      || !fiid_obj_valid (obj_rmcp_hdr)
      || !fiid_obj_valid (obj_cmd)
      || (flags & ~flags_mask))
    {
      SET_ERRNO (EINVAL);
      return (-1);
    }

  if (FIID_OBJ_TEMPLATE_COMPARE (obj_rmcp_hdr, tmpl_rmcp_hdr) < 0)
    {
      ERRNO_TRACE (errno);
      return (-1);
    }

  if (fiid_obj_clear (obj_rmcp_hdr) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_rmcp_hdr);
      return (-1);
    }

  if (fiid_obj_clear (obj_cmd) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd);
      return (-1);
    }

  if ((len = fiid_obj_set_all (obj_rmcp_hdr, pkt + indx, pkt_len - indx)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_rmcp_hdr);
      return (-1);
    }
  indx += len;

  if (pkt_len <= indx)
    {
      /* trace, but don't error out, cannot parse packet */
      ERR_TRACE ("malformed packet", EINVAL);
      return (0);
    }

  if ((len = fiid_obj_set_all (obj_cmd, pkt + indx, pkt_len - indx)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd);
      return (-1);
    }
  indx += len;

  if (FIID_OBJ_PACKET_VALID (obj_rmcp_hdr) == 1
      && ((flags & IPMI_INTERFACE_FLAGS_NO_LEGAL_CHECK) || FIID_OBJ_PACKET_SUFFICIENT (obj_cmd) == 1))
    return (1);

  return (0);
}
Example #28
0
/*
 * Convert IPv6 binary address into presentation (printable) format.
 */
static char *inet_ntop6 (const unsigned char *src, char *dst, size_t size)
{
  /*
   * Note that int32_t and int16_t need only be "at least" large enough
   * to contain a value of the specified size.  On some systems, like
   * Crays, there is no such thing as an integer variable with 16 bits.
   * Keep this in mind if you think this function should have been coded
   * to use pointer overlays.  All the world's not a VAX.
   */
  char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
  char *tp;
  struct {
    long base;
    long len;
  } best, cur;
  unsigned long words[IN6ADDRSZ / INT16SZ];
  int i;

  /* Preprocess:
   *  Copy the input (bytewise) array into a wordwise array.
   *  Find the longest run of 0x00's in src[] for :: shorthanding.
   */
  memset(words, '\0', sizeof(words));
  for (i = 0; i < IN6ADDRSZ; i++)
      words[i/2] |= (src[i] << ((1 - (i % 2)) << 3));

  best.base = -1;
  cur.base  = -1;
  best.len = 0;
  cur.len = 0;

  for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
  {
    if(words[i] == 0)
    {
      if(cur.base == -1)
        cur.base = i, cur.len = 1;
      else
        cur.len++;
    }
    else if(cur.base != -1)
    {
      if(best.base == -1 || cur.len > best.len)
         best = cur;
      cur.base = -1;
    }
  }
  if((cur.base != -1) && (best.base == -1 || cur.len > best.len))
     best = cur;
  if(best.base != -1 && best.len < 2)
     best.base = -1;

  /* Format the result.
   */
  tp = tmp;
  for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
  {
    /* Are we inside the best run of 0x00's?
     */
    if(best.base != -1 && i >= best.base && i < (best.base + best.len))
    {
      if(i == best.base)
         *tp++ = ':';
      continue;
    }

    /* Are we following an initial run of 0x00s or any real hex?
     */
    if(i != 0)
       *tp++ = ':';

    /* Is this address an encapsulated IPv4?
     */
    if(i == 6 && best.base == 0 &&
        (best.len == 6 || (best.len == 5 && words[5] == 0xffff)))
    {
      if(!inet_ntop4(src+12, tp, sizeof(tmp) - (tp - tmp)))
      {
        SET_ERRNO(ENOSPC);
        return (NULL);
      }
      tp += strlen(tp);
      break;
    }
    tp += snprintf(tp, 5, "%lx", words[i]);
  }

  /* Was it a trailing run of 0x00's?
   */
  if(best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ))
     *tp++ = ':';
  *tp++ = '\0';

  /* Check for overflow, copy, and we're done.
   */
  if((size_t)(tp - tmp) > size)
  {
    SET_ERRNO(ENOSPC);
    return (NULL);
  }
  strcpy(dst, tmp);
  return dst;
}
Example #29
0
/*
 * static int
 * inet_net_pton_ipv4(src, dst, size)
 *      convert IPv4 network number from presentation to network format.
 *      accepts hex octets, hex strings, decimal octets, and /CIDR.
 *      "size" is in bytes and describes "dst".
 * return:
 *      number of bits, either imputed classfully or specified with /CIDR,
 *      or -1 if some failure occurred (check errno).  ENOENT means it was
 *      not an IPv4 network specification.
 * note:
 *      network byte order assumed.  this means 192.5.5.240/28 has
 *      0b11110000 in its fourth octet.
 * note:
 *      On Windows we store the error in the thread errno, not
 *      in the winsock error code. This is to avoid loosing the
 *      actual last winsock error. So use macro ERRNO to fetch the
 *      errno this funtion sets when returning (-1), not SOCKERRNO.
 * author:
 *      Paul Vixie (ISC), June 1996
 */
static int
inet_net_pton_ipv4(const char *src, unsigned char *dst, size_t size)
{
  static const char xdigits[] = "0123456789abcdef";
  static const char digits[] = "0123456789";
  int n, ch, tmp = 0, dirty, bits;
  const unsigned char *odst = dst;

  ch = *src++;
  if (ch == '0' && (src[0] == 'x' || src[0] == 'X')
      && ISXDIGIT(src[1])) {
    /* Hexadecimal: Eat nybble string. */
    if (!size)
      goto emsgsize;
    dirty = 0;
    src++;  /* skip x or X. */
    while ((ch = *src++) != '\0' && ISXDIGIT(ch)) {
      if (ISUPPER(ch))
        ch = tolower(ch);
      n = (int)(strchr(xdigits, ch) - xdigits);
      if (dirty == 0)
        tmp = n;
      else
        tmp = (tmp << 4) | n;
      if (++dirty == 2) {
        if (!size--)
          goto emsgsize;
        *dst++ = (unsigned char) tmp;
        dirty = 0;
      }
    }
    if (dirty) {  /* Odd trailing nybble? */
      if (!size--)
        goto emsgsize;
      *dst++ = (unsigned char) (tmp << 4);
    }
  } else if (ISDIGIT(ch)) {
    /* Decimal: eat dotted digit string. */
    for (;;) {
      tmp = 0;
      do {
        n = (int)(strchr(digits, ch) - digits);
        tmp *= 10;
        tmp += n;
        if (tmp > 255)
          goto enoent;
      } while ((ch = *src++) != '\0' &&
               ISDIGIT(ch));
      if (!size--)
        goto emsgsize;
      *dst++ = (unsigned char) tmp;
      if (ch == '\0' || ch == '/')
        break;
      if (ch != '.')
        goto enoent;
      ch = *src++;
      if (!ISDIGIT(ch))
        goto enoent;
    }
  } else
    goto enoent;

  bits = -1;
  if (ch == '/' &&
      ISDIGIT(src[0]) && dst > odst) {
    /* CIDR width specifier.  Nothing can follow it. */
    ch = *src++;    /* Skip over the /. */
    bits = 0;
    do {
      n = (int)(strchr(digits, ch) - digits);
      bits *= 10;
      bits += n;
    } while ((ch = *src++) != '\0' && ISDIGIT(ch));
    if (ch != '\0')
      goto enoent;
    if (bits > 32)
      goto emsgsize;
  }

  /* Firey death and destruction unless we prefetched EOS. */
  if (ch != '\0')
    goto enoent;

  /* If nothing was written to the destination, we found no address. */
  if (dst == odst)
    goto enoent;
  /* If no CIDR spec was given, infer width from net class. */
  if (bits == -1) {
    if (*odst >= 240)       /* Class E */
      bits = 32;
    else if (*odst >= 224)  /* Class D */
      bits = 8;
    else if (*odst >= 192)  /* Class C */
      bits = 24;
    else if (*odst >= 128)  /* Class B */
      bits = 16;
    else                    /* Class A */
      bits = 8;
    /* If imputed mask is narrower than specified octets, widen. */
    if (bits < ((dst - odst) * 8))
      bits = (int)(dst - odst) * 8;
    /*
     * If there are no additional bits specified for a class D
     * address adjust bits to 4.
     */
    if (bits == 8 && *odst == 224)
      bits = 4;
  }
  /* Extend network to cover the actual mask. */
  while (bits > ((dst - odst) * 8)) {
    if (!size--)
      goto emsgsize;
    *dst++ = '\0';
  }
  return (bits);

  enoent:
  SET_ERRNO(ENOENT);
  return (-1);

  emsgsize:
  SET_ERRNO(EMSGSIZE);
  return (-1);
}
int
ipmi_device_type_modifer_message (uint8_t device_type,
                                  uint8_t device_modifier,
                                  char *buf,
                                  unsigned int buflen)
{
  if (!IPMI_DEVICE_TYPE_VALID (device_type)
      || !buf
      || !buflen)
    {
      SET_ERRNO (EINVAL);
      return (-1);
    }

  switch (device_type)
    {
    case IPMI_DEVICE_TYPE_DS1624_TEMPERATURE_SENSOR_EEPROM_OR_EQUIVALENT:
      return (_get_message (device_modifier,
                            buf,
                            buflen,
                            ipmi_device_type_modifier_ds1624_temperature_sensor_eeprom_or_equivalent_max_index,
                            ipmi_device_type_modifier_ds1624_temperature_sensor_eeprom_or_equivalent));
    case IPMI_DEVICE_TYPE_DS1621_TEMPERATURE_SENSOR_OR_EQUIVALENT:
      return (_get_message (device_modifier,
                            buf,
                            buflen,
                            ipmi_device_type_modifier_ds1621_temperature_sensor_eeprom_or_equivalent_max_index,
                            ipmi_device_type_modifier_ds1621_temperature_sensor_eeprom_or_equivalent));
    case IPMI_DEVICE_TYPE_LM75_TEMPERATURE_SENSOR_OR_EQUIVALENT:
      return (_get_message (device_modifier,
                            buf,
                            buflen,
                            ipmi_device_type_modifier_lm75_temperature_sensor_eeprom_or_equivalent_max_index,
                            ipmi_device_type_modifier_lm75_temperature_sensor_eeprom_or_equivalent));
    case IPMI_DEVICE_TYPE_HECETA_ASIC_OR_SIMILAR:
      return (_get_message (device_modifier,
                            buf,
                            buflen,
                            ipmi_device_type_modifier_heceta_asic_or_similar_max_index,
                            ipmi_device_type_modifier_heceta_asic_or_similar));
    case IPMI_DEVICE_TYPE_EEPROM_24C01_OR_EQUIVALENT:
      return (_get_message (device_modifier,
                            buf,
                            buflen,
                            ipmi_device_type_modifier_eeprom_24c01_or_equivalent_max_index,
                            ipmi_device_type_modifier_eeprom_24c01_or_equivalent));
    case IPMI_DEVICE_TYPE_EEPROM_24C02_OR_EQUIVALENT:
      return (_get_message (device_modifier,
                            buf,
                            buflen,
                            ipmi_device_type_modifier_eeprom_24c02_or_equivalent_max_index,
                            ipmi_device_type_modifier_eeprom_24c02_or_equivalent));
    case IPMI_DEVICE_TYPE_EEPROM_24C04_OR_EQUIVALENT:
      return (_get_message (device_modifier,
                            buf,
                            buflen,
                            ipmi_device_type_modifier_eeprom_24c04_or_equivalent_max_index,
                            ipmi_device_type_modifier_eeprom_24c04_or_equivalent));
    case IPMI_DEVICE_TYPE_EEPROM_24C08_OR_EQUIVALENT:
      return (_get_message (device_modifier,
                            buf,
                            buflen,
                            ipmi_device_type_modifier_eeprom_24c08_or_equivalent_max_index,
                            ipmi_device_type_modifier_eeprom_24c08_or_equivalent));
    case IPMI_DEVICE_TYPE_EEPROM_24C16_OR_EQUIVALENT:
      return (_get_message (device_modifier,
                            buf,
                            buflen,
                            ipmi_device_type_modifier_eeprom_24c16_or_equivalent_max_index,
                            ipmi_device_type_modifier_eeprom_24c16_or_equivalent));
    case IPMI_DEVICE_TYPE_EEPROM_24C17_OR_EQUIVALENT:
      return (_get_message (device_modifier,
                            buf,
                            buflen,
                            ipmi_device_type_modifier_eeprom_24c17_or_equivalent_max_index,
                            ipmi_device_type_modifier_eeprom_24c17_or_equivalent));
    case IPMI_DEVICE_TYPE_EEPROM_24C32_OR_EQUIVALENT:
      return (_get_message (device_modifier,
                            buf,
                            buflen,
                            ipmi_device_type_modifier_eeprom_24c32_or_equivalent_max_index,
                            ipmi_device_type_modifier_eeprom_24c32_or_equivalent));
    case IPMI_DEVICE_TYPE_EEPROM_24C64_OR_EQUIVALENT:
      return (_get_message (device_modifier,
                            buf,
                            buflen,
                            ipmi_device_type_modifier_eeprom_24c64_or_equivalent_max_index,
                            ipmi_device_type_modifier_eeprom_24c64_or_equivalent));
    case IPMI_DEVICE_TYPE_FRU_INVENTORY_DEVICE_BEHIND_MANAGEMENT_CONTROLLER:
      return (_get_message (device_modifier,
                            buf,
                            buflen,
                            ipmi_device_type_modifier_fru_inventory_device_behind_management_controller_max_index,
                            ipmi_device_type_modifier_fru_inventory_device_behind_management_controller));
    case IPMI_DEVICE_TYPE_PCF_8570_256_BYTE_RAM_OR_EQUIVALENT:
      return (_get_message (device_modifier,
                            buf,
                            buflen,
                            ipmi_device_type_modifier_pcf_8570_256_byte_ram_or_equivalent_max_index,
                            ipmi_device_type_modifier_pcf_8570_256_byte_ram_or_equivalent));
    case IPMI_DEVICE_TYPE_PCF_8573_CLOCK_CALENDAR_OR_EQUIVALENT:
      return (_get_message (device_modifier,
                            buf,
                            buflen,
                            ipmi_device_type_modifier_pcf_8573_clock_calendar_or_equivalent_max_index,
                            ipmi_device_type_modifier_pcf_8573_clock_calendar_or_equivalent));
    case IPMI_DEVICE_TYPE_PCF_8574A_IO_PORT_OR_EQUIVALENT:
      return (_get_message (device_modifier,
                            buf,
                            buflen,
                            ipmi_device_type_modifier_pcf_8574a_io_port_or_equivalent_max_index,
                            ipmi_device_type_modifier_pcf_8574a_io_port_or_equivalent));
    case IPMI_DEVICE_TYPE_PCF_8583_CLOCK_CALENDAR_OR_EQUIVALENT:
      return (_get_message (device_modifier,
                            buf,
                            buflen,
                            ipmi_device_type_modifier_pcf_8583_clock_calendar_or_equivalent_max_index,
                            ipmi_device_type_modifier_pcf_8583_clock_calendar_or_equivalent));
    case IPMI_DEVICE_TYPE_PCF_8593_CLOCK_CALENDAR_OR_EQUIVALENT:
      return (_get_message (device_modifier,
                            buf,
                            buflen,
                            ipmi_device_type_modifier_pcf_8593_clock_calendar_or_equivalent_max_index,
                            ipmi_device_type_modifier_pcf_8593_clock_calendar_or_equivalent));
    case IPMI_DEVICE_TYPE_CLOCK_CALENDAR_TYPE_NOT_SPECIFIED:
      return (_get_message (device_modifier,
                            buf,
                            buflen,
                            ipmi_device_type_modifier_clock_calendar_type_not_specified_max_index,
                            ipmi_device_type_modifier_clock_calendar_type_not_specified));
    case IPMI_DEVICE_TYPE_PCF_8591_AD_DA_CONVERTER_OR_EQUIVALENT:
      return (_get_message (device_modifier,
                            buf,
                            buflen,
                            ipmi_device_type_modifier_pcf_8591_ad_da_converter_or_equivalent_max_index,
                            ipmi_device_type_modifier_pcf_8591_ad_da_converter_or_equivalent));
    case IPMI_DEVICE_TYPE_IO_PORT_SPECIFIC_DEVICE_NOT_SPECIFIED:
      return (_get_message (device_modifier,
                            buf,
                            buflen,
                            ipmi_device_type_modifier_io_port_specific_device_not_specified_max_index,
                            ipmi_device_type_modifier_io_port_specific_device_not_specified));
    case IPMI_DEVICE_TYPE_AD_CONVERTER_SPECIFIC_DEVICE_NOT_SPECIFIED:
      return (_get_message (device_modifier,
                            buf,
                            buflen,
                            ipmi_device_type_modifier_ad_converter_specific_device_not_specified_max_index,
                            ipmi_device_type_modifier_ad_converter_specific_device_not_specified));
    case IPMI_DEVICE_TYPE_DA_CONVERTER_SPECIFIC_DEVICE_NOT_SPECIFIED:
      return (_get_message (device_modifier,
                            buf,
                            buflen,
                            ipmi_device_type_modifier_da_converter_specific_device_not_specified_max_index,
                            ipmi_device_type_modifier_da_converter_specific_device_not_specified));
    case IPMI_DEVICE_TYPE_AD_DA_CONVERTER_SPECIFIC_DEVICE_NOT_SPECIFIED:
      return (_get_message (device_modifier,
                            buf,
                            buflen,
                            ipmi_device_type_modifier_ad_da_converter_specific_device_not_specified_max_index,
                            ipmi_device_type_modifier_ad_da_converter_specific_device_not_specified));
    case IPMI_DEVICE_TYPE_LCD_CONTROLLER_DRIVER_SPECIFIC_DEVICE_NOT_SPECIFIED:
      return (_get_message (device_modifier,
                            buf,
                            buflen,
                            ipmi_device_type_modifier_lcd_controller_driver_specific_device_not_specified_max_index,
                            ipmi_device_type_modifier_lcd_controller_driver_specific_device_not_specified));
    case IPMI_DEVICE_TYPE_CORE_LOGIC_DEVICE_SPECIFIC_DEVICE_NOT_SPECIFIED:
      return (_get_message (device_modifier,
                            buf,
                            buflen,
                            ipmi_device_type_modifier_core_logic_device_specific_device_not_specified_max_index,
                            ipmi_device_type_modifier_core_logic_device_specific_device_not_specified));
    case IPMI_DEVICE_TYPE_LMC6874_INTELLIGENT_BATTERY_CONTROLLER_OR_EQUIVALENT:
      return (_get_message (device_modifier,
                            buf,
                            buflen,
                            ipmi_device_type_modifier_lmc6874_intelligent_battery_controller_or_equivalent_max_index,
                            ipmi_device_type_modifier_lmc6874_intelligent_battery_controller_or_equivalent));
    case IPMI_DEVICE_TYPE_INTELLIGENT_BATTERY_CONTROLLER_SPECIFIC_DEVICE_NOT_SPECIFIED:
      return (_get_message (device_modifier,
                            buf,
                            buflen,
                            ipmi_device_type_modifier_intelligent_battery_controller_specific_device_not_specified_max_index,
                            ipmi_device_type_modifier_intelligent_battery_controller_specific_device_not_specified));
    case IPMI_DEVICE_TYPE_COMBO_MANAGEMENT_ASIC_SPECIFIC_DEVICE_NOT_SPECIFIED:
      return (_get_message (device_modifier,
                            buf,
                            buflen,
                            ipmi_device_type_modifier_combo_management_asic_specific_device_not_specified_max_index,
                            ipmi_device_type_modifier_combo_management_asic_specific_device_not_specified));
    case IPMI_DEVICE_TYPE_MAXIM_1617_TEMPERATURE_SENSOR:
      return (_get_message (device_modifier,
                            buf,
                            buflen,
                            ipmi_device_type_modifier_maxim_1617_temperature_sensor_max_index,
                            ipmi_device_type_modifier_maxim_1617_temperature_sensor));
    case IPMI_DEVICE_TYPE_OTHER_UNSPECIFIED_DEVICE:
      return (_get_message (device_modifier,
                            buf,
                            buflen,
                            ipmi_device_type_modifier_other_unspecified_device_max_index,
                            ipmi_device_type_modifier_other_unspecified_device));
    }

  SET_ERRNO (EINVAL);
  return (-1);
}