Example #1
0
/* ARGSUSED */
static int
sctp_listener_conf_del(netstack_t *stack, cred_t *cr, mod_prop_info_t *pinfo,
    const char *ifname, const void* pval, uint_t flags)
{
	sctp_listener_t	*sl;
	long		lport;
	sctp_stack_t	*sctps = stack->netstack_sctp;

	if (flags & MOD_PROP_DEFAULT)
		return (ENOTSUP);

	if (ddi_strtol(pval, NULL, 10, &lport) != 0 || lport <= 0 ||
	    lport > USHRT_MAX) {
		return (EINVAL);
	}
	mutex_enter(&sctps->sctps_listener_conf_lock);
	for (sl = list_head(&sctps->sctps_listener_conf); sl != NULL;
	    sl = list_next(&sctps->sctps_listener_conf, sl)) {
		if (sl->sl_port == lport) {
			list_remove(&sctps->sctps_listener_conf, sl);
			mutex_exit(&sctps->sctps_listener_conf_lock);
			kmem_free(sl, sizeof (sctp_listener_t));
			return (0);
		}
	}
	mutex_exit(&sctps->sctps_listener_conf_lock);
	return (ESRCH);
}
Example #2
0
int
_init(void)
{
	int	err;
	char tty_irq_param[9] = "ttyX-irq";
	char *tty_irq;
	int i;

	if ((err = mod_install(&modlinkage)) != 0)
		return (err);

	/* Check if any tty irqs are overridden by eeprom config */
	for (i = 0; i < num_BIOS_serial; i++) {
		tty_irq_param[3] = 'a' + i;
		if (ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_root_node(),
		    DDI_PROP_DONTPASS, tty_irq_param, &tty_irq)
		    == DDI_PROP_SUCCESS) {
			long data;

			if (ddi_strtol(tty_irq, NULL, 0, &data) == 0) {
				asy_intrs[i] = (int)data;
				asy_intr_override |= 1<<i;
			}

			ddi_prop_free(tty_irq);
		}
	}

	impl_bus_add_probe(isa_enumerate);
	return (0);
}
Example #3
0
static int
str2inet_addr(char *cp, ipaddr_t *addrp)
{
	char *end;
	long byte;
	int i;
	ipaddr_t addr = 0;

	for (i = 0; i < 4; i++) {
		if (ddi_strtol(cp, &end, 10, &byte) != 0 || byte < 0 ||
		    byte > 255) {
			return (0);
		}
		addr = (addr << 8) | (uint8_t)byte;
		if (i < 3) {
			if (*end != '.') {
				return (0);
			} else {
				cp = end + 1;
			}
		} else {
			cp = end;
		}
	}
	*addrp = addr;
	return (1);
}
Example #4
0
/* ARGSUSED */
static int
sctp_extra_priv_ports_del(queue_t *q, mblk_t *mp, char *value, caddr_t cp,
    cred_t *cr)
{
	long	new_value;
	int	i;

	/*
	 * Fail the request if the new value does not lie within the
	 * port number limits.
	 */
	if (ddi_strtol(value, NULL, 10, &new_value) != 0 ||
	    new_value <= 0 || new_value >= 65536) {
		return (EINVAL);
	}

	mutex_enter(&sctp_epriv_port_lock);
	/* Check that the value is already in the list */
	for (i = 0; i < sctp_g_num_epriv_ports; i++) {
		if (sctp_g_epriv_ports[i] == new_value)
			break;
	}
	if (i == sctp_g_num_epriv_ports) {
		mutex_exit(&sctp_epriv_port_lock);
		return (ESRCH);
	}
	/* Clear the value */
	sctp_g_epriv_ports[i] = 0;
	mutex_exit(&sctp_epriv_port_lock);
	return (0);
}
Example #5
0
/* ARGSUSED */
static int
tcp_listener_conf_del(void *cbarg, cred_t *cr, mod_prop_info_t *pinfo,
    const char *ifname, const void* pval, uint_t flags)
{
	tcp_listener_t	*tl;
	long		lport;
	tcp_stack_t	*tcps = (tcp_stack_t *)cbarg;

	if (flags & MOD_PROP_DEFAULT)
		return (ENOTSUP);

	if (ddi_strtol(pval, NULL, 10, &lport) != 0 || lport <= 0 ||
	    lport > USHRT_MAX) {
		return (EINVAL);
	}
	mutex_enter(&tcps->tcps_listener_conf_lock);
	for (tl = list_head(&tcps->tcps_listener_conf); tl != NULL;
	    tl = list_next(&tcps->tcps_listener_conf, tl)) {
		if (tl->tl_port == lport) {
			list_remove(&tcps->tcps_listener_conf, tl);
			mutex_exit(&tcps->tcps_listener_conf_lock);
			kmem_free(tl, sizeof (tcp_listener_t));
			return (0);
		}
	}
	mutex_exit(&tcps->tcps_listener_conf_lock);
	return (ESRCH);
}
Example #6
0
static int
/*ARGSUSED*/
nl7c_uri_ttl_set(queue_t *q, mblk_t *mp, char *value, caddr_t nu, cred_t *cr)
{
	if (ddi_strtol(value, NULL, 10, &nl7c_uri_ttl) != 0)
		return (EINVAL);
	return (0);
}
Example #7
0
/* ARGSUSED */
static int
sctp_listener_conf_add(netstack_t *stack, cred_t *cr, mod_prop_info_t *pinfo,
    const char *ifname, const void* pval, uint_t flags)
{
	sctp_listener_t	*new_sl;
	sctp_listener_t	*sl;
	long		lport;
	long		ratio;
	char		*colon;
	sctp_stack_t	*sctps = stack->netstack_sctp;

	if (flags & MOD_PROP_DEFAULT)
		return (ENOTSUP);

	if (ddi_strtol(pval, &colon, 10, &lport) != 0 || lport <= 0 ||
	    lport > USHRT_MAX || *colon != ':') {
		return (EINVAL);
	}
	if (ddi_strtol(colon + 1, NULL, 10, &ratio) != 0 || ratio <= 0)
		return (EINVAL);

	mutex_enter(&sctps->sctps_listener_conf_lock);
	for (sl = list_head(&sctps->sctps_listener_conf); sl != NULL;
	    sl = list_next(&sctps->sctps_listener_conf, sl)) {
		/* There is an existing entry, so update its ratio value. */
		if (sl->sl_port == lport) {
			sl->sl_ratio = ratio;
			mutex_exit(&sctps->sctps_listener_conf_lock);
			return (0);
		}
	}

	if ((new_sl = kmem_alloc(sizeof (sctp_listener_t), KM_NOSLEEP)) ==
	    NULL) {
		mutex_exit(&sctps->sctps_listener_conf_lock);
		return (ENOMEM);
	}

	new_sl->sl_port = lport;
	new_sl->sl_ratio = ratio;
	list_insert_tail(&sctps->sctps_listener_conf, new_sl);
	mutex_exit(&sctps->sctps_listener_conf_lock);
	return (0);
}
Example #8
0
/* ARGSUSED */
static int
sctp_param_set(queue_t *q, mblk_t *mp, char *value, caddr_t cp, cred_t *cr)
{
	long		new_value;
	sctpparam_t	*sctppa = (sctpparam_t *)cp;

	if (ddi_strtol(value, NULL, 10, &new_value) != 0 ||
	    new_value < sctppa->sctp_param_min ||
	    new_value > sctppa->sctp_param_max) {
		return (EINVAL);
	}
	sctppa->sctp_param_val = new_value;
	return (0);
}
Example #9
0
/*
 * function to set a private property.
 * Called from the set_prop GLD entry point
 *
 * dev - sofware handle to the device
 * name - string containing the property name
 * size - length of the string in name
 * val - pointer to a location where the value to set is stored
 *
 * return EINVAL => invalid value in val 0 => success
 */
