aboutsummaryrefslogtreecommitdiffstats
path: root/gpxe/src/proto
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2010-02-03 16:06:41 -0800
committerH. Peter Anvin <hpa@zytor.com>2010-02-03 16:06:41 -0800
commitaddaeaeb3949d576c4e0eb5cfc133b7c3bcfa8fa (patch)
tree2ffea726dc494e87ecc9f506bc6a2bc9242730e3 /gpxe/src/proto
parent5c0f48e49f8d7d084810ecf0b98a76aaebb44835 (diff)
parente7a5f95432132c8fc8f8ede39fda1d368002ddd8 (diff)
downloadsyslinux.git-addaeaeb3949d576c4e0eb5cfc133b7c3bcfa8fa.tar.gz
syslinux.git-addaeaeb3949d576c4e0eb5cfc133b7c3bcfa8fa.tar.xz
syslinux.git-addaeaeb3949d576c4e0eb5cfc133b7c3bcfa8fa.zip
Merge branch 'master' into i915res
Diffstat (limited to 'gpxe/src/proto')
-rw-r--r--gpxe/src/proto/fsp.c243
-rw-r--r--gpxe/src/proto/igmp.c167
-rw-r--r--gpxe/src/proto/nfs.c616
-rw-r--r--gpxe/src/proto/nmb.c110
4 files changed, 0 insertions, 1136 deletions
diff --git a/gpxe/src/proto/fsp.c b/gpxe/src/proto/fsp.c
deleted file mode 100644
index 9a10991d..00000000
--- a/gpxe/src/proto/fsp.c
+++ /dev/null
@@ -1,243 +0,0 @@
- /*********************************************************************\
- * Copyright (c) 2005 by Radim Kolar (hsn-sendmail.cz) *
- * *
- * You may copy or modify this file in any manner you wish, provided *
- * that this notice is always included, and that you hold the author *
- * harmless for any loss or damage resulting from the installation or *
- * use of this software. *
- * *
- * This file provides support for FSP v2 protocol written from scratch *
- * by Radim Kolar, FSP project leader. *
- * *
- * ABOUT FSP *
- * FSP is a lightweight file transfer protocol and is being used for *
- * booting, Internet firmware updates, embedded devices and in *
- * wireless applications. FSP is very easy to implement; contact Radim *
- * Kolar if you need hand optimized assembler FSP stacks for various *
- * microcontrollers, CPUs or consultations. *
- * http://fsp.sourceforge.net/ *
- * *
- * REVISION HISTORY *
- * 1.0 2005-03-17 rkolar Initial coding *
- * 1.1 2005-03-24 rkolar We really need to send CC_BYE to the server *
- * at end of transfer, because next stage boot *
- * loader is unable to contact FSP server *
- * until session timeouts. *
- * 1.2 2005-03-26 rkolar We need to query filesize in advance, *
- * because NBI loader do not reads file until *
- * eof is reached.
- * REMARKS *
- * there is no support for selecting port number of fsp server, maybe *
- * we should parse fsp:// URLs in boot image filename. *
- * this implementation has filename limit 255 chars. *
- \*********************************************************************/
-
-#ifdef DOWNLOAD_PROTO_FSP
-
-#define FSP_PORT 21
-
-/* FSP commands */
-#define CC_GET_FILE 0x42
-#define CC_BYE 0x4A
-#define CC_ERR 0x40
-#define CC_STAT 0x4D
-
-/* etherboot limits */
-#define FSP_MAXFILENAME 255
-
-struct fsp_info {
- in_addr server_ip;
- uint16_t server_port;
- uint16_t local_port;
- const char *filename;
- int (*fnc)(unsigned char *, unsigned int, unsigned int, int);
-};
-
-struct fsp_header {
- uint8_t cmd;
- uint8_t sum;
- uint16_t key;
- uint16_t seq;
- uint16_t len;
- uint32_t pos;
-} PACKED;
-
-#define FSP_MAXPAYLOAD (ETH_MAX_MTU - \
- (sizeof(struct iphdr) + sizeof(struct udphdr) + sizeof(struct fsp_header)))
-
-static struct fsp_request {
- struct iphdr ip;
- struct udphdr udp;
- struct fsp_header fsp;
- unsigned char data[FSP_MAXFILENAME + 1 + 2];
-} request;
-
-struct fsp_reply {
- struct iphdr ip;
- struct udphdr udp;
- struct fsp_header fsp;
- unsigned char data[FSP_MAXPAYLOAD];
-} PACKED;
-
-
-static int await_fsp(int ival, void *ptr, unsigned short ptype __unused,
- struct iphdr *ip, struct udphdr *udp)
-{
- if(!udp)
- return 0;
- if (ip->dest.s_addr != arptable[ARP_CLIENT].ipaddr.s_addr)
- return 0;
- if (ntohs(udp->dest) != ival)
- return 0;
- if (ntohs(udp->len) < 12+sizeof(struct udphdr))
- return 0;
- return 1;
-}
-
-static int proto_fsp(struct fsp_info *info)
-{
- uint32_t filepos;
- uint32_t filelength=0;
- int i,retry;
- uint16_t reqlen;
- struct fsp_reply *reply;
- int block=1;
-
- /* prepare FSP request packet */
- filepos=0;
- i=strlen(info->filename);
- if(i>FSP_MAXFILENAME)
- {
- printf("Boot filename is too long.\n");
- return 0;
- }
- strcpy(request.data,info->filename);
- *(uint16_t *)(request.data+i+1)=htons(FSP_MAXPAYLOAD);
- request.fsp.len=htons(i+1);
- reqlen=i+3+12;
-
- rx_qdrain();
- retry=0;
-
- /* main loop */
- for(;;) {
- int sum;
- long timeout;
-
- /* query filelength if not known */
- if(filelength == 0)
- request.fsp.cmd=CC_STAT;
-
- /* prepare request packet */
- request.fsp.pos=htonl(filepos);
- request.fsp.seq=random();
- request.fsp.sum=0;
- for(i=0,sum=reqlen;i<reqlen;i++)
- {
- sum += ((uint8_t *)&request.fsp)[i];
- }
- request.fsp.sum= sum + (sum >> 8);
- /* send request */
- if (!udp_transmit(info->server_ip.s_addr, info->local_port,
- info->server_port, sizeof(request.ip) +
- sizeof(request.udp) + reqlen, &request))
- return (0);
- /* wait for retry */
-#ifdef CONGESTED
- timeout =
- rfc2131_sleep_interval(filepos ? TFTP_REXMT : TIMEOUT, retry);
-#else
- timeout = rfc2131_sleep_interval(TIMEOUT, retry);
-#endif
- retry++;
- if (!await_reply(await_fsp, info->local_port, NULL, timeout))
- continue;
- reply=(struct fsp_reply *) &nic.packet[ETH_HLEN];
- /* check received packet */
- if (reply->fsp.seq != request.fsp.seq)
- continue;
- reply->udp.len=ntohs(reply->udp.len)-sizeof(struct udphdr);
- if(reply->udp.len < ntohs(reply->fsp.len) + 12 )
- continue;
- sum=-reply->fsp.sum;
- for(i=0;i<reply->udp.len;i++)
- {
- sum += ((uint8_t *)&(reply->fsp))[i];
- }
- sum = (sum + (sum >> 8)) & 0xff;
- if(sum != reply->fsp.sum)
- {
- printf("FSP checksum failed. computed %d, but packet has %d.\n",sum,reply->fsp.sum);
- continue;
- }
- if(reply->fsp.cmd == CC_ERR)
- {
- printf("\nFSP error: %s",info->filename);
- if(reply->fsp.len)
- printf(" [%s]",reply->data);
- printf("\n");
- return 0;
- }
- if(reply->fsp.cmd == CC_BYE && filelength == 1)
- {
- info->fnc(request.data,block,1,1);
- return 1;
- }
- if(reply->fsp.cmd == CC_STAT)
- {
- if(reply->data[8] == 0)
- {
- /* file not found, etc. */
- filelength=0xffffffff;
- } else
- {
- filelength= ntohl(*((uint32_t *)&reply->data[4]));
- }
- request.fsp.cmd = CC_GET_FILE;
- request.fsp.key = reply->fsp.key;
- retry=0;
- continue;
- }
-
- if(reply->fsp.cmd == CC_GET_FILE)
- {
- if(ntohl(reply->fsp.pos) != filepos)
- continue;
- request.fsp.key = reply->fsp.key;
- retry=0;
- i=ntohs(reply->fsp.len);
- if(i == 1)
- {
- request.fsp.cmd=CC_BYE;
- request.data[0]=reply->data[0];
- continue;
- }
- /* let last byte alone */
- if(i >= filelength)
- i = filelength - 1;
- if(!info->fnc(reply->data,block++,i,0))
- return 0;
- filepos += i;
- filelength -= i;
- }
- }
-
- return 0;
-}
-
-int url_fsp(const char *name, int (*fnc)(unsigned char *, unsigned int, unsigned int, int))
-{
- struct fsp_info info;
- /* Set the defaults */
- info.server_ip.s_addr = arptable[ARP_SERVER].ipaddr.s_addr;
- info.server_port = FSP_PORT;
- info.local_port = 1024 + random() & 0xfbff;
- info.fnc = fnc;
-
- /* Now parse the url */
- /* printf("fsp-URI: [%s]\n", name); */
- /* quick hack for now */
- info.filename=name;
- return proto_fsp(&info);
-}
-#endif
diff --git a/gpxe/src/proto/igmp.c b/gpxe/src/proto/igmp.c
deleted file mode 100644
index d711421a..00000000
--- a/gpxe/src/proto/igmp.c
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Eric Biederman wrote this code originally.
- *
- */
-
-#if 0
-
-#include <ip.h>
-#include <igmp.h>
-
-static unsigned long last_igmpv1 = 0;
-static struct igmptable_t igmptable[MAX_IGMP];
-
-static long rfc1112_sleep_interval ( long base, int exp ) {
- unsigned long divisor, tmo;
-
- if ( exp > BACKOFF_LIMIT )
- exp = BACKOFF_LIMIT;
- divisor = RAND_MAX / ( base << exp );
- tmo = random() / divisor;
- return tmo;
-}
-
-static void send_igmp_reports ( unsigned long now ) {
- struct igmp_ip_t igmp;
- int i;
-
- for ( i = 0 ; i < MAX_IGMP ; i++ ) {
- if ( ! igmptable[i].time )
- continue;
- if ( now < igmptable[i].time )
- continue;
-
- igmp.router_alert[0] = 0x94;
- igmp.router_alert[1] = 0x04;
- igmp.router_alert[2] = 0;
- igmp.router_alert[3] = 0;
- build_ip_hdr ( igmptable[i].group.s_addr, 1, IP_IGMP,
- sizeof ( igmp.router_alert ),
- sizeof ( igmp ), &igmp );
- igmp.igmp.type = IGMPv2_REPORT;
- if ( last_igmpv1 &&
- ( now < last_igmpv1 + IGMPv1_ROUTER_PRESENT_TIMEOUT ) ) {
- igmp.igmp.type = IGMPv1_REPORT;
- }
- igmp.igmp.response_time = 0;
- igmp.igmp.chksum = 0;
- igmp.igmp.group.s_addr = igmptable[i].group.s_addr;
- igmp.igmp.chksum = ipchksum ( &igmp.igmp,
- sizeof ( igmp.igmp ) );
- ip_transmit ( sizeof ( igmp ), &igmp );
- DBG ( "IGMP sent report to %s\n", inet_ntoa ( igmp.igmp.group ) );
- /* Don't send another igmp report until asked */
- igmptable[i].time = 0;
- }
-}
-
-static void process_igmp ( unsigned long now, unsigned short ptype __unused,
- struct iphdr *ip ) {
- struct igmp *igmp;
- int i;
- unsigned iplen;
-
- if ( ( ! ip ) || ( ip->protocol != IP_IGMP ) ||
- ( nic.packetlen < ( sizeof ( struct iphdr ) +
- sizeof ( struct igmp ) ) ) ) {
- return;
- }
-
- iplen = ( ip->verhdrlen & 0xf ) * 4;
- igmp = ( struct igmp * ) &nic.packet[ sizeof( struct iphdr ) ];
- if ( ipchksum ( igmp, ntohs ( ip->len ) - iplen ) != 0 )
- return;
-
- if ( ( igmp->type == IGMP_QUERY ) &&
- ( ip->dest.s_addr == htonl ( GROUP_ALL_HOSTS ) ) ) {
- unsigned long interval = IGMP_INTERVAL;
-
- if ( igmp->response_time == 0 ) {
- last_igmpv1 = now;
- } else {
- interval = ( igmp->response_time * TICKS_PER_SEC ) /10;
- }
-
- DBG ( "IGMP received query for %s\n", inet_ntoa ( igmp->group ) );
- for ( i = 0 ; i < MAX_IGMP ; i++ ) {
- uint32_t group = igmptable[i].group.s_addr;
- if ( ( group == 0 ) ||
- ( group == igmp->group.s_addr ) ) {
- unsigned long time;
- time = currticks() +
- rfc1112_sleep_interval ( interval, 0 );
- if ( time < igmptable[i].time ) {
- igmptable[i].time = time;
- }
- }
- }
- }
- if ( ( ( igmp->type == IGMPv1_REPORT ) ||
- ( igmp->type == IGMPv2_REPORT ) ) &&
- ( ip->dest.s_addr == igmp->group.s_addr ) ) {
- DBG ( "IGMP received report for %s\n",
- inet_ntoa ( igmp->group ) );
- for ( i = 0 ; i < MAX_IGMP ; i++ ) {
- if ( ( igmptable[i].group.s_addr ==
- igmp->group.s_addr ) &&
- ( igmptable[i].time != 0 ) ) {
- igmptable[i].time = 0;
- }
- }
- }
-}
-
-struct background igmp_background __background = {
- .send = send_igmp_reports,
- .process = process_igmp,
-};
-
-void leave_group ( int slot ) {
- /* Be very stupid and always send a leave group message if
- * I have subscribed. Imperfect but it is standards
- * compliant, easy and reliable to implement.
- *
- * The optimal group leave method is to only send leave when,
- * we were the last host to respond to a query on this group,
- * and igmpv1 compatibility is not enabled.
- */
- if ( igmptable[slot].group.s_addr ) {
- struct igmp_ip_t igmp;
-
- igmp.router_alert[0] = 0x94;
- igmp.router_alert[1] = 0x04;
- igmp.router_alert[2] = 0;
- igmp.router_alert[3] = 0;
- build_ip_hdr ( htonl ( GROUP_ALL_HOSTS ), 1, IP_IGMP,
- sizeof ( igmp.router_alert ), sizeof ( igmp ),
- &igmp);
- igmp.igmp.type = IGMP_LEAVE;
- igmp.igmp.response_time = 0;
- igmp.igmp.chksum = 0;
- igmp.igmp.group.s_addr = igmptable[slot].group.s_addr;
- igmp.igmp.chksum = ipchksum ( &igmp.igmp, sizeof ( igmp ) );
- ip_transmit ( sizeof ( igmp ), &igmp );
- DBG ( "IGMP left group %s\n", inet_ntoa ( igmp.igmp.group ) );
- }
- memset ( &igmptable[slot], 0, sizeof ( igmptable[0] ) );
-}
-
-void join_group ( int slot, unsigned long group ) {
- /* I have already joined */
- if ( igmptable[slot].group.s_addr == group )
- return;
- if ( igmptable[slot].group.s_addr ) {
- leave_group ( slot );
- }
- /* Only join a group if we are given a multicast ip, this way
- * code can be given a non-multicast (broadcast or unicast ip)
- * and still work...
- */
- if ( ( group & htonl ( MULTICAST_MASK ) ) ==
- htonl ( MULTICAST_NETWORK ) ) {
- igmptable[slot].group.s_addr = group;
- igmptable[slot].time = currticks();
- }
-}
-
-#endif
diff --git a/gpxe/src/proto/nfs.c b/gpxe/src/proto/nfs.c
deleted file mode 100644
index 943081a2..00000000
--- a/gpxe/src/proto/nfs.c
+++ /dev/null
@@ -1,616 +0,0 @@
-#if 0
-
-#include <gpxe/init.h>
-#include <gpxe/in.h>
-
-/* NOTE: the NFS code is heavily inspired by the NetBSD netboot code (read:
- * large portions are copied verbatim) as distributed in OSKit 0.97. A few
- * changes were necessary to adapt the code to Etherboot and to fix several
- * inconsistencies. Also the RPC message preparation is done "by hand" to
- * avoid adding netsprintf() which I find hard to understand and use. */
-
-/* NOTE 2: Etherboot does not care about things beyond the kernel image, so
- * it loads the kernel image off the boot server (ARP_SERVER) and does not
- * access the client root disk (root-path in dhcpd.conf), which would use
- * ARP_ROOTSERVER. The root disk is something the operating system we are
- * about to load needs to use. This is different from the OSKit 0.97 logic. */
-
-/* NOTE 3: Symlink handling introduced by Anselm M Hoffmeister, 2003-July-14
- * If a symlink is encountered, it is followed as far as possible (recursion
- * possible, maximum 16 steps). There is no clearing of ".."'s inside the
- * path, so please DON'T DO THAT. thx. */
-
-#define START_OPORT 700 /* mountd usually insists on secure ports */
-#define OPORT_SWEEP 200 /* make sure we don't leave secure range */
-
-static int oport = START_OPORT;
-static struct sockaddr_in mount_server;
-static struct sockaddr_in nfs_server;
-static unsigned long rpc_id;
-
-/**************************************************************************
-RPC_INIT - set up the ID counter to something fairly random
-**************************************************************************/
-void rpc_init(void)
-{
- unsigned long t;
-
- t = currticks();
- rpc_id = t ^ (t << 8) ^ (t << 16);
-}
-
-/**************************************************************************
-RPC_PRINTERROR - Print a low level RPC error message
-**************************************************************************/
-static void rpc_printerror(struct rpc_t *rpc)
-{
- if (rpc->u.reply.rstatus || rpc->u.reply.verifier ||
- rpc->u.reply.astatus) {
- /* rpc_printerror() is called for any RPC related error,
- * suppress output if no low level RPC error happened. */
- DBG("RPC error: (%ld,%ld,%ld)\n", ntohl(rpc->u.reply.rstatus),
- ntohl(rpc->u.reply.verifier),
- ntohl(rpc->u.reply.astatus));
- }
-}
-
-/**************************************************************************
-AWAIT_RPC - Wait for an rpc packet
-**************************************************************************/
-static int await_rpc(int ival, void *ptr,
- unsigned short ptype __unused, struct iphdr *ip,
- struct udphdr *udp, struct tcphdr *tcp __unused)
-{
- struct rpc_t *rpc;
- if (!udp)
- return 0;
- if (arptable[ARP_CLIENT].ipaddr.s_addr != ip->dest.s_addr)
- return 0;
- if (ntohs(udp->dest) != ival)
- return 0;
- if (nic.packetlen < ETH_HLEN + sizeof(struct iphdr) + sizeof(struct udphdr) + 8)
- return 0;
- rpc = (struct rpc_t *)&nic.packet[ETH_HLEN];
- if (*(unsigned long *)ptr != ntohl(rpc->u.reply.id))
- return 0;
- if (MSG_REPLY != ntohl(rpc->u.reply.type))
- return 0;
- return 1;
-}
-
-/**************************************************************************
-RPC_LOOKUP - Lookup RPC Port numbers
-**************************************************************************/
-static int rpc_lookup(struct sockaddr_in *addr, int prog, int ver, int sport)
-{
- struct rpc_t buf, *rpc;
- unsigned long id;
- int retries;
- long *p;
-
- id = rpc_id++;
- buf.u.call.id = htonl(id);
- buf.u.call.type = htonl(MSG_CALL);
- buf.u.call.rpcvers = htonl(2); /* use RPC version 2 */
- buf.u.call.prog = htonl(PROG_PORTMAP);
- buf.u.call.vers = htonl(2); /* portmapper is version 2 */
- buf.u.call.proc = htonl(PORTMAP_GETPORT);
- p = (long *)buf.u.call.data;
- *p++ = 0; *p++ = 0; /* auth credential */
- *p++ = 0; *p++ = 0; /* auth verifier */
- *p++ = htonl(prog);
- *p++ = htonl(ver);
- *p++ = htonl(IP_UDP);
- *p++ = 0;
- for (retries = 0; retries < MAX_RPC_RETRIES; retries++) {
- long timeout;
- udp_transmit(addr->sin_addr.s_addr, sport, addr->sin_port,
- (char *)p - (char *)&buf, &buf);
- timeout = rfc2131_sleep_interval(TIMEOUT, retries);
- if (await_reply(await_rpc, sport, &id, timeout)) {
- rpc = (struct rpc_t *)&nic.packet[ETH_HLEN];
- if (rpc->u.reply.rstatus || rpc->u.reply.verifier ||
- rpc->u.reply.astatus) {
- rpc_printerror(rpc);
- return 0;
- } else {
- return ntohl(rpc->u.reply.data[0]);
- }
- }
- }
- return 0;
-}
-
-/**************************************************************************
-RPC_ADD_CREDENTIALS - Add RPC authentication/verifier entries
-**************************************************************************/
-static long *rpc_add_credentials(long *p)
-{
- int hl;
-
- /* 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;
-}
-
-/**************************************************************************
-NFS_PRINTERROR - Print a NFS error message
-**************************************************************************/
-static void nfs_printerror(int err)
-{
- switch (-err) {
- case NFSERR_PERM:
- printf("Not owner\n");
- break;
- case NFSERR_NOENT:
- printf("No such file or directory\n");
- break;
- case NFSERR_ACCES:
- printf("Permission denied\n");
- break;
- case NFSERR_ISDIR:
- printf("Directory given where filename expected\n");
- break;
- case NFSERR_INVAL:
- printf("Invalid filehandle\n");
- break; // INVAL is not defined in NFSv2, some NFS-servers
- // seem to use it in answers to v2 nevertheless.
- case 9998:
- printf("low-level RPC failure (parameter decoding problem?)\n");
- break;
- case 9999:
- printf("low-level RPC failure (authentication problem?)\n");
- break;
- default:
- printf("Unknown NFS error %d\n", -err);
- }
-}
-
-/**************************************************************************
-NFS_MOUNT - Mount an NFS Filesystem
-**************************************************************************/
-static int nfs_mount(struct sockaddr_in *server, char *path, char *fh, int sport)
-{
- struct rpc_t buf, *rpc;
- unsigned long id;
- int retries;
- long *p;
- int pathlen = strlen(path);
-
- id = rpc_id++;
- buf.u.call.id = htonl(id);
- buf.u.call.type = htonl(MSG_CALL);
- buf.u.call.rpcvers = htonl(2); /* use RPC version 2 */
- buf.u.call.prog = htonl(PROG_MOUNT);
- buf.u.call.vers = htonl(1); /* mountd is version 1 */
- buf.u.call.proc = htonl(MOUNT_ADDENTRY);
- p = rpc_add_credentials((long *)buf.u.call.data);
- *p++ = htonl(pathlen);
- if (pathlen & 3) {
- *(p + pathlen / 4) = 0; /* add zero padding */
- }
- memcpy(p, path, pathlen);
- p += (pathlen + 3) / 4;
- for (retries = 0; retries < MAX_RPC_RETRIES; retries++) {
- long timeout;
- udp_transmit(server->sin_addr.s_addr, sport, server->sin_port,
- (char *)p - (char *)&buf, &buf);
- timeout = rfc2131_sleep_interval(TIMEOUT, retries);
- if (await_reply(await_rpc, sport, &id, timeout)) {
- rpc = (struct rpc_t *)&nic.packet[ETH_HLEN];
- if (rpc->u.reply.rstatus || rpc->u.reply.verifier ||
- rpc->u.reply.astatus || rpc->u.reply.data[0]) {
- rpc_printerror(rpc);
- if (rpc->u.reply.rstatus) {
- /* RPC failed, no verifier, data[0] */
- return -9999;
- }
- if (rpc->u.reply.astatus) {
- /* RPC couldn't decode parameters */
- return -9998;
- }
- return -ntohl(rpc->u.reply.data[0]);
- } else {
- memcpy(fh, rpc->u.reply.data + 1, NFS_FHSIZE);
- return 0;
- }
- }
- }
- return -1;
-}
-
-/**************************************************************************
-NFS_UMOUNTALL - Unmount all our NFS Filesystems on the Server
-**************************************************************************/
-static void nfs_umountall(struct sockaddr_in *server)
-{
- struct rpc_t buf, *rpc;
- unsigned long id;
- int retries;
- long *p;
-
- id = rpc_id++;
- buf.u.call.id = htonl(id);
- buf.u.call.type = htonl(MSG_CALL);
- buf.u.call.rpcvers = htonl(2); /* use RPC version 2 */
- buf.u.call.prog = htonl(PROG_MOUNT);
- buf.u.call.vers = htonl(1); /* mountd is version 1 */
- buf.u.call.proc = htonl(MOUNT_UMOUNTALL);
- p = rpc_add_credentials((long *)buf.u.call.data);
- for (retries = 0; retries < MAX_RPC_RETRIES; retries++) {
- long timeout = rfc2131_sleep_interval(TIMEOUT, retries);
- udp_transmit(server->sin_addr.s_addr, oport, server->sin_port,
- (char *)p - (char *)&buf, &buf);
- if (await_reply(await_rpc, oport, &id, timeout)) {
- rpc = (struct rpc_t *)&nic.packet[ETH_HLEN];
- if (rpc->u.reply.rstatus || rpc->u.reply.verifier ||
- rpc->u.reply.astatus) {
- rpc_printerror(rpc);
- }
- break;
- }
- }
-}
-
-/**************************************************************************
-NFS_RESET - Reset the NFS subsystem
-**************************************************************************/
-static void nfs_reset ( void ) {
- /* If we have a mount server, call nfs_umountall() */
- if ( mount_server.sin_addr.s_addr ) {
- nfs_umountall ( &mount_server );
- }
- /* Zero the data structures */
- memset ( &mount_server, 0, sizeof ( mount_server ) );
- memset ( &nfs_server, 0, sizeof ( nfs_server ) );
-}
-
-/***************************************************************************
- * 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 int nfs_readlink(struct sockaddr_in *server, char *fh __unused,
- char *path, char *nfh, int sport)
-{
- struct rpc_t buf, *rpc;
- unsigned long id;
- long *p;
- int retries;
- int pathlen = strlen(path);
-
- id = rpc_id++;
- buf.u.call.id = htonl(id);
- buf.u.call.type = htonl(MSG_CALL);
- buf.u.call.rpcvers = htonl(2); /* use RPC version 2 */
- buf.u.call.prog = htonl(PROG_NFS);
- buf.u.call.vers = htonl(2); /* nfsd is version 2 */
- buf.u.call.proc = htonl(NFS_READLINK);
- p = rpc_add_credentials((long *)buf.u.call.data);
- memcpy(p, nfh, NFS_FHSIZE);
- p += (NFS_FHSIZE / 4);
- for (retries = 0; retries < MAX_RPC_RETRIES; retries++) {
- long timeout = rfc2131_sleep_interval(TIMEOUT, retries);
- udp_transmit(server->sin_addr.s_addr, sport, server->sin_port,
- (char *)p - (char *)&buf, &buf);
- if (await_reply(await_rpc, sport, &id, timeout)) {
- rpc = (struct rpc_t *)&nic.packet[ETH_HLEN];
- if (rpc->u.reply.rstatus || rpc->u.reply.verifier ||
- rpc->u.reply.astatus || rpc->u.reply.data[0]) {
- rpc_printerror(rpc);
- if (rpc->u.reply.rstatus) {
- /* RPC failed, no verifier, data[0] */
- return -9999;
- }
- if (rpc->u.reply.astatus) {
- /* RPC couldn't decode parameters */
- return -9998;
- }
- return -ntohl(rpc->u.reply.data[0]);
- } else {
- // It *is* a link.
- // If it's a relative link, append everything to dirname, filename TOO!
- retries = strlen ( (char *)(&(rpc->u.reply.data[2]) ));
- if ( *((char *)(&(rpc->u.reply.data[2]))) != '/' ) {
- path[pathlen++] = '/';
- while ( ( retries + pathlen ) > 298 ) {
- retries--;
- }
- if ( retries > 0 ) {
- memcpy(path + pathlen, &(rpc->u.reply.data[2]), retries + 1);
- } else { retries = 0; }
- path[pathlen + retries] = 0;
- } else {
- // Else make it the only path.
- if ( retries > 298 ) { retries = 298; }
- memcpy ( path, &(rpc->u.reply.data[2]), retries + 1 );
- path[retries] = 0;
- }
- return 0;
- }
- }
- }
- return -1;
-}
-/**************************************************************************
-NFS_LOOKUP - Lookup Pathname
-**************************************************************************/
-static int nfs_lookup(struct sockaddr_in *server, char *fh, char *path, char *nfh,
- int sport)
-{
- struct rpc_t buf, *rpc;
- unsigned long id;
- long *p;
- int retries;
- int pathlen = strlen(path);
-
- id = rpc_id++;
- buf.u.call.id = htonl(id);
- buf.u.call.type = htonl(MSG_CALL);
- buf.u.call.rpcvers = htonl(2); /* use RPC version 2 */
- buf.u.call.prog = htonl(PROG_NFS);
- buf.u.call.vers = htonl(2); /* nfsd is version 2 */
- buf.u.call.proc = htonl(NFS_LOOKUP);
- p = rpc_add_credentials((long *)buf.u.call.data);
- memcpy(p, fh, NFS_FHSIZE);
- p += (NFS_FHSIZE / 4);
- *p++ = htonl(pathlen);
- if (pathlen & 3) {
- *(p + pathlen / 4) = 0; /* add zero padding */
- }
- memcpy(p, path, pathlen);
- p += (pathlen + 3) / 4;
- for (retries = 0; retries < MAX_RPC_RETRIES; retries++) {
- long timeout = rfc2131_sleep_interval(TIMEOUT, retries);
- udp_transmit(server->sin_addr.s_addr, sport, server->sin_port,
- (char *)p - (char *)&buf, &buf);
- if (await_reply(await_rpc, sport, &id, timeout)) {
- rpc = (struct rpc_t *)&nic.packet[ETH_HLEN];
- if (rpc->u.reply.rstatus || rpc->u.reply.verifier ||
- rpc->u.reply.astatus || rpc->u.reply.data[0]) {
- rpc_printerror(rpc);
- if (rpc->u.reply.rstatus) {
- /* RPC failed, no verifier, data[0] */
- return -9999;
- }
- if (rpc->u.reply.astatus) {
- /* RPC couldn't decode parameters */
- return -9998;
- }
- return -ntohl(rpc->u.reply.data[0]);
- } else {
- memcpy(nfh, rpc->u.reply.data + 1, NFS_FHSIZE);
- return 0;
- }
- }
- }
- return -1;
-}
-
-/**************************************************************************
-NFS_READ - Read File on NFS Server
-**************************************************************************/
-static int nfs_read(struct sockaddr_in *server, char *fh, int offset, int len,
- int sport)
-{
- struct rpc_t buf, *rpc;
- unsigned long id;
- int retries;
- long *p;
-
- static int tokens=0;
- /*
- * Try to implement something similar to a window protocol in
- * terms of response to losses. On successful receive, increment
- * the number of tokens by 1 (cap at 256). On failure, halve it.
- * When the number of tokens is >= 2, use a very short timeout.
- */
-
- id = rpc_id++;
- buf.u.call.id = htonl(id);
- buf.u.call.type = htonl(MSG_CALL);
- buf.u.call.rpcvers = htonl(2); /* use RPC version 2 */
- buf.u.call.prog = htonl(PROG_NFS);
- buf.u.call.vers = htonl(2); /* nfsd is version 2 */
- buf.u.call.proc = htonl(NFS_READ);
- p = rpc_add_credentials((long *)buf.u.call.data);
- memcpy(p, fh, NFS_FHSIZE);
- p += NFS_FHSIZE / 4;
- *p++ = htonl(offset);
- *p++ = htonl(len);
- *p++ = 0; /* unused parameter */
- for (retries = 0; retries < MAX_RPC_RETRIES; retries++) {
- long timeout = rfc2131_sleep_interval(TIMEOUT, retries);
- if (tokens >= 2)
- timeout = TICKS_PER_SEC/2;
-
- udp_transmit(server->sin_addr.s_addr, sport, server->sin_port,
- (char *)p - (char *)&buf, &buf);
- if (await_reply(await_rpc, sport, &id, timeout)) {
- if (tokens < 256)
- tokens++;
- rpc = (struct rpc_t *)&nic.packet[ETH_HLEN];
- if (rpc->u.reply.rstatus || rpc->u.reply.verifier ||
- rpc->u.reply.astatus || rpc->u.reply.data[0]) {
- rpc_printerror(rpc);
- if (rpc->u.reply.rstatus) {
- /* RPC failed, no verifier, data[0] */
- return -9999;
- }
- if (rpc->u.reply.astatus) {
- /* RPC couldn't decode parameters */
- return -9998;
- }
- return -ntohl(rpc->u.reply.data[0]);
- } else {
- return 0;
- }
- } else
- tokens >>= 1;
- }
- return -1;
-}
-
-/**************************************************************************
-NFS - Download extended BOOTP data, or kernel image from NFS server
-**************************************************************************/
-static int nfs ( char *url __unused, struct sockaddr_in *server,
- char *name, struct buffer *buffer ) {
- static int recursion = 0;
- int sport;
- int err, namelen = strlen(name);
- char dirname[300], *fname;
- char dirfh[NFS_FHSIZE]; /* file handle of directory */
- char filefh[NFS_FHSIZE]; /* file handle of kernel image */
- int rlen, size, offs, len;
- struct rpc_t *rpc;
-
- sport = oport++;
- if (oport > START_OPORT+OPORT_SWEEP) {
- oport = START_OPORT;
- }
-
- mount_server.sin_addr = nfs_server.sin_addr = server->sin_addr;
- mount_server.sin_port = rpc_lookup(server, PROG_MOUNT, 1, sport);
- if ( ! mount_server.sin_port ) {
- DBG ( "Cannot get mount port from %s:%d\n",
- inet_ntoa ( server->sin_addr ), server->sin_port );
- return 0;
- }
- nfs_server.sin_port = rpc_lookup(server, PROG_NFS, 2, sport);
- if ( ! mount_server.sin_port ) {
- DBG ( "Cannot get nfs port from %s:%d\n",
- inet_ntoa ( server->sin_addr ), server->sin_port );
- return 0;
- }
-
- if ( name != dirname ) {
- memcpy(dirname, name, namelen + 1);
- }
- recursion = 0;
-nfssymlink:
- if ( recursion > NFS_MAXLINKDEPTH ) {
- DBG ( "\nRecursion: More than %d symlinks followed. Abort.\n",
- NFS_MAXLINKDEPTH );
- return 0;
- }
- recursion++;
- fname = dirname + (namelen - 1);
- while (fname >= dirname) {
- if (*fname == '/') {
- *fname = '\0';
- fname++;
- break;
- }
- fname--;
- }
- if (fname < dirname) {
- DBG("can't parse file name %s\n", name);
- return 0;
- }
-
- err = nfs_mount(&mount_server, dirname, dirfh, sport);
- if (err) {
- DBG("mounting %s: ", dirname);
- nfs_printerror(err);
- /* just to be sure... */
- nfs_reset();
- return 0;
- }
-
- err = nfs_lookup(&nfs_server, dirfh, fname, filefh, sport);
- if (err) {
- DBG("looking up %s: ", fname);
- nfs_printerror(err);
- nfs_reset();
- return 0;
- }
-
- offs = 0;
- size = -1; /* will be set properly with the first reply */
- len = NFS_READ_SIZE; /* first request is always full size */
- do {
- err = nfs_read(&nfs_server, filefh, offs, len, sport);
- if ((err <= -NFSERR_ISDIR)&&(err >= -NFSERR_INVAL) && (offs == 0)) {
- // An error occured. NFS servers tend to sending
- // errors 21 / 22 when symlink instead of real file
- // is requested. So check if it's a symlink!
- if ( nfs_readlink(&nfs_server, dirfh, dirname,
- filefh, sport) == 0 ) {
- printf("\nLoading symlink:%s ..",dirname);
- goto nfssymlink;
- }
- nfs_printerror(err);
- nfs_reset();
- return 0;
- }
- if (err) {
- printf("\nError reading at offset %d: ", offs);
- nfs_printerror(err);
- nfs_reset();
- return 0;
- }
-
- rpc = (struct rpc_t *)&nic.packet[ETH_HLEN];
-
- /* size must be found out early to allow EOF detection */
- if (size == -1) {
- size = ntohl(rpc->u.reply.data[6]);
- }
- rlen = ntohl(rpc->u.reply.data[18]);
- if (rlen > len) {
- rlen = len; /* shouldn't happen... */
- }
-
- if ( ! fill_buffer ( buffer, &rpc->u.reply.data[19],
- offs, rlen ) ) {
- nfs_reset();
- return 0;
- }
-
- offs += rlen;
- /* last request is done with matching requested read size */
- if (size-offs < NFS_READ_SIZE) {
- len = size-offs;
- }
- } while (len != 0);
- /* len == 0 means that all the file has been read */
- return 1;
-}
-
-struct protocol nfs_protocol __protocol = {
- .name = "nfs",
- .default_port = SUNRPC_PORT,
- .load = nfs,
-};
-
-#endif
diff --git a/gpxe/src/proto/nmb.c b/gpxe/src/proto/nmb.c
deleted file mode 100644
index e1fc911e..00000000
--- a/gpxe/src/proto/nmb.c
+++ /dev/null
@@ -1,110 +0,0 @@
-#if 0
-
-#include "resolv.h"
-#include "string.h"
-#include <gpxe/dns.h>
-#include "nic.h"
-#include "nmb.h"
-
-/*
- * Convert a standard NUL-terminated string to an NBNS query name.
- *
- * Returns a pointer to the character following the constructed NBNS
- * query name.
- *
- */
-static inline char * nbns_make_name ( char *dest, const char *name ) {
- char nb_name[16];
- char c;
- int i;
- uint16_t *d;
-
- *(dest++) = 32; /* Length is always 32 */
-
- /* Name encoding is as follows: pad the name with spaces to
- * length 15, and add a NUL. Take this 16-byte string, split
- * it into nibbles and add 0x41 to each nibble to form a byte
- * of the resulting name string.
- */
- memset ( nb_name, ' ', 15 );
- nb_name[15] = '\0';
- memcpy ( nb_name, name, strlen ( name ) ); /* Do not copy NUL */
-
- d = ( uint16_t * ) dest;
- for ( i = 0 ; i < 16 ; i++ ) {
- c = nb_name[i];
- *( d++ ) = htons ( ( ( c | ( c << 4 ) ) & 0x0f0f ) + 0x4141 );
- }
- dest = ( char * ) d;
-
- *(dest++) = 0; /* Terminating 0-length name component */
- return dest;
-}
-
-/*
- * Resolve a name using NMB
- *
- */
-static int nmb_resolv ( struct in_addr *addr, const char *name ) {
- struct dns_query query;
- struct dns_query_info *query_info;
- struct dns_header *reply;
- struct dns_rr_info *rr_info;
- struct dns_rr_info_nb *rr_info_nb;
- struct sockaddr_in nameserver;
-
- DBG ( "NMB resolving %s\n", name );
-
- /* Set up the query data */
- nameserver.sin_addr.s_addr = INADDR_BROADCAST;
- nameserver.sin_port = NBNS_UDP_PORT;
- memset ( &query, 0, sizeof ( query ) );
- query.dns.id = htons ( 1 );
- query.dns.flags = htons ( DNS_FLAG_QUERY | DNS_FLAG_OPCODE_QUERY |
- DNS_FLAG_RD | DNS_FLAG_BROADCAST );
- query.dns.qdcount = htons ( 1 );
- query_info = ( void * ) nbns_make_name ( query.payload, name );
- query_info->qtype = htons ( DNS_TYPE_NB );
- query_info->qclass = htons ( DNS_CLASS_IN );
-
- /* Issue query, wait for reply */
- reply = dns_query ( &query,
- ( ( ( char * ) query_info )
- + sizeof ( *query_info )
- - ( ( char * ) &query ) ),
- &nameserver );
- if ( ! reply ) {
- DBG ( "NMB got no response via %@ (port %d)\n",
- nameserver.sin_addr.s_addr,
- nameserver.sin_port );
- return 0;
- }
-
- /* Search through response for useful answers. */
- rr_info = dns_find_rr ( &query, reply );
- if ( ! rr_info ) {
- DBG ( "NMB got invalid response\n" );
- return 0;
- }
-
- /* Check type of response */
- if ( ntohs ( rr_info->type ) != DNS_TYPE_NB ) {
- DBG ( "NMB got answer type %hx (wanted %hx)\n",
- ntohs ( rr_info->type ), DNS_TYPE_NB );
- return 0;
- }
-
- /* Read response */
- rr_info_nb = ( struct dns_rr_info_nb * ) rr_info;
- *addr = rr_info_nb->nb_address;
- DBG ( "NMB found address %@\n", addr->s_addr );
-
- return 1;
-}
-
-struct resolver nmb_resolver __resolver = {
- .name = "NMB",
- .resolv = nmb_resolv,
-};
-
-#endif