Print this page
4770 soconfig(1M) needs an option to print the in-kernel socket configuration table

*** 19,37 **** --- 19,39 ---- * CDDL HEADER END */ /* * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2015 Nexenta Systems, Inc. All rights reserved. */ #include <sys/types.h> #include <sys/t_lock.h> #include <sys/param.h> #include <sys/systm.h> #include <sys/sysmacros.h> #include <sys/cmn_err.h> #include <sys/list.h> + #include <sys/sunddi.h> #include <sys/stropts.h> #include <sys/socket.h> #include <sys/socketvar.h>
*** 821,826 **** --- 823,907 ---- return (error); if ((error = sockparams_new_filter_impl(ent, &sp_ephem_list)) != 0) sockparams_filter_cleanup_impl(ent, &sphead); return (error); + } + + /* + * Setup and return socket configuration table. + */ + int + sockparams_copyout_socktable(uintptr_t socktable) + { + STRUCT_DECL(sockconfig_socktable, st); + struct sockparams *sp; + uint_t count; + uint_t i = 0; + int ret = 0; + sockconfig_socktable_entry_t *se; + + STRUCT_INIT(st, get_udatamodel()); + if (ddi_copyin((void *)socktable, STRUCT_BUF(st), + STRUCT_SIZE(st), 0) != 0) + return (EFAULT); + + rw_enter(&sockconf_lock, RW_READER); + + count = STRUCT_FGET(st, num_of_entries); + /* + * If the output buffer is size zero, just copy out the count. + */ + if (count == 0) { + for (sp = list_head(&sphead); sp != NULL; + sp = list_next(&sphead, sp)) { + count++; + } + STRUCT_FSET(st, num_of_entries, count); + + rw_exit(&sockconf_lock); + if (ddi_copyout(STRUCT_BUF(st), (void *)socktable, + STRUCT_SIZE(st), 0) != 0) + return (EFAULT); + + return (0); + } + + se = kmem_alloc(count * sizeof (sockconfig_socktable_entry_t), + KM_SLEEP); + for (sp = list_head(&sphead); sp != NULL; + sp = list_next(&sphead, sp)) { + if (i >= count) { + /* + * Return if the number of entries has changed. + */ + rw_exit(&sockconf_lock); + kmem_free(se, + count * sizeof (sockconfig_socktable_entry_t)); + return (EAGAIN); + } + se[i].se_family = sp->sp_family; + se[i].se_type = sp->sp_type; + se[i].se_protocol = sp->sp_protocol; + (void) strncpy(se[i].se_modname, sp->sp_smod_name, + MODMAXNAMELEN); + if (sp->sp_sdev_info.sd_devpath != NULL) + (void) strncpy(se[i].se_strdev, + sp->sp_sdev_info.sd_devpath, MAXPATHLEN); + se[i].se_refcnt = sp->sp_refcnt; + se[i].se_flags = sp->sp_flags; + i++; + } + rw_exit(&sockconf_lock); + if (ddi_copyout(se, STRUCT_FGETP(st, st_entries), + i * sizeof (sockconfig_socktable_entry_t), 0) != 0) + ret = EFAULT; + + STRUCT_FSET(st, num_of_entries, i); + kmem_free(se, count * sizeof (sockconfig_socktable_entry_t)); + + if (ddi_copyout(STRUCT_BUF(st), (void *)socktable, + STRUCT_SIZE(st), 0) != 0) + ret = EFAULT; + + return (ret); }