Standalone networking for network boot loaders.
This commit is contained in:
parent
7320b9e43b
commit
e03842d0c7
|
@ -1,15 +1,26 @@
|
|||
# $Id: Makefile,v 1.1 1994/01/26 02:03:32 brezak Exp $
|
||||
# $Id: Makefile,v 1.2 1994/05/08 16:11:14 brezak Exp $
|
||||
|
||||
LIB= sa
|
||||
|
||||
CFLAGS+=-DSTANDALONE -I${.CURDIR}
|
||||
#DEBUGFLAGS= -DNFS_DEBUG -DRPC_DEBUG -DRARP_DEBUG -DDEBUG -DPARANOID -Wall
|
||||
CFLAGS+=-DSTANDALONE $(DEBUGFLAGS) -I${.CURDIR}
|
||||
|
||||
# stand routines
|
||||
SRCS+= alloc.c bcopy.c exit.c exec.c getfile.c gets.c globals.c \
|
||||
printf.c strerror.c
|
||||
|
||||
# io routines
|
||||
SRCS+= close.c dev.c disklabel.c ioctl.c lseek.c open.c read.c \
|
||||
stat.c ufs.c write.c
|
||||
stat.c write.c
|
||||
|
||||
# other misc routines
|
||||
SRCS+= alloc.c bcopy.c exit.c getfile.c gets.c printf.c strerror.c
|
||||
# network routines
|
||||
SRCS+= arp.c ether.c in_cksum.c net.c netif.c rpc.c
|
||||
|
||||
# network info services:
|
||||
SRCS+= bootp.c rarp.c
|
||||
|
||||
# boot filesystems
|
||||
SRCS+= ufs.c nfs.c
|
||||
|
||||
NOPROFILE=
|
||||
NOPIC=
|
||||
|
|
|
@ -0,0 +1,217 @@
|
|||
/*
|
||||
* Copyright (c) 1992 Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by the Computer Systems Engineering group
|
||||
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
|
||||
* contributed to Berkeley.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Lawrence Berkeley Laboratory and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from @(#) Header: arp.c,v 1.5 93/07/15 05:52:26 leres Exp (LBL)
|
||||
* $Id: arp.c,v 1.1 1994/05/08 16:11:16 brezak Exp $
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <netinet/if_ether.h>
|
||||
#include <netinet/in_systm.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "stand.h"
|
||||
#include "net.h"
|
||||
|
||||
/* Cache stuff */
|
||||
#define ARP_NUM 8 /* need at most 3 arp entries */
|
||||
|
||||
static struct arp_list {
|
||||
n_long addr;
|
||||
u_char ea[6];
|
||||
} arp_list[ARP_NUM] = {
|
||||
{ INADDR_BROADCAST, BA }
|
||||
};
|
||||
static int arp_num = 1;
|
||||
|
||||
/* Local forwards */
|
||||
static int arpsend __P((struct iodesc *, void *, int));
|
||||
static int arprecv __P((struct iodesc *, void *, int));
|
||||
|
||||
/* Broadcast an ARP packet, asking who has addr on interface d */
|
||||
u_char *
|
||||
arpwhohas(d, addr)
|
||||
register struct iodesc *d;
|
||||
n_long addr;
|
||||
{
|
||||
register int i;
|
||||
register struct ether_arp *ah;
|
||||
register struct arp_list *al;
|
||||
struct {
|
||||
u_char header[ETHER_SIZE];
|
||||
struct ether_arp warp;
|
||||
} wbuf;
|
||||
union {
|
||||
u_char buffer[RECV_SIZE];
|
||||
struct {
|
||||
u_char header[ETHER_SIZE];
|
||||
struct ether_arp rarp;
|
||||
} ru;
|
||||
} rbuf;
|
||||
|
||||
#ifdef ARP_DEBUG
|
||||
if (debug)
|
||||
printf("arpwhohas: called for %s\n", intoa(addr));
|
||||
#endif
|
||||
/* Try for cached answer first */
|
||||
for (i = 0, al = arp_list; i < arp_num; ++i, ++al)
|
||||
if (addr == al->addr)
|
||||
return (al->ea);
|
||||
|
||||
/* Don't overflow cache */
|
||||
if (arp_num > ARP_NUM - 1)
|
||||
panic("arpwhohas: overflowed arp_list!");
|
||||
|
||||
#ifdef ARP_DEBUG
|
||||
if (debug)
|
||||
printf("arpwhohas: not cached\n");
|
||||
#endif
|
||||
ah = &wbuf.warp;
|
||||
bzero(ah, sizeof(*ah));
|
||||
|
||||
ah->arp_hrd = htons(ARPHRD_ETHER);
|
||||
ah->arp_pro = htons(ETHERTYPE_IP);
|
||||
ah->arp_hln = sizeof(ah->arp_sha); /* hardware address length */
|
||||
ah->arp_pln = sizeof(ah->arp_spa); /* protocol address length */
|
||||
ah->arp_op = htons(ARPOP_REQUEST);
|
||||
MACPY(d->myea, ah->arp_sha);
|
||||
bcopy(&d->myip, ah->arp_spa, sizeof(ah->arp_spa));
|
||||
bcopy(&addr, ah->arp_tpa, sizeof(ah->arp_tpa));
|
||||
|
||||
/* Store ip address in cache */
|
||||
al->addr = addr;
|
||||
|
||||
(void)sendrecv(d, arpsend, ah, sizeof(*ah), arprecv,
|
||||
((u_char *)&rbuf.ru.rarp) - ETHER_SIZE,
|
||||
ETHER_SIZE + sizeof(rbuf.ru.rarp));
|
||||
|
||||
/* Store ethernet address in cache */
|
||||
MACPY(rbuf.ru.rarp.arp_sha, al->ea);
|
||||
++arp_num;
|
||||
#ifdef ARP_DEBUG
|
||||
if (debug)
|
||||
printf("arpwhohas: cacheing %s --> %s\n", intoa(addr), ether_sprintf(al->ea));
|
||||
#endif
|
||||
|
||||
return (al->ea);
|
||||
}
|
||||
|
||||
static int
|
||||
arpsend(d, pkt, len)
|
||||
register struct iodesc *d;
|
||||
register void *pkt;
|
||||
register int len;
|
||||
{
|
||||
#ifdef ARP_DEBUG
|
||||
if (debug)
|
||||
printf("arpsend: called\n");
|
||||
#endif
|
||||
return (sendether(d, pkt, len, bcea, ETHERTYPE_ARP));
|
||||
}
|
||||
|
||||
/* Returns 0 if this is the packet we're waiting for else -1 (and errno == 0) */
|
||||
static int
|
||||
arprecv(d, pkt, len)
|
||||
register struct iodesc *d;
|
||||
register void *pkt;
|
||||
register int len;
|
||||
{
|
||||
register struct ether_header *eh;
|
||||
register struct ether_arp *ah;
|
||||
|
||||
#ifdef ARP_DEBUG
|
||||
if (debug)
|
||||
printf("arprecv: called\n");
|
||||
#endif
|
||||
if (len < sizeof(*eh) + sizeof(*ah)) {
|
||||
errno = 0;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
eh = (struct ether_header *)pkt;
|
||||
|
||||
/* Must be to us */
|
||||
if (bcmp(d->myea, eh->ether_dhost, 6) != 0 &&
|
||||
bcmp(bcea, eh->ether_dhost, 6) != 0) {
|
||||
#ifdef ARP_DEBUG
|
||||
if (debug)
|
||||
printf("arprecv: not ours %s\n", ether_sprintf(eh->ether_dhost));
|
||||
#endif
|
||||
errno = 0;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (ntohs(eh->ether_type) != ETHERTYPE_ARP) {
|
||||
#ifdef ARP_DEBUG
|
||||
if (debug)
|
||||
printf("arprecv: not arp %d\n", ntohs(eh->ether_type));
|
||||
#endif
|
||||
errno = 0;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
ah = (struct ether_arp *)(eh + 1);
|
||||
HTONS(ah->arp_hrd);
|
||||
HTONS(ah->arp_pro);
|
||||
HTONS(ah->arp_op);
|
||||
if (ah->arp_hrd != ARPHRD_ETHER || ah->arp_pro != ETHERTYPE_IP ||
|
||||
ah->arp_hln != sizeof(ah->arp_sha) ||
|
||||
ah->arp_pln != sizeof(ah->arp_spa) || ah->arp_op != ARPOP_REPLY) {
|
||||
#ifdef ARP_DEBUG
|
||||
if (debug)
|
||||
printf("arprecv: not valid reply\n");
|
||||
#endif
|
||||
errno = 0;
|
||||
return (-1);
|
||||
}
|
||||
if (bcmp(&arp_list[arp_num].addr, ah->arp_spa, sizeof(long)) != 0 ||
|
||||
bcmp(&d->myip, ah->arp_tpa, sizeof(d->myip)) != 0) {
|
||||
#ifdef ARP_DEBUG
|
||||
if (debug)
|
||||
printf("arprecv: already cached??\n");
|
||||
#endif
|
||||
errno = 0;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
|
@ -0,0 +1,347 @@
|
|||
/*
|
||||
* Copyright (c) 1992 Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by the Computer Systems Engineering group
|
||||
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
|
||||
* contributed to Berkeley.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Lawrence Berkeley Laboratory and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from @(#) Header: bootp.c,v 1.4 93/09/11 03:13:51 leres Exp (LBL)
|
||||
* $Id: bootp.c,v 1.1 1994/05/08 16:11:17 brezak Exp $
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "stand.h"
|
||||
#include "net.h"
|
||||
#include "netif.h"
|
||||
#include "bootp.h"
|
||||
|
||||
static n_long nmask, smask;
|
||||
|
||||
static time_t bot;
|
||||
|
||||
static char vm_rfc1048[4] = VM_RFC1048;
|
||||
static char vm_cmu[4] = VM_CMU;
|
||||
|
||||
/* Local forwards */
|
||||
static int bootpsend __P((struct iodesc *, void *, int));
|
||||
static int bootprecv __P((struct iodesc*, void *, int));
|
||||
static void vend_cmu __P((u_char *));
|
||||
static void vend_rfc1048 __P((u_char *, u_int));
|
||||
|
||||
/* Fetch required bootp infomation */
|
||||
void
|
||||
bootp(sock)
|
||||
int sock;
|
||||
{
|
||||
struct iodesc *d;
|
||||
register struct bootp *bp;
|
||||
register void *pkt;
|
||||
struct {
|
||||
u_char header[HEADER_SIZE];
|
||||
struct bootp wbootp;
|
||||
} wbuf;
|
||||
union {
|
||||
u_char buffer[RECV_SIZE];
|
||||
struct {
|
||||
u_char header[HEADER_SIZE];
|
||||
struct bootp xrbootp;
|
||||
}xrbuf;
|
||||
#define rbootp xrbuf.xrbootp
|
||||
} rbuf;
|
||||
|
||||
#ifdef BOOTP_DEBUG
|
||||
if (debug)
|
||||
printf("bootp: socket=%d\n", sock);
|
||||
#endif
|
||||
if (!bot)
|
||||
bot = getsecs();
|
||||
|
||||
if (!(d = socktodesc(sock))) {
|
||||
printf("bootp: bad socket. %d\n", sock);
|
||||
return;
|
||||
}
|
||||
#ifdef BOOTP_DEBUG
|
||||
if (debug)
|
||||
printf("bootp: d=%x\n", (u_int)d);
|
||||
#endif
|
||||
bp = &wbuf.wbootp;
|
||||
pkt = &rbuf.rbootp;
|
||||
pkt -= HEADER_SIZE;
|
||||
|
||||
bzero(bp, sizeof(*bp));
|
||||
|
||||
bp->bp_op = BOOTREQUEST;
|
||||
bp->bp_htype = 1; /* 10Mb Ethernet (48 bits) */
|
||||
bp->bp_hlen = 6;
|
||||
MACPY(d->myea, bp->bp_chaddr);
|
||||
|
||||
d->xid = 0;
|
||||
d->myip = myip;
|
||||
d->myport = IPPORT_BOOTPC;
|
||||
d->destip = INADDR_BROADCAST;
|
||||
d->destport = IPPORT_BOOTPS;
|
||||
|
||||
(void)sendrecv(d,
|
||||
bootpsend, bp, sizeof(*bp),
|
||||
bootprecv, pkt, RECV_SIZE);
|
||||
}
|
||||
|
||||
/* Transmit a bootp request */
|
||||
static int
|
||||
bootpsend(d, pkt, len)
|
||||
register struct iodesc *d;
|
||||
register void *pkt;
|
||||
register int len;
|
||||
{
|
||||
register struct bootp *bp;
|
||||
|
||||
#ifdef BOOTP_DEBUG
|
||||
if (debug)
|
||||
printf("bootpsend: d=%x called.\n", (u_int)d);
|
||||
#endif
|
||||
bp = pkt;
|
||||
bzero(bp->bp_file, sizeof(bp->bp_file));
|
||||
bcopy(vm_rfc1048, bp->bp_vend, sizeof(long));
|
||||
bp->bp_xid = d->xid;
|
||||
bp->bp_secs = (u_long)(getsecs() - bot);
|
||||
#ifdef BOOTP_DEBUG
|
||||
if (debug)
|
||||
printf("bootpsend: calling sendudp\n");
|
||||
#endif
|
||||
return (sendudp(d, pkt, len));
|
||||
}
|
||||
|
||||
/* Returns 0 if this is the packet we're waiting for else -1 (and errno == 0) */
|
||||
static int
|
||||
bootprecv(d, pkt, len)
|
||||
register struct iodesc *d;
|
||||
register void *pkt;
|
||||
int len;
|
||||
{
|
||||
register struct bootp *bp;
|
||||
|
||||
#ifdef BOOTP_DEBUG
|
||||
if (debug)
|
||||
printf("bootprecv: called\n");
|
||||
#endif
|
||||
bp = (struct bootp *)checkudp(d, pkt, &len);
|
||||
#ifdef BOOTP_DEBUG
|
||||
if (debug)
|
||||
printf("bootprecv: checked. bp = 0x%x, len = %d\n",
|
||||
(unsigned)bp, len);
|
||||
#endif
|
||||
if (bp == NULL || len < sizeof(*bp) || bp->bp_xid != d->xid) {
|
||||
#ifdef BOOTP_DEBUG
|
||||
if (debug) {
|
||||
printf("bootprecv: not for us.\n");
|
||||
if (bp == NULL)
|
||||
printf("bootprecv: bp null\n");
|
||||
else {
|
||||
if (len < sizeof(*bp))
|
||||
printf("bootprecv: expected %d bytes, got %d\n",
|
||||
sizeof(*bp), len);
|
||||
if (bp->bp_xid != d->xid)
|
||||
printf("bootprecv: expected xid 0x%x, got 0x%x\n",
|
||||
d->xid, bp->bp_xid);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
errno = 0;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* Bump xid so next request will be unique */
|
||||
++d->xid;
|
||||
|
||||
#ifdef BOOTP_DEBUG
|
||||
if (debug)
|
||||
printf("bootprecv: got one!\n");
|
||||
#endif
|
||||
|
||||
/* Pick up our ip address (and natural netmask) */
|
||||
myip = d->myip = ntohl(bp->bp_yiaddr.s_addr);
|
||||
#ifdef BOOTP_DEBUG
|
||||
if (debug)
|
||||
printf("our ip address is %s\n", intoa(d->myip));
|
||||
#endif
|
||||
if (IN_CLASSA(d->myip))
|
||||
nmask = IN_CLASSA_NET;
|
||||
else if (IN_CLASSB(d->myip))
|
||||
nmask = IN_CLASSB_NET;
|
||||
else
|
||||
nmask = IN_CLASSC_NET;
|
||||
#ifdef BOOTP_DEBUG
|
||||
if (debug)
|
||||
printf("'native netmask' is %s\n", intoa(nmask));
|
||||
#endif
|
||||
|
||||
/* Pick up root or swap server address and file spec */
|
||||
if (bp->bp_siaddr.s_addr != 0) {
|
||||
rootip = ntohl(bp->bp_siaddr.s_addr);
|
||||
}
|
||||
if (bp->bp_file[0] != '\0') {
|
||||
strncpy(bootfile, (char *)bp->bp_file,
|
||||
sizeof(bootfile));
|
||||
bootfile[sizeof(bootfile) - 1] = '\0';
|
||||
}
|
||||
|
||||
/* Suck out vendor info */
|
||||
if (bcmp(vm_cmu, bp->bp_vend, sizeof(vm_cmu)) == 0)
|
||||
vend_cmu(bp->bp_vend);
|
||||
else if (bcmp(vm_rfc1048, bp->bp_vend, sizeof(vm_rfc1048)) == 0)
|
||||
vend_rfc1048(bp->bp_vend, sizeof(bp->bp_vend));
|
||||
else
|
||||
printf("bootprecv: unknown vendor 0x%x\n", (int)bp->bp_vend);
|
||||
|
||||
/* Check subnet mask against net mask; toss if bogus */
|
||||
if ((nmask & smask) != nmask) {
|
||||
#ifdef BOOTP_DEBUG
|
||||
if (debug)
|
||||
printf("subnet mask (%s) bad\n", intoa(smask));
|
||||
#endif
|
||||
smask = 0;
|
||||
}
|
||||
|
||||
/* Get subnet (or natural net) mask */
|
||||
mask = nmask;
|
||||
if (smask)
|
||||
mask = smask;
|
||||
#ifdef BOOTP_DEBUG
|
||||
if (debug)
|
||||
printf("mask: %s\n", intoa(mask));
|
||||
#endif
|
||||
|
||||
/* We need a gateway if root or swap is on a different net */
|
||||
if (!SAMENET(d->myip, rootip, mask)) {
|
||||
#ifdef BOOTP_DEBUG
|
||||
if (debug)
|
||||
printf("need gateway for root ip\n");
|
||||
#endif
|
||||
}
|
||||
if (!SAMENET(d->myip, swapip, mask)) {
|
||||
#ifdef BOOTP_DEBUG
|
||||
if (debug)
|
||||
printf("need gateway for swap ip\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Toss gateway if on a different net */
|
||||
if (!SAMENET(d->myip, gateip, mask)) {
|
||||
#ifdef BOOTP_DEBUG
|
||||
if (debug)
|
||||
printf("gateway ip (%s) bad\n", intoa(gateip));
|
||||
#endif
|
||||
gateip = 0;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
vend_cmu(cp)
|
||||
u_char *cp;
|
||||
{
|
||||
register struct cmu_vend *vp;
|
||||
|
||||
#ifdef BOOTP_DEBUG
|
||||
if (debug)
|
||||
printf("vend_cmu bootp info.\n");
|
||||
#endif
|
||||
vp = (struct cmu_vend *)cp;
|
||||
|
||||
if (vp->v_smask.s_addr != 0) {
|
||||
smask = ntohl(vp->v_smask.s_addr);
|
||||
}
|
||||
if (vp->v_dgate.s_addr != 0) {
|
||||
gateip = ntohl(vp->v_dgate.s_addr);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
vend_rfc1048(cp, len)
|
||||
register u_char *cp;
|
||||
u_int len;
|
||||
{
|
||||
register u_char *ep;
|
||||
register int size;
|
||||
register u_char tag;
|
||||
|
||||
#ifdef BOOTP_DEBUG
|
||||
if (debug)
|
||||
printf("vend_rfc1048 bootp info. len=%d\n", len);
|
||||
#endif
|
||||
ep = cp + len;
|
||||
|
||||
/* Step over magic cookie */
|
||||
cp += sizeof(long);
|
||||
|
||||
while (cp < ep) {
|
||||
tag = *cp++;
|
||||
size = *cp++;
|
||||
if (tag == TAG_END)
|
||||
break;
|
||||
|
||||
if (tag == TAG_SUBNET_MASK) {
|
||||
bcopy(cp, &smask, sizeof(smask));
|
||||
smask = ntohl(smask);
|
||||
}
|
||||
if (tag == TAG_GATEWAY) {
|
||||
bcopy(cp, &gateip, sizeof(gateip));
|
||||
gateip = ntohl(gateip);
|
||||
}
|
||||
if (tag == TAG_SWAPSERVER) {
|
||||
bcopy(cp, &swapip, sizeof(swapip));
|
||||
swapip = ntohl(swapip);
|
||||
}
|
||||
if (tag == TAG_DOMAIN_SERVER) {
|
||||
bcopy(cp, &nameip, sizeof(nameip));
|
||||
nameip = ntohl(nameip);
|
||||
}
|
||||
if (tag == TAG_ROOTPATH) {
|
||||
strncpy(rootpath, cp, sizeof(rootpath));
|
||||
rootpath[size] = '\0';
|
||||
}
|
||||
if (tag == TAG_HOSTNAME) {
|
||||
strncpy(hostname, cp, sizeof(hostname));
|
||||
hostname[size] = '\0';
|
||||
}
|
||||
if (tag == TAG_DOMAINNAME) {
|
||||
strncpy(domainname, cp, sizeof(domainname));
|
||||
domainname[size] = '\0';
|
||||
}
|
||||
cp += size;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
/* @(#) $Header: /cvsroot/src/sys/lib/libsa/bootp.h,v 1.1 1994/05/08 16:11:18 brezak Exp $ (LBL) */
|
||||
/*
|
||||
* Bootstrap Protocol (BOOTP). RFC951 and RFC1048.
|
||||
*
|
||||
* This file specifies the "implementation-independent" BOOTP protocol
|
||||
* information which is common to both client and server.
|
||||
*
|
||||
* Copyright 1988 by Carnegie Mellon.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this program for any
|
||||
* purpose and without fee is hereby granted, provided that this copyright
|
||||
* and permission notice appear on all copies and supporting documentation,
|
||||
* the name of Carnegie Mellon not be used in advertising or publicity
|
||||
* pertaining to distribution of the program without specific prior
|
||||
* permission, and notice be given in supporting documentation that copying
|
||||
* and distribution is by permission of Carnegie Mellon and Stanford
|
||||
* University. Carnegie Mellon makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as is"
|
||||
* without express or implied warranty.
|
||||
*/
|
||||
|
||||
|
||||
struct bootp {
|
||||
unsigned char bp_op; /* packet opcode type */
|
||||
unsigned char bp_htype; /* hardware addr type */
|
||||
unsigned char bp_hlen; /* hardware addr length */
|
||||
unsigned char bp_hops; /* gateway hops */
|
||||
unsigned long bp_xid; /* transaction ID */
|
||||
unsigned short bp_secs; /* seconds since boot began */
|
||||
unsigned short bp_unused;
|
||||
struct in_addr bp_ciaddr; /* client IP address */
|
||||
struct in_addr bp_yiaddr; /* 'your' IP address */
|
||||
struct in_addr bp_siaddr; /* server IP address */
|
||||
struct in_addr bp_giaddr; /* gateway IP address */
|
||||
unsigned char bp_chaddr[16]; /* client hardware address */
|
||||
unsigned char bp_sname[64]; /* server host name */
|
||||
unsigned char bp_file[128]; /* boot file name */
|
||||
unsigned char bp_vend[64]; /* vendor-specific area */
|
||||
};
|
||||
|
||||
/*
|
||||
* UDP port numbers, server and client.
|
||||
*/
|
||||
#define IPPORT_BOOTPS 67
|
||||
#define IPPORT_BOOTPC 68
|
||||
|
||||
#define BOOTREPLY 2
|
||||
#define BOOTREQUEST 1
|
||||
|
||||
|
||||
/*
|
||||
* Vendor magic cookie (v_magic) for CMU
|
||||
*/
|
||||
#define VM_CMU "CMU"
|
||||
|
||||
/*
|
||||
* Vendor magic cookie (v_magic) for RFC1048
|
||||
*/
|
||||
#define VM_RFC1048 { 99, 130, 83, 99 }
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* RFC1048 tag values used to specify what information is being supplied in
|
||||
* the vendor field of the packet.
|
||||
*/
|
||||
|
||||
#define TAG_PAD ((unsigned char) 0)
|
||||
#define TAG_SUBNET_MASK ((unsigned char) 1)
|
||||
#define TAG_TIME_OFFSET ((unsigned char) 2)
|
||||
#define TAG_GATEWAY ((unsigned char) 3)
|
||||
#define TAG_TIME_SERVER ((unsigned char) 4)
|
||||
#define TAG_NAME_SERVER ((unsigned char) 5)
|
||||
#define TAG_DOMAIN_SERVER ((unsigned char) 6)
|
||||
#define TAG_LOG_SERVER ((unsigned char) 7)
|
||||
#define TAG_COOKIE_SERVER ((unsigned char) 8)
|
||||
#define TAG_LPR_SERVER ((unsigned char) 9)
|
||||
#define TAG_IMPRESS_SERVER ((unsigned char) 10)
|
||||
#define TAG_RLP_SERVER ((unsigned char) 11)
|
||||
#define TAG_HOSTNAME ((unsigned char) 12)
|
||||
#define TAG_BOOTSIZE ((unsigned char) 13)
|
||||
#define TAG_DUMPFILE ((unsigned char) 14)
|
||||
#define TAG_DOMAINNAME ((unsigned char) 15)
|
||||
#define TAG_SWAPSERVER ((unsigned char) 16)
|
||||
#define TAG_ROOTPATH ((unsigned char) 17)
|
||||
#define TAG_END ((unsigned char) 255)
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* "vendor" data permitted for CMU bootp clients.
|
||||
*/
|
||||
|
||||
struct cmu_vend {
|
||||
unsigned char v_magic[4]; /* magic number */
|
||||
unsigned long v_flags; /* flags/opcodes, etc. */
|
||||
struct in_addr v_smask; /* Subnet mask */
|
||||
struct in_addr v_dgate; /* Default gateway */
|
||||
struct in_addr v_dns1, v_dns2; /* Domain name servers */
|
||||
struct in_addr v_ins1, v_ins2; /* IEN-116 name servers */
|
||||
struct in_addr v_ts1, v_ts2; /* Time servers */
|
||||
unsigned char v_unused[25]; /* currently unused */
|
||||
};
|
||||
|
||||
|
||||
/* v_flags values */
|
||||
#define VF_SMASK 1 /* Subnet mask field contains valid data */
|
|
@ -61,7 +61,7 @@
|
|||
* any improvements or extensions that they make and grant Carnegie the
|
||||
* rights to redistribute these changes.
|
||||
*
|
||||
* $Id: close.c,v 1.1 1994/01/26 02:03:38 brezak Exp $
|
||||
* $Id: close.c,v 1.2 1994/05/08 16:11:19 brezak Exp $
|
||||
*/
|
||||
|
||||
#include "stand.h"
|
||||
|
@ -70,7 +70,7 @@ close(fd)
|
|||
int fd;
|
||||
{
|
||||
register struct open_file *f = &files[fd];
|
||||
int err1, err2;
|
||||
int err1 = 0, err2 = 0;
|
||||
|
||||
if ((unsigned)fd >= SOPEN_MAX || f->f_flags == 0) {
|
||||
errno = EBADF;
|
||||
|
@ -78,7 +78,8 @@ close(fd)
|
|||
}
|
||||
if (!(f->f_flags & F_RAW))
|
||||
err1 = (f->f_ops->close)(f);
|
||||
err2 = (f->f_dev->dv_close)(f);
|
||||
if (!(f->f_flags & F_NODEV))
|
||||
err2 = (f->f_dev->dv_close)(f);
|
||||
f->f_flags = 0;
|
||||
if (err1) {
|
||||
errno = err1;
|
||||
|
@ -96,7 +97,7 @@ closeall()
|
|||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < SOPEN_MAX; i++)
|
||||
if (files[i].f_flags != 0)
|
||||
(void)close(i);
|
||||
for (i = 0; i < SOPEN_MAX; i++)
|
||||
if (files[i].f_flags != 0)
|
||||
(void)close(i);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Copyright (c) 1992 Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by the Computer Systems Engineering group
|
||||
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
|
||||
* contributed to Berkeley.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Lawrence Berkeley Laboratory and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from @(#) Header: net.c,v 1.9 93/08/06 19:32:15 leres Exp (LBL)
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/socket.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <net/if.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/if_ether.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
|
||||
#include "stand.h"
|
||||
#include "net.h"
|
||||
#include "netif.h"
|
||||
|
||||
const u_char bcea[6] = {
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
||||
};
|
||||
|
||||
/* Caller must leave room for ethernet header in front!! */
|
||||
int
|
||||
sendether(d, buf, len, dea, etype)
|
||||
struct iodesc *d;
|
||||
void *buf;
|
||||
int len;
|
||||
u_char *dea;
|
||||
int etype;
|
||||
{
|
||||
register struct ether_header *eh;
|
||||
|
||||
#ifdef ETHER_DEBUG
|
||||
if (debug)
|
||||
printf("sendether: called\n");
|
||||
#endif
|
||||
eh = ((struct ether_header *)buf) - 1;
|
||||
len += ETHER_SIZE;
|
||||
|
||||
MACPY(d->myea, eh->ether_shost); /* by byte */
|
||||
MACPY(dea, eh->ether_dhost); /* by byte */
|
||||
eh->ether_type = htons(etype);
|
||||
return (netif_put(d, eh, len) - ETHER_SIZE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert Ethernet address to printable (loggable) representation.
|
||||
*/
|
||||
static char digits[] = "0123456789abcdef";
|
||||
char *
|
||||
ether_sprintf(ap)
|
||||
register u_char *ap;
|
||||
{
|
||||
register i;
|
||||
static char etherbuf[18];
|
||||
register char *cp = etherbuf;
|
||||
|
||||
for (i = 0; i < 6; i++) {
|
||||
*cp++ = digits[*ap >> 4];
|
||||
*cp++ = digits[*ap++ & 0xf];
|
||||
*cp++ = ':';
|
||||
}
|
||||
*--cp = 0;
|
||||
return (etherbuf);
|
||||
}
|
|
@ -0,0 +1,155 @@
|
|||
/*-
|
||||
* Copyright (c) 1982, 1986, 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: exec.c,v 1.1 1994/05/08 16:11:21 brezak Exp $
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/reboot.h>
|
||||
#include <a.out.h>
|
||||
|
||||
#include "stand.h"
|
||||
|
||||
static char *ssym, *esym;
|
||||
|
||||
extern u_int opendev;
|
||||
|
||||
int
|
||||
exec(path, loadaddr, howto)
|
||||
char *path;
|
||||
char *loadaddr;
|
||||
int howto;
|
||||
{
|
||||
register int io;
|
||||
struct exec x;
|
||||
int i;
|
||||
register char *addr;
|
||||
|
||||
if (machdep_exec(path, loadaddr, howto) < 0)
|
||||
return(0);
|
||||
|
||||
io = open(path, 0);
|
||||
if (io < 0)
|
||||
return(io);
|
||||
|
||||
i = read(io, (char *)&x, sizeof(x));
|
||||
if (i != sizeof(x) ||
|
||||
N_BADMAG(x)) {
|
||||
printf("exec: %s: Bad format\n", path);
|
||||
errno = ENOEXEC;
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* Text */
|
||||
printf("%d", x.a_text);
|
||||
addr = loadaddr;
|
||||
#ifdef NO_LSEEK
|
||||
if (N_GETMAGIC(x) == ZMAGIC && read(io, (char *)addr, 0x400) == -1)
|
||||
#else
|
||||
if (N_GETMAGIC(x) == ZMAGIC && lseek(io, 0x400, SEEK_SET) == -1)
|
||||
#endif
|
||||
goto shread;
|
||||
if (read(io, (char *)addr, x.a_text) != x.a_text)
|
||||
goto shread;
|
||||
addr += x.a_text;
|
||||
if (N_GETMAGIC(x) == ZMAGIC || N_GETMAGIC(x) == NMAGIC)
|
||||
while ((int)addr & CLOFSET)
|
||||
*addr++ = 0;
|
||||
/* Data */
|
||||
printf("+%d", x.a_data);
|
||||
if (read(io, addr, x.a_data) != x.a_data)
|
||||
goto shread;
|
||||
addr += x.a_data;
|
||||
|
||||
/* Bss */
|
||||
printf("+%d", x.a_bss);
|
||||
for (i = 0; i < x.a_bss; i++)
|
||||
*addr++ = 0;
|
||||
|
||||
/* Symbols */
|
||||
ssym = addr;
|
||||
bcopy(&x.a_syms, addr, sizeof(x.a_syms));
|
||||
addr += sizeof(x.a_syms);
|
||||
printf(" [%d+", x.a_syms);
|
||||
if (read(io, addr, x.a_syms) != x.a_syms)
|
||||
goto shread;
|
||||
addr += x.a_syms;
|
||||
|
||||
if (read(io, &i, sizeof(int)) != sizeof(int))
|
||||
goto shread;
|
||||
|
||||
bcopy(&i, addr, sizeof(int));
|
||||
if (i) {
|
||||
i -= sizeof(int);
|
||||
addr += sizeof(int);
|
||||
if (read(io, addr, i) != i)
|
||||
goto shread;
|
||||
addr += i;
|
||||
}
|
||||
|
||||
/* and that many bytes of (debug symbols?) */
|
||||
|
||||
printf("%d] ", i);
|
||||
|
||||
#define round_to_size(x) \
|
||||
(((int)(x) + sizeof(int) - 1) & ~(sizeof(int) - 1))
|
||||
esym = (char *)round_to_size(addr - loadaddr);
|
||||
#undef round_to_size
|
||||
|
||||
/* and note the end address of all this */
|
||||
printf("total=0x%x ", (u_int)addr);
|
||||
|
||||
x.a_entry += (int)loadaddr;
|
||||
printf(" start 0x%x\n", x.a_entry);
|
||||
|
||||
#ifdef EXEC_DEBUG
|
||||
printf("ssym=0x%x esym=0x%x\n", ssym, esym);
|
||||
printf("\n\nReturn to boot...\n");
|
||||
getchar();
|
||||
#endif
|
||||
|
||||
machdep_start((char *)x.a_entry, howto, loadaddr, ssym, esym);
|
||||
|
||||
/* exec failed */
|
||||
printf("exec: %s: Cannot exec\n", path);
|
||||
errno = ENOEXEC;
|
||||
return(-1);
|
||||
|
||||
shread:
|
||||
close(io);
|
||||
printf("exec: %s: Short read\n", path);
|
||||
errno = EIO;
|
||||
return(-1);
|
||||
}
|
|
@ -16,7 +16,7 @@
|
|||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
|
@ -25,26 +25,37 @@
|
|||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "$Id: exit.c,v 1.1 1994/01/26 02:03:43 brezak Exp $";
|
||||
static char rcsid[] = "$Id: exit.c,v 1.2 1994/05/08 16:11:22 brezak Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
void
|
||||
#ifdef __STDC__
|
||||
panic(const char *fmt, ...)
|
||||
#else
|
||||
panic(fmt /*, va_alist */)
|
||||
char *fmt;
|
||||
#endif
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
static int paniced;
|
||||
|
||||
if (!paniced) {
|
||||
paniced = 1;
|
||||
closeall();
|
||||
}
|
||||
|
||||
va_start(ap, fmt);
|
||||
printf(fmt, ap);
|
||||
printf("\n");
|
||||
va_end(ap);
|
||||
_rtt();
|
||||
}
|
||||
|
||||
exit()
|
||||
{
|
||||
panic("exit");
|
||||
}
|
||||
|
||||
panic(str)
|
||||
char *str;
|
||||
{
|
||||
static int paniced;
|
||||
|
||||
if (!paniced) {
|
||||
paniced = 1;
|
||||
closeall();
|
||||
}
|
||||
|
||||
printf("%s\n",str);
|
||||
_rtt();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* globals.c:
|
||||
*
|
||||
* global variables should be separate, so nothing else
|
||||
* must be included extraneously.
|
||||
*
|
||||
* $Id: globals.c,v 1.1 1994/05/08 16:11:23 brezak Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
|
||||
#include "stand.h"
|
||||
#include "net.h"
|
||||
|
||||
u_char bcea[6] = BA; /* broadcast ethernet address */
|
||||
|
||||
char rootpath[FNAME_SIZE] = "/"; /* root mount path */
|
||||
char bootfile[FNAME_SIZE]; /* bootp says to boot this */
|
||||
char hostname[FNAME_SIZE]; /* our hostname */
|
||||
char domainname[FNAME_SIZE]; /* our DNS domain */
|
||||
char ifname[IFNAME_SIZE]; /* name of interface (e.g. "le0") */
|
||||
n_long nameip; /* DNS server ip address */
|
||||
n_long rootip; /* root ip address */
|
||||
n_long swapip; /* swap ip address */
|
||||
n_long gateip; /* swap ip address */
|
||||
n_long mask = 0xffffff00; /* subnet or net mask */
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Copyright (c) 1992 Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by the Computer Systems Engineering group
|
||||
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
|
||||
* contributed to Berkeley.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Lawrence Berkeley Laboratory and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from @(#) Header: in_cksum.c,v 1.1 92/09/11 01:15:55 leres Exp (LBL)
|
||||
* $Id: in_cksum.c,v 1.1 1994/05/08 16:11:24 brezak Exp $
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
/*
|
||||
* Checksum routine for Internet Protocol family headers.
|
||||
* This routine is very heavily used in the network
|
||||
* code and should be modified for each CPU to be as fast as possible.
|
||||
* In particular, it should not be this one.
|
||||
*/
|
||||
int
|
||||
in_cksum(p, len)
|
||||
register void *p;
|
||||
register int len;
|
||||
{
|
||||
register int sum = 0, oddbyte = 0, v = 0;
|
||||
register u_char *cp = p;
|
||||
|
||||
/* we assume < 2^16 bytes being summed */
|
||||
while (len > 0) {
|
||||
if (oddbyte) {
|
||||
sum += v + *cp++;
|
||||
len--;
|
||||
}
|
||||
if (((int)cp & 1) == 0) {
|
||||
while ((len -= 2) >= 0) {
|
||||
sum += *(u_short *)cp;
|
||||
cp += 2;
|
||||
}
|
||||
} else {
|
||||
while ((len -= 2) >= 0) {
|
||||
sum += *cp++ << 8;
|
||||
sum += *cp++;
|
||||
}
|
||||
}
|
||||
if ((oddbyte = len & 1) != 0)
|
||||
v = *cp << 8;
|
||||
}
|
||||
if (oddbyte)
|
||||
sum += v;
|
||||
sum = (sum >> 16) + (sum & 0xffff); /* add in accumulated carries */
|
||||
sum += sum >> 16; /* add potential last carry */
|
||||
return (0xffff & ~sum);
|
||||
}
|
|
@ -61,11 +61,12 @@
|
|||
* any improvements or extensions that they make and grant Carnegie the
|
||||
* rights to redistribute these changes.
|
||||
*
|
||||
* $Id: ioctl.c,v 1.1 1994/01/26 02:03:48 brezak Exp $
|
||||
* $Id: ioctl.c,v 1.2 1994/05/08 16:11:25 brezak Exp $
|
||||
*/
|
||||
|
||||
#include "stand.h"
|
||||
|
||||
int
|
||||
ioctl(fd, cmd, arg)
|
||||
int fd;
|
||||
int cmd;
|
||||
|
@ -83,5 +84,6 @@ ioctl(fd, cmd, arg)
|
|||
return (-1);
|
||||
return (0);
|
||||
}
|
||||
errno = EIO;
|
||||
return (-1);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright (c) 1993 Adam Glass
|
||||
* Copyright (c) 1992 Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by the Computer Systems Engineering group
|
||||
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
|
||||
* contributed to Berkeley.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Lawrence Berkeley Laboratory and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: iodesc.h,v 1.1 1994/05/08 16:11:26 brezak Exp $
|
||||
*/
|
||||
|
||||
#ifndef __SYS_LIBNETBOOT_IODESC_H
|
||||
#define __SYS_LIBNETBOOT_IODESC_H
|
||||
|
||||
struct iodesc {
|
||||
n_long destip; /* destination ip address */
|
||||
n_long myip; /* my ip address */
|
||||
u_short destport; /* destination port */
|
||||
u_short myport; /* destination port */
|
||||
u_long xid; /* transaction identification */
|
||||
u_char myea[6]; /* my ethernet address */
|
||||
struct netif *io_netif;
|
||||
};
|
||||
|
||||
#endif /* __SYS_LIBNETBOOT_IODESC_H */
|
|
@ -0,0 +1,393 @@
|
|||
/*
|
||||
* Copyright (c) 1992 Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by the Computer Systems Engineering group
|
||||
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
|
||||
* contributed to Berkeley.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Lawrence Berkeley Laboratory and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from @(#) Header: net.c,v 1.9 93/08/06 19:32:15 leres Exp (LBL)
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <net/if.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/if_ether.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip_var.h>
|
||||
#include <netinet/udp.h>
|
||||
#include <netinet/udp_var.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "stand.h"
|
||||
#include "net.h"
|
||||
#include "netif.h"
|
||||
|
||||
n_long myip;
|
||||
|
||||
/* Caller must leave room for ethernet, ip and udp headers in front!! */
|
||||
int
|
||||
sendudp(d, buf, len)
|
||||
register struct iodesc *d;
|
||||
register void *buf;
|
||||
register int len;
|
||||
{
|
||||
register int cc;
|
||||
register struct ip *ip;
|
||||
register struct udpiphdr *ui;
|
||||
register struct udphdr *uh;
|
||||
register u_char *ea;
|
||||
struct ip tip;
|
||||
|
||||
#ifdef NET_DEBUG
|
||||
if (debug) {
|
||||
printf("sendudp: d=%x called.\n", (u_int)d);
|
||||
if (d) {
|
||||
printf("saddr: %s:%d",
|
||||
intoa(d->myip), d->myport);
|
||||
printf(" daddr: %s:%d\n",
|
||||
intoa(d->destip), d->destport);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
uh = ((struct udphdr *)buf) - 1;
|
||||
ip = ((struct ip *)uh) - 1;
|
||||
len += sizeof(*ip) + sizeof(*uh);
|
||||
|
||||
bzero(ip, sizeof(*ip) + sizeof(*uh));
|
||||
|
||||
ip->ip_v = IPVERSION; /* half-char */
|
||||
ip->ip_hl = sizeof(*ip) >> 2; /* half-char */
|
||||
ip->ip_len = htons(len);
|
||||
ip->ip_p = IPPROTO_UDP; /* char */
|
||||
ip->ip_ttl = IP_TTL; /* char */
|
||||
ip->ip_src.s_addr = htonl(d->myip);
|
||||
ip->ip_dst.s_addr = htonl(d->destip);
|
||||
ip->ip_sum = in_cksum(ip, sizeof(*ip)); /* short, but special */
|
||||
|
||||
uh->uh_sport = htons(d->myport);
|
||||
uh->uh_dport = htons(d->destport);
|
||||
uh->uh_ulen = htons(len - sizeof(*ip));
|
||||
|
||||
/* Calculate checksum (must save and restore ip header) */
|
||||
tip = *ip;
|
||||
ui = (struct udpiphdr *)ip;
|
||||
ui->ui_next = 0;
|
||||
ui->ui_prev = 0;
|
||||
ui->ui_x1 = 0;
|
||||
ui->ui_len = uh->uh_ulen;
|
||||
uh->uh_sum = in_cksum(ui, len);
|
||||
*ip = tip;
|
||||
|
||||
if (ip->ip_dst.s_addr == INADDR_BROADCAST || ip->ip_src.s_addr == 0 ||
|
||||
mask == 0 || SAMENET(ip->ip_src.s_addr, ip->ip_dst.s_addr, mask))
|
||||
ea = arpwhohas(d, ip->ip_dst.s_addr);
|
||||
else
|
||||
ea = arpwhohas(d, htonl(gateip));
|
||||
|
||||
cc = sendether(d, ip, len, ea, ETHERTYPE_IP);
|
||||
if (cc < 0)
|
||||
return (cc);
|
||||
if (cc != len)
|
||||
panic("sendudp: bad write (%d != %d)", cc, len);
|
||||
return (cc - (sizeof(*ip) + sizeof(*uh)));
|
||||
}
|
||||
|
||||
/* Check that packet is a valid udp packet for us */
|
||||
void *
|
||||
checkudp(d, pkt, lenp)
|
||||
register struct iodesc *d;
|
||||
register void *pkt;
|
||||
register int *lenp;
|
||||
{
|
||||
register int hlen, len;
|
||||
register struct ether_header *eh;
|
||||
register struct ip *ip;
|
||||
register struct udphdr *uh;
|
||||
register struct udpiphdr *ui;
|
||||
struct ip tip;
|
||||
|
||||
#ifdef NET_DEBUG
|
||||
if (debug)
|
||||
printf("checkudp: called\n");
|
||||
#endif
|
||||
eh = pkt;
|
||||
ip = (struct ip *)(eh + 1);
|
||||
uh = (struct udphdr *)(ip + 1);
|
||||
|
||||
/* Must be to us */
|
||||
if (bcmp(d->myea, eh->ether_dhost, 6) != 0 && /* by byte */
|
||||
bcmp(bcea, eh->ether_dhost, 6) != 0) { /* by byte */
|
||||
#ifdef NET_DEBUG
|
||||
if (debug)
|
||||
printf("checkudp: not ours. myea=%s bcea=%s\n",
|
||||
ether_sprintf(d->myea), ether_sprintf(bcea));
|
||||
#endif
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* And ip */
|
||||
if (ntohs(eh->ether_type) != ETHERTYPE_IP) {
|
||||
#ifdef NET_DEBUG
|
||||
if (debug)
|
||||
printf("checkudp: not IP. ether_type=%x\n", eh->ether_type);
|
||||
#endif
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Check ip header */
|
||||
if (ip->ip_v != IPVERSION || ip->ip_p != IPPROTO_UDP) { /* half char */
|
||||
#ifdef NET_DEBUG
|
||||
if (debug)
|
||||
printf("checkudp: IP version or not UDP. ip_v=%d ip_p=%d\n", ip->ip_v, ip->ip_p);
|
||||
#endif
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
hlen = ip->ip_hl << 2;
|
||||
if (hlen < sizeof(*ip) || in_cksum(ip, hlen) != 0) {
|
||||
#ifdef NET_DEBUG
|
||||
if (debug)
|
||||
printf("checkudp: short hdr or bad cksum.\n");
|
||||
#endif
|
||||
return (NULL);
|
||||
}
|
||||
NTOHS(ip->ip_len);
|
||||
if (*lenp - sizeof(*eh) < ip->ip_len) {
|
||||
#ifdef NET_DEBUG
|
||||
if (debug)
|
||||
printf("checkudp: bad length %d < %d.\n",
|
||||
*lenp - sizeof(*eh), ip->ip_len);
|
||||
#endif
|
||||
return (NULL);
|
||||
}
|
||||
if (d->myip && ntohl(ip->ip_dst.s_addr) != d->myip) {
|
||||
#ifdef NET_DEBUG
|
||||
if (debug) {
|
||||
printf("checkudp: bad saddr %s != ",
|
||||
intoa(d->myip));
|
||||
printf("%s\n",
|
||||
intoa(ntohl(ip->ip_dst.s_addr)));
|
||||
}
|
||||
#endif
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* If there were ip options, make them go away */
|
||||
if (hlen != sizeof(*ip)) {
|
||||
bcopy(((u_char *)ip) + hlen, uh,
|
||||
*lenp - (sizeof(*eh) + hlen));
|
||||
ip->ip_len = sizeof(*ip);
|
||||
*lenp -= hlen - sizeof(*ip);
|
||||
}
|
||||
if (ntohs(uh->uh_dport) != d->myport) {
|
||||
#ifdef NET_DEBUG
|
||||
if (debug)
|
||||
printf("checkudp: bad dport %d != %d\n",
|
||||
d->myport, ntohs(uh->uh_dport));
|
||||
#endif
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (uh->uh_sum) {
|
||||
len = ntohs(uh->uh_ulen);
|
||||
if (len > RECV_SIZE - (sizeof(*eh) + sizeof(*ip))) {
|
||||
printf("checkudp: huge packet, udp len %d\n", len);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Check checksum (must save and restore ip header) */
|
||||
tip = *ip;
|
||||
ui = (struct udpiphdr *)ip;
|
||||
ui->ui_next = 0;
|
||||
ui->ui_prev = 0;
|
||||
ui->ui_x1 = 0;
|
||||
ui->ui_len = uh->uh_ulen;
|
||||
if (in_cksum(ui, len + sizeof(*ip)) != 0) {
|
||||
#ifdef NET_DEBUG
|
||||
if (debug)
|
||||
printf("checkudp: bad cksum\n");
|
||||
#endif
|
||||
*ip = tip;
|
||||
return (NULL);
|
||||
}
|
||||
*ip = tip;
|
||||
}
|
||||
NTOHS(uh->uh_dport);
|
||||
NTOHS(uh->uh_sport);
|
||||
NTOHS(uh->uh_ulen);
|
||||
if (uh->uh_ulen < sizeof(*uh)) {
|
||||
#ifdef NET_DEBUG
|
||||
if (debug)
|
||||
printf("checkudp: bad udp len %d < %d\n",
|
||||
uh->uh_ulen, sizeof(*uh));
|
||||
#endif
|
||||
return (NULL);
|
||||
}
|
||||
*lenp -= sizeof(*eh) + sizeof(*ip) + sizeof(*uh);
|
||||
return (uh + 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a packet and wait for a reply, with exponential backoff.
|
||||
*
|
||||
* The send routine must return the actual number of bytes written.
|
||||
*
|
||||
* The receive routine can indicate success by returning the number of
|
||||
* bytes read; it can return 0 to indicate EOF; it can return -1 with a
|
||||
* non-zero errno to indicate failure; finally, it can return -1 with a
|
||||
* zero errno to indicate it isn't done yet.
|
||||
*/
|
||||
int
|
||||
sendrecv(d, sproc, sbuf, ssize, rproc, rbuf, rsize)
|
||||
register struct iodesc *d;
|
||||
register int (*sproc)(struct iodesc *, void *, int);
|
||||
register void *sbuf;
|
||||
register int ssize;
|
||||
register int (*rproc)(struct iodesc *, void *, int);
|
||||
register void *rbuf;
|
||||
register int rsize;
|
||||
{
|
||||
register int cc;
|
||||
register time_t t, tmo, tlast, tleft;
|
||||
|
||||
#ifdef NET_DEBUG
|
||||
if (debug)
|
||||
printf("sendrecv: called\n");
|
||||
#endif
|
||||
tmo = MINTMO;
|
||||
tlast = tleft = 0;
|
||||
t = getsecs();
|
||||
for (;;) {
|
||||
if (tleft <= 0) {
|
||||
cc = (*sproc)(d, sbuf, ssize);
|
||||
if (cc < ssize)
|
||||
panic("sendrecv: short write! (%d < %d)",
|
||||
cc, ssize);
|
||||
|
||||
tleft = tmo;
|
||||
tmo <<= 1;
|
||||
if (tmo > MAXTMO)
|
||||
tmo = MAXTMO;
|
||||
tlast = t;
|
||||
}
|
||||
|
||||
cc = netif_get(d, rbuf, rsize, tleft);
|
||||
if (cc >= 0) {
|
||||
/* Got a packet, process it */
|
||||
cc = (*rproc)(d, rbuf, cc);
|
||||
/* Return on data, EOF or real error */
|
||||
if (cc >= 0 || errno != 0)
|
||||
return (cc);
|
||||
}
|
||||
/* Timed out or didn't get the packet we're waiting for */
|
||||
t = getsecs();
|
||||
tleft -= t - tlast;
|
||||
tlast = t;
|
||||
}
|
||||
}
|
||||
|
||||
/* Similar to inet_ntoa() */
|
||||
char *
|
||||
intoa(addr)
|
||||
n_long addr;
|
||||
{
|
||||
register char *cp;
|
||||
register u_int byte;
|
||||
register int n;
|
||||
static char buf[17]; /* strlen(".255.255.255.255") + 1 */
|
||||
|
||||
cp = &buf[sizeof buf];
|
||||
*--cp = '\0';
|
||||
|
||||
n = 4;
|
||||
do {
|
||||
byte = addr & 0xff;
|
||||
*--cp = byte % 10 + '0';
|
||||
byte /= 10;
|
||||
if (byte > 0) {
|
||||
*--cp = byte % 10 + '0';
|
||||
byte /= 10;
|
||||
if (byte > 0)
|
||||
*--cp = byte + '0';
|
||||
}
|
||||
*--cp = '.';
|
||||
addr >>= 8;
|
||||
} while (--n > 0);
|
||||
|
||||
return (cp+1);
|
||||
}
|
||||
|
||||
static char *
|
||||
number(s, n)
|
||||
char *s;
|
||||
int *n;
|
||||
{
|
||||
for (*n = 0; isdigit(*s); s++)
|
||||
*n = (*n * 10) + *s - '0';
|
||||
return s;
|
||||
}
|
||||
|
||||
n_long
|
||||
ip_convertaddr(p)
|
||||
char *p;
|
||||
{
|
||||
#define IP_ANYADDR 0
|
||||
n_long addr = 0, n;
|
||||
|
||||
if (p == (char *)0 || *p == '\0')
|
||||
return IP_ANYADDR;
|
||||
p = number(p, &n);
|
||||
addr |= (n << 24) & 0xff000000;
|
||||
if (*p == '\0' || *p++ != '.')
|
||||
return IP_ANYADDR;
|
||||
p = number(p, &n);
|
||||
addr |= (n << 16) & 0xff0000;
|
||||
if (*p == '\0' || *p++ != '.')
|
||||
return IP_ANYADDR;
|
||||
p = number(p, &n);
|
||||
addr |= (n << 8) & 0xff00;
|
||||
if (*p == '\0' || *p++ != '.')
|
||||
return IP_ANYADDR;
|
||||
p = number(p, &n);
|
||||
addr |= n & 0xff;
|
||||
if (*p != '\0')
|
||||
return IP_ANYADDR;
|
||||
|
||||
return ntohl(addr);
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* Copyright (c) 1993 Adam Glass
|
||||
* Copyright (c) 1992 Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by the Computer Systems Engineering group
|
||||
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
|
||||
* contributed to Berkeley.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Lawrence Berkeley Laboratory and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: net.h,v 1.1 1994/05/08 16:11:28 brezak Exp $
|
||||
*/
|
||||
|
||||
#include "iodesc.h"
|
||||
|
||||
#define BA { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }
|
||||
|
||||
/* Returns true if n_long's on the same net */
|
||||
#define SAMENET(a1, a2, m) ((a1 & m) == (a2 & m))
|
||||
|
||||
#define MACPY(s, d) bcopy((char *)s, (char *)d, 6)
|
||||
|
||||
#define MAXTMO 20 /* seconds */
|
||||
#define MINTMO 2 /* seconds */
|
||||
|
||||
#define FNAME_SIZE 128
|
||||
#define IFNAME_SIZE 16
|
||||
#define RECV_SIZE 1536 /* XXX delete this */
|
||||
|
||||
/* Size of struct ether_header + struct ip + struct udphdr */
|
||||
#define ETHER_SIZE 14
|
||||
#define HEADER_SIZE (ETHER_SIZE + 20 + 8)
|
||||
|
||||
extern u_char bcea[6];
|
||||
extern char rootpath[FNAME_SIZE];
|
||||
extern char bootfile[FNAME_SIZE];
|
||||
extern char hostname[FNAME_SIZE];
|
||||
extern char domainname[FNAME_SIZE];
|
||||
extern char ifname[IFNAME_SIZE];
|
||||
|
||||
extern n_long myip;
|
||||
extern n_long rootip;
|
||||
extern n_long swapip;
|
||||
extern n_long gateip;
|
||||
extern n_long nameip;
|
||||
extern n_long mask;
|
||||
|
||||
extern int debug; /* defined in the machdep sources */
|
||||
|
||||
extern struct iodesc sockets[SOPEN_MAX];
|
||||
|
||||
/* ARP functions: */
|
||||
|
||||
u_char *arpwhohas __P((struct iodesc *, n_long));
|
||||
|
||||
int sendether __P((struct iodesc *, void *, int, u_char *, int));
|
||||
int sendudp __P((struct iodesc *, void *, int));
|
||||
int recvudp __P((struct iodesc *, void *, int, time_t));
|
||||
int sendrecv __P((struct iodesc *, int (*)(struct iodesc *, void *, int),
|
||||
void *, int, int (*)(struct iodesc *, void *, int), void *, int));
|
||||
void *checkudp __P((struct iodesc *, void *, int *));
|
||||
|
||||
/* utilties: */
|
||||
|
||||
char *ether_sprintf __P((u_char *));
|
||||
int in_cksum __P((void *, int));
|
||||
char *intoa __P((n_long)); /* similar to inet_ntoa */
|
||||
|
||||
/* Machine-dependent functions: */
|
||||
|
||||
time_t getsecs __P((void));
|
|
@ -0,0 +1,329 @@
|
|||
/*
|
||||
* Copyright (c) 1993 Adam Glass
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Adam Glass.
|
||||
* 4. The name of the Author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY Adam Glass ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: netif.c,v 1.1 1994/05/08 16:11:29 brezak Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/mount.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
|
||||
#include "stand.h"
|
||||
#include "net.h"
|
||||
#include "netif.h"
|
||||
|
||||
struct iodesc sockets[SOPEN_MAX];
|
||||
|
||||
/*
|
||||
* netif_init:
|
||||
*
|
||||
* initialize the generic network interface layer
|
||||
*/
|
||||
|
||||
void
|
||||
netif_init()
|
||||
{
|
||||
struct netif_driver *drv;
|
||||
int d, i;
|
||||
|
||||
#ifdef NETIF_DEBUG
|
||||
if (netif_debug)
|
||||
printf("netif_init: called\n");
|
||||
#endif
|
||||
for (d = 0; d < n_netif_drivers; d++) {
|
||||
drv = netif_drivers[d];
|
||||
for (i = 0; i < drv->netif_nifs; i++)
|
||||
drv->netif_ifs[i].dif_used = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
netif_match(nif, machdep_hint)
|
||||
struct netif *nif;
|
||||
void *machdep_hint;
|
||||
{
|
||||
struct netif_driver *drv = nif->nif_driver;
|
||||
|
||||
#if 0
|
||||
if (netif_debug)
|
||||
printf("%s%d: netif_match (%d)\n", drv->netif_bname,
|
||||
nif->nif_unit, nif->nif_sel);
|
||||
#endif
|
||||
return drv->netif_match(nif, machdep_hint);
|
||||
}
|
||||
|
||||
struct netif *
|
||||
netif_select(machdep_hint)
|
||||
void *machdep_hint;
|
||||
{
|
||||
int d, u, unit_done, s;
|
||||
struct netif_driver *drv;
|
||||
struct netif cur_if;
|
||||
static struct netif best_if;
|
||||
int best_val;
|
||||
int val;
|
||||
|
||||
best_val = 0;
|
||||
best_if.nif_driver = NULL;
|
||||
|
||||
#ifdef NETIF_DEBUG
|
||||
if (netif_debug)
|
||||
printf("netif_select: %d interfaces\n", n_netif_drivers);
|
||||
#endif
|
||||
|
||||
for (d = 0; d < n_netif_drivers; d++) {
|
||||
cur_if.nif_driver = netif_drivers[d];
|
||||
drv = cur_if.nif_driver;
|
||||
|
||||
for (u = 0; u < drv->netif_nifs; u++) {
|
||||
cur_if.nif_unit = u;
|
||||
unit_done = 0;
|
||||
|
||||
#ifdef NETIF_DEBUG
|
||||
if (netif_debug)
|
||||
printf("\t%s%d:", drv->netif_bname,
|
||||
cur_if.nif_unit);
|
||||
#endif
|
||||
|
||||
for (s = 0; s < drv->netif_ifs[u].dif_nsel; s++) {
|
||||
cur_if.nif_sel = s;
|
||||
|
||||
if (drv->netif_ifs[u].dif_used & (1 << s)) {
|
||||
#ifdef NETIF_DEBUG
|
||||
if (netif_debug)
|
||||
printf(" [%d used]", s);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
val = netif_match(&cur_if, machdep_hint);
|
||||
#ifdef NETIF_DEBUG
|
||||
if (netif_debug)
|
||||
printf(" [%d -> %d]", s, val);
|
||||
#endif
|
||||
if (val > best_val) {
|
||||
best_val = val;
|
||||
best_if = cur_if;
|
||||
}
|
||||
}
|
||||
#ifdef NETIF_DEBUG
|
||||
if (netif_debug)
|
||||
printf("\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (best_if.nif_driver == NULL)
|
||||
return NULL;
|
||||
|
||||
best_if.nif_driver->
|
||||
netif_ifs[best_if.nif_unit].dif_used |= (1 << best_if.nif_sel);
|
||||
|
||||
#ifdef NETIF_DEBUG
|
||||
if (netif_debug)
|
||||
printf("netif_select: %s%d(%d) wins\n",
|
||||
best_if.nif_driver->netif_bname,
|
||||
best_if.nif_unit, best_if.nif_sel);
|
||||
#endif
|
||||
return &best_if;
|
||||
}
|
||||
|
||||
int
|
||||
netif_probe(nif, machdep_hint)
|
||||
struct netif *nif;
|
||||
void *machdep_hint;
|
||||
{
|
||||
struct netif_driver *drv = nif->nif_driver;
|
||||
|
||||
#ifdef NETIF_DEBUG
|
||||
if (netif_debug)
|
||||
printf("%s%d: netif_probe\n", drv->netif_bname, nif->nif_unit);
|
||||
#endif
|
||||
return drv->netif_probe(nif, machdep_hint);
|
||||
}
|
||||
|
||||
void
|
||||
netif_attach(nif, desc, machdep_hint)
|
||||
struct netif *nif;
|
||||
struct iodesc *desc;
|
||||
void *machdep_hint;
|
||||
{
|
||||
struct netif_driver *drv = nif->nif_driver;
|
||||
|
||||
#ifdef NETIF_DEBUG
|
||||
if (netif_debug)
|
||||
printf("%s%d: netif_attach\n", drv->netif_bname, nif->nif_unit);
|
||||
#endif
|
||||
desc->io_netif = nif;
|
||||
#ifdef PARANOID
|
||||
if (drv->netif_init == NULL)
|
||||
panic("%s%d: no netif_init support\n", drv->netif_bname,
|
||||
nif->nif_unit);
|
||||
#endif
|
||||
drv->netif_init(desc, machdep_hint);
|
||||
bzero(drv->netif_ifs[nif->nif_unit].dif_stats,
|
||||
sizeof(struct netif_stats));
|
||||
}
|
||||
|
||||
void
|
||||
netif_detach(nif)
|
||||
struct netif *nif;
|
||||
{
|
||||
struct netif_driver *drv = nif->nif_driver;
|
||||
|
||||
#ifdef NETIF_DEBUG
|
||||
if (netif_debug)
|
||||
printf("%s%d: netif_detach\n", drv->netif_bname, nif->nif_unit);
|
||||
#endif
|
||||
#ifdef PARANOID
|
||||
if (drv->netif_end == NULL)
|
||||
panic("%s%d: no netif_end support\n", drv->netif_bname,
|
||||
nif->nif_unit);
|
||||
#endif
|
||||
drv->netif_end(nif);
|
||||
}
|
||||
|
||||
int
|
||||
netif_get(desc, pkt, len, timo)
|
||||
struct iodesc *desc;
|
||||
void *pkt;
|
||||
int len;
|
||||
time_t timo;
|
||||
{
|
||||
struct netif *nif = desc->io_netif;
|
||||
struct netif_driver *drv = desc->io_netif->nif_driver;
|
||||
int rv;
|
||||
|
||||
#ifdef NETIF_DEBUG
|
||||
if (netif_debug)
|
||||
printf("%s%d: netif_get\n", drv->netif_bname, nif->nif_unit);
|
||||
#endif
|
||||
#ifdef PARANOID
|
||||
if (drv->netif_get == NULL)
|
||||
panic("%s%d: no netif_get support\n", drv->netif_bname,
|
||||
nif->nif_unit);
|
||||
#endif
|
||||
rv = drv->netif_get(desc, pkt, len, timo);
|
||||
#ifdef NETIF_DEBUG
|
||||
if (netif_debug)
|
||||
printf("%s%d: netif_get returning %d\n", drv->netif_bname,
|
||||
nif->nif_unit, rv);
|
||||
#endif
|
||||
return rv;
|
||||
}
|
||||
|
||||
int
|
||||
netif_put(desc, pkt, len)
|
||||
struct iodesc *desc;
|
||||
void *pkt;
|
||||
int len;
|
||||
{
|
||||
struct netif *nif = desc->io_netif;
|
||||
struct netif_driver *drv = desc->io_netif->nif_driver;
|
||||
int rv;
|
||||
|
||||
#ifdef NETIF_DEBUG
|
||||
if (netif_debug)
|
||||
printf("%s%d: netif_put\n", drv->netif_bname, nif->nif_unit);
|
||||
#endif
|
||||
#ifdef PARANOID
|
||||
if (drv->netif_put == NULL)
|
||||
panic("%s%d: no netif_put support\n", drv->netif_bname,
|
||||
nif->nif_unit);
|
||||
#endif
|
||||
rv = drv->netif_put(desc, pkt, len);
|
||||
#ifdef NETIF_DEBUG
|
||||
if (netif_debug)
|
||||
printf("%s%d: netif_put returning %d\n", drv->netif_bname,
|
||||
nif->nif_unit, rv);
|
||||
#endif
|
||||
return rv;
|
||||
}
|
||||
|
||||
struct iodesc *
|
||||
socktodesc(sock)
|
||||
int sock;
|
||||
{
|
||||
if (sock >= SOPEN_MAX) {
|
||||
return(NULL);
|
||||
}
|
||||
return (&sockets[sock]);
|
||||
}
|
||||
|
||||
int
|
||||
netif_open(machdep_hint)
|
||||
void *machdep_hint;
|
||||
{
|
||||
int fd;
|
||||
register struct iodesc *s;
|
||||
struct netif *nif;
|
||||
|
||||
/* find a free socket */
|
||||
for (fd = 0, s = sockets; fd < SOPEN_MAX; fd++, s++)
|
||||
if (s->io_netif == (struct netif *)0)
|
||||
goto fnd;
|
||||
return (-1);
|
||||
|
||||
fnd:
|
||||
bzero(s, sizeof(*s));
|
||||
netif_init();
|
||||
nif = netif_select(machdep_hint);
|
||||
if (!nif)
|
||||
panic("netboot: no interfaces left untried");
|
||||
if (netif_probe(nif, machdep_hint)) {
|
||||
printf("netboot: couldn't probe %s%d\n",
|
||||
nif->nif_driver->netif_bname, nif->nif_unit);
|
||||
errno = EINVAL;
|
||||
return(-1);
|
||||
}
|
||||
netif_attach(nif, s, machdep_hint);
|
||||
|
||||
return(fd);
|
||||
}
|
||||
|
||||
int
|
||||
netif_close(sock)
|
||||
int sock;
|
||||
{
|
||||
if (sock >= SOPEN_MAX) {
|
||||
errno = EBADF;
|
||||
return(-1);
|
||||
}
|
||||
netif_detach(sockets[sock].io_netif);
|
||||
sockets[sock].io_netif = (struct netif *)0;
|
||||
|
||||
return(0);
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
|
||||
#ifndef __SYS_LIBNETBOOT_NETIF_H
|
||||
#define __SYS_LIBNETBOOT_NETIF_H
|
||||
#include "iodesc.h"
|
||||
|
||||
#define NENTS(x) sizeof(x)/sizeof(x[0])
|
||||
|
||||
struct netif_driver {
|
||||
char *netif_bname;
|
||||
int (*netif_match) __P((struct netif *, void *));
|
||||
int (*netif_probe) __P((struct netif *, void *));
|
||||
void (*netif_init) __P((struct iodesc *, void *));
|
||||
int (*netif_get) __P((struct iodesc *, void *, int, time_t));
|
||||
int (*netif_put) __P((struct iodesc *, void *, int));
|
||||
void (*netif_end) __P((struct netif *));
|
||||
struct netif_dif *netif_ifs;
|
||||
int netif_nifs;
|
||||
};
|
||||
|
||||
struct netif_dif {
|
||||
int dif_unit;
|
||||
int dif_nsel;
|
||||
struct netif_stats *dif_stats;
|
||||
void *dif_private;
|
||||
/* the following fields are used internally by the netif layer */
|
||||
u_long dif_used;
|
||||
};
|
||||
|
||||
struct netif_stats {
|
||||
int collisions;
|
||||
int collision_error;
|
||||
int missed;
|
||||
int sent;
|
||||
int received;
|
||||
int deferred;
|
||||
int overflow;
|
||||
};
|
||||
|
||||
struct netif {
|
||||
struct netif_driver *nif_driver;
|
||||
int nif_unit;
|
||||
int nif_sel;
|
||||
};
|
||||
|
||||
extern struct netif_driver *netif_drivers[]; /* machdep */
|
||||
extern int n_netif_drivers;
|
||||
|
||||
extern int netif_debug;
|
||||
|
||||
void netif_init __P((void));
|
||||
struct netif *netif_select __P((void *));
|
||||
int netif_probe __P((struct netif *, void *));
|
||||
void netif_attach __P((struct netif *, struct iodesc *, void *));
|
||||
void netif_detach __P((struct netif *));
|
||||
int netif_get __P((struct iodesc *, void *, int, time_t));
|
||||
int netif_put __P((struct iodesc *, void *, int));
|
||||
|
||||
int netif_open __P((void *));
|
||||
int netif_close __P((int));
|
||||
|
||||
struct iodesc *socktodesc __P((int));
|
||||
|
||||
#endif /* __SYS_LIBNETBOOT_NETIF_H */
|
|
@ -0,0 +1,720 @@
|
|||
/*-
|
||||
* Copyright (c) 1993 John Brezak
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $Id: nfs.c,v 1.1 1994/05/08 16:11:31 brezak Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
|
||||
#include <nfs/rpcv2.h>
|
||||
#include <nfs/nfsv2.h>
|
||||
#undef NFSX_FATTR
|
||||
|
||||
#include "stand.h"
|
||||
#include "net.h"
|
||||
#include "netif.h"
|
||||
#include "nfs.h"
|
||||
#include "rpc.h"
|
||||
|
||||
struct nfs_call_data {
|
||||
u_char fh[NFS_FHSIZE];
|
||||
u_long off;
|
||||
u_long len;
|
||||
u_long xxx; /* XXX what's this for? */
|
||||
};
|
||||
|
||||
/* Data part of nfs rpc reply (also the largest thing we receive) */
|
||||
struct nfs_reply_data {
|
||||
u_long errno;
|
||||
#ifndef NFSX_FATTR
|
||||
struct nfsv2_fattr fa;
|
||||
#else
|
||||
u_char fa[NFSX_FATTR(0)];
|
||||
#endif
|
||||
u_long count;
|
||||
u_char data[1200];
|
||||
};
|
||||
#define NFSREAD_SIZE sizeof(((struct nfs_reply_data *)0)->data)
|
||||
|
||||
/* max number of nfs reads pending */
|
||||
#define NFS_COUNT 10
|
||||
|
||||
static struct nfsstate {
|
||||
u_long off;
|
||||
u_long len;
|
||||
int done;
|
||||
void *addr;
|
||||
u_long xid;
|
||||
} nfsstate[NFS_COUNT];
|
||||
|
||||
static u_long nfscc;
|
||||
|
||||
struct nfs_iodesc {
|
||||
off_t off;
|
||||
size_t size;
|
||||
u_char *fh;
|
||||
struct iodesc *iodesc;
|
||||
};
|
||||
|
||||
/* Fetch (mount) file handle */
|
||||
static int
|
||||
getmountfh(d, path, fhp)
|
||||
register struct iodesc *d;
|
||||
char *path;
|
||||
u_char *fhp;
|
||||
{
|
||||
register int len;
|
||||
struct {
|
||||
u_long len;
|
||||
char path[FNAME_SIZE];
|
||||
} sdata;
|
||||
struct {
|
||||
u_long errno;
|
||||
u_char fh[NFS_FHSIZE];
|
||||
} rdata;
|
||||
int cc;
|
||||
|
||||
#ifdef NFS_DEBUG
|
||||
if (debug)
|
||||
printf("getmountfh: called\n");
|
||||
#endif
|
||||
bzero(&sdata, sizeof(sdata));
|
||||
len = strlen(path);
|
||||
if (len > sizeof(sdata.path))
|
||||
len = sizeof(sdata.path);
|
||||
bcopy(path, sdata.path, len);
|
||||
sdata.len = htonl(len);
|
||||
len = sizeof(sdata) - sizeof(sdata.path) + roundup(len, sizeof(long));
|
||||
|
||||
if ((cc = callrpc(d, RPCPROG_MNT, RPCMNT_VER1, RPCMNT_MOUNT,
|
||||
&sdata, len, &rdata, sizeof(rdata))) < 0)
|
||||
return(-1);
|
||||
if (cc < sizeof(rdata.errno))
|
||||
panic("getmountfh: callrpc small read");
|
||||
if (rdata.errno) {
|
||||
errno = ntohl(rdata.errno);
|
||||
return(-1);
|
||||
}
|
||||
bcopy(rdata.fh, fhp, sizeof(rdata.fh));
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Fetch file timestamp and size */
|
||||
static int
|
||||
getnfsinfo(d, tp, sp, fp, mp, up, gp)
|
||||
register struct nfs_iodesc *d;
|
||||
register time_t *tp;
|
||||
u_long *sp, *fp;
|
||||
mode_t *mp;
|
||||
uid_t *up;
|
||||
gid_t *gp;
|
||||
{
|
||||
register int rlen;
|
||||
register u_long t;
|
||||
struct {
|
||||
u_long errno;
|
||||
struct nfsv2_fattr fa;
|
||||
} rdata;
|
||||
int cc;
|
||||
|
||||
#ifdef NFS_DEBUG
|
||||
if (debug)
|
||||
printf("getnfsinfo: called\n");
|
||||
#endif
|
||||
rlen = sizeof(rdata);
|
||||
#if 0
|
||||
#ifdef NFSX_FATTR
|
||||
#if NFSX_FATTR(1) > NFSX_FATTR(0)
|
||||
/* nqnfs makes this more painful than it needs to be */
|
||||
rlen -= NFSX_FATTR(1) - NFSX_FATTR(0);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
if ((cc = callrpc(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_GETATTR,
|
||||
d->fh, NFS_FHSIZE, &rdata, rlen)) < 0)
|
||||
return(-1);
|
||||
if (cc < sizeof(rdata.errno))
|
||||
panic("getnfsinfo: callrpc small read");
|
||||
if (rdata.errno) {
|
||||
errno = ntohl(rdata.errno);
|
||||
return(-1);
|
||||
}
|
||||
if (tp) {
|
||||
*tp = ntohl(rdata.fa.fa_mtime.tv_sec);
|
||||
t = ntohl(rdata.fa.fa_atime.tv_sec);
|
||||
if (*tp < t)
|
||||
*tp = t;
|
||||
}
|
||||
if (sp)
|
||||
*sp = ntohl(rdata.fa.fa_size);
|
||||
if (fp)
|
||||
*fp = ntohl(rdata.fa.fa_type);
|
||||
if (mp)
|
||||
*mp = ntohl(rdata.fa.fa_mode);
|
||||
if (up)
|
||||
*up = ntohl(rdata.fa.fa_uid);
|
||||
if (gp)
|
||||
*gp = ntohl(rdata.fa.fa_gid);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Lookup a file. Optionally return timestamp and size */
|
||||
static int
|
||||
lookupfh(d, name, fhp, tp, sp, fp)
|
||||
struct nfs_iodesc *d;
|
||||
char *name;
|
||||
u_char *fhp;
|
||||
time_t *tp;
|
||||
u_long *sp, *fp;
|
||||
{
|
||||
register int len, rlen;
|
||||
struct {
|
||||
u_char fh[NFS_FHSIZE];
|
||||
u_long len;
|
||||
char name[FNAME_SIZE];
|
||||
} sdata;
|
||||
struct {
|
||||
u_long errno;
|
||||
u_char fh[NFS_FHSIZE];
|
||||
struct nfsv2_fattr fa;
|
||||
} rdata;
|
||||
int cc;
|
||||
|
||||
#ifdef NFS_DEBUG
|
||||
if (debug)
|
||||
printf("lookupfh: called\n");
|
||||
#endif
|
||||
|
||||
bzero(&sdata, sizeof(sdata));
|
||||
bcopy(d->fh, sdata.fh, sizeof(sdata.fh));
|
||||
len = strlen(name);
|
||||
if (len > sizeof(sdata.name))
|
||||
len = sizeof(sdata.name);
|
||||
bcopy(name, sdata.name, len);
|
||||
sdata.len = htonl(len);
|
||||
len = sizeof(sdata) - sizeof(sdata.name) + roundup(len, sizeof(long));
|
||||
|
||||
rlen = sizeof(rdata);
|
||||
#if 0
|
||||
#ifdef NFSX_FATTR
|
||||
#if NFSX_FATTR(1) > NFSX_FATTR(0)
|
||||
/* nqnfs makes this more painful than it needs to be */
|
||||
rlen -= NFSX_FATTR(1) - NFSX_FATTR(0);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
if ((cc = callrpc(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_LOOKUP,
|
||||
&sdata, len, &rdata, rlen)) < 0)
|
||||
return (-1);
|
||||
if (cc < sizeof(rdata.errno))
|
||||
panic("lookupfh: callrpc small read");
|
||||
if (rdata.errno) {
|
||||
errno = ntohl(rdata.errno);
|
||||
return(-1);
|
||||
}
|
||||
bcopy(rdata.fh, fhp, sizeof(rdata.fh));
|
||||
if (tp)
|
||||
*tp = ntohl(rdata.fa.fa_ctime.tv_sec);
|
||||
if (sp)
|
||||
*sp = ntohl(rdata.fa.fa_size);
|
||||
if (fp)
|
||||
*fp = ntohl(rdata.fa.fa_type);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
sendreaddata(d, pkt, len)
|
||||
register struct nfs_iodesc *d;
|
||||
register void *pkt;
|
||||
register int len;
|
||||
{
|
||||
register int i;
|
||||
register u_long cc;
|
||||
register struct rpc_call *rpc;
|
||||
register struct nfs_call_data *nfs;
|
||||
register struct nfsstate *ns;
|
||||
|
||||
#ifdef NFS_DEBUG
|
||||
if (debug)
|
||||
printf("sendreaddata: called\n");
|
||||
#endif
|
||||
|
||||
if (len != sizeof(*rpc) + sizeof(*nfs))
|
||||
panic("sendreaddata: bad buffer (%d != %d)",
|
||||
len, sizeof(*rpc) + sizeof(*nfs));
|
||||
rpc = pkt;
|
||||
nfs = (struct nfs_call_data *)(rpc + 1);
|
||||
for (i = 0, ns = nfsstate; i < NFS_COUNT; ++i, ++ns) {
|
||||
if (ns->done)
|
||||
continue;
|
||||
|
||||
rpc->rp_xid = ns->xid;
|
||||
nfs->off = htonl(ns->off);
|
||||
nfs->len = htonl(ns->len);
|
||||
cc = sendudp(d->iodesc, rpc, len);
|
||||
|
||||
if (cc != len)
|
||||
panic("sendreaddata: short write (%d != %d)", cc, len);
|
||||
}
|
||||
/* XXX we may have actually sent a lot more bytes... */
|
||||
|
||||
return (len);
|
||||
}
|
||||
|
||||
/* Returns char count if done else -1 (and errno == 0) */
|
||||
static int
|
||||
recvreaddata(d, pkt, len)
|
||||
register struct nfs_iodesc *d;
|
||||
register void *pkt;
|
||||
int len;
|
||||
{
|
||||
register int i;
|
||||
register struct rpc_reply *rpc;
|
||||
register struct nfs_reply_data *nfs;
|
||||
register struct nfsstate *ns;
|
||||
|
||||
#ifdef NFS_DEBUG
|
||||
if (debug)
|
||||
printf("recvreaddata: called\n");
|
||||
#endif
|
||||
rpc = (struct rpc_reply *)checkudp(d->iodesc, pkt, &len);
|
||||
if (rpc == NULL || len < sizeof(*rpc)) {
|
||||
errno = 0;
|
||||
return (-1);
|
||||
}
|
||||
len -= sizeof(*rpc);
|
||||
|
||||
NTOHL(rpc->rp_direction);
|
||||
NTOHL(rpc->rp_stat);
|
||||
|
||||
if (rpc->rp_direction != REPLY || rpc->rp_stat != MSG_ACCEPTED) {
|
||||
errno = 0;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
for (i = 0, ns = nfsstate; i < NFS_COUNT; ++i, ++ns)
|
||||
if (rpc->rp_xid == ns->xid)
|
||||
break;
|
||||
if (i >= NFS_COUNT) {
|
||||
errno = 0;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (ns->done) {
|
||||
errno = 0;
|
||||
return (-1);
|
||||
}
|
||||
#ifdef NFS_DEBUG
|
||||
if (debug)
|
||||
printf("recvreaddata: ns=%x\n", (u_int)ns);
|
||||
#endif
|
||||
nfs = (struct nfs_reply_data *)(rpc + 1);
|
||||
if (len < sizeof(nfs->errno))
|
||||
panic("recvreaddata: bad read %d", len);
|
||||
if (nfs->errno) {
|
||||
errno = ntohl(nfs->errno);
|
||||
return (-1);
|
||||
}
|
||||
if (len < sizeof(*nfs) - sizeof(nfs->data))
|
||||
panic("recvreaddata: less than nfs sized %d", len);
|
||||
len -= sizeof(*nfs) - sizeof(nfs->data);
|
||||
|
||||
if (len < nfs->count)
|
||||
panic("recvreaddata: short read (%d < %d)", len, nfs->count);
|
||||
len = nfs->count;
|
||||
if (len > ns->len)
|
||||
panic("recvreaddata: huge read (%d > %d)", len, ns->len);
|
||||
|
||||
|
||||
#ifdef NFS_DEBUG
|
||||
if (debug)
|
||||
printf("recvreaddata: read %d bytes.\n", len);
|
||||
#endif
|
||||
bcopy(nfs->data, ns->addr, len);
|
||||
ns->done = 1;
|
||||
nfscc += len;
|
||||
|
||||
if (len < ns->len) {
|
||||
/* If first packet assume no more data to read */
|
||||
if (i == 0)
|
||||
return (0);
|
||||
|
||||
/* Short read, assume we are at EOF */
|
||||
++i;
|
||||
++ns;
|
||||
while (i < NFS_COUNT) {
|
||||
ns->done = 1;
|
||||
++i;
|
||||
++ns;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0, ns = nfsstate; i < NFS_COUNT; ++i, ++ns)
|
||||
if (!ns->done) {
|
||||
errno = 0;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* Return data count (thus indicating success) */
|
||||
return (nfscc);
|
||||
}
|
||||
|
||||
/* Read data from a file */
|
||||
static int
|
||||
readdata(d, off, addr, len)
|
||||
register struct nfs_iodesc *d;
|
||||
register u_long off;
|
||||
register void *addr;
|
||||
register u_long len;
|
||||
{
|
||||
register int i, cc;
|
||||
register struct rpc_call *rpc;
|
||||
register struct nfsstate *ns;
|
||||
struct {
|
||||
u_char header[HEADER_SIZE];
|
||||
struct rpc_call rpc;
|
||||
struct nfs_call_data nfs;
|
||||
} sdata;
|
||||
struct {
|
||||
u_char header[HEADER_SIZE];
|
||||
struct rpc_call rpc;
|
||||
struct nfs_reply_data nfs;
|
||||
} rdata;
|
||||
|
||||
#ifdef NFS_DEBUG
|
||||
if (debug)
|
||||
printf("readdata: addr=%x, off=%d len=%d\n", (u_int)addr, off, len);
|
||||
#endif
|
||||
if (len == 0)
|
||||
return (0);
|
||||
d->iodesc->destport = getport(d->iodesc, NFS_PROG, NFS_VER2);
|
||||
|
||||
bzero(&sdata, sizeof(sdata));
|
||||
|
||||
for (i = 0, ns = nfsstate; i < NFS_COUNT; ++i, ++ns) {
|
||||
if (len <= 0) {
|
||||
ns->done = 1;
|
||||
continue;
|
||||
}
|
||||
ns->done = 0;
|
||||
|
||||
ns->xid = d->iodesc->xid;
|
||||
++d->iodesc->xid;
|
||||
|
||||
ns->off = off;
|
||||
ns->len = len;
|
||||
if (ns->len > NFSREAD_SIZE)
|
||||
ns->len = NFSREAD_SIZE;
|
||||
#ifdef notdef
|
||||
/* XXX to align or not align? It doesn't seem to speed things up... */
|
||||
if ((ns->off % NFSREAD_SIZE) != 0)
|
||||
ns->len -= off % NFSREAD_SIZE;
|
||||
#endif
|
||||
|
||||
off += ns->len;
|
||||
len -= ns->len;
|
||||
|
||||
ns->addr = addr;
|
||||
addr += NFSREAD_SIZE;
|
||||
}
|
||||
|
||||
rpc = &sdata.rpc;
|
||||
rpc->rp_rpcvers = htonl(RPC_MSG_VERSION);
|
||||
rpc->rp_prog = htonl(NFS_PROG);
|
||||
rpc->rp_vers = htonl(NFS_VER2);
|
||||
rpc->rp_proc = htonl(NFSPROC_READ);
|
||||
bcopy(d->fh, sdata.nfs.fh, sizeof(sdata.nfs.fh));
|
||||
|
||||
nfscc = 0;
|
||||
cc = sendrecv(d->iodesc,
|
||||
sendreaddata, &sdata.rpc,
|
||||
sizeof(struct rpc_call) + sizeof(struct nfs_call_data),
|
||||
recvreaddata,
|
||||
((u_char *)&rdata.rpc) - HEADER_SIZE, HEADER_SIZE +
|
||||
sizeof(struct rpc_call) + sizeof(struct nfs_reply_data));
|
||||
return (cc);
|
||||
}
|
||||
|
||||
static struct iodesc *mountfs;
|
||||
static u_char mountfh[NFS_FHSIZE];
|
||||
static time_t mounttime;
|
||||
|
||||
/*
|
||||
* nfs_mount - mount this nfs filesystem to a host
|
||||
*/
|
||||
int
|
||||
nfs_mount(sock, ip, path)
|
||||
int sock;
|
||||
n_long ip;
|
||||
char *path;
|
||||
{
|
||||
struct iodesc *desc;
|
||||
struct nfs_iodesc *fp;
|
||||
u_long ftype;
|
||||
|
||||
if (!(desc = socktodesc(sock))) {
|
||||
errno = EINVAL;
|
||||
return(-1);
|
||||
}
|
||||
bcopy(&desc->myea[4], &desc->myport, 2);
|
||||
desc->destip = ip;
|
||||
getmountfh(desc, path, mountfh);
|
||||
|
||||
fp = alloc(sizeof(struct nfs_iodesc));
|
||||
fp->iodesc = desc;
|
||||
fp->fh = mountfh;
|
||||
fp->off = 0;
|
||||
if (getnfsinfo(fp, &mounttime, NULL, &ftype, NULL, NULL, NULL) < 0) {
|
||||
free(fp, sizeof(struct nfs_iodesc));
|
||||
return(-1);
|
||||
}
|
||||
|
||||
if (ftype != NFDIR) {
|
||||
free(fp, sizeof(struct nfs_iodesc));
|
||||
errno = EINVAL;
|
||||
printf("nfs_mount: bad mount ftype %d", ftype);
|
||||
return(-1);
|
||||
}
|
||||
#ifdef NFS_DEBUG
|
||||
if (debug)
|
||||
printf("nfs_mount: got fh for %s, mtime=%d, ftype=%d\n",
|
||||
path, mounttime, ftype);
|
||||
#endif
|
||||
mountfs = desc;
|
||||
free(fp, sizeof(struct nfs_iodesc));
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Open a file.
|
||||
*/
|
||||
int
|
||||
nfs_open(path, f)
|
||||
char *path;
|
||||
struct open_file *f;
|
||||
{
|
||||
register struct nfs_iodesc *fp;
|
||||
u_char *imagefh;
|
||||
u_long size, ftype;
|
||||
int rc = 0;
|
||||
|
||||
#ifdef NFS_DEBUG
|
||||
if (debug)
|
||||
printf("nfs_open: %s\n", path);
|
||||
#endif
|
||||
if (!mountfs) {
|
||||
errno = EIO;
|
||||
printf("nfs_open: must mount first.\n");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* allocate file system specific data structure */
|
||||
fp = alloc(sizeof(struct nfs_iodesc));
|
||||
fp->iodesc = mountfs;
|
||||
fp->fh = mountfh;
|
||||
fp->off = 0;
|
||||
|
||||
f->f_fsdata = (void *)fp;
|
||||
imagefh = alloc(NFS_FHSIZE);
|
||||
bzero(imagefh, NFS_FHSIZE);
|
||||
|
||||
/* lookup a file handle */
|
||||
rc = lookupfh(fp, path, imagefh, NULL, &size, &ftype);
|
||||
if (rc < 0) {
|
||||
#ifdef NFS_DEBUG
|
||||
if (debug)
|
||||
printf("nfs_open: %s lookupfh failed: %s\n", path, strerror(errno));
|
||||
#endif
|
||||
f->f_fsdata = (void *)0;
|
||||
free(fp, sizeof(struct nfs_iodesc));
|
||||
free(imagefh, NFS_FHSIZE);
|
||||
return(rc);
|
||||
}
|
||||
fp->fh = imagefh;
|
||||
|
||||
#ifdef NFS_DEBUG
|
||||
if (debug)
|
||||
printf("nfs_open: %s success, size=%d ftype=%d\n",
|
||||
path, size, ftype);
|
||||
#endif
|
||||
fp->size = size;
|
||||
|
||||
return(rc);
|
||||
}
|
||||
|
||||
int
|
||||
nfs_close(f)
|
||||
struct open_file *f;
|
||||
{
|
||||
register struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata;
|
||||
|
||||
#ifdef NFS_DEBUG
|
||||
if (debug)
|
||||
printf("nfs_close: called\n");
|
||||
#endif
|
||||
f->f_fsdata = (void *)0;
|
||||
if (fp == (struct nfs_iodesc *)0)
|
||||
return (0);
|
||||
|
||||
free(fp->fh, NFS_FHSIZE);
|
||||
free(fp, sizeof(struct nfs_iodesc));
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* read a portion of a file
|
||||
*/
|
||||
int
|
||||
nfs_read(f, addr, size, resid)
|
||||
struct open_file *f;
|
||||
char *addr;
|
||||
u_int size;
|
||||
u_int *resid; /* out */
|
||||
{
|
||||
register struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata;
|
||||
register int cc;
|
||||
|
||||
#ifdef NFS_DEBUG
|
||||
if (debug)
|
||||
printf("nfs_read: size=%d off=%d\n", size, fp->off);
|
||||
#endif
|
||||
while (size > 0) {
|
||||
cc = readdata(fp->iodesc, fp->off, (void *)addr, size);
|
||||
if (cc <= 0) {
|
||||
/* XXX maybe should retry on certain errors */
|
||||
if (cc < 0) {
|
||||
#ifdef NFS_DEBUG
|
||||
if (debug)
|
||||
printf("nfs_read: read: %s",
|
||||
strerror(errno));
|
||||
#endif
|
||||
return (-1);
|
||||
}
|
||||
if (debug)
|
||||
printf("nfs_read: hit EOF unexpectantly");
|
||||
goto ret;
|
||||
}
|
||||
fp->off += cc;
|
||||
addr += cc;
|
||||
size -= cc;
|
||||
}
|
||||
ret:
|
||||
if (resid)
|
||||
*resid = size;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Not implemented.
|
||||
*/
|
||||
int
|
||||
nfs_write(f, start, size, resid)
|
||||
struct open_file *f;
|
||||
char *start;
|
||||
u_int size;
|
||||
u_int *resid; /* out */
|
||||
{
|
||||
errno = EROFS;
|
||||
|
||||
return (-1);
|
||||
}
|
||||
|
||||
off_t
|
||||
nfs_seek(f, offset, where)
|
||||
struct open_file *f;
|
||||
off_t offset;
|
||||
int where;
|
||||
{
|
||||
register struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata;
|
||||
|
||||
switch (where) {
|
||||
case SEEK_SET:
|
||||
fp->off = offset;
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
fp->off += offset;
|
||||
break;
|
||||
case SEEK_END:
|
||||
fp->off = fp->size - offset;
|
||||
break;
|
||||
default:
|
||||
return (-1);
|
||||
}
|
||||
return (fp->off);
|
||||
}
|
||||
|
||||
int
|
||||
nfs_stat(f, sb)
|
||||
struct open_file *f;
|
||||
struct stat *sb;
|
||||
{
|
||||
register struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata;
|
||||
mode_t mode = 0;
|
||||
u_long ftype = 0;
|
||||
|
||||
#ifdef NFS_DEBUG
|
||||
if (debug)
|
||||
printf("nfs_stat: called\n");
|
||||
#endif
|
||||
if (getnfsinfo(fp, &mounttime, &sb->st_size, &ftype, &mode, &sb->st_uid, &sb->st_gid) < 0)
|
||||
return(-1);
|
||||
|
||||
/* create a mode */
|
||||
switch (ftype) {
|
||||
case NFNON:
|
||||
sb->st_mode = 0;
|
||||
break;
|
||||
case NFREG:
|
||||
sb->st_mode = S_IFREG;
|
||||
break;
|
||||
case NFDIR:
|
||||
sb->st_mode = S_IFDIR;
|
||||
break;
|
||||
case NFBLK:
|
||||
sb->st_mode = S_IFBLK;
|
||||
break;
|
||||
case NFCHR:
|
||||
sb->st_mode = S_IFCHR;
|
||||
break;
|
||||
case NFLNK:
|
||||
sb->st_mode = S_IFLNK;
|
||||
break;
|
||||
}
|
||||
sb->st_mode |= mode;
|
||||
|
||||
return (0);
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*-
|
||||
* Copyright (c) 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: nfs.h,v 1.1 1994/05/08 16:11:32 brezak Exp $
|
||||
*/
|
||||
|
||||
int nfs_open __P((char *path, struct open_file *f));
|
||||
int nfs_close __P((struct open_file *f));
|
||||
int nfs_read __P((struct open_file *f, char *buf,
|
||||
u_int size, u_int *resid));
|
||||
int nfs_write __P((struct open_file *f, char *buf,
|
||||
u_int size, u_int *resid));
|
||||
off_t nfs_seek __P((struct open_file *f, off_t offset, int where));
|
||||
int nfs_stat __P((struct open_file *f, struct stat *sb));
|
|
@ -61,23 +61,17 @@
|
|||
* any improvements or extensions that they make and grant Carnegie the
|
||||
* rights to redistribute these changes.
|
||||
*
|
||||
* $Id: open.c,v 1.2 1994/03/01 20:57:56 pk Exp $
|
||||
* $Id: open.c,v 1.3 1994/05/08 16:11:33 brezak Exp $
|
||||
*/
|
||||
|
||||
#include "stand.h"
|
||||
#include "ufs.h"
|
||||
struct open_file files[SOPEN_MAX];
|
||||
|
||||
/*
|
||||
* File primitives proper
|
||||
*/
|
||||
|
||||
struct fs_ops file_system[] = {
|
||||
{ ufs_open, ufs_close, ufs_read, ufs_write, ufs_seek, ufs_stat }
|
||||
};
|
||||
#define NFSYS (sizeof(file_system) / sizeof(struct fs_ops))
|
||||
|
||||
struct open_file files[SOPEN_MAX];
|
||||
|
||||
int
|
||||
open(fname, mode)
|
||||
char *fname;
|
||||
int mode;
|
||||
|
@ -101,7 +95,8 @@ fnd:
|
|||
f->f_dev = (struct devsw *)0;
|
||||
file = (char *)0;
|
||||
error = devopen(f, fname, &file);
|
||||
if (error || f->f_dev == (struct devsw *)0)
|
||||
if (error ||
|
||||
(((f->f_flags & F_NODEV) == 0) && f->f_dev == (struct devsw *)0))
|
||||
goto err;
|
||||
|
||||
/* see if we opened a raw device; otherwise, 'file' is the file name. */
|
||||
|
@ -111,7 +106,7 @@ fnd:
|
|||
}
|
||||
|
||||
/* pass file name to the different filesystem open routines */
|
||||
for (i = 0; i < NFSYS; i++) {
|
||||
for (i = 0; i < nfsys; i++) {
|
||||
/* convert mode (0,1,2) to FREAD, FWRITE. */
|
||||
error = (file_system[i].open)(file, f);
|
||||
if (error == 0) {
|
||||
|
@ -126,3 +121,42 @@ err:
|
|||
errno = error;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Null filesystem
|
||||
*/
|
||||
int null_open (char *path, struct open_file *f)
|
||||
{
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int null_close(struct open_file *f)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int null_read (struct open_file *f, char *buf, u_int size, u_int *resid)
|
||||
{
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int null_write (struct open_file *f, char *buf, u_int size, u_int *resid)
|
||||
{
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
off_t null_seek (struct open_file *f, off_t offset, int where)
|
||||
{
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int null_stat (struct open_file *f, struct stat *sb)
|
||||
{
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,137 @@
|
|||
#include <sys/param.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <netinet/if_ether.h>
|
||||
#include <netinet/in_systm.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "stand.h"
|
||||
#include "net.h"
|
||||
#include "netif.h"
|
||||
|
||||
static int rarpsend(struct iodesc *, void *, int);
|
||||
static int rarprecv(struct iodesc *, void *, int);
|
||||
|
||||
/*
|
||||
* Ethernet (Reverse) Address Resolution Protocol (see RFC 903, and 826).
|
||||
*/
|
||||
n_long
|
||||
rarp_getipaddress(sock)
|
||||
int sock;
|
||||
{
|
||||
struct iodesc *d;
|
||||
register struct ether_arp *ap;
|
||||
register void *pkt;
|
||||
struct {
|
||||
u_char header[HEADER_SIZE];
|
||||
struct ether_arp wrarp;
|
||||
} wbuf;
|
||||
union {
|
||||
u_char buffer[RECV_SIZE];
|
||||
struct {
|
||||
u_char header[HEADER_SIZE];
|
||||
struct ether_arp xrrarp;
|
||||
}xrbuf;
|
||||
#define rrarp xrbuf.xrrarp
|
||||
} rbuf;
|
||||
|
||||
#ifdef RARP_DEBUG
|
||||
if (debug)
|
||||
printf("rarp: socket=%d\n", sock);
|
||||
#endif
|
||||
if (!(d = socktodesc(sock))) {
|
||||
printf("rarp: bad socket. %d\n", sock);
|
||||
return(INADDR_ANY);
|
||||
}
|
||||
#ifdef RARP_DEBUG
|
||||
if (debug)
|
||||
printf("rarp: d=%x\n", (u_int)d);
|
||||
#endif
|
||||
ap = &wbuf.wrarp;
|
||||
pkt = &rbuf.rrarp;
|
||||
pkt -= HEADER_SIZE;
|
||||
|
||||
bzero(ap, sizeof(*ap));
|
||||
|
||||
ap->arp_hrd = htons(ARPHRD_ETHER);
|
||||
ap->arp_pro = htons(ETHERTYPE_IP);
|
||||
ap->arp_hln = sizeof(ap->arp_sha); /* hardware address length */
|
||||
ap->arp_pln = sizeof(ap->arp_spa); /* protocol address length */
|
||||
ap->arp_op = htons(REVARP_REQUEST);
|
||||
bcopy(d->myea, ap->arp_sha, 6);
|
||||
bcopy(d->myea, ap->arp_tha, 6);
|
||||
|
||||
if (sendrecv(d,
|
||||
rarpsend, ap, sizeof(*ap),
|
||||
rarprecv, pkt, RECV_SIZE) < 0) {
|
||||
printf("No response for RARP request\n");
|
||||
return(INADDR_ANY);
|
||||
}
|
||||
|
||||
return(myip);
|
||||
}
|
||||
|
||||
/*
|
||||
* Broadcast a RARP request (i.e. who knows who I am)
|
||||
*/
|
||||
static int
|
||||
rarpsend(d, pkt, len)
|
||||
register struct iodesc *d;
|
||||
register void *pkt;
|
||||
register int len;
|
||||
{
|
||||
#ifdef RARP_DEBUG
|
||||
if (debug)
|
||||
printf("rarpsend: called\n");
|
||||
#endif
|
||||
return (sendether(d, pkt, len, bcea, ETHERTYPE_REVARP));
|
||||
}
|
||||
|
||||
/*
|
||||
* Called when packet containing RARP is received
|
||||
*/
|
||||
static int
|
||||
rarprecv(d, pkt, len)
|
||||
register struct iodesc *d;
|
||||
register void *pkt;
|
||||
register int len;
|
||||
{
|
||||
register struct ether_header *ep;
|
||||
register struct ether_arp *ap;
|
||||
|
||||
#ifdef RARP_DEBUG
|
||||
if (debug)
|
||||
printf("rarprecv: called\n");
|
||||
#endif
|
||||
if (len < sizeof(struct ether_header) + sizeof(struct ether_arp)) {
|
||||
errno = 0;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
ep = (struct ether_header *)pkt;
|
||||
if (ntohs(ep->ether_type) != ETHERTYPE_REVARP) {
|
||||
errno = 0;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
ap = (struct ether_arp *)(ep + 1);
|
||||
if (ntohs(ap->arp_op) != REVARP_REPLY ||
|
||||
ntohs(ap->arp_pro) != ETHERTYPE_IP) {
|
||||
errno = 0;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (bcmp(ap->arp_tha, d->myea, 6)) {
|
||||
errno = 0;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
bcopy(ap->arp_tpa, (char *)&myip, sizeof(myip));
|
||||
bcopy(ap->arp_spa, (char *)&rootip, sizeof(rootip));
|
||||
|
||||
return(0);
|
||||
}
|
|
@ -0,0 +1,251 @@
|
|||
/*
|
||||
* Copyright (c) 1992 Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by the Computer Systems Engineering group
|
||||
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
|
||||
* contributed to Berkeley.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Lawrence Berkeley Laboratory and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from @(#) Header: rpc.c,v 1.12 93/09/28 08:31:56 leres Exp (LBL)
|
||||
* $Id: rpc.c,v 1.1 1994/05/08 16:11:35 brezak Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
|
||||
#include <nfs/rpcv2.h>
|
||||
#include <nfs/nfsv2.h>
|
||||
#undef NFSX_FATTR
|
||||
#include <string.h>
|
||||
|
||||
#include "stand.h"
|
||||
#include "net.h"
|
||||
#include "netif.h"
|
||||
#include "rpc.h"
|
||||
|
||||
/* XXX Data part of nfs rpc reply (also the largest thing we receive) */
|
||||
struct nfs_reply_data {
|
||||
u_long errno;
|
||||
#ifndef NFSX_FATTR
|
||||
struct nfsv2_fattr fa;
|
||||
#else
|
||||
u_char fa[NFSX_FATTR(0)];
|
||||
#endif
|
||||
u_long count;
|
||||
u_char data[1200];
|
||||
};
|
||||
#define NFSREAD_SIZE sizeof(((struct nfs_reply_data *)0)->data)
|
||||
|
||||
/* Cache stuff */
|
||||
#define PMAP_NUM 8 /* need at most 5 pmap entries */
|
||||
|
||||
static struct pmap_list {
|
||||
u_long addr; /* address of server */
|
||||
u_long prog;
|
||||
u_long vers;
|
||||
u_short port; /* cached port for service */
|
||||
} pmap_list[PMAP_NUM] = {
|
||||
{ 0, PMAPPROG, PMAPVERS, PMAPPORT }
|
||||
};
|
||||
static int pmap_num = 1;
|
||||
|
||||
/* Local forwards */
|
||||
static int recvrpc __P((struct iodesc *, void *, int));
|
||||
|
||||
/* Make a rpc call; return length of answer */
|
||||
int
|
||||
callrpc(d, prog, vers, proc, sdata, slen, rdata, rlen)
|
||||
register struct iodesc *d;
|
||||
register u_long prog, vers, proc;
|
||||
register void *sdata;
|
||||
register int slen;
|
||||
register void *rdata;
|
||||
register int rlen;
|
||||
{
|
||||
register int cc;
|
||||
register struct rpc_call *rpc;
|
||||
struct {
|
||||
u_char header[HEADER_SIZE];
|
||||
struct rpc_call wrpc;
|
||||
u_char data[sizeof(struct nfs_reply_data)]; /* XXX */
|
||||
} wbuf;
|
||||
struct {
|
||||
u_char header[HEADER_SIZE];
|
||||
struct rpc_reply rrpc;
|
||||
union {
|
||||
u_long errno;
|
||||
u_char data[sizeof(struct nfs_reply_data)];
|
||||
} ru;
|
||||
} rbuf;
|
||||
|
||||
#ifdef RPC_DEBUG
|
||||
if (debug)
|
||||
printf("callrpc: called\n");
|
||||
#endif
|
||||
if (rlen > sizeof(rbuf.ru.data))
|
||||
panic("callrpc: huge read (%d > %d)",
|
||||
rlen, sizeof(rbuf.ru.data));
|
||||
|
||||
d->destport = getport(d, prog, vers);
|
||||
|
||||
rpc = &wbuf.wrpc;
|
||||
|
||||
bzero(rpc, sizeof(*rpc));
|
||||
|
||||
rpc->rp_xid = d->xid;
|
||||
rpc->rp_rpcvers = htonl(RPC_MSG_VERSION);
|
||||
rpc->rp_prog = htonl(prog);
|
||||
rpc->rp_vers = htonl(vers);
|
||||
rpc->rp_proc = htonl(proc);
|
||||
bcopy(sdata, wbuf.data, slen);
|
||||
|
||||
cc = sendrecv(d, sendudp, rpc, sizeof(*rpc) + slen, recvrpc,
|
||||
((u_char *)&rbuf.rrpc) - HEADER_SIZE, sizeof(rbuf) - HEADER_SIZE);
|
||||
|
||||
if (cc < rlen) {
|
||||
/* Check for an error return */
|
||||
if (cc >= sizeof(rbuf.ru.errno) && rbuf.ru.errno != 0) {
|
||||
errno = ntohl(rbuf.ru.errno);
|
||||
return (-1);
|
||||
}
|
||||
panic("callrpc: missing data (%d < %d)", cc, rlen);
|
||||
}
|
||||
if (cc > sizeof(rbuf.ru.data))
|
||||
panic("callrpc: huge return (%d > %d)",
|
||||
cc, sizeof(rbuf.ru.data));
|
||||
bcopy(rbuf.ru.data, rdata, cc);
|
||||
return (cc);
|
||||
}
|
||||
|
||||
/* Returns true if packet is the one we're waiting for */
|
||||
static int
|
||||
recvrpc(d, pkt, len)
|
||||
register struct iodesc *d;
|
||||
register void *pkt;
|
||||
int len;
|
||||
{
|
||||
register struct rpc_reply *rpc;
|
||||
|
||||
errno = 0;
|
||||
#ifdef RPC_DEBUG
|
||||
if (debug)
|
||||
printf("recvrpc: called\n");
|
||||
#endif
|
||||
rpc = (struct rpc_reply *)checkudp(d, pkt, &len);
|
||||
if (rpc == NULL || len < sizeof(*rpc)) {
|
||||
#ifdef RPC_DEBUG
|
||||
if (debug)
|
||||
printf("recvrpc: bad response rpc=%x len=%d\n",
|
||||
(u_int)rpc, len);
|
||||
#endif
|
||||
return (-1);
|
||||
}
|
||||
|
||||
NTOHL(rpc->rp_direction);
|
||||
NTOHL(rpc->rp_stat);
|
||||
|
||||
if (rpc->rp_xid != d->xid || rpc->rp_direction != REPLY ||
|
||||
rpc->rp_stat != MSG_ACCEPTED) {
|
||||
#ifdef RPC_DEBUG
|
||||
if (debug) {
|
||||
if (rpc->rp_xid != d->xid)
|
||||
printf("recvrpc: rp_xid %d != xid %d\n",
|
||||
rpc->rp_xid, d->xid);
|
||||
if (rpc->rp_direction != REPLY)
|
||||
printf("recvrpc: %d != REPLY\n", rpc->rp_direction);
|
||||
if (rpc->rp_stat != MSG_ACCEPTED)
|
||||
printf("recvrpc: %d != MSG_ACCEPTED\n", rpc->rp_stat);
|
||||
}
|
||||
#endif
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* Bump xid so next request will be unique */
|
||||
++d->xid;
|
||||
|
||||
/* Return data count (thus indicating success) */
|
||||
return (len - sizeof(*rpc));
|
||||
}
|
||||
|
||||
/* Request a port number from the port mapper */
|
||||
u_short
|
||||
getport(d, prog, vers)
|
||||
register struct iodesc *d;
|
||||
u_long prog;
|
||||
u_long vers;
|
||||
{
|
||||
register int i;
|
||||
register struct pmap_list *pl;
|
||||
u_long port;
|
||||
struct {
|
||||
u_long prog; /* call program */
|
||||
u_long vers; /* call version */
|
||||
u_long proto; /* call protocol */
|
||||
u_long port; /* call port (unused) */
|
||||
} sdata;
|
||||
|
||||
#ifdef RPC_DEBUG
|
||||
if (debug)
|
||||
printf("getport: called\n");
|
||||
#endif
|
||||
/* Try for cached answer first */
|
||||
for (i = 0, pl = pmap_list; i < pmap_num; ++i, ++pl)
|
||||
if ((pl->addr == d->destip || pl->addr == 0) &&
|
||||
pl->prog == prog && pl->vers == vers)
|
||||
return (pl->port);
|
||||
|
||||
/* Don't overflow cache */
|
||||
if (pmap_num > PMAP_NUM - 1)
|
||||
panic("getport: overflowed pmap_list!");
|
||||
|
||||
sdata.prog = htonl(prog);
|
||||
sdata.vers = htonl(vers);
|
||||
sdata.proto = htonl(IPPROTO_UDP);
|
||||
sdata.port = 0;
|
||||
|
||||
if (callrpc(d, PMAPPROG, PMAPVERS, PMAPPROC_GETPORT,
|
||||
&sdata, sizeof(sdata), &port, sizeof(port)) < 0) {
|
||||
printf("getport: %s", strerror(errno));
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* Cache answer */
|
||||
pl->addr = d->destip;
|
||||
pl->prog = prog;
|
||||
pl->vers = vers;
|
||||
pl->port = port;
|
||||
++pmap_num;
|
||||
|
||||
return ((u_short)port);
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Copyright (c) 1992 Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by the Computer Systems Engineering group
|
||||
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
|
||||
* contributed to Berkeley.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Lawrence Berkeley Laboratory and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: rpc.h,v 1.1 1994/05/08 16:11:36 brezak Exp $
|
||||
*/
|
||||
|
||||
/* XXX defines we can't easily get from system includes */
|
||||
#define PMAPPORT 111
|
||||
#define PMAPPROG 100000
|
||||
#define PMAPVERS 2
|
||||
#define PMAPPROC_GETPORT 3
|
||||
|
||||
#define RPC_MSG_VERSION 2
|
||||
#define MSG_ACCEPTED 0
|
||||
#define CALL 0
|
||||
#define REPLY 1
|
||||
|
||||
|
||||
/* Null rpc auth info */
|
||||
struct auth_info {
|
||||
int rp_atype; /* zero (really AUTH_NULL) */
|
||||
u_long rp_alen; /* zero (size of auth struct) */
|
||||
};
|
||||
|
||||
/* Generic rpc call header */
|
||||
struct rpc_call {
|
||||
u_long rp_xid; /* request transaction id */
|
||||
int rp_direction; /* call direction */
|
||||
u_long rp_rpcvers; /* rpc version (2) */
|
||||
u_long rp_prog; /* program */
|
||||
u_long rp_vers; /* version */
|
||||
u_long rp_proc; /* procedure */
|
||||
struct auth_info rp_auth; /* AUTH_NULL */
|
||||
struct auth_info rp_verf; /* AUTH_NULL */
|
||||
};
|
||||
|
||||
/* Generic rpc reply header */
|
||||
struct rpc_reply {
|
||||
u_long rp_xid; /* request transaction id */
|
||||
int rp_direction; /* call direction */
|
||||
int rp_stat; /* accept status */
|
||||
u_long rp_prog; /* program (unused) */
|
||||
u_long rp_vers; /* version (unused) */
|
||||
u_long rp_proc; /* procedure (unused) */
|
||||
};
|
||||
|
||||
/* RPC functions: */
|
||||
int callrpc __P((struct iodesc *d, u_long prog, u_long ver, u_long op,
|
||||
void *sdata, int slen, void *rdata, int rlen));
|
||||
u_short getport __P((struct iodesc *d, u_long prog, u_long vers));
|
||||
|
|
@ -31,7 +31,7 @@
|
|||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)stand.h 8.1 (Berkeley) 6/11/93
|
||||
* $Id: stand.h,v 1.1 1994/01/26 02:03:58 brezak Exp $
|
||||
* $Id: stand.h,v 1.2 1994/05/08 16:11:37 brezak Exp $
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
@ -92,11 +92,13 @@ struct open_file {
|
|||
|
||||
#define SOPEN_MAX 4
|
||||
extern struct open_file files[SOPEN_MAX];
|
||||
extern int nfsys;
|
||||
|
||||
/* f_flags values */
|
||||
#define F_READ 0x0001 /* file opened for reading */
|
||||
#define F_WRITE 0x0002 /* file opened for writing */
|
||||
#define F_RAW 0x0004 /* raw device open - no file system */
|
||||
#define F_NODEV 0x0008 /* network open - no device */
|
||||
|
||||
#define isupper(c) ((c) >= 'A' && (c) <= 'Z')
|
||||
#define tolower(c) ((c) - 'A' + 'a')
|
||||
|
@ -108,5 +110,24 @@ void *alloc __P((unsigned size));
|
|||
void free __P((void *ptr, unsigned size));
|
||||
struct disklabel;
|
||||
char *getdisklabel __P((const char *buf, struct disklabel *lp));
|
||||
|
||||
int printf __P((char *, ...));
|
||||
void panic __P((char *, ...));
|
||||
int getchar __P((void));
|
||||
int exec __P((char *, char *, int));
|
||||
|
||||
int nodev(), noioctl();
|
||||
void nullsys();
|
||||
|
||||
int null_open __P((char *path, struct open_file *f));
|
||||
int null_close __P((struct open_file *f));
|
||||
int null_read __P((struct open_file *f, char *buf,
|
||||
u_int size, u_int *resid));
|
||||
int null_write __P((struct open_file *f, char *buf,
|
||||
u_int size, u_int *resid));
|
||||
off_t null_seek __P((struct open_file *f, off_t offset, int where));
|
||||
int null_stat __P((struct open_file *f, struct stat *sb));
|
||||
|
||||
/* Machine dependant functions */
|
||||
void machdep_start __P((char *, int, char *, char *, char *));
|
||||
int machdep_exec __P((char *, char *, int));
|
||||
|
|
Loading…
Reference in New Issue