125540Sdfr/*- 2330449Seadler * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3330449Seadler * 425540Sdfr * Copyright (c) 1997 Doug Rabson 525540Sdfr * All rights reserved. 625540Sdfr * 725540Sdfr * Redistribution and use in source and binary forms, with or without 825540Sdfr * modification, are permitted provided that the following conditions 925540Sdfr * are met: 1025540Sdfr * 1. Redistributions of source code must retain the above copyright 1125540Sdfr * notice, this list of conditions and the following disclaimer. 1225540Sdfr * 2. Redistributions in binary form must reproduce the above copyright 1325540Sdfr * notice, this list of conditions and the following disclaimer in the 1425540Sdfr * documentation and/or other materials provided with the distribution. 1525540Sdfr * 1625540Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1725540Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1825540Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1925540Sdfr * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2025540Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2125540Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2225540Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2325540Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2425540Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2525540Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2625540Sdfr * SUCH DAMAGE. 2725540Sdfr */ 2825540Sdfr 29114589Sobrien#include <sys/cdefs.h> 30114589Sobrien__FBSDID("$FreeBSD: stable/11/sbin/kldload/kldload.c 330449 2018-03-05 07:26:05Z eadler $"); 3132269Scharnier 32193475Sbenno#include <sys/types.h> 33193473Sbenno#include <sys/param.h> 34193473Sbenno#include <sys/linker.h> 35193475Sbenno#include <sys/sysctl.h> 36193475Sbenno#include <sys/stat.h> 3730573Sjmg#include <err.h> 3825540Sdfr#include <stdio.h> 3978732Sdd#include <stdlib.h> 40193475Sbenno#include <string.h> 4125540Sdfr#include <unistd.h> 42233109Shselasky#include <errno.h> 4325540Sdfr 44193475Sbenno#define PATHCTL "kern.module_path" 45193475Sbenno 46193475Sbenno/* 47193475Sbenno * Check to see if the requested module is specified as a filename with no 48193475Sbenno * path. If so and if a file by the same name exists in the module path, 49193475Sbenno * warn the user that the module in the path will be used in preference. 50193475Sbenno */ 51193475Sbennostatic int 52193475Sbennopath_check(const char *kldname, int quiet) 53193475Sbenno{ 54193475Sbenno char *path, *tmppath, *element; 55193475Sbenno struct stat sb; 56313681Sngie int mib[5]; 57313681Sngie char kldpath[MAXPATHLEN]; 58313681Sngie size_t miblen, pathlen; 59193475Sbenno dev_t dev; 60193475Sbenno ino_t ino; 61313681Sngie int found; 62193475Sbenno 63313681Sngie if (strchr(kldname, '/') != NULL) 64193475Sbenno return (0); 65313681Sngie if (strstr(kldname, ".ko") == NULL) 66193475Sbenno return (0); 67313681Sngie if (stat(kldname, &sb) != 0) 68193475Sbenno return (0); 69193475Sbenno 70193475Sbenno found = 0; 71193475Sbenno dev = sb.st_dev; 72193475Sbenno ino = sb.st_ino; 73193475Sbenno 74298249Saraujo miblen = nitems(mib); 75313681Sngie if (sysctlnametomib(PATHCTL, mib, &miblen) != 0) 76193475Sbenno err(1, "sysctlnametomib(%s)", PATHCTL); 77313681Sngie if (sysctl(mib, miblen, NULL, &pathlen, NULL, 0) == -1) 78193475Sbenno err(1, "getting path: sysctl(%s) - size only", PATHCTL); 79193475Sbenno path = malloc(pathlen + 1); 80313681Sngie if (path == NULL) 81193475Sbenno err(1, "allocating %lu bytes for the path", 82193475Sbenno (unsigned long)pathlen + 1); 83313681Sngie if (sysctl(mib, miblen, path, &pathlen, NULL, 0) == -1) 84193475Sbenno err(1, "getting path: sysctl(%s)", PATHCTL); 85193475Sbenno tmppath = path; 86193475Sbenno 87193475Sbenno while ((element = strsep(&tmppath, ";")) != NULL) { 88193475Sbenno strlcpy(kldpath, element, MAXPATHLEN); 89193475Sbenno if (kldpath[strlen(kldpath) - 1] != '/') { 90193475Sbenno strlcat(kldpath, "/", MAXPATHLEN); 91193475Sbenno } 92193475Sbenno strlcat(kldpath, kldname, MAXPATHLEN); 93313681Sngie 94313681Sngie if (stat(kldpath, &sb) == -1) 95193475Sbenno continue; 96193475Sbenno 97193475Sbenno found = 1; 98193475Sbenno 99193475Sbenno if (sb.st_dev != dev || sb.st_ino != ino) { 100313681Sngie if (!quiet) 101193475Sbenno warnx("%s will be loaded from %s, not the " 102193475Sbenno "current directory", kldname, element); 103193475Sbenno break; 104313681Sngie } else if (sb.st_dev == dev && sb.st_ino == ino) 105193475Sbenno break; 106193475Sbenno } 107193475Sbenno 108193475Sbenno free(path); 109313681Sngie 110193475Sbenno if (!found) { 111313681Sngie if (!quiet) 112193475Sbenno warnx("%s is not in the module path", kldname); 113193475Sbenno return (-1); 114193475Sbenno } 115313681Sngie 116193475Sbenno return (0); 117193475Sbenno} 118193475Sbenno 11930627Sjmgstatic void 12030627Sjmgusage(void) 12125540Sdfr{ 122313681Sngie 123233109Shselasky fprintf(stderr, "usage: kldload [-nqv] file ...\n"); 124193473Sbenno exit(1); 12525540Sdfr} 12625540Sdfr 12730627Sjmgint 12830627Sjmgmain(int argc, char** argv) 12925540Sdfr{ 130193473Sbenno int c; 131313681Sngie int check_loaded; 132193473Sbenno int errors; 133193473Sbenno int fileid; 134313681Sngie int quiet; 135193473Sbenno int verbose; 13625540Sdfr 137193473Sbenno errors = 0; 138193473Sbenno verbose = 0; 139193475Sbenno quiet = 0; 140233109Shselasky check_loaded = 0; 141313681Sngie 142233109Shselasky while ((c = getopt(argc, argv, "nqv")) != -1) { 143193473Sbenno switch (c) { 144193475Sbenno case 'q': 145193475Sbenno quiet = 1; 146193475Sbenno verbose = 0; 147193475Sbenno break; 148193473Sbenno case 'v': 149193473Sbenno verbose = 1; 150193475Sbenno quiet = 0; 151193473Sbenno break; 152233109Shselasky case 'n': 153233109Shselasky check_loaded = 1; 154233109Shselasky break; 155193473Sbenno default: 156193473Sbenno usage(); 157193473Sbenno } 15825540Sdfr } 159193473Sbenno argc -= optind; 160193473Sbenno argv += optind; 16125540Sdfr 162193473Sbenno if (argc == 0) 163193473Sbenno usage(); 16425540Sdfr 165193473Sbenno while (argc-- != 0) { 166193475Sbenno if (path_check(argv[0], quiet) == 0) { 167193475Sbenno fileid = kldload(argv[0]); 168193475Sbenno if (fileid < 0) { 169233109Shselasky if (check_loaded != 0 && errno == EEXIST) { 170233109Shselasky if (verbose) 171233109Shselasky printf("%s is already " 172233109Shselasky "loaded\n", argv[0]); 173233109Shselasky } else { 174260594Sbapt switch (errno) { 175260594Sbapt case EEXIST: 176260483Sbapt warnx("can't load %s: module " 177260483Sbapt "already loaded or " 178260483Sbapt "in kernel", argv[0]); 179260594Sbapt break; 180260594Sbapt case ENOEXEC: 181260596Sbapt warnx("an error occurred while " 182260594Sbapt "loading the module. " 183260597Sbapt "Please check dmesg(8) for " 184260594Sbapt "more details."); 185260594Sbapt break; 186260594Sbapt default: 187260483Sbapt warn("can't load %s", argv[0]); 188260594Sbapt break; 189260594Sbapt } 190260484Sbapt errors++; 191233109Shselasky } 192193475Sbenno } else { 193193475Sbenno if (verbose) 194193475Sbenno printf("Loaded %s, id=%d\n", argv[0], 195193475Sbenno fileid); 196193475Sbenno } 197313681Sngie } else 198193473Sbenno errors++; 199193473Sbenno argv++; 200193473Sbenno } 20125540Sdfr 202193473Sbenno return (errors ? 1 : 0); 20325540Sdfr} 204