Example #1
0
void check_promisc(int fildes, dl_promiscon_req_t * promiscon)
{
    char *device;
    file_t *file;
    cred_t *cred;
    dev_t rdev;

    if (promiscon->dl_primitive == DL_PROMISCON_REQ &&
        promiscon->dl_level == DL_PROMISC_PHYS) {

        file = getf(fildes);

        if (!file)
            return;

        rdev = file->f_vnode->v_rdev;
        device = ddi_major_to_name(getmajor(rdev));
        cred = ddi_get_cred();

        log_msg(CE_WARN, "Promiscuous mode enabled on interface %s",
                device ? device : "unknown");

        releasef(fildes);
    }

    return;
}
Example #2
0
static int
dr_resolve_devname(dev_info_t *dip, char *buffer, char *alias)
{
	major_t	devmajor;
	char	*aka, *name;

	*buffer = *alias = 0;

	if (dip == NULL)
		return (-1);

	if ((name = ddi_get_name(dip)) == NULL)
		name = "<null name>";

	aka = name;

	if ((devmajor = ddi_name_to_major(aka)) != -1)
		aka = ddi_major_to_name(devmajor);

	strcpy(buffer, name);

	if (strcmp(name, aka))
		strcpy(alias, aka);
	else
		*alias = 0;

	return (0);
}
Example #3
0
/*
 * For a given instance, load that driver and its parents
 */
static int
load_parent_drivers(dev_info_t *dip, char *path)
{
	int	rval = 0;
	major_t	major = (major_t)-1;
	char	*drv;
	char	*p;

	while (dip) {
		/* check for path-oriented alias */
		if (path)
			major = ddi_name_to_major(path);
		else
			major = (major_t)-1;

		if (major != (major_t)-1)
			drv = ddi_major_to_name(major);
		else
			drv = ddi_binding_name(dip);

		if (load_boot_driver(drv) != 0)
			rval = -1;

		dip = ddi_get_parent(dip);
		if (path) {
			p = strrchr(path, '/');
			if (p)
				*p = 0;
		}
	}

	return (rval);
}
Example #4
0
/*
 * Create the "mac" kstat.  The "mac" kstat is comprised of three kinds of
 * statistics: statistics maintained by the mac module itself, generic mac
 * statistics maintained by the driver, and MAC-type specific statistics
 * also maintained by the driver.
 */
void
mac_driver_stat_create(mac_impl_t *mip)
{
	kstat_t		*ksp;
	kstat_named_t	*knp;
	uint_t		count;
	major_t		major = getmajor(mip->mi_phy_dev);

	count = MAC_MOD_NKSTAT + MAC_NKSTAT + mip->mi_type->mt_statcount;
	ksp = kstat_create_zone((const char *)ddi_major_to_name(major),
	    getminor(mip->mi_phy_dev) - 1, MAC_KSTAT_NAME,
	    MAC_KSTAT_CLASS, KSTAT_TYPE_NAMED, count, 0, getzoneid());
	if (ksp == NULL)
		return;

	ksp->ks_update = i_mac_driver_stat_update;
	ksp->ks_private = mip;
	mip->mi_ksp = ksp;
	mip->mi_kstat_count = count;

	knp = (kstat_named_t *)ksp->ks_data;
	i_mac_kstat_init(knp, i_mac_mod_si, MAC_MOD_NKSTAT);
	knp += MAC_MOD_NKSTAT;
	i_mac_kstat_init(knp, i_mac_si, MAC_NKSTAT);
	if (mip->mi_type->mt_statcount > 0) {
		knp += MAC_NKSTAT;
		i_mac_kstat_init(knp, mip->mi_type->mt_stats,
		    mip->mi_type->mt_statcount);
	}

	kstat_install(ksp);
}
Example #5
0
/*
 * Construct an sbd_error_t featuring a string representation of an array of
 * integers as its e_rsc.
 */
static sbd_error_t *
drerr_int(int e_code, uint64_t *arr, int idx, int majors)
{
	int		i, n, buf_len, buf_idx, buf_avail;
	char		*dname;
	char		*buf;
	sbd_error_t	*new_sbd_err;
	static char	s_ellipsis[] = "...";

	if (arr == NULL || idx <= 0)
		return (NULL);

	/* MAXPATHLEN is the size of the e_rsc field in sbd_error_t. */
	buf = (char *)kmem_zalloc(MAXPATHLEN, KM_SLEEP);

	/*
	 * This is the total working area of the buffer.  It must be computed
	 * as the size of 'buf', minus reserved space for the null terminator
	 * and the ellipsis string.
	 */
	buf_len = MAXPATHLEN - (strlen(s_ellipsis) + 1);

	/* Construct a string representation of the array values */
	for (buf_idx = 0, i = 0; i < idx; i++) {
		buf_avail = buf_len - buf_idx;
		if (majors) {
			dname = ddi_major_to_name(arr[i]);
			if (dname) {
				n = snprintf(&buf[buf_idx], buf_avail,
					"%s, ", dname);
			} else {
				n = snprintf(&buf[buf_idx], buf_avail,
					"major %lu, ", arr[i]);
			}
		} else {
			n = snprintf(&buf[buf_idx], buf_avail, "%lu, ",
				arr[i]);
		}

		/* An ellipsis gets appended when no more values fit */
		if (n >= buf_avail) {
			(void) strcpy(&buf[buf_idx], s_ellipsis);
			break;
		}

		buf_idx += n;
	}

	/* If all the contents fit, remove the trailing comma */
	if (n < buf_avail) {
		buf[--buf_idx] = '\0';
		buf[--buf_idx] = '\0';
	}

	/* Return an sbd_error_t with the buffer and e_code */
	new_sbd_err = drerr_new(1, e_code, buf);
	kmem_free(buf, MAXPATHLEN);
	return (new_sbd_err);
}
Example #6
0
/*
 * Get a physical device name, and maybe load and attach
 * the driver.
 *
 * XXX	Need better checking of whether or not a device
 *	actually exists if the user typed in a pathname.
 *
 * XXX	Are we sure we want to expose users to this sort
 *	of physical namespace gobbledygook (now there's
 *	a word to conjure with..)
 *
 * XXX	Note that on an OBP machine, we can easily ask the
 *	prom and pretty-print some plausible set of bootable
 *	devices.  We can also user the prom to verify any
 *	such device.  Later tim.. later.
 */
static int
getphysdev(char *askfor, char *name, size_t namelen)
{
	static char fmt[] = "Enter physical name of %s device\n[%s]: ";
	dev_t dev;
	static char defaultpath[BO_MAXOBJNAME];

	/*
	 * Establish 'default' values - we get the root device from
	 * boot, and we infer the swap device is the same but with
	 * a 'b' on the end instead of an 'a'.  A first stab at
	 * ease-of-use ..
	 */
	if (strcmp(askfor, "root") == 0) {
		if (get_bootpath_prop(defaultpath) == -1)
			boothowto |= RB_ASKNAME | RB_VERBOSE;
	} else {
		(void) strcpy(defaultpath, rootfs.bo_name);
		defaultpath[strlen(defaultpath) - 1] = 'b';
	}

retry:
	if (boothowto & RB_ASKNAME) {
		printf(fmt, askfor, defaultpath);
		console_gets(name, namelen);
	}
	if (*name == '\0')
		(void) strcpy(name, defaultpath);

	if (strcmp(askfor, "swap") == 0)   {

		/*
		 * Try to load and install the swap device driver.
		 */
		dev = ddi_pathname_to_dev_t(name);

		if (dev == (dev_t)-1)  {
			printf("Not a supported device for swap.\n");
			boothowto |= RB_ASKNAME | RB_VERBOSE;
			goto retry;
		}

		/*
		 * Ensure that we're not trying to swap on the floppy.
		 */
		if (strncmp(ddi_major_to_name(getmajor(dev)), "fd", 2) == 0) {
			printf("Too dangerous to swap on the floppy\n");
			if (boothowto & RB_ASKNAME)
				goto retry;
			return (-1);
		}
	}

	return (0);
}
Example #7
0
/*
 * Load drivers required for a platform
 * Since all hardware nodes should be available in the device
 * tree, walk the per-driver list and load the parents of
 * each node found. If not a hardware node, try to load it.
 * Pseudo nexus is already loaded.
 */
static int
load_boot_platform_modules(char *drv)
{
	major_t	major;
	dev_info_t *dip;
	char	*drvname;
	int	rval = 0;

	if ((major = ddi_name_to_major(drv)) == (major_t)-1) {
		cmn_err(CE_CONT, "%s: no major number\n", drv);
		return (-1);
	}

	/*
	 * resolve aliases
	 */
	drvname = ddi_major_to_name(major);
	if ((major = ddi_name_to_major(drvname)) == (major_t)-1)
		return (-1);

#ifdef	DEBUG
	if (strcmp(drv, drvname) == 0) {
		BMDPRINTF(("load_boot_platform_modules: %s\n", drv));
	} else {
		BMDPRINTF(("load_boot_platform_modules: %s -> %s\n",
		    drv, drvname));
	}
#endif	/* DEBUG */

	dip = devnamesp[major].dn_head;
	if (dip == NULL) {
		/* pseudo node, not-enumerated, needs to be loaded */
		if (modloadonly("drv", drvname) == -1) {
			cmn_err(CE_CONT, "%s: cannot load platform driver\n",
			    drvname);
			rval = -1;
		}
	} else {
		while (dip) {
			if (load_parent_drivers(dip, NULL) != 0)
				rval = -1;
			dip = ddi_get_next(dip);
		}
	}

	return (rval);
}
Example #8
0
static int
dr_is_unsafe_major(major_t major)
{
	char    *dname, **cpp;
	int	i, ndevs;

	if ((dname = ddi_major_to_name(major)) == NULL) {
		PR_QR("dr_is_unsafe_major: invalid major # %d\n", major);
		return (0);
	}

	ndevs = dr_unsafe_devs.ndevs;
	for (i = 0, cpp = dr_unsafe_devs.devnames; i < ndevs; i++) {
		if (strcmp(dname, *cpp++) == 0)
			return (1);
	}
	return (0);
}
Example #9
0
/*
 * DL_INFO_REQ
 */
static void
proto_info_req(dld_str_t *dsp, mblk_t *mp)
{
	dl_info_ack_wrapper_t	*dlwp;
	dl_info_ack_t		*dlp;
	dl_qos_cl_sel1_t	*selp;
	dl_qos_cl_range1_t	*rangep;
	uint8_t			*addr;
	uint8_t			*brdcst_addr;
	uint_t			addr_length;
	uint_t			sap_length;
	mac_info_t		minfo;
	mac_info_t		*minfop;
	queue_t			*q = dsp->ds_wq;

	/*
	 * Swap the request message for one large enough to contain the
	 * wrapper structure defined above.
	 */
	if ((mp = mexchange(q, mp, sizeof (dl_info_ack_wrapper_t),
	    M_PCPROTO, 0)) == NULL)
		return;

	bzero(mp->b_rptr, sizeof (dl_info_ack_wrapper_t));
	dlwp = (dl_info_ack_wrapper_t *)mp->b_rptr;

	dlp = &(dlwp->dl_info);
	ASSERT(dlp == (dl_info_ack_t *)mp->b_rptr);

	dlp->dl_primitive = DL_INFO_ACK;

	/*
	 * Set up the sub-structure pointers.
	 */
	addr = dlwp->dl_addr;
	brdcst_addr = dlwp->dl_brdcst_addr;
	rangep = &(dlwp->dl_qos_range1);
	selp = &(dlwp->dl_qos_sel1);

	/*
	 * This driver supports only version 2 connectionless DLPI provider
	 * nodes.
	 */
	dlp->dl_service_mode = DL_CLDLS;
	dlp->dl_version = DL_VERSION_2;

	/*
	 * Set the style of the provider
	 */
	dlp->dl_provider_style = dsp->ds_style;
	ASSERT(dlp->dl_provider_style == DL_STYLE1 ||
	    dlp->dl_provider_style == DL_STYLE2);

	/*
	 * Set the current DLPI state.
	 */
	dlp->dl_current_state = dsp->ds_dlstate;

	/*
	 * Gratuitously set the media type. This is to deal with modules
	 * that assume the media type is known prior to DL_ATTACH_REQ
	 * being completed.
	 */
	dlp->dl_mac_type = DL_ETHER;

	/*
	 * If the stream is not at least attached we try to retrieve the
	 * mac_info using mac_info_get()
	 */
	if (dsp->ds_dlstate == DL_UNATTACHED ||
	    dsp->ds_dlstate == DL_ATTACH_PENDING ||
	    dsp->ds_dlstate == DL_DETACH_PENDING) {
		if (!mac_info_get(ddi_major_to_name(dsp->ds_major), &minfo)) {
			/*
			 * Cannot find mac_info. giving up.
			 */
			goto done;
		}
		minfop = &minfo;
	} else {
		minfop = (mac_info_t *)dsp->ds_mip;
		/* We can only get the sdu if we're attached. */
		mac_sdu_get(dsp->ds_mh, &dlp->dl_min_sdu, &dlp->dl_max_sdu);
	}

	/*
	 * Set the media type (properly this time).
	 */
	if (dsp->ds_native)
		dlp->dl_mac_type = minfop->mi_nativemedia;
	else
		dlp->dl_mac_type = minfop->mi_media;

	/*
	 * Set the DLSAP length. We only support 16 bit values and they
	 * appear after the MAC address portion of DLSAP addresses.
	 */
	sap_length = sizeof (uint16_t);
	dlp->dl_sap_length = NEG(sap_length);

	addr_length = minfop->mi_addr_length;

	/*
	 * Copy in the media broadcast address.
	 */
	if (minfop->mi_brdcst_addr != NULL) {
		dlp->dl_brdcst_addr_offset =
		    (uintptr_t)brdcst_addr - (uintptr_t)dlp;
		bcopy(minfop->mi_brdcst_addr, brdcst_addr, addr_length);
		dlp->dl_brdcst_addr_length = addr_length;
	}

	/* Only VLAN links and links that have a normal tag mode support QOS. */
	if ((dsp->ds_mch != NULL &&
	    mac_client_vid(dsp->ds_mch) != VLAN_ID_NONE) ||
	    (dsp->ds_dlp != NULL &&
	    dsp->ds_dlp->dl_tagmode == LINK_TAGMODE_NORMAL)) {
		dlp->dl_qos_range_offset = (uintptr_t)rangep - (uintptr_t)dlp;
		dlp->dl_qos_range_length = sizeof (dl_qos_cl_range1_t);

		rangep->dl_qos_type = DL_QOS_CL_RANGE1;
		rangep->dl_trans_delay.dl_target_value = DL_UNKNOWN;
		rangep->dl_trans_delay.dl_accept_value = DL_UNKNOWN;
		rangep->dl_protection.dl_min = DL_UNKNOWN;
		rangep->dl_protection.dl_max = DL_UNKNOWN;
		rangep->dl_residual_error = DL_UNKNOWN;

		/*
		 * Specify the supported range of priorities.
		 */
		rangep->dl_priority.dl_min = 0;
		rangep->dl_priority.dl_max = (1 << VLAN_PRI_SIZE) - 1;

		dlp->dl_qos_offset = (uintptr_t)selp - (uintptr_t)dlp;
		dlp->dl_qos_length = sizeof (dl_qos_cl_sel1_t);

		selp->dl_qos_type = DL_QOS_CL_SEL1;
		selp->dl_trans_delay = DL_UNKNOWN;
		selp->dl_protection = DL_UNKNOWN;
		selp->dl_residual_error = DL_UNKNOWN;

		/*
		 * Specify the current priority (which can be changed by
		 * the DL_UDQOS_REQ primitive).
		 */
		selp->dl_priority = dsp->ds_pri;
	}

	dlp->dl_addr_length = addr_length + sizeof (uint16_t);
	if (dsp->ds_dlstate == DL_IDLE) {
		/*
		 * The stream is bound. Therefore we can formulate a valid
		 * DLSAP address.
		 */
		dlp->dl_addr_offset = (uintptr_t)addr - (uintptr_t)dlp;
		if (addr_length > 0)
			mac_unicast_primary_get(dsp->ds_mh, addr);

		*(uint16_t *)(addr + addr_length) = dsp->ds_sap;
	}

done:
	IMPLY(dlp->dl_qos_offset != 0, dlp->dl_qos_length != 0);
	IMPLY(dlp->dl_qos_range_offset != 0,
	    dlp->dl_qos_range_length != 0);
	IMPLY(dlp->dl_addr_offset != 0, dlp->dl_addr_length != 0);
	IMPLY(dlp->dl_brdcst_addr_offset != 0,
	    dlp->dl_brdcst_addr_length != 0);

	qreply(q, mp);
}
Example #10
0
/*
 * Load a driver needed to boot.
 */
static int
load_boot_driver(char *drv)
{
	char		*drvname;
	major_t		major;
#ifdef	sparc
	struct devnames *dnp;
	ddi_prop_t	*propp;
	char		*module;
	char		*dir, *mf;
	int		plen;
	int		mlen;
#endif	/* sparc */

	if ((major = ddi_name_to_major(drv)) == (major_t)-1) {
		cmn_err(CE_CONT, "%s: no major number\n", drv);
		return (-1);
	}
	/*
	 * resolve aliases
	 */
	drvname = ddi_major_to_name(major);

#ifdef	DEBUG
	if (strcmp(drv, drvname) == 0) {
		BMDPRINTF(("load_boot_driver: %s\n", drv));
	} else {
		BMDPRINTF(("load_boot_driver: %s -> %s\n", drv, drvname));
	}
#endif	/* DEBUG */

	if (modloadonly("drv", drvname) == -1) {
		cmn_err(CE_CONT, "%s: cannot load driver\n", drvname);
		return (-1);
	}

#ifdef	sparc
	/*
	 * NOTE: this can be removed when newboot-sparc is delivered.
	 *
	 * Check to see if the driver had a 'ddi-forceload' global driver.conf
	 * property to identify additional modules that need to be loaded.
	 * The driver still needs to use ddi_modopen() to open these modules,
	 * but the 'ddi-forceload' property allows the modules to be loaded
	 * into memory prior to lights-out, so that driver ddi_modopen()
	 * calls during lights-out (when mounting root) will work correctly.
	 * Use of 'ddi-forceload' is only required for drivers involved in
	 * getting root mounted.
	 */
	dnp = &devnamesp[major];
	if (dnp->dn_global_prop_ptr && dnp->dn_global_prop_ptr->prop_list &&
	    ((propp = i_ddi_prop_search(DDI_DEV_T_ANY,
	    "ddi-forceload", DDI_PROP_TYPE_STRING,
	    &dnp->dn_global_prop_ptr->prop_list)) != NULL)) {

		module = (char *)propp->prop_val;
		plen = propp->prop_len;
		while (plen > 0) {
			mlen = strlen(module);
			mf = strrchr(module, '/');
			if (mf) {
				dir = module;
				*mf++ = '\0';		/* '/' -> '\0' */
			} else {
				dir = "misc";
				mf = module;
			}
			if (modloadonly(dir, mf) == -1)
				cmn_err(CE_CONT,
				    "misc/%s: can't load module\n", mf);
			if (mf != module)
				*(mf - 1) = '/';	/* '\0' -> '/' */

			module += mlen + 1;
			plen -= mlen + 1;
		}
	}
#endif	/* sparc */

	return (0);
}