static int
oce_set_priv_prop(struct oce_dev *dev, const char *name,
    uint_t size, const void *val)
{
	int ret = ENOTSUP;
	long result;

	_NOTE(ARGUNUSED(size));

	if (NULL == val) {
		ret = EINVAL;
		return (ret);
	}

	if (strcmp(name, "_tx_bcopy_limit") == 0) {
		(void) ddi_strtol(val, (char **)NULL, 0, &result);
		if (result <= OCE_WQ_BUF_SIZE) {
			if (result != dev->tx_bcopy_limit)
				dev->tx_bcopy_limit = (uint32_t)result;
			ret = 0;
		} else {
			ret = EINVAL;
		}
	}
	if (strcmp(name, "_rx_bcopy_limit") == 0) {
		(void) ddi_strtol(val, (char **)NULL, 0, &result);
		if (result <= OCE_RQ_BUF_SIZE) {
			if (result != dev->rx_bcopy_limit)
				dev->rx_bcopy_limit = (uint32_t)result;
			ret = 0;
		} else {
			ret = EINVAL;
		}
	}

	return (ret);
} /* oce_set_priv_prop */
Example #10
0
static int
/*ARGSUSED*/
nca_logging_on_set(queue_t *q, mblk_t *mp, char *value, caddr_t nu, cred_t *cr)
{
	long new_value;

	if (ddi_strtol(value, NULL, 10, &new_value) != 0 || new_value < 0 ||
	    new_value > 1) {
		return (EINVAL);
	}
	if (nca_fio_cnt(nl7c_logd_fio) == 0)
		return (EINVAL);
	nl7c_logd_enabled = new_value;

	return (0);
}
Example #11
0
/*
 * Convert string to minor number. Some care must be taken
 * as we are processing user input. Catch cases like
 * /dev/pts/4foo and /dev/pts/-1
 */
