⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nfsroot.c

📁 elinux jffs初始版本 具体了解JFFS的文件系统!
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *  linux/fs/nfs/nfsroot.c -- version 2.3 * *  Copyright (C) 1995, 1996  Gero Kuhlmann <gero@gkminix.han.de> * *  For parts of this file: *  Copyright (C) 1996  Martin Mares <mj@k332.feld.cvut.cz> * *  Allow an NFS filesystem to be mounted as root. The way this works is: *     (1) Determine the local IP address via RARP or BOOTP or from the *         kernel command line. *     (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=FCmmler	:	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. * *//* Define this to allow debugging output */#undef NFSROOT_DEBUG#undef NFSROOT_BOOTP_DEBUG#include <linux/config.h>#include <linux/types.h>#include <linux/string.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/fs.h>#include <linux/random.h>#include <linux/fcntl.h>#include <asm/param.h>#include <linux/utsname.h>#include <linux/in.h>#include <linux/if.h>#include <linux/inet.h>#include <linux/net.h>#include <linux/netdevice.h>#include <linux/if_arp.h>#ifdef CONFIG_AX25#include <net/ax25.h>	/* For AX25_P_IP */#endif#include <linux/skbuff.h>#include <linux/socket.h>#include <linux/route.h>#include <linux/nfs.h>#include <linux/nfs_fs.h>#include <linux/nfs_mount.h>#include <linux/in.h>#include <net/route.h>#include <net/sock.h>#include <asm/segment.h>/* Range of privileged ports */#define STARTPORT	600#define ENDPORT		1023#define NPORTS		(ENDPORT - STARTPORT + 1)/* Define the timeout for waiting for a RARP/BOOTP reply */#define CONF_BASE_TIMEOUT	(HZ*5)	/* Initial timeout: 5 seconds */#define CONF_RETRIES	 	10	/* 10 retries */#define CONF_TIMEOUT_RANDOM	(HZ)	/* Maximum amount of randomization */#define CONF_TIMEOUT_MULT	*5/4	/* Speed of timeout growth */#define CONF_TIMEOUT_MAX	(HZ*30)	/* Maximum allowed timeout *//* List of open devices */struct open_dev {	struct device *dev;	unsigned short old_flags;	struct open_dev *next;};static struct open_dev *open_base = NULL;/* IP configuration */static struct device *root_dev = NULL;	/* Device selected for booting */static char user_dev_name[IFNAMSIZ];	/* Name of user-selected boot device */static struct sockaddr_in myaddr;	/* My IP address */static struct sockaddr_in server;	/* Server IP address */static struct sockaddr_in gateway;	/* Gateway IP address */static struct sockaddr_in netmask;	/* Netmask for local subnet *//* BOOTP/RARP variables */static int bootp_flag;			/* User said: Use BOOTP! */static int rarp_flag;			/* User said: Use RARP! */static int bootp_dev_count = 0;		/* Number of devices allowing BOOTP */static int rarp_dev_count = 0;		/* Number of devices allowing RARP */static struct sockaddr_in rarp_serv;	/* IP address of RARP server */#if defined(CONFIG_RNFS_BOOTP) || defined(CONFIG_RNFS_RARP)#define CONFIG_RNFS_DYNAMIC		/* Enable dynamic IP config */static volatile int pkt_arrived;	/* BOOTP/RARP packet detected */#define ARRIVED_BOOTP	1#define ARRIVED_RARP	2#endif/* NFS-related data */static struct nfs_mount_data nfs_data;		/* NFS mount info */static char nfs_path[NFS_MAXPATHLEN] = "";	/* Name of directory to mount */static int nfs_port;				/* Port to connect to for NFS *//* Yes, we use sys_socket, but there's no include file for it */extern asmlinkage int sys_socket(int family, int type, int protocol);/***************************************************************************			Device Handling Subroutines ***************************************************************************//* * Setup and initialize all network devices. If there is a user-preferred * interface, ignore all other interfaces. */static int root_dev_open(void){	struct open_dev *openp, **last;	struct device *dev;	unsigned short old_flags;	last = &open_base;	for (dev = dev_base; dev != NULL; dev = dev->next) {		if (dev->type < ARPHRD_SLIP &&		    dev->family == AF_INET &&		    !(dev->flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) &&		    (0 != strncmp(dev->name, "dummy", 5)) &&		    (!user_dev_name[0] || !strcmp(dev->name, user_dev_name))) {			/* First up the interface */			old_flags = dev->flags;			dev->flags = IFF_UP | IFF_BROADCAST | IFF_RUNNING;			if (!(old_flags & IFF_UP) && dev_open(dev)) {				dev->flags = old_flags;				continue;			}			openp = (struct open_dev *) kmalloc(sizeof(struct open_dev),						GFP_ATOMIC);			if (openp == NULL)				continue;			openp->dev = dev;			openp->old_flags = old_flags;			*last = openp;			last = &openp->next;			bootp_dev_count++;			if (!(dev->flags & IFF_NOARP))				rarp_dev_count++;#ifdef NFSROOT_DEBUG			printk(KERN_NOTICE "Root-NFS: Opened %s\n", dev->name);#endif		}	}	*last = NULL;	if (!bootp_dev_count && !rarp_dev_count) {		printk(KERN_ERR "Root-NFS: Unable to open at least one network device\n");		return -1;	}	return 0;}/* *  Restore the state of all devices. However, keep the root device open *  for the upcoming mount. */static void root_dev_close(void){	struct open_dev *openp;	struct open_dev *nextp;	openp = open_base;	while (openp != NULL) {		nextp = openp->next;		openp->next = NULL;		if (openp->dev != root_dev) {			if (!(openp->old_flags & IFF_UP))				dev_close(openp->dev);			openp->dev->flags = openp->old_flags;		}		kfree_s(openp, sizeof(struct open_dev));		openp = nextp;	}}/***************************************************************************			      RARP Subroutines ***************************************************************************/#ifdef CONFIG_RNFS_RARPextern void arp_send(int type, int ptype, unsigned long target_ip,		     struct device *dev, unsigned long src_ip,		     unsigned char *dest_hw, unsigned char *src_hw,		     unsigned char *target_hw);static int root_rarp_recv(struct sk_buff *skb, struct device *dev,			  struct packet_type *pt);static struct packet_type rarp_packet_type = {	0,			/* Should be: __constant_htons(ETH_P_RARP)				 * - but this _doesn't_ come out constant! */	NULL,			/* Listen to all devices */	root_rarp_recv,	NULL,	NULL};/* *  Register the packet type for RARP */static void root_rarp_open(void){	rarp_packet_type.type = htons(ETH_P_RARP);	dev_add_pack(&rarp_packet_type);}/* *  Deregister the RARP packet type */static void root_rarp_close(void){	rarp_packet_type.type = htons(ETH_P_RARP);	dev_remove_pack(&rarp_packet_type);}/* *  Receive RARP packets. */static int root_rarp_recv(struct sk_buff *skb, struct device *dev, struct packet_type *pt){	struct arphdr *rarp = (struct arphdr *)skb->h.raw;	unsigned char *rarp_ptr = (unsigned char *) (rarp + 1);	unsigned long sip, tip;	unsigned char *sha, *tha;		/* s for "source", t for "target" */	/* 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)) {		kfree_skb(skb, FREE_READ);		return 0;	}	/* If it's not a RARP reply, delete it. */	if (rarp->ar_op != htons(ARPOP_RREPLY)) {		kfree_skb(skb, FREE_READ);		return 0;	}	/* If it's not ethernet or AX25, delete it. */	if ((rarp->ar_pro != htons(ETH_P_IP) && dev->type != ARPHRD_AX25) ||#ifdef CONFIG_AX25	   (rarp->ar_pro != htons(AX25_P_IP) && dev->type == ARPHRD_AX25) ||#endif	    rarp->ar_pln != 4) {		kfree_skb(skb, FREE_READ);		return 0;	}	/* 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)) {		kfree_skb(skb, FREE_READ);		return 0;	}	/* Discard packets which are not from specified server. */	if (rarp_flag && !bootp_flag &&	    rarp_serv.sin_addr.s_addr != INADDR_NONE &&	    rarp_serv.sin_addr.s_addr != sip) {		kfree_skb(skb, FREE_READ);		return 0;	}	/*	 * The packet is what we were looking for. Setup the global	 * variables.	 */	cli();	if (pkt_arrived) {		sti();		kfree_skb(skb, FREE_READ);		return 0;	}	pkt_arrived = ARRIVED_RARP;	sti();	root_dev = dev;	if (myaddr.sin_addr.s_addr == INADDR_NONE) {		myaddr.sin_family = dev->family;		myaddr.sin_addr.s_addr = tip;	}	if (server.sin_addr.s_addr == INADDR_NONE) {		server.sin_family = dev->family;		server.sin_addr.s_addr = sip;	}	kfree_skb(skb, FREE_READ);	return 0;}/* *  Send RARP request packet over all devices which allow RARP. */static void root_rarp_send(void){	struct open_dev *openp;	struct device *dev;	int num = 0;	for (openp = open_base; openp != NULL; openp = openp->next) {		dev = openp->dev;		if (!(dev->flags & IFF_NOARP)) {			arp_send(ARPOP_RREQUEST, ETH_P_RARP, 0, dev, 0, NULL,				 dev->dev_addr, dev->dev_addr);			num++;		}	}}#endif/***************************************************************************			     BOOTP Subroutines ***************************************************************************/#ifdef CONFIG_RNFS_BOOTPstatic struct device *bootp_dev = NULL;	/* Device selected as best BOOTP target */static int bootp_xmit_fd = -1;		/* Socket descriptor for transmit */static struct socket *bootp_xmit_sock;	/* The socket itself */static int bootp_recv_fd = -1;		/* Socket descriptor for receive */static struct socket *bootp_recv_sock;	/* The socket itself */struct bootp_pkt {		/* BOOTP packet format */	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 is says */	u32 client_ip;		/* Client's IP address if known */	u32 your_ip;		/* Assigned IP address */	u32 server_ip;		/* 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 vendor_area[128];	/* Area for extensions */};#define BOOTP_REQUEST 1#define BOOTP_REPLY 2static struct bootp_pkt *xmit_bootp;	/* Packet being transmitted */static struct bootp_pkt *recv_bootp;	/* Packet being received */static int bootp_have_route = 0;	/* BOOTP route installed *//* *  Free BOOTP packet buffers */static void root_free_bootp(void){	if (xmit_bootp) {		kfree_s(xmit_bootp, sizeof(struct bootp_pkt));		xmit_bootp = NULL;	}	if (recv_bootp) {		kfree_s(recv_bootp, sizeof(struct bootp_pkt));		recv_bootp = NULL;	}}/* *  Allocate memory for BOOTP packet buffers */static inline int root_alloc_bootp(void){	if (!(xmit_bootp = kmalloc(sizeof(struct bootp_pkt), GFP_KERNEL)) ||	    !(recv_bootp = kmalloc(sizeof(struct bootp_pkt), GFP_KERNEL))) {		printk("BOOTP: Out of memory!");		return -1;	}	return 0;}/* *  Create default route for BOOTP sending */static int root_add_bootp_route(void){	struct rtentry route;	memset(&route, 0, sizeof(route));	route.rt_dev = bootp_dev->name;	route.rt_mss = bootp_dev->mtu;	route.rt_flags = RTF_UP;	((struct sockaddr_in *) &(route.rt_dst)) -> sin_addr.s_addr = 0;	((struct sockaddr_in *) &(route.rt_dst)) -> sin_family = AF_INET;	((struct sockaddr_in *) &(route.rt_genmask)) -> sin_addr.s_addr = 0;	((struct sockaddr_in *) &(route.rt_genmask)) -> sin_family = AF_INET;	if (ip_rt_new(&route)) {		printk(KERN_ERR "BOOTP: Adding of route failed!\n");		return -1;	}	bootp_have_route = 1;	return 0;}/* *  Delete default route for BOOTP sending */static int root_del_bootp_route(void){	struct rtentry route;	if (!bootp_have_route)		return 0;	memset(&route, 0, sizeof(route));	((struct sockaddr_in *) &(route.rt_dst)) -> sin_addr.s_addr = 0;	((struct sockaddr_in *) &(route.rt_genmask)) -> sin_addr.s_addr = 0;	if (ip_rt_kill(&route)) {		printk(KERN_ERR "BOOTP: Deleting of route failed!\n");		return -1;	}	bootp_have_route = 0;	return 0;}/* *  Open UDP socket. */static int root_open_udp_sock(int *fd, struct socket **sock){	struct file *file;	struct inode *inode;	*fd = sys_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);	if (*fd >= 0) {		file = current->files->fd[*fd];		inode = file->f_inode;		*sock = &inode->u.socket_i;		return 0;	}	printk(KERN_ERR "BOOTP: Cannot open UDP socket!\n");	return -1;}/* *  Connect UDP socket. */static int root_connect_udp_sock(struct socket *sock, u32 addr, u16 port){	struct sockaddr_in sa;	int result;	sa.sin_family = AF_INET;	sa.sin_addr.s_addr = htonl(addr);	sa.sin_port = htons(port);	result = sock->ops->connect(sock, (struct sockaddr *) &sa, sizeof(sa), 0);	if (result < 0) {		printk(KERN_ERR "BOOTP: connect() failed\n");		return -1;	}	return 0;}/* *  Bind UDP socket. */static int root_bind_udp_sock(struct socket *sock, u32 addr, u16 port){	struct sockaddr_in sa;	int result;	sa.sin_family = AF_INET;	sa.sin_addr.s_addr = htonl(addr);	sa.sin_port = htons(port);	result = sock->ops->bind(sock, (struct sockaddr *) &sa, sizeof(sa));	if (result < 0) {		printk(KERN_ERR "BOOTP: bind() failed\n");		return -1;	}	return 0;}/* *  Send UDP packet. */static inline int root_send_udp(struct socket *sock, void *buf, int size){	u32 oldfs;	int result;	struct msghdr msg;	struct iovec iov;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -