[klibc] Remove in-kernel root-mounting code This removes the root mounting code from the kernel proper. This includes ip autoconfiguration, nfsroot, and name_to_dev_t(). Signed-off-by: H. Peter Anvin --- commit f18b78199b11d1e0e3ed504deed9309aff6d40f9 tree 8218df2f2385caa2480f1fe8b57cae08412b3d20 parent 7a954d574303481190b6e377607851ff31c6c2c9 author H. Peter Anvin Sun, 02 Jul 2006 12:26:30 -0700 committer H. Peter Anvin Sun, 02 Jul 2006 12:26:30 -0700 arch/i386/kernel/setup.c | 8 arch/x86_64/kernel/setup.c | 7 fs/Kconfig | 14 fs/nfs/Makefile | 1 fs/nfs/mount_clnt.c | 191 ------ fs/nfs/nfsroot.c | 525 --------------- include/linux/mount.h | 1 init/Makefile | 7 init/do_mounts.c | 433 ------------- init/do_mounts.h | 77 -- init/do_mounts_initrd.c | 123 ---- init/do_mounts_md.c | 285 -------- init/do_mounts_rd.c | 429 ------------- init/initramfs.c | 3 init/main.c | 45 - net/ipv4/Makefile | 1 net/ipv4/ipconfig.c | 1510 -------------------------------------------- 17 files changed, 21 insertions(+), 3639 deletions(-) diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index 08c00d2..cc79fa7 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c @@ -149,7 +149,6 @@ struct e820map e820; extern void early_cpu_init(void); extern void generic_apic_probe(char *); -extern int root_mountflags; unsigned long saved_videomode; @@ -1469,11 +1468,6 @@ #endif } bootloader_type = LOADER_TYPE; -#ifdef CONFIG_BLK_DEV_RAM - rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK; - rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0); - rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0); -#endif ARCH_SETUP if (efi_enabled) efi_init(); @@ -1484,8 +1478,6 @@ #endif copy_edd(); - if (!MOUNT_ROOT_RDONLY) - root_mountflags &= ~MS_RDONLY; init_mm.start_code = (unsigned long) _text; init_mm.end_code = (unsigned long) _etext; init_mm.end_data = (unsigned long) _edata; diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c index 0925518..788735e 100644 --- a/arch/x86_64/kernel/setup.c +++ b/arch/x86_64/kernel/setup.c @@ -529,16 +529,9 @@ void __init setup_arch(char **cmdline_p) saved_video_mode = SAVED_VIDEO_MODE; bootloader_type = LOADER_TYPE; -#ifdef CONFIG_BLK_DEV_RAM - rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK; - rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0); - rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0); -#endif setup_memory_region(); copy_edd(); - if (!MOUNT_ROOT_RDONLY) - root_mountflags &= ~MS_RDONLY; init_mm.start_code = (unsigned long) &_text; init_mm.end_code = (unsigned long) &_etext; init_mm.end_data = (unsigned long) &_edata; diff --git a/fs/Kconfig b/fs/Kconfig index 53f5c6d..01f084e 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -1567,20 +1567,6 @@ config NFSD_TCP TCP connections usually perform better than the default UDP when the network is lossy or congested. If unsure, say Y. -config ROOT_NFS - bool "Root file system on NFS" - depends on NFS_FS=y && IP_PNP - help - If you want your Linux box to mount its whole root file system (the - one containing the directory /) from some other computer over the - net via NFS (presumably because your box doesn't have a hard disk), - say Y. Read for details. It is - likely that in this case, you also want to say Y to "Kernel level IP - autoconfiguration" so that your box can discover its network address - at boot time. - - Most people say N here. - config LOCKD tristate diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile index 0b572a0..c7d6392 100644 --- a/fs/nfs/Makefile +++ b/fs/nfs/Makefile @@ -7,7 +7,6 @@ obj-$(CONFIG_NFS_FS) += nfs.o nfs-y := dir.o file.o inode.o super.o nfs2xdr.o pagelist.o \ proc.o read.o symlink.o unlink.o write.o \ namespace.o -nfs-$(CONFIG_ROOT_NFS) += nfsroot.o mount_clnt.o nfs-$(CONFIG_NFS_V3) += nfs3proc.o nfs3xdr.o nfs-$(CONFIG_NFS_V3_ACL) += nfs3acl.o nfs-$(CONFIG_NFS_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \ diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c deleted file mode 100644 index 445abb4..0000000 --- a/fs/nfs/mount_clnt.c +++ /dev/null @@ -1,191 +0,0 @@ -/* - * linux/fs/nfs/mount_clnt.c - * - * MOUNT client to support NFSroot. - * - * Copyright (C) 1997, Olaf Kirch - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef RPC_DEBUG -# define NFSDBG_FACILITY NFSDBG_ROOT -#endif - -/* -#define MOUNT_PROGRAM 100005 -#define MOUNT_VERSION 1 -#define MOUNT_MNT 1 -#define MOUNT_UMNT 3 - */ - -static struct rpc_clnt * mnt_create(char *, struct sockaddr_in *, - int, int); -static struct rpc_program mnt_program; - -struct mnt_fhstatus { - unsigned int status; - struct nfs_fh * fh; -}; - -/* - * Obtain an NFS file handle for the given host and path - */ -int -nfsroot_mount(struct sockaddr_in *addr, char *path, struct nfs_fh *fh, - int version, int protocol) -{ - struct rpc_clnt *mnt_clnt; - struct mnt_fhstatus result = { - .fh = fh - }; - struct rpc_message msg = { - .rpc_argp = path, - .rpc_resp = &result, - }; - char hostname[32]; - int status; - - dprintk("NFS: nfs_mount(%08x:%s)\n", - (unsigned)ntohl(addr->sin_addr.s_addr), path); - - sprintf(hostname, "%u.%u.%u.%u", NIPQUAD(addr->sin_addr.s_addr)); - mnt_clnt = mnt_create(hostname, addr, version, protocol); - if (IS_ERR(mnt_clnt)) - return PTR_ERR(mnt_clnt); - - if (version == NFS_MNT3_VERSION) - msg.rpc_proc = &mnt_clnt->cl_procinfo[MOUNTPROC3_MNT]; - else - msg.rpc_proc = &mnt_clnt->cl_procinfo[MNTPROC_MNT]; - - status = rpc_call_sync(mnt_clnt, &msg, 0); - return status < 0? status : (result.status? -EACCES : 0); -} - -static struct rpc_clnt * -mnt_create(char *hostname, struct sockaddr_in *srvaddr, int version, - int protocol) -{ - struct rpc_xprt *xprt; - struct rpc_clnt *clnt; - - xprt = xprt_create_proto(protocol, srvaddr, NULL); - if (IS_ERR(xprt)) - return (struct rpc_clnt *)xprt; - - clnt = rpc_create_client(xprt, hostname, - &mnt_program, version, - RPC_AUTH_UNIX); - if (!IS_ERR(clnt)) { - clnt->cl_softrtry = 1; - clnt->cl_oneshot = 1; - clnt->cl_intr = 1; - } - return clnt; -} - -/* - * XDR encode/decode functions for MOUNT - */ -static int -xdr_encode_dirpath(struct rpc_rqst *req, u32 *p, const char *path) -{ - p = xdr_encode_string(p, path); - - req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); - return 0; -} - -static int -xdr_decode_fhstatus(struct rpc_rqst *req, u32 *p, struct mnt_fhstatus *res) -{ - struct nfs_fh *fh = res->fh; - - if ((res->status = ntohl(*p++)) == 0) { - fh->size = NFS2_FHSIZE; - memcpy(fh->data, p, NFS2_FHSIZE); - } - return 0; -} - -static int -xdr_decode_fhstatus3(struct rpc_rqst *req, u32 *p, struct mnt_fhstatus *res) -{ - struct nfs_fh *fh = res->fh; - - if ((res->status = ntohl(*p++)) == 0) { - int size = ntohl(*p++); - if (size <= NFS3_FHSIZE) { - fh->size = size; - memcpy(fh->data, p, size); - } else - res->status = -EBADHANDLE; - } - return 0; -} - -#define MNT_dirpath_sz (1 + 256) -#define MNT_fhstatus_sz (1 + 8) - -static struct rpc_procinfo mnt_procedures[] = { -[MNTPROC_MNT] = { - .p_proc = MNTPROC_MNT, - .p_encode = (kxdrproc_t) xdr_encode_dirpath, - .p_decode = (kxdrproc_t) xdr_decode_fhstatus, - .p_bufsiz = MNT_dirpath_sz << 2, - .p_statidx = MNTPROC_MNT, - .p_name = "MOUNT", - }, -}; - -static struct rpc_procinfo mnt3_procedures[] = { -[MOUNTPROC3_MNT] = { - .p_proc = MOUNTPROC3_MNT, - .p_encode = (kxdrproc_t) xdr_encode_dirpath, - .p_decode = (kxdrproc_t) xdr_decode_fhstatus3, - .p_bufsiz = MNT_dirpath_sz << 2, - .p_statidx = MOUNTPROC3_MNT, - .p_name = "MOUNT", - }, -}; - - -static struct rpc_version mnt_version1 = { - .number = 1, - .nrprocs = 2, - .procs = mnt_procedures -}; - -static struct rpc_version mnt_version3 = { - .number = 3, - .nrprocs = 2, - .procs = mnt3_procedures -}; - -static struct rpc_version * mnt_version[] = { - NULL, - &mnt_version1, - NULL, - &mnt_version3, -}; - -static struct rpc_stat mnt_stats; - -static struct rpc_program mnt_program = { - .name = "mount", - .number = NFS_MNT_PROGRAM, - .nrvers = ARRAY_SIZE(mnt_version), - .version = mnt_version, - .stats = &mnt_stats, -}; diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c deleted file mode 100644 index c0a754e..0000000 --- a/fs/nfs/nfsroot.c +++ /dev/null @@ -1,525 +0,0 @@ -/* - * $Id: nfsroot.c,v 1.45 1998/03/07 10:44:46 mj Exp $ - * - * Copyright (C) 1995, 1996 Gero Kuhlmann - * - * Allow an NFS filesystem to be mounted as root. The way this works is: - * (1) Use the IP autoconfig mechanism to set local IP addresses and routes. - * (2) Handle RPC negotiation with the system which replied to RARP or - * was reported as a boot server by BOOTP or manually. - * (3) The actual mounting is done later, when init() is running. - * - * - * Changes: - * - * Alan Cox : Removed get_address name clash with FPU. - * Alan Cox : Reformatted a bit. - * Gero Kuhlmann : Code cleanup - * Michael Rausch : Fixed recognition of an incoming RARP answer. - * Martin Mares : (2.0) Auto-configuration via BOOTP supported. - * Martin Mares : Manual selection of interface & BOOTP/RARP. - * Martin Mares : Using network routes instead of host routes, - * allowing the default configuration to be used - * for normal operation of the host. - * Martin Mares : Randomized timer with exponential backoff - * installed to minimize network congestion. - * Martin Mares : Code cleanup. - * Martin Mares : (2.1) BOOTP and RARP made configuration options. - * Martin Mares : Server hostname generation fixed. - * Gerd Knorr : Fixed wired inode handling - * Martin Mares : (2.2) "0.0.0.0" addresses from command line ignored. - * Martin Mares : RARP replies not tested for server address. - * Gero Kuhlmann : (2.3) Some bug fixes and code cleanup again (please - * send me your new patches _before_ bothering - * Linus so that I don' always have to cleanup - * _afterwards_ - thanks) - * Gero Kuhlmann : Last changes of Martin Mares undone. - * Gero Kuhlmann : RARP replies are tested for specified server - * again. However, it's now possible to have - * different RARP and NFS servers. - * Gero Kuhlmann : "0.0.0.0" addresses from command line are - * now mapped to INADDR_NONE. - * Gero Kuhlmann : Fixed a bug which prevented BOOTP path name - * from being used (thanks to Leo Spiekman) - * Andy Walker : Allow to specify the NFS server in nfs_root - * without giving a path name - * Swen Thümmler : Allow to specify the NFS options in nfs_root - * without giving a path name. Fix BOOTP request - * for domainname (domainname is NIS domain, not - * DNS domain!). Skip dummy devices for BOOTP. - * Jacek Zapala : Fixed a bug which prevented server-ip address - * from nfsroot parameter from being used. - * Olaf Kirch : Adapted to new NFS code. - * Jakub Jelinek : Free used code segment. - * Marko Kohtala : Fixed some bugs. - * Martin Mares : Debug message cleanup - * Martin Mares : Changed to use the new generic IP layer autoconfig - * code. BOOTP and RARP moved there. - * Martin Mares : Default path now contains host name instead of - * host IP address (but host name defaults to IP - * address anyway). - * Martin Mares : Use root_server_addr appropriately during setup. - * Martin Mares : Rewrote parameter parsing, now hopefully giving - * correct overriding. - * Trond Myklebust : Add in preliminary support for NFSv3 and TCP. - * Fix bug in root_nfs_addr(). nfs_data.namlen - * is NOT for the length of the hostname. - * Hua Qin : Support for mounting root file system via - * NFS over TCP. - * Fabian Frederick: Option parser rebuilt (using parser lib) -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Define this to allow debugging output */ -#undef NFSROOT_DEBUG -#define NFSDBG_FACILITY NFSDBG_ROOT - -/* Default path we try to mount. "%s" gets replaced by our IP address */ -#define NFS_ROOT "/tftpboot/%s" - -/* Parameters passed from the kernel command line */ -static char nfs_root_name[256] __initdata = ""; - -/* Address of NFS server */ -static __u32 servaddr __initdata = 0; - -/* Name of directory to mount */ -static char nfs_path[NFS_MAXPATHLEN] __initdata = { 0, }; - -/* NFS-related data */ -static struct nfs_mount_data nfs_data __initdata = { 0, };/* NFS mount info */ -static int nfs_port __initdata = 0; /* Port to connect to for NFS */ -static int mount_port __initdata = 0; /* Mount daemon port number */ - - -/*************************************************************************** - - Parsing of options - - ***************************************************************************/ - -enum { - /* Options that take integer arguments */ - Opt_port, Opt_rsize, Opt_wsize, Opt_timeo, Opt_retrans, Opt_acregmin, - Opt_acregmax, Opt_acdirmin, Opt_acdirmax, - /* Options that take no arguments */ - Opt_soft, Opt_hard, Opt_intr, - Opt_nointr, Opt_posix, Opt_noposix, Opt_cto, Opt_nocto, Opt_ac, - Opt_noac, Opt_lock, Opt_nolock, Opt_v2, Opt_v3, Opt_udp, Opt_tcp, - Opt_acl, Opt_noacl, - /* Error token */ - Opt_err -}; - -static match_table_t __initdata tokens = { - {Opt_port, "port=%u"}, - {Opt_rsize, "rsize=%u"}, - {Opt_wsize, "wsize=%u"}, - {Opt_timeo, "timeo=%u"}, - {Opt_retrans, "retrans=%u"}, - {Opt_acregmin, "acregmin=%u"}, - {Opt_acregmax, "acregmax=%u"}, - {Opt_acdirmin, "acdirmin=%u"}, - {Opt_acdirmax, "acdirmax=%u"}, - {Opt_soft, "soft"}, - {Opt_hard, "hard"}, - {Opt_intr, "intr"}, - {Opt_nointr, "nointr"}, - {Opt_posix, "posix"}, - {Opt_noposix, "noposix"}, - {Opt_cto, "cto"}, - {Opt_nocto, "nocto"}, - {Opt_ac, "ac"}, - {Opt_noac, "noac"}, - {Opt_lock, "lock"}, - {Opt_nolock, "nolock"}, - {Opt_v2, "nfsvers=2"}, - {Opt_v2, "v2"}, - {Opt_v3, "nfsvers=3"}, - {Opt_v3, "v3"}, - {Opt_udp, "proto=udp"}, - {Opt_udp, "udp"}, - {Opt_tcp, "proto=tcp"}, - {Opt_tcp, "tcp"}, - {Opt_acl, "acl"}, - {Opt_noacl, "noacl"}, - {Opt_err, NULL} - -}; - -/* - * Parse option string. - */ - -static int __init root_nfs_parse(char *name, char *buf) -{ - - char *p; - substring_t args[MAX_OPT_ARGS]; - int option; - - if (!name) - return 1; - - /* Set the NFS remote path */ - p = strsep(&name, ","); - if (p[0] != '\0' && strcmp(p, "default") != 0) - strlcpy(buf, p, NFS_MAXPATHLEN); - - while ((p = strsep (&name, ",")) != NULL) { - int token; - if (!*p) - continue; - token = match_token(p, tokens, args); - - /* %u tokens only. Beware if you add new tokens! */ - if (token < Opt_soft && match_int(&args[0], &option)) - return 0; - switch (token) { - case Opt_port: - nfs_port = option; - break; - case Opt_rsize: - nfs_data.rsize = option; - break; - case Opt_wsize: - nfs_data.wsize = option; - break; - case Opt_timeo: - nfs_data.timeo = option; - break; - case Opt_retrans: - nfs_data.retrans = option; - break; - case Opt_acregmin: - nfs_data.acregmin = option; - break; - case Opt_acregmax: - nfs_data.acregmax = option; - break; - case Opt_acdirmin: - nfs_data.acdirmin = option; - break; - case Opt_acdirmax: - nfs_data.acdirmax = option; - break; - case Opt_soft: - nfs_data.flags |= NFS_MOUNT_SOFT; - break; - case Opt_hard: - nfs_data.flags &= ~NFS_MOUNT_SOFT; - break; - case Opt_intr: - nfs_data.flags |= NFS_MOUNT_INTR; - break; - case Opt_nointr: - nfs_data.flags &= ~NFS_MOUNT_INTR; - break; - case Opt_posix: - nfs_data.flags |= NFS_MOUNT_POSIX; - break; - case Opt_noposix: - nfs_data.flags &= ~NFS_MOUNT_POSIX; - break; - case Opt_cto: - nfs_data.flags &= ~NFS_MOUNT_NOCTO; - break; - case Opt_nocto: - nfs_data.flags |= NFS_MOUNT_NOCTO; - break; - case Opt_ac: - nfs_data.flags &= ~NFS_MOUNT_NOAC; - break; - case Opt_noac: - nfs_data.flags |= NFS_MOUNT_NOAC; - break; - case Opt_lock: - nfs_data.flags &= ~NFS_MOUNT_NONLM; - break; - case Opt_nolock: - nfs_data.flags |= NFS_MOUNT_NONLM; - break; - case Opt_v2: - nfs_data.flags &= ~NFS_MOUNT_VER3; - break; - case Opt_v3: - nfs_data.flags |= NFS_MOUNT_VER3; - break; - case Opt_udp: - nfs_data.flags &= ~NFS_MOUNT_TCP; - break; - case Opt_tcp: - nfs_data.flags |= NFS_MOUNT_TCP; - break; - case Opt_acl: - nfs_data.flags &= ~NFS_MOUNT_NOACL; - break; - case Opt_noacl: - nfs_data.flags |= NFS_MOUNT_NOACL; - break; - default: - printk(KERN_WARNING "Root-NFS: unknown " - "option: %s\n", p); - return 0; - } - } - - return 1; -} - -/* - * Prepare the NFS data structure and parse all options. - */ -static int __init root_nfs_name(char *name) -{ - static char buf[NFS_MAXPATHLEN] __initdata; - char *cp; - - /* Set some default values */ - memset(&nfs_data, 0, sizeof(nfs_data)); - nfs_port = -1; - nfs_data.version = NFS_MOUNT_VERSION; - nfs_data.flags = NFS_MOUNT_NONLM; /* No lockd in nfs root yet */ - nfs_data.rsize = NFS_DEF_FILE_IO_SIZE; - nfs_data.wsize = NFS_DEF_FILE_IO_SIZE; - nfs_data.acregmin = 3; - nfs_data.acregmax = 60; - nfs_data.acdirmin = 30; - nfs_data.acdirmax = 60; - strcpy(buf, NFS_ROOT); - - /* Process options received from the remote server */ - root_nfs_parse(root_server_path, buf); - - /* Override them by options set on kernel command-line */ - root_nfs_parse(name, buf); - - cp = system_utsname.nodename; - if (strlen(buf) + strlen(cp) > NFS_MAXPATHLEN) { - printk(KERN_ERR "Root-NFS: Pathname for remote directory too long.\n"); - return -1; - } - sprintf(nfs_path, buf, cp); - - return 1; -} - - -/* - * Get NFS server address. - */ -static int __init root_nfs_addr(void) -{ - if ((servaddr = root_server_addr) == INADDR_NONE) { - printk(KERN_ERR "Root-NFS: No NFS server available, giving up.\n"); - return -1; - } - - snprintf(nfs_data.hostname, sizeof(nfs_data.hostname), - "%u.%u.%u.%u", NIPQUAD(servaddr)); - return 0; -} - -/* - * Tell the user what's going on. - */ -#ifdef NFSROOT_DEBUG -static void __init root_nfs_print(void) -{ - printk(KERN_NOTICE "Root-NFS: Mounting %s on server %s as root\n", - nfs_path, nfs_data.hostname); - printk(KERN_NOTICE "Root-NFS: rsize = %d, wsize = %d, timeo = %d, retrans = %d\n", - nfs_data.rsize, nfs_data.wsize, nfs_data.timeo, nfs_data.retrans); - printk(KERN_NOTICE "Root-NFS: acreg (min,max) = (%d,%d), acdir (min,max) = (%d,%d)\n", - nfs_data.acregmin, nfs_data.acregmax, - nfs_data.acdirmin, nfs_data.acdirmax); - printk(KERN_NOTICE "Root-NFS: nfsd port = %d, mountd port = %d, flags = %08x\n", - nfs_port, mount_port, nfs_data.flags); -} -#endif - - -static int __init root_nfs_init(void) -{ -#ifdef NFSROOT_DEBUG - nfs_debug |= NFSDBG_ROOT; -#endif - - /* - * Decode the root directory path name and NFS options from - * the kernel command line. This has to go here in order to - * be able to use the client IP address for the remote root - * directory (necessary for pure RARP booting). - */ - if (root_nfs_name(nfs_root_name) < 0 || - root_nfs_addr() < 0) - return -1; - -#ifdef NFSROOT_DEBUG - root_nfs_print(); -#endif - - return 0; -} - - -/* - * Parse NFS server and directory information passed on the kernel - * command line. - */ -static int __init nfs_root_setup(char *line) -{ - ROOT_DEV = Root_NFS; - if (line[0] == '/' || line[0] == ',' || (line[0] >= '0' && line[0] <= '9')) { - strlcpy(nfs_root_name, line, sizeof(nfs_root_name)); - } else { - int n = strlen(line) + sizeof(NFS_ROOT) - 1; - if (n >= sizeof(nfs_root_name)) - line[sizeof(nfs_root_name) - sizeof(NFS_ROOT) - 2] = '\0'; - sprintf(nfs_root_name, NFS_ROOT, line); - } - root_server_addr = root_nfs_parse_addr(nfs_root_name); - return 1; -} - -__setup("nfsroot=", nfs_root_setup); - -/*************************************************************************** - - Routines to actually mount the root directory - - ***************************************************************************/ - -/* - * Construct sockaddr_in from address and port number. - */ -static inline void -set_sockaddr(struct sockaddr_in *sin, __u32 addr, __u16 port) -{ - sin->sin_family = AF_INET; - sin->sin_addr.s_addr = addr; - sin->sin_port = port; -} - -/* - * Query server portmapper for the port of a daemon program. - */ -static int __init root_nfs_getport(int program, int version, int proto) -{ - struct sockaddr_in sin; - - printk(KERN_NOTICE "Looking up port of RPC %d/%d on %u.%u.%u.%u\n", - program, version, NIPQUAD(servaddr)); - set_sockaddr(&sin, servaddr, 0); - return rpc_getport_external(&sin, program, version, proto); -} - - -/* - * Use portmapper to find mountd and nfsd port numbers if not overriden - * by the user. Use defaults if portmapper is not available. - * XXX: Is there any nfs server with no portmapper? - */ -static int __init root_nfs_ports(void) -{ - int port; - int nfsd_ver, mountd_ver; - int nfsd_port, mountd_port; - int proto; - - if (nfs_data.flags & NFS_MOUNT_VER3) { - nfsd_ver = NFS3_VERSION; - mountd_ver = NFS_MNT3_VERSION; - nfsd_port = NFS_PORT; - mountd_port = NFS_MNT_PORT; - } else { - nfsd_ver = NFS2_VERSION; - mountd_ver = NFS_MNT_VERSION; - nfsd_port = NFS_PORT; - mountd_port = NFS_MNT_PORT; - } - - proto = (nfs_data.flags & NFS_MOUNT_TCP) ? IPPROTO_TCP : IPPROTO_UDP; - - if (nfs_port < 0) { - if ((port = root_nfs_getport(NFS_PROGRAM, nfsd_ver, proto)) < 0) { - printk(KERN_ERR "Root-NFS: Unable to get nfsd port " - "number from server, using default\n"); - port = nfsd_port; - } - nfs_port = port; - dprintk("Root-NFS: Portmapper on server returned %d " - "as nfsd port\n", port); - } - nfs_port = htons(nfs_port); - - if ((port = root_nfs_getport(NFS_MNT_PROGRAM, mountd_ver, proto)) < 0) { - printk(KERN_ERR "Root-NFS: Unable to get mountd port " - "number from server, using default\n"); - port = mountd_port; - } - mount_port = htons(port); - dprintk("Root-NFS: mountd port is %d\n", port); - - return 0; -} - - -/* - * Get a file handle from the server for the directory which is to be - * mounted. - */ -static int __init root_nfs_get_handle(void) -{ - struct nfs_fh fh; - struct sockaddr_in sin; - int status; - int protocol = (nfs_data.flags & NFS_MOUNT_TCP) ? - IPPROTO_TCP : IPPROTO_UDP; - int version = (nfs_data.flags & NFS_MOUNT_VER3) ? - NFS_MNT3_VERSION : NFS_MNT_VERSION; - - set_sockaddr(&sin, servaddr, mount_port); - status = nfsroot_mount(&sin, nfs_path, &fh, version, protocol); - if (status < 0) - printk(KERN_ERR "Root-NFS: Server returned error %d " - "while mounting %s\n", status, nfs_path); - else { - nfs_data.root.size = fh.size; - memcpy(nfs_data.root.data, fh.data, fh.size); - } - - return status; -} - -/* - * Get the NFS port numbers and file handle, and return the prepared 'data' - * argument for mount() if everything went OK. Return NULL otherwise. - */ -void * __init nfs_root_data(void) -{ - if (root_nfs_init() < 0 - || root_nfs_ports() < 0 - || root_nfs_get_handle() < 0) - return NULL; - set_sockaddr((struct sockaddr_in *) &nfs_data.addr, servaddr, nfs_port); - return (void*)&nfs_data; -} diff --git a/include/linux/mount.h b/include/linux/mount.h index 403d1a9..ef5908e 100644 --- a/include/linux/mount.h +++ b/include/linux/mount.h @@ -94,7 +94,6 @@ extern void mark_mounts_for_expiry(struc extern void shrink_submounts(struct vfsmount *mountpoint, struct list_head *mounts); extern spinlock_t vfsmount_lock; -extern dev_t name_to_dev_t(char *name); #endif #endif /* _LINUX_MOUNT_H */ diff --git a/init/Makefile b/init/Makefile index 633a268..acfdb2c 100644 --- a/init/Makefile +++ b/init/Makefile @@ -2,14 +2,9 @@ # # Makefile for the linux kernel. # -obj-y := main.o version.o mounts.o initramfs.o +obj-y := main.o version.o initramfs.o obj-$(CONFIG_GENERIC_CALIBRATE_DELAY) += calibrate.o -mounts-y := do_mounts.o -mounts-$(CONFIG_BLK_DEV_RAM) += do_mounts_rd.o -mounts-$(CONFIG_BLK_DEV_INITRD) += do_mounts_initrd.o -mounts-$(CONFIG_BLK_DEV_MD) += do_mounts_md.o - # files to be removed upon make clean clean-files := ../include/linux/compile.h diff --git a/init/do_mounts.c b/init/do_mounts.c deleted file mode 100644 index 94aeec7..0000000 --- a/init/do_mounts.c +++ /dev/null @@ -1,433 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "do_mounts.h" - -extern int get_filesystem_list(char * buf); - -int __initdata rd_doload; /* 1 = load RAM disk, 0 = don't load */ - -int root_mountflags = MS_RDONLY | MS_SILENT; -char * __initdata root_device_name; -static char __initdata saved_root_name[64]; - -dev_t ROOT_DEV; - -static int __init load_ramdisk(char *str) -{ - rd_doload = simple_strtol(str,NULL,0) & 3; - return 1; -} -__setup("load_ramdisk=", load_ramdisk); - -static int __init readonly(char *str) -{ - if (*str) - return 0; - root_mountflags |= MS_RDONLY; - return 1; -} - -static int __init readwrite(char *str) -{ - if (*str) - return 0; - root_mountflags &= ~MS_RDONLY; - return 1; -} - -__setup("ro", readonly); -__setup("rw", readwrite); - -static dev_t try_name(char *name, int part) -{ - char path[64]; - char buf[32]; - int range; - dev_t res; - char *s; - int len; - int fd; - unsigned int maj, min; - - /* read device number from .../dev */ - - sprintf(path, "/sys/block/%s/dev", name); - fd = sys_open(path, 0, 0); - if (fd < 0) - goto fail; - len = sys_read(fd, buf, 32); - sys_close(fd); - if (len <= 0 || len == 32 || buf[len - 1] != '\n') - goto fail; - buf[len - 1] = '\0'; - if (sscanf(buf, "%u:%u", &maj, &min) == 2) { - /* - * Try the %u:%u format -- see print_dev_t() - */ - res = MKDEV(maj, min); - if (maj != MAJOR(res) || min != MINOR(res)) - goto fail; - } else { - /* - * Nope. Try old-style "0321" - */ - res = new_decode_dev(simple_strtoul(buf, &s, 16)); - if (*s) - goto fail; - } - - /* if it's there and we are not looking for a partition - that's it */ - if (!part) - return res; - - /* otherwise read range from .../range */ - sprintf(path, "/sys/block/%s/range", name); - fd = sys_open(path, 0, 0); - if (fd < 0) - goto fail; - len = sys_read(fd, buf, 32); - sys_close(fd); - if (len <= 0 || len == 32 || buf[len - 1] != '\n') - goto fail; - buf[len - 1] = '\0'; - range = simple_strtoul(buf, &s, 10); - if (*s) - goto fail; - - /* if partition is within range - we got it */ - if (part < range) - return res + part; -fail: - return 0; -} - -/* - * Convert a name into device number. We accept the following variants: - * - * 1) device number in hexadecimal represents itself - * 2) /dev/nfs represents Root_NFS (0xff) - * 3) /dev/ represents the device number of disk - * 4) /dev/ represents the device number - * of partition - device number of disk plus the partition number - * 5) /dev/p - same as the above, that form is - * used when disk name of partitioned disk ends on a digit. - * - * If name doesn't have fall into the categories above, we return 0. - * Sysfs is used to check if something is a disk name - it has - * all known disks under bus/block/devices. If the disk name - * contains slashes, name of sysfs node has them replaced with - * bangs. try_name() does the actual checks, assuming that sysfs - * is mounted on rootfs /sys. - */ - -dev_t name_to_dev_t(char *name) -{ - char s[32]; - char *p; - dev_t res = 0; - int part; - -#ifdef CONFIG_SYSFS - int mkdir_err = sys_mkdir("/sys", 0700); - if (sys_mount("sysfs", "/sys", "sysfs", 0, NULL) < 0) - goto out; -#endif - - if (strncmp(name, "/dev/", 5) != 0) { - unsigned maj, min; - - if (sscanf(name, "%u:%u", &maj, &min) == 2) { - res = MKDEV(maj, min); - if (maj != MAJOR(res) || min != MINOR(res)) - goto fail; - } else { - res = new_decode_dev(simple_strtoul(name, &p, 16)); - if (*p) - goto fail; - } - goto done; - } - name += 5; - res = Root_NFS; - if (strcmp(name, "nfs") == 0) - goto done; - res = Root_RAM0; - if (strcmp(name, "ram") == 0) - goto done; - - if (strlen(name) > 31) - goto fail; - strcpy(s, name); - for (p = s; *p; p++) - if (*p == '/') - *p = '!'; - res = try_name(s, 0); - if (res) - goto done; - - while (p > s && isdigit(p[-1])) - p--; - if (p == s || !*p || *p == '0') - goto fail; - part = simple_strtoul(p, NULL, 10); - *p = '\0'; - res = try_name(s, part); - if (res) - goto done; - - if (p < s + 2 || !isdigit(p[-2]) || p[-1] != 'p') - goto fail; - p[-1] = '\0'; - res = try_name(s, part); -done: -#ifdef CONFIG_SYSFS - sys_umount("/sys", 0); -out: - if (!mkdir_err) - sys_rmdir("/sys"); -#endif - return res; -fail: - res = 0; - goto done; -} - -static int __init root_dev_setup(char *line) -{ - strlcpy(saved_root_name, line, sizeof(saved_root_name)); - return 1; -} - -__setup("root=", root_dev_setup); - -static char * __initdata root_mount_data; -static int __init root_data_setup(char *str) -{ - root_mount_data = str; - return 1; -} - -static char * __initdata root_fs_names; -static int __init fs_names_setup(char *str) -{ - root_fs_names = str; - return 1; -} - -static unsigned int __initdata root_delay; -static int __init root_delay_setup(char *str) -{ - root_delay = simple_strtoul(str, NULL, 0); - return 1; -} - -__setup("rootflags=", root_data_setup); -__setup("rootfstype=", fs_names_setup); -__setup("rootdelay=", root_delay_setup); - -static void __init get_fs_names(char *page) -{ - char *s = page; - - if (root_fs_names) { - strcpy(page, root_fs_names); - while (*s++) { - if (s[-1] == ',') - s[-1] = '\0'; - } - } else { - int len = get_filesystem_list(page); - char *p, *next; - - page[len] = '\0'; - for (p = page-1; p; p = next) { - next = strchr(++p, '\n'); - if (*p++ != '\t') - continue; - while ((*s++ = *p++) != '\n') - ; - s[-1] = '\0'; - } - } - *s = '\0'; -} - -static int __init do_mount_root(char *name, char *fs, int flags, void *data) -{ - int err = sys_mount(name, "/root", fs, flags, data); - if (err) - return err; - - sys_chdir("/root"); - ROOT_DEV = current->fs->pwdmnt->mnt_sb->s_dev; - printk("VFS: Mounted root (%s filesystem)%s.\n", - current->fs->pwdmnt->mnt_sb->s_type->name, - current->fs->pwdmnt->mnt_sb->s_flags & MS_RDONLY ? - " readonly" : ""); - return 0; -} - -void __init mount_block_root(char *name, int flags) -{ - char *fs_names = __getname(); - char *p; - char b[BDEVNAME_SIZE]; - - get_fs_names(fs_names); -retry: - for (p = fs_names; *p; p += strlen(p)+1) { - int err = do_mount_root(name, p, flags, root_mount_data); - switch (err) { - case 0: - goto out; - case -EACCES: - flags |= MS_RDONLY; - goto retry; - case -EINVAL: - continue; - } - /* - * Allow the user to distinguish between failed sys_open - * and bad superblock on root device. - */ - __bdevname(ROOT_DEV, b); - printk("VFS: Cannot open root device \"%s\" or %s\n", - root_device_name, b); - printk("Please append a correct \"root=\" boot option\n"); - - panic("VFS: Unable to mount root fs on %s", b); - } - - printk("No filesystem could mount root, tried: "); - for (p = fs_names; *p; p += strlen(p)+1) - printk(" %s", p); - printk("\n"); - panic("VFS: Unable to mount root fs on %s", __bdevname(ROOT_DEV, b)); -out: - putname(fs_names); -} - -#ifdef CONFIG_ROOT_NFS -static int __init mount_nfs_root(void) -{ - void *data = nfs_root_data(); - - create_dev("/dev/root", ROOT_DEV); - if (data && - do_mount_root("/dev/root", "nfs", root_mountflags, data) == 0) - return 1; - return 0; -} -#endif - -#if defined(CONFIG_BLK_DEV_RAM) || defined(CONFIG_BLK_DEV_FD) -void __init change_floppy(char *fmt, ...) -{ - struct termios termios; - char buf[80]; - char c; - int fd; - va_list args; - va_start(args, fmt); - vsprintf(buf, fmt, args); - va_end(args); - fd = sys_open("/dev/root", O_RDWR | O_NDELAY, 0); - if (fd >= 0) { - sys_ioctl(fd, FDEJECT, 0); - sys_close(fd); - } - printk(KERN_NOTICE "VFS: Insert %s and press ENTER\n", buf); - fd = sys_open("/dev/console", O_RDWR, 0); - if (fd >= 0) { - sys_ioctl(fd, TCGETS, (long)&termios); - termios.c_lflag &= ~ICANON; - sys_ioctl(fd, TCSETSF, (long)&termios); - sys_read(fd, &c, 1); - termios.c_lflag |= ICANON; - sys_ioctl(fd, TCSETSF, (long)&termios); - sys_close(fd); - } -} -#endif - -void __init mount_root(void) -{ -#ifdef CONFIG_ROOT_NFS - if (MAJOR(ROOT_DEV) == UNNAMED_MAJOR) { - if (mount_nfs_root()) - return; - - printk(KERN_ERR "VFS: Unable to mount root fs via NFS, trying floppy.\n"); - ROOT_DEV = Root_FD0; - } -#endif -#ifdef CONFIG_BLK_DEV_FD - if (MAJOR(ROOT_DEV) == FLOPPY_MAJOR) { - /* rd_doload is 2 for a dual initrd/ramload setup */ - if (rd_doload==2) { - if (rd_load_disk(1)) { - ROOT_DEV = Root_RAM1; - root_device_name = NULL; - } - } else - change_floppy("root floppy"); - } -#endif - create_dev("/dev/root", ROOT_DEV); - mount_block_root("/dev/root", root_mountflags); -} - -/* - * Prepare the namespace - decide what/where to mount, load ramdisks, etc. - */ -void __init prepare_namespace(void) -{ - int is_floppy; - - if (root_delay) { - printk(KERN_INFO "Waiting %dsec before mounting root device...\n", - root_delay); - ssleep(root_delay); - } - - md_run_setup(); - - if (saved_root_name[0]) { - root_device_name = saved_root_name; - if (!strncmp(root_device_name, "mtd", 3)) { - mount_block_root(root_device_name, root_mountflags); - goto out; - } - ROOT_DEV = name_to_dev_t(root_device_name); - if (strncmp(root_device_name, "/dev/", 5) == 0) - root_device_name += 5; - } - - is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR; - - if (initrd_load()) - goto out; - - if (is_floppy && rd_doload && rd_load_disk(0)) - ROOT_DEV = Root_RAM0; - - mount_root(); -out: - sys_mount(".", "/", NULL, MS_MOVE, NULL); - sys_chroot("."); - security_sb_post_mountroot(); -} - diff --git a/init/do_mounts.h b/init/do_mounts.h deleted file mode 100644 index e7f2e7f..0000000 --- a/init/do_mounts.h +++ /dev/null @@ -1,77 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -void change_floppy(char *fmt, ...); -void mount_block_root(char *name, int flags); -void mount_root(void); -extern int root_mountflags; -extern char *root_device_name; - -static inline int create_dev(char *name, dev_t dev) -{ - sys_unlink(name); - return sys_mknod(name, S_IFBLK|0600, new_encode_dev(dev)); -} - -#if BITS_PER_LONG == 32 -static inline u32 bstat(char *name) -{ - struct stat64 stat; - if (sys_stat64(name, &stat) != 0) - return 0; - if (!S_ISBLK(stat.st_mode)) - return 0; - if (stat.st_rdev != (u32)stat.st_rdev) - return 0; - return stat.st_rdev; -} -#else -static inline u32 bstat(char *name) -{ - struct stat stat; - if (sys_newstat(name, &stat) != 0) - return 0; - if (!S_ISBLK(stat.st_mode)) - return 0; - return stat.st_rdev; -} -#endif - -#ifdef CONFIG_BLK_DEV_RAM - -int __init rd_load_disk(int n); -int __init rd_load_image(char *from); - -#else - -static inline int rd_load_disk(int n) { return 0; } -static inline int rd_load_image(char *from) { return 0; } - -#endif - -#ifdef CONFIG_BLK_DEV_INITRD - -int __init initrd_load(void); - -#else - -static inline int initrd_load(void) { return 0; } - -#endif - -#ifdef CONFIG_BLK_DEV_MD - -void md_run_setup(void); - -#else - -static inline void md_run_setup(void) {} - -#endif diff --git a/init/do_mounts_initrd.c b/init/do_mounts_initrd.c deleted file mode 100644 index a06f037..0000000 --- a/init/do_mounts_initrd.c +++ /dev/null @@ -1,123 +0,0 @@ -#define __KERNEL_SYSCALLS__ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "do_mounts.h" - -unsigned long initrd_start, initrd_end; -int initrd_below_start_ok; -unsigned int real_root_dev; /* do_proc_dointvec cannot handle kdev_t */ -static int __initdata old_fd, root_fd; -static int __initdata mount_initrd = 1; - -static int __init no_initrd(char *str) -{ - mount_initrd = 0; - return 1; -} - -__setup("noinitrd", no_initrd); - -static int __init do_linuxrc(void * shell) -{ - static char *argv[] = { "linuxrc", NULL, }; - extern char * envp_init[]; - - sys_close(old_fd);sys_close(root_fd); - sys_close(0);sys_close(1);sys_close(2); - sys_setsid(); - (void) sys_open("/dev/console",O_RDWR,0); - (void) sys_dup(0); - (void) sys_dup(0); - return execve(shell, argv, envp_init); -} - -static void __init handle_initrd(void) -{ - int error; - int pid; - - real_root_dev = new_encode_dev(ROOT_DEV); - create_dev("/dev/root.old", Root_RAM0); - /* mount initrd on rootfs' /root */ - mount_block_root("/dev/root.old", root_mountflags & ~MS_RDONLY); - sys_mkdir("/old", 0700); - root_fd = sys_open("/", 0, 0); - old_fd = sys_open("/old", 0, 0); - /* move initrd over / and chdir/chroot in initrd root */ - sys_chdir("/root"); - sys_mount(".", "/", NULL, MS_MOVE, NULL); - sys_chroot("."); - - current->flags |= PF_NOFREEZE; - pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD); - if (pid > 0) { - while (pid != sys_wait4(-1, NULL, 0, NULL)) - yield(); - } - - /* move initrd to rootfs' /old */ - sys_fchdir(old_fd); - sys_mount("/", ".", NULL, MS_MOVE, NULL); - /* switch root and cwd back to / of rootfs */ - sys_fchdir(root_fd); - sys_chroot("."); - sys_close(old_fd); - sys_close(root_fd); - - if (new_decode_dev(real_root_dev) == Root_RAM0) { - sys_chdir("/old"); - return; - } - - ROOT_DEV = new_decode_dev(real_root_dev); - mount_root(); - - printk(KERN_NOTICE "Trying to move old root to /initrd ... "); - error = sys_mount("/old", "/root/initrd", NULL, MS_MOVE, NULL); - if (!error) - printk("okay\n"); - else { - int fd = sys_open("/dev/root.old", O_RDWR, 0); - if (error == -ENOENT) - printk("/initrd does not exist. Ignored.\n"); - else - printk("failed\n"); - printk(KERN_NOTICE "Unmounting old root\n"); - sys_umount("/old", MNT_DETACH); - printk(KERN_NOTICE "Trying to free ramdisk memory ... "); - if (fd < 0) { - error = fd; - } else { - error = sys_ioctl(fd, BLKFLSBUF, 0); - sys_close(fd); - } - printk(!error ? "okay\n" : "failed\n"); - } -} - -int __init initrd_load(void) -{ - if (mount_initrd) { - create_dev("/dev/ram", Root_RAM0); - /* - * Load the initrd data into /dev/ram0. Execute it as initrd - * unless /dev/ram0 is supposed to be our actual root device, - * in that case the ram disk is just set up here, and gets - * mounted in the normal path. - */ - if (rd_load_image("/initrd.image") && ROOT_DEV != Root_RAM0) { - sys_unlink("/initrd.image"); - handle_initrd(); - return 1; - } - } - sys_unlink("/initrd.image"); - return 0; -} diff --git a/init/do_mounts_md.c b/init/do_mounts_md.c deleted file mode 100644 index 2429e1b..0000000 --- a/init/do_mounts_md.c +++ /dev/null @@ -1,285 +0,0 @@ - -#include - -#include "do_mounts.h" - -/* - * When md (and any require personalities) are compiled into the kernel - * (not a module), arrays can be assembles are boot time using with AUTODETECT - * where specially marked partitions are registered with md_autodetect_dev(), - * and with MD_BOOT where devices to be collected are given on the boot line - * with md=..... - * The code for that is here. - */ - -static int __initdata raid_noautodetect, raid_autopart; - -static struct { - int minor; - int partitioned; - int level; - int chunk; - char *device_names; -} md_setup_args[MAX_MD_DEVS] __initdata; - -static int md_setup_ents __initdata; - -extern int mdp_major; -/* - * Parse the command-line parameters given our kernel, but do not - * actually try to invoke the MD device now; that is handled by - * md_setup_drive after the low-level disk drivers have initialised. - * - * 27/11/1999: Fixed to work correctly with the 2.3 kernel (which - * assigns the task of parsing integer arguments to the - * invoked program now). Added ability to initialise all - * the MD devices (by specifying multiple "md=" lines) - * instead of just one. -- KTK - * 18May2000: Added support for persistent-superblock arrays: - * md=n,0,factor,fault,device-list uses RAID0 for device n - * md=n,-1,factor,fault,device-list uses LINEAR for device n - * md=n,device-list reads a RAID superblock from the devices - * elements in device-list are read by name_to_kdev_t so can be - * a hex number or something like /dev/hda1 /dev/sdb - * 2001-06-03: Dave Cinege - * Shifted name_to_kdev_t() and related operations to md_set_drive() - * for later execution. Rewrote section to make devfs compatible. - */ -static int __init md_setup(char *str) -{ - int minor, level, factor, fault, partitioned = 0; - char *pername = ""; - char *str1; - int ent; - - if (*str == 'd') { - partitioned = 1; - str++; - } - if (get_option(&str, &minor) != 2) { /* MD Number */ - printk(KERN_WARNING "md: Too few arguments supplied to md=.\n"); - return 0; - } - str1 = str; - if (minor >= MAX_MD_DEVS) { - printk(KERN_WARNING "md: md=%d, Minor device number too high.\n", minor); - return 0; - } - for (ent=0 ; ent< md_setup_ents ; ent++) - if (md_setup_args[ent].minor == minor && - md_setup_args[ent].partitioned == partitioned) { - printk(KERN_WARNING "md: md=%s%d, Specified more than once. " - "Replacing previous definition.\n", partitioned?"d":"", minor); - break; - } - if (ent >= MAX_MD_DEVS) { - printk(KERN_WARNING "md: md=%s%d - too many md initialisations\n", partitioned?"d":"", minor); - return 0; - } - if (ent >= md_setup_ents) - md_setup_ents++; - switch (get_option(&str, &level)) { /* RAID level */ - case 2: /* could be 0 or -1.. */ - if (level == 0 || level == LEVEL_LINEAR) { - if (get_option(&str, &factor) != 2 || /* Chunk Size */ - get_option(&str, &fault) != 2) { - printk(KERN_WARNING "md: Too few arguments supplied to md=.\n"); - return 0; - } - md_setup_args[ent].level = level; - md_setup_args[ent].chunk = 1 << (factor+12); - if (level == LEVEL_LINEAR) - pername = "linear"; - else - pername = "raid0"; - break; - } - /* FALL THROUGH */ - case 1: /* the first device is numeric */ - str = str1; - /* FALL THROUGH */ - case 0: - md_setup_args[ent].level = LEVEL_NONE; - pername="super-block"; - } - - printk(KERN_INFO "md: Will configure md%d (%s) from %s, below.\n", - minor, pername, str); - md_setup_args[ent].device_names = str; - md_setup_args[ent].partitioned = partitioned; - md_setup_args[ent].minor = minor; - - return 1; -} - -#define MdpMinorShift 6 - -static void __init md_setup_drive(void) -{ - int minor, i, ent, partitioned; - dev_t dev; - dev_t devices[MD_SB_DISKS+1]; - - for (ent = 0; ent < md_setup_ents ; ent++) { - int fd; - int err = 0; - char *devname; - mdu_disk_info_t dinfo; - char name[16]; - - minor = md_setup_args[ent].minor; - partitioned = md_setup_args[ent].partitioned; - devname = md_setup_args[ent].device_names; - - sprintf(name, "/dev/md%s%d", partitioned?"_d":"", minor); - if (partitioned) - dev = MKDEV(mdp_major, minor << MdpMinorShift); - else - dev = MKDEV(MD_MAJOR, minor); - create_dev(name, dev); - for (i = 0; i < MD_SB_DISKS && devname != 0; i++) { - char *p; - char comp_name[64]; - u32 rdev; - - p = strchr(devname, ','); - if (p) - *p++ = 0; - - dev = name_to_dev_t(devname); - if (strncmp(devname, "/dev/", 5) == 0) - devname += 5; - snprintf(comp_name, 63, "/dev/%s", devname); - rdev = bstat(comp_name); - if (rdev) - dev = new_decode_dev(rdev); - if (!dev) { - printk(KERN_WARNING "md: Unknown device name: %s\n", devname); - break; - } - - devices[i] = dev; - - devname = p; - } - devices[i] = 0; - - if (!i) - continue; - - printk(KERN_INFO "md: Loading md%s%d: %s\n", - partitioned ? "_d" : "", minor, - md_setup_args[ent].device_names); - - fd = sys_open(name, 0, 0); - if (fd < 0) { - printk(KERN_ERR "md: open failed - cannot start " - "array %s\n", name); - continue; - } - if (sys_ioctl(fd, SET_ARRAY_INFO, 0) == -EBUSY) { - printk(KERN_WARNING - "md: Ignoring md=%d, already autodetected. (Use raid=noautodetect)\n", - minor); - sys_close(fd); - continue; - } - - if (md_setup_args[ent].level != LEVEL_NONE) { - /* non-persistent */ - mdu_array_info_t ainfo; - ainfo.level = md_setup_args[ent].level; - ainfo.size = 0; - ainfo.nr_disks =0; - ainfo.raid_disks =0; - while (devices[ainfo.raid_disks]) - ainfo.raid_disks++; - ainfo.md_minor =minor; - ainfo.not_persistent = 1; - - ainfo.state = (1 << MD_SB_CLEAN); - ainfo.layout = 0; - ainfo.chunk_size = md_setup_args[ent].chunk; - err = sys_ioctl(fd, SET_ARRAY_INFO, (long)&ainfo); - for (i = 0; !err && i <= MD_SB_DISKS; i++) { - dev = devices[i]; - if (!dev) - break; - dinfo.number = i; - dinfo.raid_disk = i; - dinfo.state = (1<= 0) { - sys_ioctl(fd, RAID_AUTORUN, raid_autopart); - sys_close(fd); - } - } - md_setup_drive(); -} diff --git a/init/do_mounts_rd.c b/init/do_mounts_rd.c deleted file mode 100644 index ed652f4..0000000 --- a/init/do_mounts_rd.c +++ /dev/null @@ -1,429 +0,0 @@ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "do_mounts.h" - -#define BUILD_CRAMDISK - -int __initdata rd_prompt = 1;/* 1 = prompt for RAM disk, 0 = don't prompt */ - -static int __init prompt_ramdisk(char *str) -{ - rd_prompt = simple_strtol(str,NULL,0) & 1; - return 1; -} -__setup("prompt_ramdisk=", prompt_ramdisk); - -int __initdata rd_image_start; /* starting block # of image */ - -static int __init ramdisk_start_setup(char *str) -{ - rd_image_start = simple_strtol(str,NULL,0); - return 1; -} -__setup("ramdisk_start=", ramdisk_start_setup); - -static int __init crd_load(int in_fd, int out_fd); - -/* - * This routine tries to find a RAM disk image to load, and returns the - * number of blocks to read for a non-compressed image, 0 if the image - * is a compressed image, and -1 if an image with the right magic - * numbers could not be found. - * - * We currently check for the following magic numbers: - * minix - * ext2 - * romfs - * cramfs - * gzip - */ -static int __init -identify_ramdisk_image(int fd, int start_block) -{ - const int size = 512; - struct minix_super_block *minixsb; - struct ext2_super_block *ext2sb; - struct romfs_super_block *romfsb; - struct cramfs_super *cramfsb; - int nblocks = -1; - unsigned char *buf; - - buf = kmalloc(size, GFP_KERNEL); - if (buf == 0) - return -1; - - minixsb = (struct minix_super_block *) buf; - ext2sb = (struct ext2_super_block *) buf; - romfsb = (struct romfs_super_block *) buf; - cramfsb = (struct cramfs_super *) buf; - memset(buf, 0xe5, size); - - /* - * Read block 0 to test for gzipped kernel - */ - sys_lseek(fd, start_block * BLOCK_SIZE, 0); - sys_read(fd, buf, size); - - /* - * If it matches the gzip magic numbers, return -1 - */ - if (buf[0] == 037 && ((buf[1] == 0213) || (buf[1] == 0236))) { - printk(KERN_NOTICE - "RAMDISK: Compressed image found at block %d\n", - start_block); - nblocks = 0; - goto done; - } - - /* romfs is at block zero too */ - if (romfsb->word0 == ROMSB_WORD0 && - romfsb->word1 == ROMSB_WORD1) { - printk(KERN_NOTICE - "RAMDISK: romfs filesystem found at block %d\n", - start_block); - nblocks = (ntohl(romfsb->size)+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; - goto done; - } - - if (cramfsb->magic == CRAMFS_MAGIC) { - printk(KERN_NOTICE - "RAMDISK: cramfs filesystem found at block %d\n", - start_block); - nblocks = (cramfsb->size + BLOCK_SIZE - 1) >> BLOCK_SIZE_BITS; - goto done; - } - - /* - * Read block 1 to test for minix and ext2 superblock - */ - sys_lseek(fd, (start_block+1) * BLOCK_SIZE, 0); - sys_read(fd, buf, size); - - /* Try minix */ - if (minixsb->s_magic == MINIX_SUPER_MAGIC || - minixsb->s_magic == MINIX_SUPER_MAGIC2) { - printk(KERN_NOTICE - "RAMDISK: Minix filesystem found at block %d\n", - start_block); - nblocks = minixsb->s_nzones << minixsb->s_log_zone_size; - goto done; - } - - /* Try ext2 */ - if (ext2sb->s_magic == cpu_to_le16(EXT2_SUPER_MAGIC)) { - printk(KERN_NOTICE - "RAMDISK: ext2 filesystem found at block %d\n", - start_block); - nblocks = le32_to_cpu(ext2sb->s_blocks_count) << - le32_to_cpu(ext2sb->s_log_block_size); - goto done; - } - - printk(KERN_NOTICE - "RAMDISK: Couldn't find valid RAM disk image starting at %d.\n", - start_block); - -done: - sys_lseek(fd, start_block * BLOCK_SIZE, 0); - kfree(buf); - return nblocks; -} - -int __init rd_load_image(char *from) -{ - int res = 0; - int in_fd, out_fd; - unsigned long rd_blocks, devblocks; - int nblocks, i, disk; - char *buf = NULL; - unsigned short rotate = 0; -#if !defined(CONFIG_S390) && !defined(CONFIG_PPC_ISERIES) - char rotator[4] = { '|' , '/' , '-' , '\\' }; -#endif - - out_fd = sys_open("/dev/ram", O_RDWR, 0); - if (out_fd < 0) - goto out; - - in_fd = sys_open(from, O_RDONLY, 0); - if (in_fd < 0) - goto noclose_input; - - nblocks = identify_ramdisk_image(in_fd, rd_image_start); - if (nblocks < 0) - goto done; - - if (nblocks == 0) { -#ifdef BUILD_CRAMDISK - if (crd_load(in_fd, out_fd) == 0) - goto successful_load; -#else - printk(KERN_NOTICE - "RAMDISK: Kernel does not support compressed " - "RAM disk images\n"); -#endif - goto done; - } - - /* - * NOTE NOTE: nblocks is not actually blocks but - * the number of kibibytes of data to load into a ramdisk. - * So any ramdisk block size that is a multiple of 1KiB should - * work when the appropriate ramdisk_blocksize is specified - * on the command line. - * - * The default ramdisk_blocksize is 1KiB and it is generally - * silly to use anything else, so make sure to use 1KiB - * blocksize while generating ext2fs ramdisk-images. - */ - if (sys_ioctl(out_fd, BLKGETSIZE, (unsigned long)&rd_blocks) < 0) - rd_blocks = 0; - else - rd_blocks >>= 1; - - if (nblocks > rd_blocks) { - printk("RAMDISK: image too big! (%dKiB/%ldKiB)\n", - nblocks, rd_blocks); - goto done; - } - - /* - * OK, time to copy in the data - */ - if (sys_ioctl(in_fd, BLKGETSIZE, (unsigned long)&devblocks) < 0) - devblocks = 0; - else - devblocks >>= 1; - - if (strcmp(from, "/initrd.image") == 0) - devblocks = nblocks; - - if (devblocks == 0) { - printk(KERN_ERR "RAMDISK: could not determine device size\n"); - goto done; - } - - buf = kmalloc(BLOCK_SIZE, GFP_KERNEL); - if (buf == 0) { - printk(KERN_ERR "RAMDISK: could not allocate buffer\n"); - goto done; - } - - printk(KERN_NOTICE "RAMDISK: Loading %dKiB [%ld disk%s] into ram disk... ", - nblocks, ((nblocks-1)/devblocks)+1, nblocks>devblocks ? "s" : ""); - for (i = 0, disk = 1; i < nblocks; i++) { - if (i && (i % devblocks == 0)) { - printk("done disk #%d.\n", disk++); - rotate = 0; - if (sys_close(in_fd)) { - printk("Error closing the disk.\n"); - goto noclose_input; - } - change_floppy("disk #%d", disk); - in_fd = sys_open(from, O_RDONLY, 0); - if (in_fd < 0) { - printk("Error opening disk.\n"); - goto noclose_input; - } - printk("Loading disk #%d... ", disk); - } - sys_read(in_fd, buf, BLOCK_SIZE); - sys_write(out_fd, buf, BLOCK_SIZE); -#if !defined(CONFIG_S390) && !defined(CONFIG_PPC_ISERIES) - if (!(i % 16)) { - printk("%c\b", rotator[rotate & 0x3]); - rotate++; - } -#endif - } - printk("done.\n"); - -successful_load: - res = 1; -done: - sys_close(in_fd); -noclose_input: - sys_close(out_fd); -out: - kfree(buf); - sys_unlink("/dev/ram"); - return res; -} - -int __init rd_load_disk(int n) -{ - if (rd_prompt) - change_floppy("root floppy disk to be loaded into RAM disk"); - create_dev("/dev/root", ROOT_DEV); - create_dev("/dev/ram", MKDEV(RAMDISK_MAJOR, n)); - return rd_load_image("/dev/root"); -} - -#ifdef BUILD_CRAMDISK - -/* - * gzip declarations - */ - -#define OF(args) args - -#ifndef memzero -#define memzero(s, n) memset ((s), 0, (n)) -#endif - -typedef unsigned char uch; -typedef unsigned short ush; -typedef unsigned long ulg; - -#define INBUFSIZ 4096 -#define WSIZE 0x8000 /* window size--must be a power of two, and */ - /* at least 32K for zip's deflate method */ - -static uch *inbuf; -static uch *window; - -static unsigned insize; /* valid bytes in inbuf */ -static unsigned inptr; /* index of next byte to be processed in inbuf */ -static unsigned outcnt; /* bytes in output buffer */ -static int exit_code; -static int unzip_error; -static long bytes_out; -static int crd_infd, crd_outfd; - -#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) - -/* Diagnostic functions (stubbed out) */ -#define Assert(cond,msg) -#define Trace(x) -#define Tracev(x) -#define Tracevv(x) -#define Tracec(c,x) -#define Tracecv(c,x) - -#define STATIC static -#define INIT __init - -static int __init fill_inbuf(void); -static void __init flush_window(void); -static void __init *malloc(size_t size); -static void __init free(void *where); -static void __init error(char *m); -static void __init gzip_mark(void **); -static void __init gzip_release(void **); - -#include "../lib/inflate.c" - -static void __init *malloc(size_t size) -{ - return kmalloc(size, GFP_KERNEL); -} - -static void __init free(void *where) -{ - kfree(where); -} - -static void __init gzip_mark(void **ptr) -{ -} - -static void __init gzip_release(void **ptr) -{ -} - - -/* =========================================================================== - * Fill the input buffer. This is called only when the buffer is empty - * and at least one byte is really needed. - * Returning -1 does not guarantee that gunzip() will ever return. - */ -static int __init fill_inbuf(void) -{ - if (exit_code) return -1; - - insize = sys_read(crd_infd, inbuf, INBUFSIZ); - if (insize == 0) { - error("RAMDISK: ran out of compressed data"); - return -1; - } - - inptr = 1; - - return inbuf[0]; -} - -/* =========================================================================== - * Write the output window window[0..outcnt-1] and update crc and bytes_out. - * (Used for the decompressed data only.) - */ -static void __init flush_window(void) -{ - ulg c = crc; /* temporary variable */ - unsigned n, written; - uch *in, ch; - - written = sys_write(crd_outfd, window, outcnt); - if (written != outcnt && unzip_error == 0) { - printk(KERN_ERR "RAMDISK: incomplete write (%d != %d) %ld\n", - written, outcnt, bytes_out); - unzip_error = 1; - } - in = window; - for (n = 0; n < outcnt; n++) { - ch = *in++; - c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); - } - crc = c; - bytes_out += (ulg)outcnt; - outcnt = 0; -} - -static void __init error(char *x) -{ - printk(KERN_ERR "%s\n", x); - exit_code = 1; - unzip_error = 1; -} - -static int __init crd_load(int in_fd, int out_fd) -{ - int result; - - insize = 0; /* valid bytes in inbuf */ - inptr = 0; /* index of next byte to be processed in inbuf */ - outcnt = 0; /* bytes in output buffer */ - exit_code = 0; - bytes_out = 0; - crc = (ulg)0xffffffffL; /* shift register contents */ - - crd_infd = in_fd; - crd_outfd = out_fd; - inbuf = kmalloc(INBUFSIZ, GFP_KERNEL); - if (inbuf == 0) { - printk(KERN_ERR "RAMDISK: Couldn't allocate gzip buffer\n"); - return -1; - } - window = kmalloc(WSIZE, GFP_KERNEL); - if (window == 0) { - printk(KERN_ERR "RAMDISK: Couldn't allocate gzip window\n"); - kfree(inbuf); - return -1; - } - makecrc(); - result = gunzip(); - if (unzip_error) - result = 1; - kfree(inbuf); - kfree(window); - return result; -} - -#endif /* BUILD_CRAMDISK */ diff --git a/init/initramfs.c b/init/initramfs.c index d28c109..57109d4 100644 --- a/init/initramfs.c +++ b/init/initramfs.c @@ -7,6 +7,9 @@ #include #include #include +unsigned long __initdata initrd_start, initrd_end; +int __initdata initrd_below_start_ok; + static __initdata char *message; static void __init error(char *x) { diff --git a/init/main.c b/init/main.c index b2f3b56..e94e3ef 100644 --- a/init/main.c +++ b/init/main.c @@ -7,6 +7,8 @@ * Added initrd & change_root: Werner Almesberger & Hans Lermen, Feb '96 * Moan early if gcc is old, avoiding bogus kernels - Paul Gortmaker, May '96 * Simplified starting of init: Michael A. Griffith + * + * 2006-02-12 H. Peter Anvin: Eliminated in-kernel root mounting. */ #define __KERNEL_SYSCALLS__ @@ -45,6 +47,7 @@ #include #include #include #include +#include #include #include @@ -123,6 +126,11 @@ static char *ramdisk_execute_command; /* Setup configured maximum number of CPUs to activate */ static unsigned int max_cpus = NR_CPUS; +/* ROOT_DEV contains any architecture-specific default root device. */ +/* real_root_dev is used (via sysctl) to communicate ROOT_DEV to kinit. */ +dev_t ROOT_DEV; +unsigned int real_root_dev; + /* * Setup routine for controlling SMP activation * @@ -688,6 +696,12 @@ static int init(void * unused) do_basic_setup(); /* + * If we have a root device set by architecture-specific means, + * let kinit know about it. + */ + real_root_dev = new_encode_dev(ROOT_DEV); + + /* * check if there is an early userspace init. If yes, let it do all * the work */ @@ -695,11 +709,6 @@ static int init(void * unused) if (!ramdisk_execute_command) ramdisk_execute_command = "/init"; - if (sys_access((const char __user *) ramdisk_execute_command, 0) != 0) { - ramdisk_execute_command = NULL; - prepare_namespace(); - } - /* * Ok, we have completed the initial bootup, and * we're essentially up and running. Get rid of the @@ -711,33 +720,13 @@ static int init(void * unused) system_state = SYSTEM_RUNNING; numa_default_policy(); + /* This could be done by (k)init as well... */ if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0) printk(KERN_WARNING "Warning: unable to open an initial console.\n"); (void) sys_dup(0); (void) sys_dup(0); - if (ramdisk_execute_command) { - run_init_process(ramdisk_execute_command); - printk(KERN_WARNING "Failed to execute %s\n", - ramdisk_execute_command); - } - - /* - * We try each of these until one succeeds. - * - * The Bourne shell can be used instead of init if we are - * trying to recover a really broken machine. - */ - if (execute_command) { - run_init_process(execute_command); - printk(KERN_WARNING "Failed to execute %s. Attempting " - "defaults...\n", execute_command); - } - run_init_process("/sbin/init"); - run_init_process("/etc/init"); - run_init_process("/bin/init"); - run_init_process("/bin/sh"); - - panic("No init found. Try passing init= option to kernel."); + run_init_process(ramdisk_execute_command); + panic("Failed to execute %s", ramdisk_execute_command); } diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile index 38b8039..964403f 100644 --- a/net/ipv4/Makefile +++ b/net/ipv4/Makefile @@ -26,7 +26,6 @@ obj-$(CONFIG_INET_XFRM_TUNNEL) += xfrm4_ obj-$(CONFIG_INET_TUNNEL) += tunnel4.o obj-$(CONFIG_INET_XFRM_MODE_TRANSPORT) += xfrm4_mode_transport.o obj-$(CONFIG_INET_XFRM_MODE_TUNNEL) += xfrm4_mode_tunnel.o -obj-$(CONFIG_IP_PNP) += ipconfig.o obj-$(CONFIG_IP_ROUTE_MULTIPATH_RR) += multipath_rr.o obj-$(CONFIG_IP_ROUTE_MULTIPATH_RANDOM) += multipath_random.o obj-$(CONFIG_IP_ROUTE_MULTIPATH_WRANDOM) += multipath_wrandom.o diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c deleted file mode 100644 index cb8a92f..0000000 --- a/net/ipv4/ipconfig.c +++ /dev/null @@ -1,1510 +0,0 @@ -/* - * $Id: ipconfig.c,v 1.46 2002/02/01 22:01:04 davem Exp $ - * - * Automatic Configuration of IP -- use DHCP, BOOTP, RARP, or - * user-supplied information to configure own IP address and routes. - * - * Copyright (C) 1996-1998 Martin Mares - * - * Derived from network configuration code in fs/nfs/nfsroot.c, - * originally Copyright (C) 1995, 1996 Gero Kuhlmann and me. - * - * BOOTP rewritten to construct and analyse packets itself instead - * of misusing the IP layer. num_bugs_causing_wrong_arp_replies--; - * -- MJ, December 1998 - * - * Fixed ip_auto_config_setup calling at startup in the new "Linker Magic" - * initialization scheme. - * - Arnaldo Carvalho de Melo , 08/11/1999 - * - * DHCP support added. To users this looks like a whole separate - * protocol, but we know it's just a bag on the side of BOOTP. - * -- Chip Salzenberg , May 2000 - * - * Ported DHCP support from 2.2.16 to 2.4.0-test4 - * -- Eric Biederman , 30 Aug 2000 - * - * Merged changes from 2.2.19 into 2.4.3 - * -- Eric Biederman , 22 April Aug 2001 - * - * Multiple Nameservers in /proc/net/pnp - * -- Josef Siemes , Aug 2002 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -/* Define this to allow debugging output */ -#undef IPCONFIG_DEBUG - -#ifdef IPCONFIG_DEBUG -#define DBG(x) printk x -#else -#define DBG(x) do { } while(0) -#endif - -#if defined(CONFIG_IP_PNP_DHCP) -#define IPCONFIG_DHCP -#endif -#if defined(CONFIG_IP_PNP_BOOTP) || defined(CONFIG_IP_PNP_DHCP) -#define IPCONFIG_BOOTP -#endif -#if defined(CONFIG_IP_PNP_RARP) -#define IPCONFIG_RARP -#endif -#if defined(IPCONFIG_BOOTP) || defined(IPCONFIG_RARP) -#define IPCONFIG_DYNAMIC -#endif - -/* Define the friendly delay before and after opening net devices */ -#define CONF_PRE_OPEN 500 /* Before opening: 1/2 second */ -#define CONF_POST_OPEN 1 /* After opening: 1 second */ - -/* Define the timeout for waiting for a DHCP/BOOTP/RARP reply */ -#define CONF_OPEN_RETRIES 2 /* (Re)open devices twice */ -#define CONF_SEND_RETRIES 6 /* Send six requests per open */ -#define CONF_INTER_TIMEOUT (HZ/2) /* Inter-device timeout: 1/2 second */ -#define CONF_BASE_TIMEOUT (HZ*2) /* Initial timeout: 2 seconds */ -#define CONF_TIMEOUT_RANDOM (HZ) /* Maximum amount of randomization */ -#define CONF_TIMEOUT_MULT *7/4 /* Rate of timeout growth */ -#define CONF_TIMEOUT_MAX (HZ*30) /* Maximum allowed timeout */ -#define CONF_NAMESERVERS_MAX 3 /* Maximum number of nameservers - - '3' from resolv.h */ - - -/* - * Public IP configuration - */ - -/* This is used by platforms which might be able to set the ipconfig - * variables using firmware environment vars. If this is set, it will - * ignore such firmware variables. - */ -int ic_set_manually __initdata = 0; /* IPconfig parameters set manually */ - -static int ic_enable __initdata = 0; /* IP config enabled? */ - -/* Protocol choice */ -int ic_proto_enabled __initdata = 0 -#ifdef IPCONFIG_BOOTP - | IC_BOOTP -#endif -#ifdef CONFIG_IP_PNP_DHCP - | IC_USE_DHCP -#endif -#ifdef IPCONFIG_RARP - | IC_RARP -#endif - ; - -static int ic_host_name_set __initdata = 0; /* Host name set by us? */ - -u32 ic_myaddr = INADDR_NONE; /* My IP address */ -static u32 ic_netmask = INADDR_NONE; /* Netmask for local subnet */ -u32 ic_gateway = INADDR_NONE; /* Gateway IP address */ - -u32 ic_servaddr = INADDR_NONE; /* Boot server IP address */ - -u32 root_server_addr = INADDR_NONE; /* Address of NFS server */ -u8 root_server_path[256] = { 0, }; /* Path to mount as root */ - -/* Persistent data: */ - -static int ic_proto_used; /* Protocol used, if any */ -static u32 ic_nameservers[CONF_NAMESERVERS_MAX]; /* DNS Server IP addresses */ -static u8 ic_domain[64]; /* DNS (not NIS) domain name */ - -/* - * Private state. - */ - -/* Name of user-selected boot device */ -static char user_dev_name[IFNAMSIZ] __initdata = { 0, }; - -/* Protocols supported by available interfaces */ -static int ic_proto_have_if __initdata = 0; - -#ifdef IPCONFIG_DYNAMIC -static DEFINE_SPINLOCK(ic_recv_lock); -static volatile int ic_got_reply __initdata = 0; /* Proto(s) that replied */ -#endif -#ifdef IPCONFIG_DHCP -static int ic_dhcp_msgtype __initdata = 0; /* DHCP msg type received */ -#endif - - -/* - * Network devices - */ - -struct ic_device { - struct ic_device *next; - struct net_device *dev; - unsigned short flags; - short able; - u32 xid; -}; - -static struct ic_device *ic_first_dev __initdata = NULL;/* List of open device */ -static struct net_device *ic_dev __initdata = NULL; /* Selected device */ - -static int __init ic_open_devs(void) -{ - struct ic_device *d, **last; - struct net_device *dev; - unsigned short oflags; - - last = &ic_first_dev; - rtnl_lock(); - - /* bring loopback device up first */ - if (dev_change_flags(&loopback_dev, loopback_dev.flags | IFF_UP) < 0) - printk(KERN_ERR "IP-Config: Failed to open %s\n", loopback_dev.name); - - for (dev = dev_base; dev; dev = dev->next) { - if (dev == &loopback_dev) - continue; - if (user_dev_name[0] ? !strcmp(dev->name, user_dev_name) : - (!(dev->flags & IFF_LOOPBACK) && - (dev->flags & (IFF_POINTOPOINT|IFF_BROADCAST)) && - strncmp(dev->name, "dummy", 5))) { - int able = 0; - if (dev->mtu >= 364) - able |= IC_BOOTP; - else - printk(KERN_WARNING "DHCP/BOOTP: Ignoring device %s, MTU %d too small", dev->name, dev->mtu); - if (!(dev->flags & IFF_NOARP)) - able |= IC_RARP; - able &= ic_proto_enabled; - if (ic_proto_enabled && !able) - continue; - oflags = dev->flags; - if (dev_change_flags(dev, oflags | IFF_UP) < 0) { - printk(KERN_ERR "IP-Config: Failed to open %s\n", dev->name); - continue; - } - if (!(d = kmalloc(sizeof(struct ic_device), GFP_KERNEL))) { - rtnl_unlock(); - return -1; - } - d->dev = dev; - *last = d; - last = &d->next; - d->flags = oflags; - d->able = able; - if (able & IC_BOOTP) - get_random_bytes(&d->xid, sizeof(u32)); - else - d->xid = 0; - ic_proto_have_if |= able; - DBG(("IP-Config: %s UP (able=%d, xid=%08x)\n", - dev->name, able, d->xid)); - } - } - rtnl_unlock(); - - *last = NULL; - - if (!ic_first_dev) { - if (user_dev_name[0]) - printk(KERN_ERR "IP-Config: Device `%s' not found.\n", user_dev_name); - else - printk(KERN_ERR "IP-Config: No network devices available.\n"); - return -1; - } - return 0; -} - -static void __init ic_close_devs(void) -{ - struct ic_device *d, *next; - struct net_device *dev; - - rtnl_lock(); - next = ic_first_dev; - while ((d = next)) { - next = d->next; - dev = d->dev; - if (dev != ic_dev) { - DBG(("IP-Config: Downing %s\n", dev->name)); - dev_change_flags(dev, d->flags); - } - kfree(d); - } - rtnl_unlock(); -} - -/* - * Interface to various network functions. - */ - -static inline void -set_sockaddr(struct sockaddr_in *sin, u32 addr, u16 port) -{ - sin->sin_family = AF_INET; - sin->sin_addr.s_addr = addr; - sin->sin_port = port; -} - -static int __init ic_dev_ioctl(unsigned int cmd, struct ifreq *arg) -{ - int res; - - mm_segment_t oldfs = get_fs(); - set_fs(get_ds()); - res = devinet_ioctl(cmd, (struct ifreq __user *) arg); - set_fs(oldfs); - return res; -} - -static int __init ic_route_ioctl(unsigned int cmd, struct rtentry *arg) -{ - int res; - - mm_segment_t oldfs = get_fs(); - set_fs(get_ds()); - res = ip_rt_ioctl(cmd, (void __user *) arg); - set_fs(oldfs); - return res; -} - -/* - * Set up interface addresses and routes. - */ - -static int __init ic_setup_if(void) -{ - struct ifreq ir; - struct sockaddr_in *sin = (void *) &ir.ifr_ifru.ifru_addr; - int err; - - memset(&ir, 0, sizeof(ir)); - strcpy(ir.ifr_ifrn.ifrn_name, ic_dev->name); - set_sockaddr(sin, ic_myaddr, 0); - if ((err = ic_dev_ioctl(SIOCSIFADDR, &ir)) < 0) { - printk(KERN_ERR "IP-Config: Unable to set interface address (%d).\n", err); - return -1; - } - set_sockaddr(sin, ic_netmask, 0); - if ((err = ic_dev_ioctl(SIOCSIFNETMASK, &ir)) < 0) { - printk(KERN_ERR "IP-Config: Unable to set interface netmask (%d).\n", err); - return -1; - } - set_sockaddr(sin, ic_myaddr | ~ic_netmask, 0); - if ((err = ic_dev_ioctl(SIOCSIFBRDADDR, &ir)) < 0) { - printk(KERN_ERR "IP-Config: Unable to set interface broadcast address (%d).\n", err); - return -1; - } - return 0; -} - -static int __init ic_setup_routes(void) -{ - /* No need to setup device routes, only the default route... */ - - if (ic_gateway != INADDR_NONE) { - struct rtentry rm; - int err; - - memset(&rm, 0, sizeof(rm)); - if ((ic_gateway ^ ic_myaddr) & ic_netmask) { - printk(KERN_ERR "IP-Config: Gateway not on directly connected network.\n"); - return -1; - } - set_sockaddr((struct sockaddr_in *) &rm.rt_dst, 0, 0); - set_sockaddr((struct sockaddr_in *) &rm.rt_genmask, 0, 0); - set_sockaddr((struct sockaddr_in *) &rm.rt_gateway, ic_gateway, 0); - rm.rt_flags = RTF_UP | RTF_GATEWAY; - if ((err = ic_route_ioctl(SIOCADDRT, &rm)) < 0) { - printk(KERN_ERR "IP-Config: Cannot add default route (%d).\n", err); - return -1; - } - } - - return 0; -} - -/* - * Fill in default values for all missing parameters. - */ - -static int __init ic_defaults(void) -{ - /* - * At this point we have no userspace running so need not - * claim locks on system_utsname - */ - - if (!ic_host_name_set) - sprintf(system_utsname.nodename, "%u.%u.%u.%u", NIPQUAD(ic_myaddr)); - - if (root_server_addr == INADDR_NONE) - root_server_addr = ic_servaddr; - - if (ic_netmask == INADDR_NONE) { - if (IN_CLASSA(ntohl(ic_myaddr))) - ic_netmask = htonl(IN_CLASSA_NET); - else if (IN_CLASSB(ntohl(ic_myaddr))) - ic_netmask = htonl(IN_CLASSB_NET); - else if (IN_CLASSC(ntohl(ic_myaddr))) - ic_netmask = htonl(IN_CLASSC_NET); - else { - printk(KERN_ERR "IP-Config: Unable to guess netmask for address %u.%u.%u.%u\n", - NIPQUAD(ic_myaddr)); - return -1; - } - printk("IP-Config: Guessing netmask %u.%u.%u.%u\n", NIPQUAD(ic_netmask)); - } - - return 0; -} - -/* - * RARP support. - */ - -#ifdef IPCONFIG_RARP - -static int ic_rarp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev); - -static struct packet_type rarp_packet_type __initdata = { - .type = __constant_htons(ETH_P_RARP), - .func = ic_rarp_recv, -}; - -static inline void ic_rarp_init(void) -{ - dev_add_pack(&rarp_packet_type); -} - -static inline void ic_rarp_cleanup(void) -{ - dev_remove_pack(&rarp_packet_type); -} - -/* - * Process received RARP packet. - */ -static int __init -ic_rarp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev) -{ - struct arphdr *rarp; - unsigned char *rarp_ptr; - unsigned long sip, tip; - unsigned char *sha, *tha; /* s for "source", t for "target" */ - struct ic_device *d; - - if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) - return NET_RX_DROP; - - if (!pskb_may_pull(skb, sizeof(struct arphdr))) - goto drop; - - /* Basic sanity checks can be done without the lock. */ - rarp = (struct arphdr *)skb->h.raw; - - /* If this test doesn't pass, it's not IP, or we should - * ignore it anyway. - */ - if (rarp->ar_hln != dev->addr_len || dev->type != ntohs(rarp->ar_hrd)) - goto drop; - - /* If it's not a RARP reply, delete it. */ - if (rarp->ar_op != htons(ARPOP_RREPLY)) - goto drop; - - /* If it's not Ethernet, delete it. */ - if (rarp->ar_pro != htons(ETH_P_IP)) - goto drop; - - if (!pskb_may_pull(skb, - sizeof(struct arphdr) + - (2 * dev->addr_len) + - (2 * 4))) - goto drop; - - /* OK, it is all there and looks valid, process... */ - rarp = (struct arphdr *)skb->h.raw; - rarp_ptr = (unsigned char *) (rarp + 1); - - /* One reply at a time, please. */ - spin_lock(&ic_recv_lock); - - /* If we already have a reply, just drop the packet */ - if (ic_got_reply) - goto drop_unlock; - - /* Find the ic_device that the packet arrived on */ - d = ic_first_dev; - while (d && d->dev != dev) - d = d->next; - if (!d) - goto drop_unlock; /* should never happen */ - - /* Extract variable-width fields */ - sha = rarp_ptr; - rarp_ptr += dev->addr_len; - memcpy(&sip, rarp_ptr, 4); - rarp_ptr += 4; - tha = rarp_ptr; - rarp_ptr += dev->addr_len; - memcpy(&tip, rarp_ptr, 4); - - /* Discard packets which are not meant for us. */ - if (memcmp(tha, dev->dev_addr, dev->addr_len)) - goto drop_unlock; - - /* Discard packets which are not from specified server. */ - if (ic_servaddr != INADDR_NONE && ic_servaddr != sip) - goto drop_unlock; - - /* We have a winner! */ - ic_dev = dev; - if (ic_myaddr == INADDR_NONE) - ic_myaddr = tip; - ic_servaddr = sip; - ic_got_reply = IC_RARP; - -drop_unlock: - /* Show's over. Nothing to see here. */ - spin_unlock(&ic_recv_lock); - -drop: - /* Throw the packet out. */ - kfree_skb(skb); - return 0; -} - - -/* - * Send RARP request packet over a single interface. - */ -static void __init ic_rarp_send_if(struct ic_device *d) -{ - struct net_device *dev = d->dev; - arp_send(ARPOP_RREQUEST, ETH_P_RARP, 0, dev, 0, NULL, - dev->dev_addr, dev->dev_addr); -} -#endif - -/* - * DHCP/BOOTP support. - */ - -#ifdef IPCONFIG_BOOTP - -struct bootp_pkt { /* BOOTP packet format */ - struct iphdr iph; /* IP header */ - struct udphdr udph; /* UDP header */ - u8 op; /* 1=request, 2=reply */ - u8 htype; /* HW address type */ - u8 hlen; /* HW address length */ - u8 hops; /* Used only by gateways */ - u32 xid; /* Transaction ID */ - u16 secs; /* Seconds since we started */ - u16 flags; /* Just what it says */ - u32 client_ip; /* Client's IP address if known */ - u32 your_ip; /* Assigned IP address */ - u32 server_ip; /* (Next, e.g. NFS) Server's IP address */ - u32 relay_ip; /* IP address of BOOTP relay */ - u8 hw_addr[16]; /* Client's HW address */ - u8 serv_name[64]; /* Server host name */ - u8 boot_file[128]; /* Name of boot file */ - u8 exten[312]; /* DHCP options / BOOTP vendor extensions */ -}; - -/* packet ops */ -#define BOOTP_REQUEST 1 -#define BOOTP_REPLY 2 - -/* DHCP message types */ -#define DHCPDISCOVER 1 -#define DHCPOFFER 2 -#define DHCPREQUEST 3 -#define DHCPDECLINE 4 -#define DHCPACK 5 -#define DHCPNAK 6 -#define DHCPRELEASE 7 -#define DHCPINFORM 8 - -static int ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev); - -static struct packet_type bootp_packet_type __initdata = { - .type = __constant_htons(ETH_P_IP), - .func = ic_bootp_recv, -}; - - -/* - * Initialize DHCP/BOOTP extension fields in the request. - */ - -static const u8 ic_bootp_cookie[4] = { 99, 130, 83, 99 }; - -#ifdef IPCONFIG_DHCP - -static void __init -ic_dhcp_init_options(u8 *options) -{ - u8 mt = ((ic_servaddr == INADDR_NONE) - ? DHCPDISCOVER : DHCPREQUEST); - u8 *e = options; - -#ifdef IPCONFIG_DEBUG - printk("DHCP: Sending message type %d\n", mt); -#endif - - memcpy(e, ic_bootp_cookie, 4); /* RFC1048 Magic Cookie */ - e += 4; - - *e++ = 53; /* DHCP message type */ - *e++ = 1; - *e++ = mt; - - if (mt == DHCPREQUEST) { - *e++ = 54; /* Server ID (IP address) */ - *e++ = 4; - memcpy(e, &ic_servaddr, 4); - e += 4; - - *e++ = 50; /* Requested IP address */ - *e++ = 4; - memcpy(e, &ic_myaddr, 4); - e += 4; - } - - /* always? */ - { - static const u8 ic_req_params[] = { - 1, /* Subnet mask */ - 3, /* Default gateway */ - 6, /* DNS server */ - 12, /* Host name */ - 15, /* Domain name */ - 17, /* Boot path */ - 40, /* NIS domain name */ - }; - - *e++ = 55; /* Parameter request list */ - *e++ = sizeof(ic_req_params); - memcpy(e, ic_req_params, sizeof(ic_req_params)); - e += sizeof(ic_req_params); - } - - *e++ = 255; /* End of the list */ -} - -#endif /* IPCONFIG_DHCP */ - -static void __init ic_bootp_init_ext(u8 *e) -{ - memcpy(e, ic_bootp_cookie, 4); /* RFC1048 Magic Cookie */ - e += 4; - *e++ = 1; /* Subnet mask request */ - *e++ = 4; - e += 4; - *e++ = 3; /* Default gateway request */ - *e++ = 4; - e += 4; - *e++ = 5; /* Name server request */ - *e++ = 8; - e += 8; - *e++ = 12; /* Host name request */ - *e++ = 32; - e += 32; - *e++ = 40; /* NIS Domain name request */ - *e++ = 32; - e += 32; - *e++ = 17; /* Boot path */ - *e++ = 40; - e += 40; - - *e++ = 57; /* set extension buffer size for reply */ - *e++ = 2; - *e++ = 1; /* 128+236+8+20+14, see dhcpd sources */ - *e++ = 150; - - *e++ = 255; /* End of the list */ -} - - -/* - * Initialize the DHCP/BOOTP mechanism. - */ -static inline void ic_bootp_init(void) -{ - int i; - - for (i = 0; i < CONF_NAMESERVERS_MAX; i++) - ic_nameservers[i] = INADDR_NONE; - - dev_add_pack(&bootp_packet_type); -} - - -/* - * DHCP/BOOTP cleanup. - */ -static inline void ic_bootp_cleanup(void) -{ - dev_remove_pack(&bootp_packet_type); -} - - -/* - * Send DHCP/BOOTP request to single interface. - */ -static void __init ic_bootp_send_if(struct ic_device *d, unsigned long jiffies_diff) -{ - struct net_device *dev = d->dev; - struct sk_buff *skb; - struct bootp_pkt *b; - int hh_len = LL_RESERVED_SPACE(dev); - struct iphdr *h; - - /* Allocate packet */ - skb = alloc_skb(sizeof(struct bootp_pkt) + hh_len + 15, GFP_KERNEL); - if (!skb) - return; - skb_reserve(skb, hh_len); - b = (struct bootp_pkt *) skb_put(skb, sizeof(struct bootp_pkt)); - memset(b, 0, sizeof(struct bootp_pkt)); - - /* Construct IP header */ - skb->nh.iph = h = &b->iph; - h->version = 4; - h->ihl = 5; - h->tot_len = htons(sizeof(struct bootp_pkt)); - h->frag_off = htons(IP_DF); - h->ttl = 64; - h->protocol = IPPROTO_UDP; - h->daddr = INADDR_BROADCAST; - h->check = ip_fast_csum((unsigned char *) h, h->ihl); - - /* Construct UDP header */ - b->udph.source = htons(68); - b->udph.dest = htons(67); - b->udph.len = htons(sizeof(struct bootp_pkt) - sizeof(struct iphdr)); - /* UDP checksum not calculated -- explicitly allowed in BOOTP RFC */ - - /* Construct DHCP/BOOTP header */ - b->op = BOOTP_REQUEST; - if (dev->type < 256) /* check for false types */ - b->htype = dev->type; - else if (dev->type == ARPHRD_IEEE802_TR) /* fix for token ring */ - b->htype = ARPHRD_IEEE802; - else if (dev->type == ARPHRD_FDDI) - b->htype = ARPHRD_ETHER; - else { - printk("Unknown ARP type 0x%04x for device %s\n", dev->type, dev->name); - b->htype = dev->type; /* can cause undefined behavior */ - } - b->hlen = dev->addr_len; - b->your_ip = INADDR_NONE; - b->server_ip = INADDR_NONE; - memcpy(b->hw_addr, dev->dev_addr, dev->addr_len); - b->secs = htons(jiffies_diff / HZ); - b->xid = d->xid; - - /* add DHCP options or BOOTP extensions */ -#ifdef IPCONFIG_DHCP - if (ic_proto_enabled & IC_USE_DHCP) - ic_dhcp_init_options(b->exten); - else -#endif - ic_bootp_init_ext(b->exten); - - /* Chain packet down the line... */ - skb->dev = dev; - skb->protocol = htons(ETH_P_IP); - if ((dev->hard_header && - dev->hard_header(skb, dev, ntohs(skb->protocol), dev->broadcast, dev->dev_addr, skb->len) < 0) || - dev_queue_xmit(skb) < 0) - printk("E"); -} - - -/* - * Copy BOOTP-supplied string if not already set. - */ -static int __init ic_bootp_string(char *dest, char *src, int len, int max) -{ - if (!len) - return 0; - if (len > max-1) - len = max-1; - memcpy(dest, src, len); - dest[len] = '\0'; - return 1; -} - - -/* - * Process BOOTP extensions. - */ -static void __init ic_do_bootp_ext(u8 *ext) -{ - u8 servers; - int i; - -#ifdef IPCONFIG_DEBUG - u8 *c; - - printk("DHCP/BOOTP: Got extension %d:",*ext); - for(c=ext+2; c CONF_NAMESERVERS_MAX) - servers = CONF_NAMESERVERS_MAX; - for (i = 0; i < servers; i++) { - if (ic_nameservers[i] == INADDR_NONE) - memcpy(&ic_nameservers[i], ext+1+4*i, 4); - } - break; - case 12: /* Host name */ - ic_bootp_string(system_utsname.nodename, ext+1, *ext, __NEW_UTS_LEN); - ic_host_name_set = 1; - break; - case 15: /* Domain name (DNS) */ - ic_bootp_string(ic_domain, ext+1, *ext, sizeof(ic_domain)); - break; - case 17: /* Root path */ - if (!root_server_path[0]) - ic_bootp_string(root_server_path, ext+1, *ext, sizeof(root_server_path)); - break; - case 40: /* NIS Domain name (_not_ DNS) */ - ic_bootp_string(system_utsname.domainname, ext+1, *ext, __NEW_UTS_LEN); - break; - } -} - - -/* - * Receive BOOTP reply. - */ -static int __init ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev) -{ - struct bootp_pkt *b; - struct iphdr *h; - struct ic_device *d; - int len, ext_len; - - /* Perform verifications before taking the lock. */ - if (skb->pkt_type == PACKET_OTHERHOST) - goto drop; - - if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) - return NET_RX_DROP; - - if (!pskb_may_pull(skb, - sizeof(struct iphdr) + - sizeof(struct udphdr))) - goto drop; - - b = (struct bootp_pkt *) skb->nh.iph; - h = &b->iph; - - if (h->ihl != 5 || h->version != 4 || h->protocol != IPPROTO_UDP) - goto drop; - - /* Fragments are not supported */ - if (h->frag_off & htons(IP_OFFSET | IP_MF)) { - if (net_ratelimit()) - printk(KERN_ERR "DHCP/BOOTP: Ignoring fragmented " - "reply.\n"); - goto drop; - } - - if (skb->len < ntohs(h->tot_len)) - goto drop; - - if (ip_fast_csum((char *) h, h->ihl)) - goto drop; - - if (b->udph.source != htons(67) || b->udph.dest != htons(68)) - goto drop; - - if (ntohs(h->tot_len) < ntohs(b->udph.len) + sizeof(struct iphdr)) - goto drop; - - len = ntohs(b->udph.len) - sizeof(struct udphdr); - ext_len = len - (sizeof(*b) - - sizeof(struct iphdr) - - sizeof(struct udphdr) - - sizeof(b->exten)); - if (ext_len < 0) - goto drop; - - /* Ok the front looks good, make sure we can get at the rest. */ - if (!pskb_may_pull(skb, skb->len)) - goto drop; - - b = (struct bootp_pkt *) skb->nh.iph; - h = &b->iph; - - /* One reply at a time, please. */ - spin_lock(&ic_recv_lock); - - /* If we already have a reply, just drop the packet */ - if (ic_got_reply) - goto drop_unlock; - - /* Find the ic_device that the packet arrived on */ - d = ic_first_dev; - while (d && d->dev != dev) - d = d->next; - if (!d) - goto drop_unlock; /* should never happen */ - - /* Is it a reply to our BOOTP request? */ - if (b->op != BOOTP_REPLY || - b->xid != d->xid) { - if (net_ratelimit()) - printk(KERN_ERR "DHCP/BOOTP: Reply not for us, " - "op[%x] xid[%x]\n", - b->op, b->xid); - goto drop_unlock; - } - - /* Parse extensions */ - if (ext_len >= 4 && - !memcmp(b->exten, ic_bootp_cookie, 4)) { /* Check magic cookie */ - u8 *end = (u8 *) b + ntohs(b->iph.tot_len); - u8 *ext; - -#ifdef IPCONFIG_DHCP - if (ic_proto_enabled & IC_USE_DHCP) { - u32 server_id = INADDR_NONE; - int mt = 0; - - ext = &b->exten[4]; - while (ext < end && *ext != 0xff) { - u8 *opt = ext++; - if (*opt == 0) /* Padding */ - continue; - ext += *ext + 1; - if (ext >= end) - break; - switch (*opt) { - case 53: /* Message type */ - if (opt[1]) - mt = opt[2]; - break; - case 54: /* Server ID (IP address) */ - if (opt[1] >= 4) - memcpy(&server_id, opt + 2, 4); - break; - }; - } - -#ifdef IPCONFIG_DEBUG - printk("DHCP: Got message type %d\n", mt); -#endif - - switch (mt) { - case DHCPOFFER: - /* While in the process of accepting one offer, - * ignore all others. - */ - if (ic_myaddr != INADDR_NONE) - goto drop_unlock; - - /* Let's accept that offer. */ - ic_myaddr = b->your_ip; - ic_servaddr = server_id; -#ifdef IPCONFIG_DEBUG - printk("DHCP: Offered address %u.%u.%u.%u", - NIPQUAD(ic_myaddr)); - printk(" by server %u.%u.%u.%u\n", - NIPQUAD(ic_servaddr)); -#endif - /* The DHCP indicated server address takes - * precedence over the bootp header one if - * they are different. - */ - if ((server_id != INADDR_NONE) && - (b->server_ip != server_id)) - b->server_ip = ic_servaddr; - break; - - case DHCPACK: - if (memcmp(dev->dev_addr, b->hw_addr, dev->addr_len) != 0) - goto drop_unlock; - - /* Yeah! */ - break; - - default: - /* Urque. Forget it*/ - ic_myaddr = INADDR_NONE; - ic_servaddr = INADDR_NONE; - goto drop_unlock; - }; - - ic_dhcp_msgtype = mt; - - } -#endif /* IPCONFIG_DHCP */ - - ext = &b->exten[4]; - while (ext < end && *ext != 0xff) { - u8 *opt = ext++; - if (*opt == 0) /* Padding */ - continue; - ext += *ext + 1; - if (ext < end) - ic_do_bootp_ext(opt); - } - } - - /* We have a winner! */ - ic_dev = dev; - ic_myaddr = b->your_ip; - ic_servaddr = b->server_ip; - if (ic_gateway == INADDR_NONE && b->relay_ip) - ic_gateway = b->relay_ip; - if (ic_nameservers[0] == INADDR_NONE) - ic_nameservers[0] = ic_servaddr; - ic_got_reply = IC_BOOTP; - -drop_unlock: - /* Show's over. Nothing to see here. */ - spin_unlock(&ic_recv_lock); - -drop: - /* Throw the packet out. */ - kfree_skb(skb); - - return 0; -} - - -#endif - - -/* - * Dynamic IP configuration -- DHCP, BOOTP, RARP. - */ - -#ifdef IPCONFIG_DYNAMIC - -static int __init ic_dynamic(void) -{ - int retries; - struct ic_device *d; - unsigned long start_jiffies, timeout, jiff; - int do_bootp = ic_proto_have_if & IC_BOOTP; - int do_rarp = ic_proto_have_if & IC_RARP; - - /* - * If none of DHCP/BOOTP/RARP was selected, return with an error. - * This routine gets only called when some pieces of information - * are missing, and without DHCP/BOOTP/RARP we are unable to get it. - */ - if (!ic_proto_enabled) { - printk(KERN_ERR "IP-Config: Incomplete network configuration information.\n"); - return -1; - } - -#ifdef IPCONFIG_BOOTP - if ((ic_proto_enabled ^ ic_proto_have_if) & IC_BOOTP) - printk(KERN_ERR "DHCP/BOOTP: No suitable device found.\n"); -#endif -#ifdef IPCONFIG_RARP - if ((ic_proto_enabled ^ ic_proto_have_if) & IC_RARP) - printk(KERN_ERR "RARP: No suitable device found.\n"); -#endif - - if (!ic_proto_have_if) - /* Error message already printed */ - return -1; - - /* - * Setup protocols - */ -#ifdef IPCONFIG_BOOTP - if (do_bootp) - ic_bootp_init(); -#endif -#ifdef IPCONFIG_RARP - if (do_rarp) - ic_rarp_init(); -#endif - - /* - * Send requests and wait, until we get an answer. This loop - * seems to be a terrible waste of CPU time, but actually there is - * only one process running at all, so we don't need to use any - * scheduler functions. - * [Actually we could now, but the nothing else running note still - * applies.. - AC] - */ - printk(KERN_NOTICE "Sending %s%s%s requests .", - do_bootp - ? ((ic_proto_enabled & IC_USE_DHCP) ? "DHCP" : "BOOTP") : "", - (do_bootp && do_rarp) ? " and " : "", - do_rarp ? "RARP" : ""); - - start_jiffies = jiffies; - d = ic_first_dev; - retries = CONF_SEND_RETRIES; - get_random_bytes(&timeout, sizeof(timeout)); - timeout = CONF_BASE_TIMEOUT + (timeout % (unsigned) CONF_TIMEOUT_RANDOM); - for(;;) { -#ifdef IPCONFIG_BOOTP - if (do_bootp && (d->able & IC_BOOTP)) - ic_bootp_send_if(d, jiffies - start_jiffies); -#endif -#ifdef IPCONFIG_RARP - if (do_rarp && (d->able & IC_RARP)) - ic_rarp_send_if(d); -#endif - - jiff = jiffies + (d->next ? CONF_INTER_TIMEOUT : timeout); - while (time_before(jiffies, jiff) && !ic_got_reply) - schedule_timeout_uninterruptible(1); -#ifdef IPCONFIG_DHCP - /* DHCP isn't done until we get a DHCPACK. */ - if ((ic_got_reply & IC_BOOTP) - && (ic_proto_enabled & IC_USE_DHCP) - && ic_dhcp_msgtype != DHCPACK) - { - ic_got_reply = 0; - printk(","); - continue; - } -#endif /* IPCONFIG_DHCP */ - - if (ic_got_reply) { - printk(" OK\n"); - break; - } - - if ((d = d->next)) - continue; - - if (! --retries) { - printk(" timed out!\n"); - break; - } - - d = ic_first_dev; - - timeout = timeout CONF_TIMEOUT_MULT; - if (timeout > CONF_TIMEOUT_MAX) - timeout = CONF_TIMEOUT_MAX; - - printk("."); - } - -#ifdef IPCONFIG_BOOTP - if (do_bootp) - ic_bootp_cleanup(); -#endif -#ifdef IPCONFIG_RARP - if (do_rarp) - ic_rarp_cleanup(); -#endif - - if (!ic_got_reply) { - ic_myaddr = INADDR_NONE; - return -1; - } - - printk("IP-Config: Got %s answer from %u.%u.%u.%u, ", - ((ic_got_reply & IC_RARP) ? "RARP" - : (ic_proto_enabled & IC_USE_DHCP) ? "DHCP" : "BOOTP"), - NIPQUAD(ic_servaddr)); - printk("my address is %u.%u.%u.%u\n", NIPQUAD(ic_myaddr)); - - return 0; -} - -#endif /* IPCONFIG_DYNAMIC */ - -#ifdef CONFIG_PROC_FS - -static int pnp_seq_show(struct seq_file *seq, void *v) -{ - int i; - - if (ic_proto_used & IC_PROTO) - seq_printf(seq, "#PROTO: %s\n", - (ic_proto_used & IC_RARP) ? "RARP" - : (ic_proto_used & IC_USE_DHCP) ? "DHCP" : "BOOTP"); - else - seq_puts(seq, "#MANUAL\n"); - - if (ic_domain[0]) - seq_printf(seq, - "domain %s\n", ic_domain); - for (i = 0; i < CONF_NAMESERVERS_MAX; i++) { - if (ic_nameservers[i] != INADDR_NONE) - seq_printf(seq, - "nameserver %u.%u.%u.%u\n", - NIPQUAD(ic_nameservers[i])); - } - if (ic_servaddr != INADDR_NONE) - seq_printf(seq, - "bootserver %u.%u.%u.%u\n", - NIPQUAD(ic_servaddr)); - return 0; -} - -static int pnp_seq_open(struct inode *indoe, struct file *file) -{ - return single_open(file, pnp_seq_show, NULL); -} - -static struct file_operations pnp_seq_fops = { - .owner = THIS_MODULE, - .open = pnp_seq_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; -#endif /* CONFIG_PROC_FS */ - -/* - * Extract IP address from the parameter string if needed. Note that we - * need to have root_server_addr set _before_ IPConfig gets called as it - * can override it. - */ -u32 __init root_nfs_parse_addr(char *name) -{ - u32 addr; - int octets = 0; - char *cp, *cq; - - cp = cq = name; - while (octets < 4) { - while (*cp >= '0' && *cp <= '9') - cp++; - if (cp == cq || cp - cq > 3) - break; - if (*cp == '.' || octets == 3) - octets++; - if (octets < 4) - cp++; - cq = cp; - } - if (octets == 4 && (*cp == ':' || *cp == '\0')) { - if (*cp == ':') - *cp++ = '\0'; - addr = in_aton(name); - memmove(name, cp, strlen(cp) + 1); - } else - addr = INADDR_NONE; - - return addr; -} - -/* - * IP Autoconfig dispatcher. - */ - -static int __init ip_auto_config(void) -{ - u32 addr; - -#ifdef CONFIG_PROC_FS - proc_net_fops_create("pnp", S_IRUGO, &pnp_seq_fops); -#endif /* CONFIG_PROC_FS */ - - if (!ic_enable) - return 0; - - DBG(("IP-Config: Entered.\n")); -#ifdef IPCONFIG_DYNAMIC - try_try_again: -#endif - /* Give hardware a chance to settle */ - msleep(CONF_PRE_OPEN); - - /* Setup all network devices */ - if (ic_open_devs() < 0) - return -1; - - /* Give drivers a chance to settle */ - ssleep(CONF_POST_OPEN); - - /* - * If the config information is insufficient (e.g., our IP address or - * IP address of the boot server is missing or we have multiple network - * interfaces and no default was set), use BOOTP or RARP to get the - * missing values. - */ - if (ic_myaddr == INADDR_NONE || -#ifdef CONFIG_ROOT_NFS - (MAJOR(ROOT_DEV) == UNNAMED_MAJOR - && root_server_addr == INADDR_NONE - && ic_servaddr == INADDR_NONE) || -#endif - ic_first_dev->next) { -#ifdef IPCONFIG_DYNAMIC - - int retries = CONF_OPEN_RETRIES; - - if (ic_dynamic() < 0) { - ic_close_devs(); - - /* - * I don't know why, but sometimes the - * eepro100 driver (at least) gets upset and - * doesn't work the first time it's opened. - * But then if you close it and reopen it, it - * works just fine. So we need to try that at - * least once before giving up. - * - * Also, if the root will be NFS-mounted, we - * have nowhere to go if DHCP fails. So we - * just have to keep trying forever. - * - * -- Chip - */ -#ifdef CONFIG_ROOT_NFS - if (ROOT_DEV == Root_NFS) { - printk(KERN_ERR - "IP-Config: Retrying forever (NFS root)...\n"); - goto try_try_again; - } -#endif - - if (--retries) { - printk(KERN_ERR - "IP-Config: Reopening network devices...\n"); - goto try_try_again; - } - - /* Oh, well. At least we tried. */ - printk(KERN_ERR "IP-Config: Auto-configuration of network failed.\n"); - return -1; - } -#else /* !DYNAMIC */ - printk(KERN_ERR "IP-Config: Incomplete network configuration information.\n"); - ic_close_devs(); - return -1; -#endif /* IPCONFIG_DYNAMIC */ - } else { - /* Device selected manually or only one device -> use it */ - ic_dev = ic_first_dev->dev; - } - - addr = root_nfs_parse_addr(root_server_path); - if (root_server_addr == INADDR_NONE) - root_server_addr = addr; - - /* - * Use defaults whereever applicable. - */ - if (ic_defaults() < 0) - return -1; - - /* - * Close all network devices except the device we've - * autoconfigured and set up routes. - */ - ic_close_devs(); - if (ic_setup_if() < 0 || ic_setup_routes() < 0) - return -1; - - /* - * Record which protocol was actually used. - */ -#ifdef IPCONFIG_DYNAMIC - ic_proto_used = ic_got_reply | (ic_proto_enabled & IC_USE_DHCP); -#endif - -#ifndef IPCONFIG_SILENT - /* - * Clue in the operator. - */ - printk("IP-Config: Complete:"); - printk("\n device=%s", ic_dev->name); - printk(", addr=%u.%u.%u.%u", NIPQUAD(ic_myaddr)); - printk(", mask=%u.%u.%u.%u", NIPQUAD(ic_netmask)); - printk(", gw=%u.%u.%u.%u", NIPQUAD(ic_gateway)); - printk(",\n host=%s, domain=%s, nis-domain=%s", - system_utsname.nodename, ic_domain, system_utsname.domainname); - printk(",\n bootserver=%u.%u.%u.%u", NIPQUAD(ic_servaddr)); - printk(", rootserver=%u.%u.%u.%u", NIPQUAD(root_server_addr)); - printk(", rootpath=%s", root_server_path); - printk("\n"); -#endif /* !SILENT */ - - return 0; -} - -late_initcall(ip_auto_config); - - -/* - * Decode any IP configuration options in the "ip=" or "nfsaddrs=" kernel - * command line parameter. It consists of option fields separated by colons in - * the following order: - * - * :::::: - * - * Any of the fields can be empty which means to use a default value: - * - address given by BOOTP or RARP - * - address of host returning BOOTP or RARP packet - * - none, or the address returned by BOOTP - * - automatically determined from , or the - * one returned by BOOTP - * - in ASCII notation, or the name returned - * by BOOTP - * - use all available devices - * : - * off|none - don't do autoconfig at all (DEFAULT) - * on|any - use any configured protocol - * dhcp|bootp|rarp - use only the specified protocol - * both - use both BOOTP and RARP (not DHCP) - */ -static int __init ic_proto_name(char *name) -{ - if (!strcmp(name, "on") || !strcmp(name, "any")) { - return 1; - } -#ifdef CONFIG_IP_PNP_DHCP - else if (!strcmp(name, "dhcp")) { - ic_proto_enabled &= ~IC_RARP; - return 1; - } -#endif -#ifdef CONFIG_IP_PNP_BOOTP - else if (!strcmp(name, "bootp")) { - ic_proto_enabled &= ~(IC_RARP | IC_USE_DHCP); - return 1; - } -#endif -#ifdef CONFIG_IP_PNP_RARP - else if (!strcmp(name, "rarp")) { - ic_proto_enabled &= ~(IC_BOOTP | IC_USE_DHCP); - return 1; - } -#endif -#ifdef IPCONFIG_DYNAMIC - else if (!strcmp(name, "both")) { - ic_proto_enabled &= ~IC_USE_DHCP; /* backward compat :-( */ - return 1; - } -#endif - return 0; -} - -static int __init ip_auto_config_setup(char *addrs) -{ - char *cp, *ip, *dp; - int num = 0; - - ic_set_manually = 1; - - ic_enable = (*addrs && - (strcmp(addrs, "off") != 0) && - (strcmp(addrs, "none") != 0)); - if (!ic_enable) - return 1; - - if (ic_proto_name(addrs)) - return 1; - - /* Parse the whole string */ - ip = addrs; - while (ip && *ip) { - if ((cp = strchr(ip, ':'))) - *cp++ = '\0'; - if (strlen(ip) > 0) { - DBG(("IP-Config: Parameter #%d: `%s'\n", num, ip)); - switch (num) { - case 0: - if ((ic_myaddr = in_aton(ip)) == INADDR_ANY) - ic_myaddr = INADDR_NONE; - break; - case 1: - if ((ic_servaddr = in_aton(ip)) == INADDR_ANY) - ic_servaddr = INADDR_NONE; - break; - case 2: - if ((ic_gateway = in_aton(ip)) == INADDR_ANY) - ic_gateway = INADDR_NONE; - break; - case 3: - if ((ic_netmask = in_aton(ip)) == INADDR_ANY) - ic_netmask = INADDR_NONE; - break; - case 4: - if ((dp = strchr(ip, '.'))) { - *dp++ = '\0'; - strlcpy(system_utsname.domainname, dp, - sizeof(system_utsname.domainname)); - } - strlcpy(system_utsname.nodename, ip, - sizeof(system_utsname.nodename)); - ic_host_name_set = 1; - break; - case 5: - strlcpy(user_dev_name, ip, sizeof(user_dev_name)); - break; - case 6: - ic_proto_name(ip); - break; - } - } - ip = cp; - num++; - } - - return 1; -} - -static int __init nfsaddrs_config_setup(char *addrs) -{ - return ip_auto_config_setup(addrs); -} - -__setup("ip=", ip_auto_config_setup); -__setup("nfsaddrs=", nfsaddrs_config_setup);