static int
devpts_strtol(const char *nm, minor_t *mp)
{
	long uminor = 0;
	char *endptr = NULL;

	if (nm == NULL || !isdigit(*nm))
		return (EINVAL);

	*mp = 0;
	if (ddi_strtol(nm, &endptr, 10, &uminor) != 0 ||
	    *endptr != '\0' || uminor < 0) {
		return (EINVAL);
	}

	*mp = (minor_t)uminor;
	return (0);
}
Example #12
0
/*
 * sets master_ops_debug flag from propertyu passed by the boot
 */
static void
set_master_ops_debug_flags()
{
	char *prop;
	long flags;

	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_root_node(),
	    DDI_PROP_DONTPASS, "master_ops_debug", &prop) == DDI_PROP_SUCCESS) {
		long data;
		if (ddi_strtol(prop, NULL, 0, &data) == 0) {
			master_ops_debug = (unsigned long)data;
			e_ddi_prop_remove(DDI_DEV_T_NONE, ddi_root_node(),
			    "master_ops_debug");
			e_ddi_prop_update_int(DDI_DEV_T_NONE, ddi_root_node(),
			    "master_ops_debug", data);
		}
		ddi_prop_free(prop);
	}
}
Example #13
0
/* ARGSUSED */
static int
sctp_wroff_xtra_set(queue_t *q, mblk_t *mp, char *value, caddr_t cp,
    cred_t *cr)
{
	long		new_value;
	sctpparam_t	*sctppa = (sctpparam_t *)cp;

	if (ddi_strtol(value, NULL, 10, &new_value) != 0 ||
	    new_value < sctppa->sctp_param_min ||
	    new_value > sctppa->sctp_param_max) {
		return (EINVAL);
	}
	/*
	 * Need to make sure new_value is a multiple of 8.  If it is not,
	 * round it up.
	 */
	if (new_value & 0x7) {
		new_value = (new_value & ~0x7) + 0x8;
	}
	sctppa->sctp_param_val = new_value;
	return (0);
}
Example #14
0
/* ARGSUSED */
static int
sctp_extra_priv_ports_add(queue_t *q, mblk_t *mp, char *value, caddr_t cp,
    cred_t *cr)
{
	long	new_value;
	int	i;

	/*
	 * Fail the request if the new value does not lie within the
	 * port number limits.
	 */
	if (ddi_strtol(value, NULL, 10, &new_value) != 0 ||
	    new_value <= 0 || new_value >= 65536) {
		return (EINVAL);
	}

	mutex_enter(&sctp_epriv_port_lock);
	/* Check if the value is already in the list */
	for (i = 0; i < sctp_g_num_epriv_ports; i++) {
		if (new_value == sctp_g_epriv_ports[i]) {
			mutex_exit(&sctp_epriv_port_lock);
			return (EEXIST);
		}
	}
	/* Find an empty slot */
	for (i = 0; i < sctp_g_num_epriv_ports; i++) {
		if (sctp_g_epriv_ports[i] == 0)
			break;
	}
	if (i == sctp_g_num_epriv_ports) {
		mutex_exit(&sctp_epriv_port_lock);
		return (EOVERFLOW);
	}
	/* Set the new value */
	sctp_g_epriv_ports[i] = (uint16_t)new_value;
	mutex_exit(&sctp_epriv_port_lock);
	return (0);
}
Example #15
0
/* ARGSUSED */
static int
i40e_m_setprop_private(i40e_t *i40e, const char *pr_name, uint_t pr_valsize,
    const void *pr_val)
{
	int ret;
	long val;
	char *eptr;

	ASSERT(MUTEX_HELD(&i40e->i40e_general_lock));

	if ((ret = ddi_strtol(pr_val, &eptr, 10, &val)) != 0 ||
	    *eptr != '\0') {
		return (ret);
	}

	if (strcmp(pr_name, I40E_PROP_RX_DMA_THRESH) == 0) {
		if (val < I40E_MIN_RX_DMA_THRESH ||
		    val > I40E_MAX_RX_DMA_THRESH) {
			return (EINVAL);
		}
		i40e->i40e_rx_dma_min = (uint32_t)val;
		return (0);
	}

	if (strcmp(pr_name, I40E_PROP_TX_DMA_THRESH) == 0) {
		if (val < I40E_MIN_TX_DMA_THRESH ||
		    val > I40E_MAX_TX_DMA_THRESH) {
			return (EINVAL);
		}
		i40e->i40e_tx_dma_min = (uint32_t)val;
		return (0);
	}

	if (strcmp(pr_name, I40E_PROP_RX_ITR) == 0) {
		if (val < I40E_MIN_ITR ||
		    val > I40E_MAX_ITR) {
			return (EINVAL);
		}
		i40e->i40e_rx_itr = (uint32_t)val;
		i40e_intr_set_itr(i40e, I40E_ITR_INDEX_RX, i40e->i40e_rx_itr);
		return (0);
	}

	if (strcmp(pr_name, I40E_PROP_TX_ITR) == 0) {
		if (val < I40E_MIN_ITR ||
		    val > I40E_MAX_ITR) {
			return (EINVAL);
		}
		i40e->i40e_tx_itr = (uint32_t)val;
		i40e_intr_set_itr(i40e, I40E_ITR_INDEX_TX, i40e->i40e_tx_itr);
		return (0);
	}

	if (strcmp(pr_name, I40E_PROP_OTHER_ITR) == 0) {
		if (val < I40E_MIN_ITR ||
		    val > I40E_MAX_ITR) {
			return (EINVAL);
		}
		i40e->i40e_tx_itr = (uint32_t)val;
		i40e_intr_set_itr(i40e, I40E_ITR_INDEX_OTHER,
		    i40e->i40e_other_itr);
		return (0);
	}

	return (ENOTSUP);
}
Example #16
0
/*
 * Process acpi-user-options property  if present
 */
static void
acpica_process_user_options()
{
	static int processed = 0;
	int acpi_user_options;
	char *acpi_prop;

	/*
	 * return if acpi-user-options has already been processed
	 */
	if (processed)
		return;
	else
		processed = 1;

	/* converts acpi-user-options from type string to int, if any */
	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_root_node(),
	    DDI_PROP_DONTPASS, "acpi-user-options", &acpi_prop) ==
	    DDI_PROP_SUCCESS) {
		long data;
		int ret;
		ret = ddi_strtol(acpi_prop, NULL, 0, &data);
		if (ret == 0) {
			e_ddi_prop_remove(DDI_DEV_T_NONE, ddi_root_node(),
			    "acpi-user-options");
			e_ddi_prop_update_int(DDI_DEV_T_NONE, ddi_root_node(),
			    "acpi-user-options", data);
		}
		ddi_prop_free(acpi_prop);
	}

	/*
	 * fetch the optional options property
	 */
	acpi_user_options = ddi_prop_get_int(DDI_DEV_T_ANY, ddi_root_node(),
	    DDI_PROP_DONTPASS, "acpi-user-options", 0);

	/*
	 * Note that 'off' has precedence over 'on'
	 * Also note - all cases of ACPI_OUSER_MASK
	 * provided here, no default: case is present
	 */
	switch (acpi_user_options & ACPI_OUSER_MASK) {
	case ACPI_OUSER_DFLT:
		acpica_enable = acpica_check_bios_date(1999, 1, 1);
		break;
	case ACPI_OUSER_ON:
		acpica_enable = TRUE;
		break;
	case ACPI_OUSER_OFF:
	case ACPI_OUSER_OFF | ACPI_OUSER_ON:
		acpica_enable = FALSE;
		break;
	}

	acpi_init_level = ACPI_FULL_INITIALIZATION;

	/*
	 * special test here; may be generalized in the
	 * future - test for a machines that are known to
	 * work only in legacy mode, and set OUSER_LEGACY if
	 * we're on one
	 */
	if (acpica_metro_old_bios())
		acpi_user_options |= ACPI_OUSER_LEGACY;

	/*
	 * If legacy mode is specified, set initialization
	 * options to avoid entering ACPI mode and hooking SCI
	 * - basically try to act like legacy acpi_intp
	 */
	if ((acpi_user_options & ACPI_OUSER_LEGACY) != 0)
		acpi_init_level |= (ACPI_NO_ACPI_ENABLE | ACPI_NO_HANDLER_INIT);

	/*
	 * modify default ACPI CA debug output level for non-DEBUG builds
	 * (to avoid BIOS debug chatter in /var/adm/messages)
	 */
	if (acpica_muzzle_debug_output)
		AcpiDbgLevel = 0;
}
Example #17
0
/*
 * inet_pton: This function takes string format IPv4 or IPv6 address and
 * converts it to binary form. The format of this function corresponds to
 * inet_pton() in the socket library.
 *
 * Return values:
 *  0 invalid IPv4 or IPv6 address
 *  1 successful conversion
 * -1 af is not AF_INET or AF_INET6
 */
int
__inet_pton(int af, char *inp, void *outp, int compat)
{
	int i;
	long byte;
	char *end;

	switch (af) {
	case AF_INET:
		if (str2inet_addr(inp, (ipaddr_t *)outp) != 0) {
			if (!compat)
				*(uint32_t *)outp = htonl(*(uint32_t *)outp);
			return (1);
		} else {
			return (0);
		}
	case AF_INET6: {
		union v6buf_u {
			uint16_t v6words_u[8];
			in6_addr_t v6addr_u;
		} v6buf, *v6outp;
		uint16_t	*dbl_col = NULL;
		char lastbyte = NULL;

		v6outp = (union v6buf_u *)outp;

		if (strchr_w(inp, '.') != NULL) {
			/* v4 mapped or v4 compatable */
			if (strncmp(inp, "::ffff:", 7) == 0) {
				ipaddr_t ipv4_all_zeroes = 0;
				/* mapped - first init prefix and then fill */
				IN6_IPADDR_TO_V4MAPPED(ipv4_all_zeroes,
				    &v6outp->v6addr_u);
				return (str2inet_addr(inp + 7,
				    &(v6outp->v6addr_u.s6_addr32[3])));
			} else if (strncmp(inp, "::", 2) == 0) {
				/* v4 compatable - prefix all zeroes */
				bzero(&v6outp->v6addr_u, sizeof (in6_addr_t));
				return (str2inet_addr(inp + 2,
				    &(v6outp->v6addr_u.s6_addr32[3])));
			}
			return (0);
		}
		for (i = 0; i < 8; i++) {
			int error;
			/*
			 * if ddi_strtol() fails it could be because
			 * the string is "::".  That is valid and
			 * checked for below so just set the value to
			 * 0 and continue.
			 */
			if ((error = ddi_strtol(inp, &end, 16, &byte)) != 0) {
				if (error == ERANGE)
					return (0);
				byte = 0;
			}
			if (byte < 0 || byte > 0x0ffff) {
				return (0);
			}
			if (compat) {
				v6buf.v6words_u[i] = (uint16_t)byte;
			} else {
				v6buf.v6words_u[i] = htons((uint16_t)byte);
			}
			if (*end == NULL || i == 7) {
				inp = end;
				break;
			}
			if (inp == end) {	/* not a number must be */
				if (*inp == ':' &&
				    ((i == 0 && *(inp + 1) == ':') ||
				    lastbyte == ':')) {
					if (dbl_col) {
						return (0);
					}
					if (byte != 0)
						i++;
					dbl_col = &v6buf.v6words_u[i];
					if (i == 0)
						inp++;
				} else if (*inp == NULL || *inp == ' ' ||
				    *inp == '\t') {
					break;
				} else {
					return (0);
				}
			} else {
				inp = end;
			}
			if (*inp != ':') {
				return (0);
			}
			inp++;
			if (*inp == NULL || *inp == ' ' || *inp == '\t') {
				break;
			}
			lastbyte = *inp;
		}
		if (*inp != NULL && *inp != ' ' && *inp != '\t') {
			return (0);
		}
		/*
		 * v6words now contains the bytes we could translate
		 * dbl_col points to the word (should be 0) where
		 * a double colon was found
		 */
		if (i == 7) {
			v6outp->v6addr_u = v6buf.v6addr_u;
		} else {
			int rem;
			int word;
			int next;
			if (dbl_col == NULL) {
				return (0);
			}
			bzero(&v6outp->v6addr_u, sizeof (in6_addr_t));
			rem = dbl_col - &v6buf.v6words_u[0];
			for (next = 0; next < rem; next++) {
				v6outp->v6words_u[next] = v6buf.v6words_u[next];
			}
			next++;	/* skip dbl_col 0 */
			rem = i - rem;
			word = 8 - rem;
			while (rem > 0) {
				v6outp->v6words_u[word] = v6buf.v6words_u[next];
				word++;
				rem--;
				next++;
			}
		}
		return (1);	/* Success */
	}
	}	/* switch */
	return (-1);	/* return -1 for default case */
}
/*
 * iscsi_create_sendtgts_list -  Based upon the given data, build a
 * linked list of SendTarget information.  The data passed into this
 * function  is expected to be the data portion(s) of SendTarget text
 * response.
 */
static iscsi_status_t
iscsi_create_sendtgts_list(iscsi_conn_t *icp, char *data, int data_len,
    iscsi_sendtgts_list_t *stl)
{
	char			*line = NULL;
	boolean_t		targetname_added = B_FALSE;
	iscsi_sendtgts_entry_t	*curr_ste = NULL,
	    *prev_ste = NULL;
	struct hostent		*hptr;
	int			error_num;

	/* initialize number of targets found */
	stl->stl_out_cnt = 0;

	if (data_len == 0)
		return (ISCSI_STATUS_SUCCESS);

	while ((line = iscsi_get_next_text(data, data_len, line)) != NULL) {
		if (strncmp(TARGETNAME, line, strlen(TARGETNAME)) == 0) {
			/* check if this is first targetname */
			if (prev_ste != NULL) {
				stl->stl_out_cnt++;
			}
			if (stl->stl_out_cnt >= stl->stl_in_cnt) {
				/*
				 * continue processing the data so that
				 * the total number of targets are known
				 * and the caller can retry with the correct
				 * number of entries in the list
				 */
				continue;
			}
			curr_ste = &(stl->stl_list[stl->stl_out_cnt]);

			/*
			 * This entry will use the IP address and port
			 * that was passed into this routine. If the next
			 * line that we receive is a TargetAddress we will
			 * know to modify this entry with the new IP address,
			 * port and portal group tag. If this state flag
			 * is not set we'll just create a new entry using
			 * only the previous entries targetname.
			 */
			(void) strncpy((char *)curr_ste->ste_name,
			    line + strlen(TARGETNAME),
			    sizeof (curr_ste->ste_name));

			if (icp->conn_base_addr.sin.sa_family == AF_INET) {

				struct sockaddr_in *addr_in =
				    &icp->conn_base_addr.sin4;
				curr_ste->ste_ipaddr.a_addr.i_insize =
				    sizeof (struct in_addr);
				bcopy(&addr_in->sin_addr.s_addr,
				    &curr_ste->ste_ipaddr.a_addr.i_addr,
				    sizeof (struct in_addr));
				curr_ste->ste_ipaddr.a_port =
				    htons(addr_in->sin_port);

			} else {

				struct sockaddr_in6 *addr_in6 =
				    &icp->conn_base_addr.sin6;
				curr_ste->ste_ipaddr.a_addr.i_insize =
				    sizeof (struct in6_addr);
				bcopy(&addr_in6->sin6_addr.s6_addr,
				    &curr_ste->ste_ipaddr.a_addr.i_addr,
				    sizeof (struct in6_addr));
				curr_ste->ste_ipaddr.a_port =
				    htons(addr_in6->sin6_port);
			}
			curr_ste->ste_tpgt = -1;

			targetname_added = B_TRUE;

		} else if (strncmp(TARGETADDRESS, line,
		    strlen(TARGETADDRESS)) == 0) {

			char *in_str,
			    *tmp_buf,
			    *addr_str,
			    *port_str,
			    *tpgt_str;
			int type,
			    tmp_buf_len;
			long result;

			/*
			 * If TARGETADDRESS is first line a SendTarget response
			 * (i.e. no TARGETNAME lines preceding), treat as
			 * an error.  To check this an assumption is made that
			 * at least one sendtarget_entry_t should exist prior
			 * to entering this code.
			 */
			if (prev_ste == NULL) {
				cmn_err(CE_NOTE, "SendTargets protocol error: "
				    "TARGETADDRESS first");
				return (ISCSI_STATUS_PROTOCOL_ERROR);
			}

			/*
			 * If we can't find an '=' then the sendtargets
			 * response if invalid per spec.  Return empty list.
			 */
			in_str = strchr(line, '=');
			if (in_str == NULL) {
				return (ISCSI_STATUS_PROTOCOL_ERROR);
			}

			/* move past the '=' */
			in_str++;

			/* Copy  addr, port, and tpgt into temporary buffer */
			tmp_buf_len = strlen(in_str) + 1;
			tmp_buf = kmem_zalloc(tmp_buf_len, KM_SLEEP);
			(void) strncpy(tmp_buf, in_str, tmp_buf_len);

			/*
			 * Parse the addr, port, and tpgt from
			 * sendtarget response
			 */
			if (parse_addr_port_tpgt(tmp_buf, &addr_str, &type,
			    &port_str, &tpgt_str) == B_FALSE) {
				/* Unable to extract addr */
				kmem_free(tmp_buf, tmp_buf_len);
				return (ISCSI_STATUS_PROTOCOL_ERROR);
			}

			/* Now convert string addr to binary */
			hptr = kgetipnodebyname(addr_str, type,
			    AI_ALL, &error_num);
			if (!hptr) {
				/* Unable to get valid address */
				kmem_free(tmp_buf, tmp_buf_len);
				return (ISCSI_STATUS_PROTOCOL_ERROR);
			}

			/* Check if space for response */
			if (targetname_added == B_FALSE) {
				stl->stl_out_cnt++;
				if (stl->stl_out_cnt >= stl->stl_in_cnt) {
					/*
					 * continue processing the data so that
					 * the total number of targets are
					 * known and the caller can retry with
					 * the correct number of entries in
					 * the list
					 */
					kfreehostent(hptr);
					kmem_free(tmp_buf, tmp_buf_len);
					continue;
				}
				curr_ste = &(stl->stl_list[stl->stl_out_cnt]);
				(void) strcpy((char *)curr_ste->ste_name,
				    (char *)prev_ste->ste_name);
			}

			curr_ste->ste_ipaddr.a_addr.i_insize = hptr->h_length;
			bcopy(*hptr->h_addr_list,
			    &(curr_ste->ste_ipaddr.a_addr.i_addr),
			    curr_ste->ste_ipaddr.a_addr.i_insize);
			kfreehostent(hptr);

			if (port_str != NULL) {
				(void) ddi_strtol(port_str, NULL, 0, &result);
				curr_ste->ste_ipaddr.a_port = (short)result;
			} else {
				curr_ste->ste_ipaddr.a_port = ISCSI_LISTEN_PORT;
			}

			if (tpgt_str != NULL) {
				(void) ddi_strtol(tpgt_str, NULL, 0, &result);
				curr_ste->ste_tpgt = (short)result;
			} else {
				cmn_err(CE_NOTE, "SendTargets protocol error: "
				    "TPGT not specified");
				kmem_free(tmp_buf, tmp_buf_len);
				return (ISCSI_STATUS_PROTOCOL_ERROR);
			}

			kmem_free(tmp_buf, tmp_buf_len);

			targetname_added = B_FALSE;

		} else if (strlen(line) != 0) {
			/*
			 * Any other string besides an empty string
			 * is a protocol error
			 */
			cmn_err(CE_NOTE, "SendTargets protocol error: "
			    "unexpected response");
			return (ISCSI_STATUS_PROTOCOL_ERROR);
		}

		prev_ste = curr_ste;
	}

	/*
	 * If target found increment out count one more time because
	 * this is the total number of entries in the list not an index
	 * like it was used above
	 */
	if (prev_ste != NULL) {
		stl->stl_out_cnt++;
	}

	return (ISCSI_STATUS_SUCCESS);
}
Example #19
0
/*
 * Create classes and major number bindings for the name of my root.
 * Called immediately before 'loadrootmodules'
 */
static void
impl_create_root_class(void)
{
	major_t major;
	size_t size;
	char *cp;

	/*
	 * The name for the root nexus is exactly as the manufacturer
	 * placed it in the prom name property.  No translation.
	 */
	if ((major = ddi_name_to_major("rootnex")) == DDI_MAJOR_T_NONE)
		panic("Couldn't find major number for 'rootnex'");

	/*
	 * C OBP (Serengeti) does not include the NULL when returning
	 * the length of the name property, while this violates 1275,
	 * Solaris needs to work around this by allocating space for
	 * an extra character.
	 */
	size = (size_t)BOP_GETPROPLEN(bootops, "mfg-name") + 1;
	rootname = kmem_zalloc(size, KM_SLEEP);
	(void) BOP_GETPROP(bootops, "mfg-name", rootname);

	/*
	 * Fix conflict between OBP names and filesystem names.
	 * Substitute '_' for '/' in the name.  Ick.  This is only
	 * needed for the root node since '/' is not a legal name
	 * character in an OBP device name.
	 */
	for (cp = rootname; *cp; cp++)
		if (*cp == '/')
			*cp = '_';

	/*
	 * Bind rootname to rootnex driver
	 */
	if (make_mbind(rootname, major, NULL, mb_hashtab) != 0) {
		cmn_err(CE_WARN, "A driver or driver alias has already "
		    "registered the name \"%s\".  The root nexus needs to "
		    "use this name, and will override the existing entry. "
		    "Please correct /etc/name_to_major and/or "
		    "/etc/driver_aliases and reboot.", rootname);

		/*
		 * Resort to the emergency measure of blowing away the
		 * existing hash entry and replacing it with rootname's.
		 */
		delete_mbind(rootname, mb_hashtab);
		if (make_mbind(rootname, major, NULL, mb_hashtab) != 0)
			panic("mb_hashtab: inconsistent state.");
	}

	/*
	 * The `platform' or `implementation architecture' name has been
	 * translated by boot to be proper for file system use.  It is
	 * the `name' of the platform actually booted.  Note the assumption
	 * is that the name will `fit' in the buffer platform (which is
	 * of size SYS_NMLN, which is far bigger than will actually ever
	 * be needed).
	 */
	(void) BOP_GETPROP(bootops, "impl-arch-name", platform);

	/*
	 * If boot-aoepath is defined, assume it's AoE boot and set bootpath to
	 * aoeblk/blkdev device corresponding to specified shelf.slot numbers.
	 */
	size = (size_t)BOP_GETPROPLEN(bootops, "boot-aoepath");
	if (size != -1) {
		char	aoedev[MAXPATHLEN];
		char	*delim;
		int	shelf, slot;

		aoepath_prop = kmem_zalloc(size, KM_SLEEP);
		(void) BOP_GETPROP(bootops, "boot-aoepath", aoepath_prop);
		/*
		 * If boot-aoepath is set to "auto", device will be
		 * configured later during AoE autoconfiguration.
		 */
		if (strcmp(aoepath_prop, "auto") != 0) {
			if ((delim = strchr(aoepath_prop, '.')) != NULL)
				*delim++ = '\0';
			if (ddi_strtol(aoepath_prop, (char **)NULL, 10,
			    (long *)&shelf) != 0)
				shelf = 0;
			if (delim == NULL ||
			    ddi_strtol(delim, (char **)NULL, 10,
			    (long *)&slot) != 0)
				slot = 0;
			/* FIXME aoeblk@0,0 ?! */
			(void) snprintf(aoedev, MAXPATHLEN,
			    "/aoe/aoeblk@0,0/blkdev@%d,%d",
			    shelf, slot);
			setbootpath(aoedev);
		}
	}

#if defined(__x86)
	/*
	 * Retrieve and honor the bootpath and optional fstype properties
	 */
	size = (size_t)BOP_GETPROPLEN(bootops, "bootpath");
	if (size != -1) {
		bootpath_prop = kmem_zalloc(size, KM_SLEEP);
		(void) BOP_GETPROP(bootops, "bootpath", bootpath_prop);
		setbootpath(bootpath_prop);
	}

	size = (size_t)BOP_GETPROPLEN(bootops, "fstype");
	if (size != -1) {
		fstype_prop = kmem_zalloc(size, KM_SLEEP);
		(void) BOP_GETPROP(bootops, "fstype", fstype_prop);
		setbootfstype(fstype_prop);
	}
#endif
}
/*ARGSUSED*/
static int
opt_pcbe_configure(uint_t picnum, char *event, uint64_t preset, uint32_t flags,
    uint_t nattrs, kcpc_attr_t *attrs, void **data, void *token)
{
	opt_pcbe_config_t	*cfg;
	amd_event_t		*evp;
	amd_event_t		ev_raw = { "raw", 0};
	amd_generic_event_t	*gevp;
	int			i;
	uint64_t		evsel = 0, evsel_tmp = 0;

	/*
	 * If we've been handed an existing configuration, we need only preset
	 * the counter value.
	 */
	if (*data != NULL) {
		cfg = *data;
		cfg->opt_rawpic = preset & MASK48;
		return (0);
	}

	if (picnum >= 4)
		return (CPC_INVALID_PICNUM);

	if ((evp = find_event(event)) == NULL) {
		if ((gevp = find_generic_event(event)) != NULL) {
			evp = find_event(gevp->event);
			ASSERT(evp != NULL);

			if (nattrs > 0)
				return (CPC_ATTRIBUTE_OUT_OF_RANGE);

			evsel |= gevp->umask << OPT_PES_UMASK_SHIFT;
		} else {
			long tmp;

			/*
			 * If ddi_strtol() likes this event, use it as a raw
			 * event code.
			 */
			if (ddi_strtol(event, NULL, 0, &tmp) != 0)
				return (CPC_INVALID_EVENT);

			ev_raw.emask = tmp;
			evp = &ev_raw;
		}
	}

	/*
	 * Configuration of EventSelect register. While on some families
	 * certain bits might not be supported (e.g. Guest/Host on family
	 * 11h), setting these bits is harmless
	 */

	/* Set GuestOnly bit to 0 and HostOnly bit to 1 */
	evsel &= ~OPT_PES_HOST;
	evsel &= ~OPT_PES_GUEST;

	/* Set bits [35:32] for extended part of Event Select field */
	evsel_tmp = evp->emask & 0x0f00;
	evsel |= evsel_tmp << 24;

	evsel |= evp->emask & 0x00ff;

	if (flags & CPC_COUNT_USER)
		evsel |= OPT_PES_USR;
	if (flags & CPC_COUNT_SYSTEM)
		evsel |= OPT_PES_OS;
	if (flags & CPC_OVF_NOTIFY_EMT)
		evsel |= OPT_PES_INT;

	for (i = 0; i < nattrs; i++) {
		if (strcmp(attrs[i].ka_name, "edge") == 0) {
			if (attrs[i].ka_val != 0)
				evsel |= OPT_PES_EDGE;
		} else if (strcmp(attrs[i].ka_name, "pc") == 0) {
			if (attrs[i].ka_val != 0)
				evsel |= OPT_PES_PC;
		} else if (strcmp(attrs[i].ka_name, "inv") == 0) {
			if (attrs[i].ka_val != 0)
				evsel |= OPT_PES_INV;
		} else if (strcmp(attrs[i].ka_name, "cmask") == 0) {
			if ((attrs[i].ka_val | OPT_PES_CMASK_MASK) !=
			    OPT_PES_CMASK_MASK)
				return (CPC_ATTRIBUTE_OUT_OF_RANGE);
			evsel |= attrs[i].ka_val << OPT_PES_CMASK_SHIFT;
		} else if (strcmp(attrs[i].ka_name, "umask") == 0) {
			if ((attrs[i].ka_val | OPT_PES_UMASK_MASK) !=
			    OPT_PES_UMASK_MASK)
				return (CPC_ATTRIBUTE_OUT_OF_RANGE);
			evsel |= attrs[i].ka_val << OPT_PES_UMASK_SHIFT;
		} else
			return (CPC_INVALID_ATTRIBUTE);
	}

	cfg = kmem_alloc(sizeof (*cfg), KM_SLEEP);

	cfg->opt_picno = picnum;
	cfg->opt_evsel = evsel;
	cfg->opt_rawpic = preset & MASK48;

	*data = cfg;
	return (0);
}