?? nfs.c
字號:
/* * vivi/net/nfs.c * * Based on u-boot * * $Id: nfs.c,v 1.0 2004/08/12 11:14:01 kingmonkey Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Description: net nfs protocol routines . * */ #include "printk.h"#include "command.h"#include "net.h"#include "nfs.h"#include "bootp.h"#include <malloc.h>#include <string.h>/*#define NFS_DEBUG*/#if (CONFIG_CMD_NET) && CONFIG_CMD_NFS)#define HASHES_PER_LINE 65 /* Number of "loading" hashes per line */#define NFS_TIMEOUT 10static int fs_mounted = 0;static unsigned long rpc_id = 0;static int nfs_offset = -1;static int nfs_len;static char dirfh[NFS_FHSIZE]; /* file handle of directory */static char filefh[NFS_FHSIZE]; /* file handle of kernel image */static IPaddr_t NfsServerIP;static int NfsSrvMountPort;static int NfsSrvNfsPort;static int NfsOurPort;static int NfsTimeoutCount;static int NfsState;#define STATE_PRCLOOKUP_PROG_MOUNT_REQ 1#define STATE_PRCLOOKUP_PROG_NFS_REQ 2#define STATE_MOUNT_REQ 3#define STATE_UMOUNT_REQ 4#define STATE_LOOKUP_REQ 5#define STATE_READ_REQ 6#define STATE_READLINK_REQ 7static char default_filename[64];static char *nfs_filename;static char *nfs_path;static char nfs_path_buff[2048];static __inline__ voidstore_block (uchar * src, unsigned offset, unsigned len){ ulong newsize = offset + len; (void)memcpy ((void *)(load_addr + offset), src, len); if (NetBootFileXferSize < (offset+len)) NetBootFileXferSize = newsize;}static char*basename (char *path){ char *fname; fname = path + strlen(path) - 1; while (fname >= path) { if (*fname == '/') { fname++; break; } fname--; } return fname;}static char*dirname (char *path){ char *fname; fname = basename (path); --fname; *fname = '\0'; return path;}/**************************************************************************RPC_ADD_CREDENTIALS - Add RPC authentication/verifier entries**************************************************************************/static long *rpc_add_credentials (long *p){ int hl; int hostnamelen; char hostname[256]; strcpy (hostname, ""); hostnamelen=strlen (hostname); /* Here's the executive summary on authentication requirements of the * various NFS server implementations: Linux accepts both AUTH_NONE * and AUTH_UNIX authentication (also accepts an empty hostname field * in the AUTH_UNIX scheme). *BSD refuses AUTH_NONE, but accepts * AUTH_UNIX (also accepts an empty hostname field in the AUTH_UNIX * scheme). To be safe, use AUTH_UNIX and pass the hostname if we have * it (if the BOOTP/DHCP reply didn't give one, just use an empty * hostname). */ hl = (hostnamelen + 3) & ~3; /* Provide an AUTH_UNIX credential. */ *p++ = htonl(1); /* AUTH_UNIX */ *p++ = htonl(hl+20); /* auth length */ *p++ = htonl(0); /* stamp */ *p++ = htonl(hostnamelen); /* hostname string */ if (hostnamelen & 3) { *(p + hostnamelen / 4) = 0; /* add zero padding */ } memcpy (p, hostname, hostnamelen); p += hl / 4; *p++ = 0; /* uid */ *p++ = 0; /* gid */ *p++ = 0; /* auxiliary gid list */ /* Provide an AUTH_NONE verifier. */ *p++ = 0; /* AUTH_NONE */ *p++ = 0; /* auth length */ return p;}/**************************************************************************RPC_LOOKUP - Lookup RPC Port numbers**************************************************************************/static voidrpc_req (int rpc_prog, int rpc_proc, u32 *data, int datalen){ struct rpc_t pkt; unsigned long id; u32 *p; int pktlen; int sport; id = ++rpc_id; pkt.u.call.id = htonl(id); pkt.u.call.type = htonl(MSG_CALL); pkt.u.call.rpcvers = htonl(2); /* use RPC version 2 */ pkt.u.call.prog = htonl(rpc_prog); pkt.u.call.vers = htonl(2); /* portmapper is version 2 */ pkt.u.call.proc = htonl(rpc_proc); p = (u32 *)&(pkt.u.call.data); if (datalen) memcpy ((char *)p, (char *)data, datalen*sizeof(u32)); pktlen = (char *)p + datalen*sizeof(u32) - (char *)&pkt; memcpy ((char *)NetTxPacket + NetEthHdrSize() + IP_HDR_SIZE, (char *)&pkt, pktlen); if (rpc_prog == PROG_PORTMAP) sport = SUNRPC_PORT; else if (rpc_prog == PROG_MOUNT) sport = NfsSrvMountPort; else sport = NfsSrvNfsPort; NetSendUDPPacket (NetServerEther, NfsServerIP, sport, NfsOurPort, pktlen);}/**************************************************************************RPC_LOOKUP - Lookup RPC Port numbers**************************************************************************/static voidrpc_lookup_req (int prog, int ver){ u32 data[16]; data[0] = 0; data[1] = 0; /* auth credential */ data[2] = 0; data[3] = 0; /* auth verifier */ data[4] = htonl(prog); data[5] = htonl(ver); data[6] = htonl(17); /* IP_UDP */ data[7] = 0; rpc_req (PROG_PORTMAP, PORTMAP_GETPORT, data, 8);}/**************************************************************************NFS_MOUNT - Mount an NFS Filesystem**************************************************************************/static voidnfs_mount_req (char *path){ u32 data[1024]; u32 *p; int len; int pathlen; pathlen = strlen (path); p = &(data[0]); p = (u32 *)rpc_add_credentials((long *)p); *p++ = htonl(pathlen); if (pathlen & 3) *(p + pathlen / 4) = 0; memcpy (p, path, pathlen); p += (pathlen + 3) / 4; len = (u32 *)p - (u32 *)&(data[0]); rpc_req (PROG_MOUNT, MOUNT_ADDENTRY, data, len);}/**************************************************************************NFS_UMOUNTALL - Unmount all our NFS Filesystems on the Server**************************************************************************/static voidnfs_umountall_req (void){ u32 data[1024]; u32 *p; int len; if ((NfsSrvMountPort == -1) || (!fs_mounted)) { /* Nothing mounted, nothing to umount */ return; } p = &(data[0]); p = (u32 *)rpc_add_credentials ((long *)p); len = (u32 *)p - (u32 *)&(data[0]); rpc_req (PROG_MOUNT, MOUNT_UMOUNTALL, data, len);}/*************************************************************************** * NFS_READLINK (AH 2003-07-14) * This procedure is called when read of the first block fails - * this probably happens when it's a directory or a symlink * In case of successful readlink(), the dirname is manipulated, * so that inside the nfs() function a recursion can be done. **************************************************************************/static voidnfs_readlink_req (void){ u32 data[1024]; u32 *p; int len; p = &(data[0]); p = (u32 *)rpc_add_credentials ((long *)p); memcpy (p, filefh, NFS_FHSIZE); p += (NFS_FHSIZE / 4); len = (u32 *)p - (u32 *)&(data[0]); rpc_req (PROG_NFS, NFS_READLINK, data, len);}/**************************************************************************NFS_LOOKUP - Lookup Pathname**************************************************************************/static voidnfs_lookup_req (char *fname){ u32 data[1024]; u32 *p; int len; int fnamelen; fnamelen = strlen (fname); p = &(data[0]); p = (u32 *)rpc_add_credentials ((long *)p); memcpy (p, dirfh, NFS_FHSIZE); p += (NFS_FHSIZE / 4); *p++ = htonl(fnamelen); if (fnamelen & 3) *(p + fnamelen / 4) = 0; memcpy (p, fname, fnamelen); p += (fnamelen + 3) / 4; len = (u32 *)p - (u32 *)&(data[0]); rpc_req (PROG_NFS, NFS_LOOKUP, data, len);}/**************************************************************************NFS_READ - Read File on NFS Server**************************************************************************/static voidnfs_read_req (int offset, int readlen){ u32 data[1024]; u32 *p; int len; p = &(data[0]); p = (u32 *)rpc_add_credentials ((long *)p); memcpy (p, filefh, NFS_FHSIZE); p += (NFS_FHSIZE / 4); *p++ = htonl(offset); *p++ = htonl(readlen); *p++ = 0; len = (u32 *)p - (u32 *)&(data[0]); rpc_req (PROG_NFS, NFS_READ, data, len);}/**************************************************************************RPC request dispatcher**************************************************************************/static voidNfsSend (void){#ifdef NFS_DEBUG printk ("%s\n", __FUNCTION__);#endif switch (NfsState) { case STATE_PRCLOOKUP_PROG_MOUNT_REQ: rpc_lookup_req (PROG_MOUNT, 1); break; case STATE_PRCLOOKUP_PROG_NFS_REQ: rpc_lookup_req (PROG_NFS, 2); break; case STATE_MOUNT_REQ: nfs_mount_req (nfs_path); break; case STATE_UMOUNT_REQ: nfs_umountall_req (); break; case STATE_LOOKUP_REQ: nfs_lookup_req (nfs_filename); break; case STATE_READ_REQ: nfs_read_req (nfs_offset, nfs_len); break; case STATE_READLINK_REQ: nfs_readlink_req (); break; }}/**************************************************************************Handlers for the reply from server**************************************************************************/static intrpc_lookup_reply (int prog, uchar *pkt, unsigned len){ struct rpc_t rpc_pkt; memcpy ((unsigned char *)&rpc_pkt, pkt, len);#ifdef NFS_DEBUG printk ("%s\n", __FUNCTION__);#endif
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -