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; }
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); }
/* * 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); }
/* * 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); }
/* * 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); }
/* * 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); }
/* * 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); }
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); }
/* * 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); }
/* * 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); }