summaryrefslogtreecommitdiffstats
path: root/release/sysinstall/devices.c
diff options
context:
space:
mode:
Diffstat (limited to 'release/sysinstall/devices.c')
-rw-r--r--release/sysinstall/devices.c396
1 files changed, 396 insertions, 0 deletions
diff --git a/release/sysinstall/devices.c b/release/sysinstall/devices.c
new file mode 100644
index 0000000..b1b91d7
--- /dev/null
+++ b/release/sysinstall/devices.c
@@ -0,0 +1,396 @@
+/*
+ * The new sysinstall program.
+ *
+ * This is probably the last program in the `sysinstall' line - the next
+ * generation being essentially a complete rewrite.
+ *
+ * $Id: devices.c,v 1.35.2.9 1995/06/05 12:03:46 jkh Exp $
+ *
+ * Copyright (c) 1995
+ * Jordan Hubbard. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer,
+ * verbatim and that no modifications are made prior to this
+ * point in the file.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Jordan Hubbard
+ * for the FreeBSD Project.
+ * 4. The name of Jordan Hubbard or the FreeBSD project may not be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include "sysinstall.h"
+
+#include <sys/fcntl.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <netinet/in.h>
+#include <netinet/in_var.h>
+#include <arpa/inet.h>
+
+#define NSIP
+#include <netns/ns.h>
+#include <netns/ns_if.h>
+#include <netdb.h>
+
+#define EON
+#include <netiso/iso.h>
+#include <netiso/iso_var.h>
+#include <sys/protosw.h>
+
+#include <ctype.h>
+
+static Device *Devices[DEV_MAX];
+static int numDevs;
+
+static struct {
+ DeviceType type;
+ char *name;
+ char *description;
+} device_names[] = {
+ { DEVICE_TYPE_CDROM, "cd0a", "SCSI CDROM drive" },
+ { DEVICE_TYPE_CDROM, "cd1a", "SCSI CDROM drive (2nd unit)" },
+ { DEVICE_TYPE_CDROM, "mcd0a", "Mitsumi (old model) CDROM drive" },
+ { DEVICE_TYPE_CDROM, "mcd1a", "Mitsumi (old model) CDROM drive (2nd unit)" },
+ { DEVICE_TYPE_CDROM, "scd0a", "Sony CDROM drive - CDU31/33A type", },
+ { DEVICE_TYPE_CDROM, "scd1a", "Sony CDROM drive - CDU31/33A type (2nd unit)" },
+ { DEVICE_TYPE_CDROM, "matcd0a", "Matsushita CDROM ('sound blaster' type)" },
+ { DEVICE_TYPE_CDROM, "matcd1a", "Matsushita CDROM (2nd unit)" },
+ { DEVICE_TYPE_TAPE, "rst0", "SCSI tape drive" },
+ { DEVICE_TYPE_TAPE, "rst1", "SCSI tape drive (2nd unit)" },
+ { DEVICE_TYPE_TAPE, "ft0", "Floppy tape drive (QIC-02)" },
+ { DEVICE_TYPE_TAPE, "wt0", "Wangtek tape drive" },
+ { DEVICE_TYPE_DISK, "sd", "SCSI disk device" },
+ { DEVICE_TYPE_DISK, "wd", "IDE/ESDI/MFM/ST506 disk device" },
+ { DEVICE_TYPE_FLOPPY, "fd0", "floppy drive unit A" },
+ { DEVICE_TYPE_FLOPPY, "fd1", "floppy drive unit B" },
+ { DEVICE_TYPE_NETWORK, "cuaa0", "Serial port (COM1) - possible PPP/SLIP device" },
+ { DEVICE_TYPE_NETWORK, "cuaa1", "Serial port (COM2) - possible PPP/SLIP device" },
+ { DEVICE_TYPE_NETWORK, "lp0", "Parallel Port IP (PLIP) using laplink cable" },
+ { DEVICE_TYPE_NETWORK, "lo", "Loop-back (local) network interface" },
+ { DEVICE_TYPE_NETWORK, "sl", "Serial-line IP (SLIP) interface" },
+ { DEVICE_TYPE_NETWORK, "ppp", "Point-to-Point Protocol (PPP) interface" },
+ { DEVICE_TYPE_NETWORK, "de", "DEC DE435 PCI NIC or other DC21040-AA based card" },
+ { DEVICE_TYPE_NETWORK, "ed", "WD/SMC 80xx; Novell NE1000/2000; 3Com 3C503 cards" },
+ { DEVICE_TYPE_NETWORK, "ep", "3Com 3C509 ethernet card" },
+ { DEVICE_TYPE_NETWORK, "el", "3Com 3C501 ethernet card" },
+ { DEVICE_TYPE_NETWORK, "fe", "Fujitsu MB86960A/MB86965A ethernet card" },
+ { DEVICE_TYPE_NETWORK, "ie", "AT&T StarLAN 10 and EN100; 3Com 3C507; NI5210" },
+ { DEVICE_TYPE_NETWORK, "ix", "Intel Etherexpress ethernet card" },
+ { DEVICE_TYPE_NETWORK, "le", "DEC EtherWorks 2 or 3 ethernet card" },
+ { DEVICE_TYPE_NETWORK, "lnc", "Lance/PCnet (Isolan/Novell NE2100/NE32-VL) ethernet" },
+ { DEVICE_TYPE_NETWORK, "ze", "IBM/National Semiconductor PCMCIA ethernet card" },
+ { DEVICE_TYPE_NETWORK, "zp", "3Com Etherlink III PCMCIA ethernet card" },
+ { NULL },
+};
+
+Device *
+new_device(char *name)
+{
+ Device *dev;
+
+ dev = safe_malloc(sizeof(Device));
+ bzero(dev, sizeof(Device));
+ if (name)
+ strcpy(dev->name, name);
+ return dev;
+}
+
+/* Stubs for unimplemented strategy routines */
+Boolean
+dummyInit(Device *dev)
+{
+ return TRUE;
+}
+
+int
+dummyGet(Device *dev, char *dist, Attribs *dist_attrs)
+{
+ return -1;
+}
+
+Boolean
+dummyClose(Device *dev, int fd)
+{
+ if (!close(fd))
+ return TRUE;
+ return FALSE;
+}
+
+void
+dummyShutdown(Device *dev)
+{
+ return;
+}
+
+static int
+deviceTry(char *name, char *try)
+{
+ int fd;
+
+ snprintf(try, FILENAME_MAX, "/dev/%s", name);
+ fd = open(try, O_RDWR);
+ if (fd > 0)
+ return fd;
+ snprintf(try, FILENAME_MAX, "/mnt/dev/%s", name);
+ fd = open(try, O_RDWR);
+ return fd;
+}
+
+/* Register a new device in the devices array */
+Device *
+deviceRegister(char *name, char *desc, char *devname, DeviceType type, Boolean enabled,
+ Boolean (*init)(Device *), int (*get)(Device *, char *, Attribs *),
+ Boolean (*close)(Device *, int), void (*shutdown)(Device *), void *private)
+{
+ Device *newdev;
+
+ if (numDevs == DEV_MAX)
+ msgFatal("Too many devices found!");
+ newdev = new_device(name);
+ newdev->description = desc;
+ newdev->devname = devname;
+ newdev->type = type;
+ newdev->enabled = enabled;
+ newdev->init = init ? init : dummyInit;
+ newdev->get = get ? get : dummyGet;
+ newdev->close = close ? close : dummyClose;
+ newdev->shutdown = shutdown ? shutdown : dummyShutdown;
+ newdev->private = private;
+ Devices[numDevs] = newdev;
+ Devices[++numDevs] = NULL;
+ return newdev;
+}
+
+/* Get all device information for devices we have attached */
+void
+deviceGetAll(void)
+{
+ int i, fd, s;
+ struct ifconf ifc;
+ struct ifreq *ifptr, *end;
+ int ifflags;
+ char buffer[INTERFACE_MAX * sizeof(struct ifreq)];
+ char **names;
+
+ /* Try and get the disks first */
+ if ((names = Disk_Names()) != NULL) {
+ int i;
+
+ for (i = 0; names[i]; i++) {
+ Chunk *c1;
+ Disk *d;
+
+ d = Open_Disk(names[i]);
+ if (!d)
+ msgFatal("Unable to open disk %s", names[i]);
+
+ (void)deviceRegister(names[i], names[i], d->name, DEVICE_TYPE_DISK, FALSE, NULL, NULL, NULL, NULL, d);
+ msgDebug("Found a device of type disk named: %s\n", names[i]);
+
+ /* Look for existing DOS partitions to register */
+ for (c1 = d->chunks->part; c1; c1 = c1->next) {
+ if (c1->type == fat) {
+ Device *dev;
+ char devname[80];
+
+ /* Got one! */
+ sprintf(devname, "/dev/%s", c1->name);
+ dev = deviceRegister(c1->name, c1->name, strdup(devname), DEVICE_TYPE_DOS, TRUE,
+ mediaInitDOS, mediaGetDOS, NULL, mediaShutdownDOS, NULL);
+ dev->private = c1;
+ msgDebug("Found a DOS partition %s on drive %s\n", c1->name, d->name);
+ }
+ }
+ }
+ free(names);
+ }
+
+ /*
+ * Try to get all the types of devices it makes sense to get at the
+ * second stage of the installation.
+ */
+ for (i = 0; device_names[i].name; i++) {
+ char try[FILENAME_MAX];
+
+ switch(device_names[i].type) {
+ case DEVICE_TYPE_CDROM:
+ fd = deviceTry(device_names[i].name, try);
+ if (fd >= 0) {
+ close(fd);
+ (void)deviceRegister(device_names[i].name, device_names[i].description, strdup(try),
+ DEVICE_TYPE_CDROM, TRUE, mediaInitCDROM, mediaGetCDROM, NULL,
+ mediaShutdownCDROM, NULL);
+ msgDebug("Found a device of type CDROM named: %s\n", device_names[i].name);
+ }
+ break;
+
+ case DEVICE_TYPE_TAPE:
+ fd = deviceTry(device_names[i].name, try);
+ if (fd >= 0) {
+ close(fd);
+ deviceRegister(device_names[i].name, device_names[i].description, strdup(try),
+ DEVICE_TYPE_TAPE, TRUE, mediaInitTape, mediaGetTape, NULL, mediaShutdownTape, NULL);
+ msgDebug("Found a device of type TAPE named: %s\n", device_names[i].name);
+ }
+ break;
+
+ case DEVICE_TYPE_FLOPPY:
+ fd = deviceTry(device_names[i].name, try);
+ if (fd >= 0) {
+ close(fd);
+ deviceRegister(device_names[i].name, device_names[i].description, strdup(try),
+ DEVICE_TYPE_FLOPPY, TRUE, mediaInitFloppy, mediaGetFloppy, NULL,
+ mediaShutdownFloppy, NULL);
+ msgDebug("Found a device of type floppy named: %s\n", device_names[i].name);
+ }
+ break;
+
+ case DEVICE_TYPE_NETWORK:
+ fd = deviceTry(device_names[i].name, try);
+ if (fd >= 0) {
+ close(fd);
+ /* The only network devices that have fds associated are serial ones */
+ deviceRegister(device_names[i].name, device_names[i].description, strdup(try), DEVICE_TYPE_NETWORK,
+ TRUE, mediaInitNetwork, NULL, NULL, mediaShutdownNetwork, NULL);
+ msgDebug("Found a device of type network named: %s\n", device_names[i].name);
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /* Now go for the (other) network interfaces dynamically. Stolen shamelessly from ifconfig! */
+ ifc.ifc_len = sizeof(buffer);
+ ifc.ifc_buf = buffer;
+
+ s = socket(AF_INET, SOCK_DGRAM, 0);
+ if (s < 0) {
+ msgConfirm("ifconfig: socket");
+ return;
+ }
+ if (ioctl(s, SIOCGIFCONF, (char *) &ifc) < 0) {
+ msgConfirm("ifconfig (SIOCGIFCONF)");
+ return;
+ }
+ ifflags = ifc.ifc_req->ifr_flags;
+ end = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
+ for (ifptr = ifc.ifc_req; ifptr < end; ifptr++) {
+ /* If it's not a link entry, forget it */
+ if (ifptr->ifr_ifru.ifru_addr.sa_family != AF_LINK)
+ continue;
+ /* Eliminate network devices that don't make sense */
+ if (!strncmp(ifptr->ifr_name, "tun", 3)
+ || !strncmp(ifptr->ifr_name, "lo0", 3))
+ continue;
+ deviceRegister(ifptr->ifr_name, ifptr->ifr_name, ifptr->ifr_name, DEVICE_TYPE_NETWORK, TRUE,
+ mediaInitNetwork, NULL, NULL, mediaShutdownNetwork, NULL);
+ msgDebug("Found a device of type network named: %s\n", ifptr->ifr_name);
+ close(s);
+ if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ msgConfirm("ifconfig: socket");
+ continue;
+ }
+ if (ifptr->ifr_addr.sa_len) /* I'm not sure why this is here - it's inherited */
+ ifptr = (struct ifreq *)((caddr_t)ifptr + ifptr->ifr_addr.sa_len - sizeof(struct sockaddr));
+ }
+}
+
+/*
+ * Find all devices that match the criteria, allowing "wildcarding" as well
+ * by allowing NULL or ANY values to match all. The array returned is static
+ * and may be used until the next invocation of deviceFind().
+ */
+Device **
+deviceFind(char *name, DeviceType class)
+{
+ static Device *found[DEV_MAX];
+ int i, j;
+
+ for (i = 0, j = 0; i < numDevs; i++) {
+ if ((!name || !strcmp(Devices[i]->name, name))
+ && (class == DEVICE_TYPE_ANY || class == Devices[i]->type))
+ found[j++] = Devices[i];
+ }
+ found[j] = NULL;
+ return j ? found : NULL;
+}
+
+int
+deviceCount(Device **devs)
+{
+ int i;
+
+ if (!devs)
+ return 0;
+ for (i = 0; devs[i]; i++);
+ return i;
+}
+
+/*
+ * Create a menu listing all the devices of a certain type in the system.
+ * The passed-in menu is expected to be a "prototype" from which the new
+ * menu is cloned.
+ */
+DMenu *
+deviceCreateMenu(DMenu *menu, DeviceType type, int (*hook)())
+{
+ Device **devs;
+ int numdevs;
+ DMenu *tmp = NULL;
+ int i, j;
+
+ devs = deviceFind(NULL, type);
+ if (!devs)
+ return NULL;
+
+ for (numdevs = 0; devs[numdevs]; numdevs++);
+ tmp = (DMenu *)safe_malloc(sizeof(DMenu) + (sizeof(DMenuItem) * (numdevs + 1)));
+ bcopy(menu, tmp, sizeof(DMenu));
+ for (i = 0; devs[i]; i++) {
+ tmp->items[i].title = devs[i]->name;
+ for (j = 0; device_names[j].name; j++) {
+ if (!strncmp(devs[i]->name, device_names[j].name, strlen(device_names[j].name))) {
+ tmp->items[i].prompt = device_names[j].description;
+ break;
+ }
+ }
+ if (!device_names[j].name)
+ tmp->items[i].prompt = "<unknown device type>";
+ tmp->items[i].type = DMENU_CALL;
+ tmp->items[i].ptr = hook;
+ tmp->items[i].disabled = FALSE;
+ tmp->items[i].check = NULL;
+ }
+ tmp->items[i].type = DMENU_NOP;
+ tmp->items[i].title = NULL;
+ return tmp;
+}
OpenPOWER on IntegriCloud