Home | History | Annotate | Line # | Download | only in modules
t_modctl.c revision 1.12.32.1
      1  1.12.32.1  christos /*	$NetBSD: t_modctl.c,v 1.12.32.1 2019/06/10 22:10:08 christos Exp $	*/
      2        1.1      jmmv /*
      3        1.1      jmmv  * Copyright (c) 2008 The NetBSD Foundation, Inc.
      4        1.1      jmmv  * All rights reserved.
      5        1.1      jmmv  *
      6        1.1      jmmv  * Redistribution and use in source and binary forms, with or without
      7        1.1      jmmv  * modification, are permitted provided that the following conditions
      8        1.1      jmmv  * are met:
      9        1.1      jmmv  * 1. Redistributions of source code must retain the above copyright
     10        1.1      jmmv  *    notice, this list of conditions and the following disclaimer.
     11        1.1      jmmv  * 2. Redistributions in binary form must reproduce the above copyright
     12        1.1      jmmv  *    notice, this list of conditions and the following disclaimer in the
     13        1.1      jmmv  *    documentation and/or other materials provided with the distribution.
     14        1.1      jmmv  *
     15        1.1      jmmv  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
     16        1.1      jmmv  * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
     17        1.1      jmmv  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     18        1.1      jmmv  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     19        1.1      jmmv  * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
     20        1.1      jmmv  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21        1.1      jmmv  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     22        1.1      jmmv  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     23        1.1      jmmv  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
     24        1.1      jmmv  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     25        1.1      jmmv  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
     26        1.1      jmmv  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27        1.1      jmmv  */
     28        1.1      jmmv 
     29        1.1      jmmv #include <sys/cdefs.h>
     30  1.12.32.1  christos __KERNEL_RCSID(0, "$NetBSD: t_modctl.c,v 1.12.32.1 2019/06/10 22:10:08 christos Exp $");
     31        1.1      jmmv 
     32        1.1      jmmv #include <sys/module.h>
     33        1.1      jmmv #include <sys/sysctl.h>
     34        1.1      jmmv 
     35        1.1      jmmv #include <assert.h>
     36        1.1      jmmv #include <errno.h>
     37        1.1      jmmv #include <stdarg.h>
     38        1.1      jmmv #include <stdbool.h>
     39        1.1      jmmv #include <stdio.h>
     40        1.1      jmmv #include <stdlib.h>
     41        1.1      jmmv #include <string.h>
     42        1.1      jmmv 
     43        1.1      jmmv #include <prop/proplib.h>
     44        1.1      jmmv 
     45        1.1      jmmv #include <atf-c.h>
     46        1.1      jmmv 
     47        1.7    jruoho enum presence_check { both_checks, stat_check, sysctl_check };
     48        1.1      jmmv 
     49       1.10    martin static void	check_permission(void);
     50        1.7    jruoho static bool	get_modstat_info(const char *, modstat_t *);
     51        1.7    jruoho static bool	get_sysctl(const char *, void *buf, const size_t);
     52        1.7    jruoho static bool	k_helper_is_present_stat(void);
     53        1.7    jruoho static bool	k_helper_is_present_sysctl(void);
     54        1.7    jruoho static bool	k_helper_is_present(enum presence_check);
     55        1.7    jruoho static int	load(prop_dictionary_t, bool, const char *, ...);
     56        1.7    jruoho static int	unload(const char *, bool);
     57        1.7    jruoho static void	unload_cleanup(const char *);
     58        1.1      jmmv 
     59        1.1      jmmv /* --------------------------------------------------------------------- */
     60        1.1      jmmv /* Auxiliary functions                                                   */
     61        1.1      jmmv /* --------------------------------------------------------------------- */
     62        1.1      jmmv 
     63        1.1      jmmv /*
     64  1.12.32.1  christos  * A function checking whether we are allowed to load modules currently
     65       1.10    martin  * (either the kernel is not modular, or securelevel may prevent it)
     66        1.1      jmmv  */
     67       1.10    martin static void
     68       1.10    martin check_permission(void)
     69        1.1      jmmv {
     70       1.10    martin 	int err;
     71       1.10    martin 
     72       1.10    martin 	err = modctl(MODCTL_EXISTS, 0);
     73       1.12    martin 	if (err == 0) return;
     74       1.12    martin 	if (errno == ENOSYS)
     75       1.10    martin 		atf_tc_skip("Kernel does not have 'options MODULAR'.");
     76       1.12    martin 	else if (errno == EPERM)
     77       1.10    martin 		atf_tc_skip("Module loading administratively forbidden");
     78       1.12    martin 	ATF_REQUIRE_EQ_MSG(errno, 0, "unexpected error %d from "
     79       1.12    martin 	    "modctl(MODCTL_EXISTS, 0)", errno);
     80        1.1      jmmv }
     81        1.1      jmmv 
     82        1.7    jruoho static bool
     83        1.1      jmmv get_modstat_info(const char *name, modstat_t *msdest)
     84        1.1      jmmv {
     85        1.1      jmmv 	bool found;
     86        1.1      jmmv 	size_t len;
     87  1.12.32.1  christos 	int count;
     88        1.1      jmmv 	struct iovec iov;
     89        1.1      jmmv 	modstat_t *ms;
     90        1.1      jmmv 
     91       1.10    martin 	check_permission();
     92  1.12.32.1  christos 	for (len = 8192; ;) {
     93        1.1      jmmv 		iov.iov_base = malloc(len);
     94        1.1      jmmv 		iov.iov_len = len;
     95        1.7    jruoho 
     96        1.7    jruoho 		errno = 0;
     97        1.7    jruoho 
     98        1.1      jmmv 		if (modctl(MODCTL_STAT, &iov) != 0) {
     99        1.1      jmmv 			int err = errno;
    100        1.1      jmmv 			fprintf(stderr, "modctl(MODCTL_STAT) failed: %s\n",
    101        1.1      jmmv 			    strerror(err));
    102        1.1      jmmv 			atf_tc_fail("Failed to query module status");
    103        1.1      jmmv 		}
    104        1.1      jmmv 		if (len >= iov.iov_len)
    105        1.1      jmmv 			break;
    106        1.1      jmmv 		free(iov.iov_base);
    107        1.1      jmmv 		len = iov.iov_len;
    108        1.1      jmmv 	}
    109        1.1      jmmv 
    110        1.1      jmmv 	found = false;
    111  1.12.32.1  christos 	count = *(int *)iov.iov_base;
    112  1.12.32.1  christos 	ms = (modstat_t *)((char *)iov.iov_base + sizeof(int));
    113  1.12.32.1  christos 	while ( count ) {
    114        1.1      jmmv 		if (strcmp(ms->ms_name, name) == 0) {
    115        1.1      jmmv 			if (msdest != NULL)
    116        1.1      jmmv 				*msdest = *ms;
    117        1.1      jmmv 			found = true;
    118  1.12.32.1  christos 			break;
    119        1.1      jmmv 		}
    120  1.12.32.1  christos 		ms++;
    121  1.12.32.1  christos 		count--;
    122        1.1      jmmv 	}
    123        1.1      jmmv 
    124        1.1      jmmv 	free(iov.iov_base);
    125        1.1      jmmv 
    126        1.1      jmmv 	return found;
    127        1.1      jmmv }
    128        1.1      jmmv 
    129        1.1      jmmv /*
    130        1.1      jmmv  * Queries a sysctl property.
    131        1.1      jmmv  */
    132        1.7    jruoho static bool
    133        1.1      jmmv get_sysctl(const char *name, void *buf, const size_t len)
    134        1.1      jmmv {
    135        1.1      jmmv 	size_t len2 = len;
    136        1.1      jmmv 	printf("Querying sysctl variable: %s\n", name);
    137        1.1      jmmv 	int ret = sysctlbyname(name, buf, &len2, NULL, 0);
    138        1.1      jmmv 	if (ret == -1 && errno != ENOENT) {
    139        1.1      jmmv 		fprintf(stderr, "sysctlbyname(2) failed: %s\n",
    140        1.1      jmmv 		    strerror(errno));
    141        1.1      jmmv 		atf_tc_fail("Failed to query %s", name);
    142        1.1      jmmv 	}
    143        1.1      jmmv 	return ret != -1;
    144        1.1      jmmv }
    145        1.1      jmmv 
    146        1.1      jmmv /*
    147        1.1      jmmv  * Returns a boolean indicating if the k_helper module was loaded
    148        1.1      jmmv  * successfully.  This implementation uses modctl(2)'s MODCTL_STAT
    149        1.1      jmmv  * subcommand to do the check.
    150        1.1      jmmv  */
    151        1.7    jruoho static bool
    152        1.1      jmmv k_helper_is_present_stat(void)
    153        1.1      jmmv {
    154        1.1      jmmv 
    155        1.1      jmmv 	return get_modstat_info("k_helper", NULL);
    156        1.1      jmmv }
    157        1.1      jmmv 
    158        1.1      jmmv /*
    159        1.1      jmmv  * Returns a boolean indicating if the k_helper module was loaded
    160        1.1      jmmv  * successfully.  This implementation uses the module's sysctl
    161        1.1      jmmv  * installed node to do the check.
    162        1.1      jmmv  */
    163        1.7    jruoho static bool
    164        1.1      jmmv k_helper_is_present_sysctl(void)
    165        1.1      jmmv {
    166        1.1      jmmv 	size_t present;
    167        1.1      jmmv 
    168        1.1      jmmv 	return get_sysctl("vendor.k_helper.present", &present,
    169        1.1      jmmv 	    sizeof(present));
    170        1.1      jmmv }
    171        1.1      jmmv 
    172        1.1      jmmv /*
    173        1.1      jmmv  * Returns a boolean indicating if the k_helper module was loaded
    174        1.1      jmmv  * successfully.  The 'how' parameter specifies the implementation to
    175        1.1      jmmv  * use to do the check.
    176        1.1      jmmv  */
    177        1.7    jruoho static bool
    178        1.1      jmmv k_helper_is_present(enum presence_check how)
    179        1.1      jmmv {
    180        1.1      jmmv 	bool found;
    181        1.1      jmmv 
    182        1.1      jmmv 	switch (how) {
    183        1.1      jmmv 	case both_checks:
    184        1.1      jmmv 		found = k_helper_is_present_stat();
    185        1.1      jmmv 		ATF_CHECK(k_helper_is_present_sysctl() == found);
    186        1.1      jmmv 		break;
    187        1.1      jmmv 
    188        1.1      jmmv 	case stat_check:
    189        1.1      jmmv 		found = k_helper_is_present_stat();
    190        1.1      jmmv 		break;
    191        1.1      jmmv 
    192        1.1      jmmv 	case sysctl_check:
    193        1.1      jmmv 		found = k_helper_is_present_sysctl();
    194        1.1      jmmv 		break;
    195        1.1      jmmv 
    196        1.1      jmmv 	default:
    197        1.5  christos 		found = false;
    198        1.5  christos 		assert(found);
    199        1.1      jmmv 	}
    200        1.1      jmmv 
    201        1.1      jmmv 	return found;
    202        1.1      jmmv }
    203        1.1      jmmv 
    204        1.1      jmmv /*
    205        1.1      jmmv  * Loads the specified module from a file.  If fatal is set and an error
    206        1.1      jmmv  * occurs when loading the module, an error message is printed and the
    207        1.1      jmmv  * test case is aborted.
    208        1.1      jmmv  */
    209        1.8     joerg static __printflike(3, 4) int
    210        1.1      jmmv load(prop_dictionary_t props, bool fatal, const char *fmt, ...)
    211        1.1      jmmv {
    212        1.1      jmmv 	int err;
    213        1.1      jmmv 	va_list ap;
    214        1.1      jmmv 	char filename[MAXPATHLEN], *propsstr;
    215        1.1      jmmv 	modctl_load_t ml;
    216        1.1      jmmv 
    217       1.10    martin 	check_permission();
    218        1.1      jmmv 	if (props == NULL) {
    219        1.1      jmmv 		props = prop_dictionary_create();
    220        1.1      jmmv 		propsstr = prop_dictionary_externalize(props);
    221        1.1      jmmv 		ATF_CHECK(propsstr != NULL);
    222        1.1      jmmv 		prop_object_release(props);
    223        1.1      jmmv 	} else {
    224        1.1      jmmv 		propsstr = prop_dictionary_externalize(props);
    225        1.1      jmmv 		ATF_CHECK(propsstr != NULL);
    226        1.1      jmmv 	}
    227        1.1      jmmv 
    228        1.1      jmmv 	va_start(ap, fmt);
    229        1.1      jmmv 	vsnprintf(filename, sizeof(filename), fmt, ap);
    230        1.1      jmmv 	va_end(ap);
    231        1.1      jmmv 
    232        1.1      jmmv 	ml.ml_filename = filename;
    233        1.1      jmmv 	ml.ml_flags = 0;
    234        1.1      jmmv 	ml.ml_props = propsstr;
    235        1.1      jmmv 	ml.ml_propslen = strlen(propsstr);
    236        1.1      jmmv 
    237        1.1      jmmv 	printf("Loading module %s\n", filename);
    238        1.7    jruoho 	errno = err = 0;
    239        1.7    jruoho 
    240        1.1      jmmv 	if (modctl(MODCTL_LOAD, &ml) == -1) {
    241        1.1      jmmv 		err = errno;
    242        1.1      jmmv 		fprintf(stderr, "modctl(MODCTL_LOAD, %s), failed: %s\n",
    243        1.1      jmmv 		    filename, strerror(err));
    244        1.1      jmmv 		if (fatal)
    245        1.1      jmmv 			atf_tc_fail("Module load failed");
    246        1.1      jmmv 	}
    247        1.1      jmmv 
    248        1.1      jmmv 	free(propsstr);
    249        1.1      jmmv 
    250        1.1      jmmv 	return err;
    251        1.1      jmmv }
    252        1.1      jmmv 
    253        1.1      jmmv /*
    254        1.1      jmmv  * Unloads the specified module.  If silent is true, nothing will be
    255        1.1      jmmv  * printed and no errors will be raised if the unload was unsuccessful.
    256        1.1      jmmv  */
    257        1.7    jruoho static int
    258        1.1      jmmv unload(const char *name, bool fatal)
    259        1.1      jmmv {
    260        1.1      jmmv 	int err;
    261        1.1      jmmv 
    262       1.10    martin 	check_permission();
    263        1.1      jmmv 	printf("Unloading module %s\n", name);
    264        1.7    jruoho 	errno = err = 0;
    265        1.7    jruoho 
    266        1.1      jmmv 	if (modctl(MODCTL_UNLOAD, __UNCONST(name)) == -1) {
    267        1.1      jmmv 		err = errno;
    268        1.1      jmmv 		fprintf(stderr, "modctl(MODCTL_UNLOAD, %s) failed: %s\n",
    269        1.1      jmmv 		    name, strerror(err));
    270        1.1      jmmv 		if (fatal)
    271        1.1      jmmv 			atf_tc_fail("Module unload failed");
    272        1.1      jmmv 	}
    273        1.1      jmmv 	return err;
    274        1.1      jmmv }
    275        1.1      jmmv 
    276        1.1      jmmv /*
    277        1.1      jmmv  * A silent version of unload, to be called as part of the cleanup
    278        1.1      jmmv  * process only.
    279        1.1      jmmv  */
    280        1.7    jruoho static void
    281        1.1      jmmv unload_cleanup(const char *name)
    282        1.1      jmmv {
    283        1.1      jmmv 
    284        1.1      jmmv 	(void)modctl(MODCTL_UNLOAD, __UNCONST(name));
    285        1.1      jmmv }
    286        1.1      jmmv 
    287        1.1      jmmv /* --------------------------------------------------------------------- */
    288        1.1      jmmv /* Test cases                                                            */
    289        1.1      jmmv /* --------------------------------------------------------------------- */
    290        1.1      jmmv 
    291        1.1      jmmv ATF_TC_WITH_CLEANUP(cmd_load);
    292        1.1      jmmv ATF_TC_HEAD(cmd_load, tc)
    293        1.1      jmmv {
    294        1.1      jmmv 	atf_tc_set_md_var(tc, "descr", "Tests for the MODCTL_LOAD command");
    295        1.1      jmmv 	atf_tc_set_md_var(tc, "require.user", "root");
    296        1.1      jmmv }
    297        1.1      jmmv ATF_TC_BODY(cmd_load, tc)
    298        1.1      jmmv {
    299        1.1      jmmv 	char longname[MAXPATHLEN];
    300        1.1      jmmv 	size_t i;
    301        1.1      jmmv 
    302        1.9    jruoho 	ATF_CHECK(load(NULL, false, " ") == ENOENT);
    303        1.1      jmmv 	ATF_CHECK(load(NULL, false, "non-existent.o") == ENOENT);
    304        1.1      jmmv 
    305        1.1      jmmv 	for (i = 0; i < MAXPATHLEN - 1; i++)
    306        1.1      jmmv 		longname[i] = 'a';
    307        1.1      jmmv 	longname[MAXPATHLEN - 1] = '\0';
    308        1.8     joerg 	ATF_CHECK(load(NULL, false, "%s", longname) == ENAMETOOLONG);
    309        1.1      jmmv 
    310        1.1      jmmv 	ATF_CHECK(!k_helper_is_present(stat_check));
    311        1.3      jmmv 	load(NULL, true, "%s/k_helper/k_helper.kmod",
    312        1.3      jmmv 	    atf_tc_get_config_var(tc, "srcdir"));
    313        1.1      jmmv 	printf("Checking if load was successful\n");
    314        1.1      jmmv 	ATF_CHECK(k_helper_is_present(stat_check));
    315        1.1      jmmv }
    316        1.1      jmmv ATF_TC_CLEANUP(cmd_load, tc)
    317        1.1      jmmv {
    318        1.1      jmmv 	unload_cleanup("k_helper");
    319        1.1      jmmv }
    320        1.1      jmmv 
    321        1.1      jmmv ATF_TC_WITH_CLEANUP(cmd_load_props);
    322        1.1      jmmv ATF_TC_HEAD(cmd_load_props, tc)
    323        1.1      jmmv {
    324        1.1      jmmv 	atf_tc_set_md_var(tc, "descr", "Tests for the MODCTL_LOAD command, "
    325        1.1      jmmv 	    "providing extra load-time properties");
    326        1.1      jmmv 	atf_tc_set_md_var(tc, "require.user", "root");
    327        1.1      jmmv }
    328        1.1      jmmv ATF_TC_BODY(cmd_load_props, tc)
    329        1.1      jmmv {
    330        1.1      jmmv 	prop_dictionary_t props;
    331        1.1      jmmv 
    332        1.1      jmmv 	printf("Loading module without properties\n");
    333        1.1      jmmv 	props = prop_dictionary_create();
    334        1.3      jmmv 	load(props, true, "%s/k_helper/k_helper.kmod",
    335        1.3      jmmv 	    atf_tc_get_config_var(tc, "srcdir"));
    336        1.1      jmmv 	prop_object_release(props);
    337        1.1      jmmv 	{
    338        1.1      jmmv 		int ok;
    339        1.1      jmmv 		ATF_CHECK(get_sysctl("vendor.k_helper.prop_str_ok",
    340        1.1      jmmv 		    &ok, sizeof(ok)));
    341        1.1      jmmv 		ATF_CHECK(!ok);
    342        1.1      jmmv 	}
    343        1.1      jmmv 	unload("k_helper", true);
    344        1.1      jmmv 
    345        1.1      jmmv 	printf("Loading module with a string property\n");
    346        1.1      jmmv 	props = prop_dictionary_create();
    347        1.1      jmmv 	prop_dictionary_set(props, "prop_str",
    348        1.1      jmmv 	    prop_string_create_cstring("1st string"));
    349        1.3      jmmv 	load(props, true, "%s/k_helper/k_helper.kmod",
    350        1.3      jmmv 	    atf_tc_get_config_var(tc, "srcdir"));
    351        1.1      jmmv 	prop_object_release(props);
    352        1.1      jmmv 	{
    353        1.1      jmmv 		int ok;
    354        1.1      jmmv 		ATF_CHECK(get_sysctl("vendor.k_helper.prop_str_ok",
    355        1.1      jmmv 		    &ok, sizeof(ok)));
    356        1.1      jmmv 		ATF_CHECK(ok);
    357        1.1      jmmv 
    358        1.1      jmmv 		char val[128];
    359        1.1      jmmv 		ATF_CHECK(get_sysctl("vendor.k_helper.prop_str_val",
    360        1.1      jmmv 		    &val, sizeof(val)));
    361        1.1      jmmv 		ATF_CHECK(strcmp(val, "1st string") == 0);
    362        1.1      jmmv 	}
    363        1.1      jmmv 	unload("k_helper", true);
    364        1.1      jmmv 
    365        1.1      jmmv 	printf("Loading module with a different string property\n");
    366        1.1      jmmv 	props = prop_dictionary_create();
    367        1.1      jmmv 	prop_dictionary_set(props, "prop_str",
    368        1.1      jmmv 	    prop_string_create_cstring("2nd string"));
    369        1.3      jmmv 	load(props, true, "%s/k_helper/k_helper.kmod",
    370        1.3      jmmv 	    atf_tc_get_config_var(tc, "srcdir"));
    371        1.1      jmmv 	prop_object_release(props);
    372        1.1      jmmv 	{
    373        1.1      jmmv 		int ok;
    374        1.1      jmmv 		ATF_CHECK(get_sysctl("vendor.k_helper.prop_str_ok",
    375        1.1      jmmv 		    &ok, sizeof(ok)));
    376        1.1      jmmv 		ATF_CHECK(ok);
    377        1.1      jmmv 
    378        1.1      jmmv 		char val[128];
    379        1.1      jmmv 		ATF_CHECK(get_sysctl("vendor.k_helper.prop_str_val",
    380        1.1      jmmv 		    &val, sizeof(val)));
    381        1.1      jmmv 		ATF_CHECK(strcmp(val, "2nd string") == 0);
    382        1.1      jmmv 	}
    383        1.1      jmmv 	unload("k_helper", true);
    384        1.1      jmmv }
    385        1.1      jmmv ATF_TC_CLEANUP(cmd_load_props, tc)
    386        1.1      jmmv {
    387        1.1      jmmv 	unload_cleanup("k_helper");
    388        1.1      jmmv }
    389        1.1      jmmv 
    390        1.4  pgoyette ATF_TC_WITH_CLEANUP(cmd_load_recurse);
    391        1.4  pgoyette ATF_TC_HEAD(cmd_load_recurse, tc)
    392        1.4  pgoyette {
    393        1.4  pgoyette 	atf_tc_set_md_var(tc, "descr", "Tests for the MODCTL_LOAD command, "
    394        1.4  pgoyette 	    "with recursive module_load()");
    395        1.4  pgoyette 	atf_tc_set_md_var(tc, "require.user", "root");
    396        1.4  pgoyette }
    397        1.4  pgoyette ATF_TC_BODY(cmd_load_recurse, tc)
    398        1.4  pgoyette {
    399        1.4  pgoyette 	prop_dictionary_t props;
    400        1.4  pgoyette 	char filename[MAXPATHLEN];
    401        1.4  pgoyette 
    402        1.4  pgoyette 	printf("Loading module with request to load another module\n");
    403        1.4  pgoyette 	props = prop_dictionary_create();
    404        1.4  pgoyette 	snprintf(filename, sizeof(filename), "%s/k_helper2/k_helper2.kmod",
    405        1.4  pgoyette 	    atf_tc_get_config_var(tc, "srcdir"));
    406        1.4  pgoyette 	prop_dictionary_set(props, "prop_recurse",
    407        1.4  pgoyette 	    prop_string_create_cstring(filename));
    408        1.4  pgoyette 	load(props, true, "%s/k_helper/k_helper.kmod",
    409        1.4  pgoyette 	    atf_tc_get_config_var(tc, "srcdir"));
    410        1.4  pgoyette 	{
    411        1.4  pgoyette 		int ok;
    412        1.4  pgoyette 		ATF_CHECK(get_sysctl("vendor.k_helper.prop_int_load",
    413        1.4  pgoyette 		    &ok, sizeof(ok)));
    414        1.4  pgoyette 		ATF_CHECK(ok == 0);
    415        1.4  pgoyette 		ATF_CHECK(get_sysctl("vendor.k_helper2.present",
    416        1.4  pgoyette 		    &ok, sizeof(ok)));
    417        1.4  pgoyette 		ATF_CHECK(ok);
    418        1.4  pgoyette 	}
    419        1.4  pgoyette 	unload("k_helper", true);
    420        1.4  pgoyette 	unload("k_helper2", true);
    421        1.4  pgoyette }
    422        1.4  pgoyette ATF_TC_CLEANUP(cmd_load_recurse, tc)
    423        1.4  pgoyette {
    424        1.4  pgoyette 	unload_cleanup("k_helper");
    425        1.4  pgoyette 	unload_cleanup("k_helper2");
    426        1.4  pgoyette }
    427        1.4  pgoyette 
    428        1.1      jmmv ATF_TC_WITH_CLEANUP(cmd_stat);
    429        1.1      jmmv ATF_TC_HEAD(cmd_stat, tc)
    430        1.1      jmmv {
    431        1.1      jmmv 	atf_tc_set_md_var(tc, "descr", "Tests for the MODCTL_STAT command");
    432        1.1      jmmv 	atf_tc_set_md_var(tc, "require.user", "root");
    433        1.1      jmmv }
    434        1.1      jmmv ATF_TC_BODY(cmd_stat, tc)
    435        1.1      jmmv {
    436        1.1      jmmv 	ATF_CHECK(!k_helper_is_present(both_checks));
    437        1.1      jmmv 
    438        1.3      jmmv 	load(NULL, true, "%s/k_helper/k_helper.kmod",
    439        1.3      jmmv 	    atf_tc_get_config_var(tc, "srcdir"));
    440        1.1      jmmv 	ATF_CHECK(k_helper_is_present(both_checks));
    441        1.1      jmmv 	{
    442        1.1      jmmv 		modstat_t ms;
    443        1.1      jmmv 		ATF_CHECK(get_modstat_info("k_helper", &ms));
    444        1.1      jmmv 
    445        1.1      jmmv 		ATF_CHECK(ms.ms_class == MODULE_CLASS_MISC);
    446        1.1      jmmv 		ATF_CHECK(ms.ms_source == MODULE_SOURCE_FILESYS);
    447        1.1      jmmv 		ATF_CHECK(ms.ms_refcnt == 0);
    448        1.1      jmmv 	}
    449        1.1      jmmv 	unload("k_helper", true);
    450        1.1      jmmv 
    451        1.1      jmmv 	ATF_CHECK(!k_helper_is_present(both_checks));
    452        1.1      jmmv }
    453        1.1      jmmv ATF_TC_CLEANUP(cmd_stat, tc)
    454        1.1      jmmv {
    455        1.1      jmmv 	unload_cleanup("k_helper");
    456        1.1      jmmv }
    457        1.1      jmmv 
    458        1.1      jmmv ATF_TC_WITH_CLEANUP(cmd_unload);
    459        1.1      jmmv ATF_TC_HEAD(cmd_unload, tc)
    460        1.1      jmmv {
    461        1.1      jmmv 	atf_tc_set_md_var(tc, "descr", "Tests for the MODCTL_UNLOAD command");
    462        1.1      jmmv 	atf_tc_set_md_var(tc, "require.user", "root");
    463        1.1      jmmv }
    464        1.1      jmmv ATF_TC_BODY(cmd_unload, tc)
    465        1.1      jmmv {
    466        1.3      jmmv 	load(NULL, true, "%s/k_helper/k_helper.kmod",
    467        1.3      jmmv 	    atf_tc_get_config_var(tc, "srcdir"));
    468        1.1      jmmv 
    469        1.1      jmmv 	ATF_CHECK(unload("", false) == ENOENT);
    470        1.2        ad 	ATF_CHECK(unload("non-existent.kmod", false) == ENOENT);
    471        1.2        ad 	ATF_CHECK(unload("k_helper.kmod", false) == ENOENT);
    472        1.1      jmmv 
    473        1.1      jmmv 	ATF_CHECK(k_helper_is_present(stat_check));
    474        1.1      jmmv 	unload("k_helper", true);
    475        1.1      jmmv 	printf("Checking if unload was successful\n");
    476        1.1      jmmv 	ATF_CHECK(!k_helper_is_present(stat_check));
    477        1.1      jmmv }
    478        1.1      jmmv ATF_TC_CLEANUP(cmd_unload, tc)
    479        1.1      jmmv {
    480        1.1      jmmv 	unload_cleanup("k_helper");
    481        1.1      jmmv }
    482        1.1      jmmv 
    483        1.1      jmmv /* --------------------------------------------------------------------- */
    484        1.1      jmmv /* Main                                                                  */
    485        1.1      jmmv /* --------------------------------------------------------------------- */
    486        1.1      jmmv 
    487        1.1      jmmv ATF_TP_ADD_TCS(tp)
    488        1.1      jmmv {
    489        1.1      jmmv 
    490        1.1      jmmv 	ATF_TP_ADD_TC(tp, cmd_load);
    491        1.1      jmmv 	ATF_TP_ADD_TC(tp, cmd_load_props);
    492        1.1      jmmv 	ATF_TP_ADD_TC(tp, cmd_stat);
    493        1.4  pgoyette 	ATF_TP_ADD_TC(tp, cmd_load_recurse);
    494        1.1      jmmv 	ATF_TP_ADD_TC(tp, cmd_unload);
    495        1.1      jmmv 
    496        1.1      jmmv 	return atf_no_error();
    497        1.1      jmmv }
    498