Standalone networking for network boot loaders.

This commit is contained in:
brezak 1994-05-08 16:11:14 +00:00
parent 7320b9e43b
commit e03842d0c7
23 changed files with 3330 additions and 40 deletions

View File

@ -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=

217
sys/lib/libsa/arp.c Normal file
View File

@ -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);
}

347
sys/lib/libsa/bootp.c Normal file
View File

@ -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;
}
}

107
sys/lib/libsa/bootp.h Normal file
View File

@ -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 */

View File

@ -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);
}

102
sys/lib/libsa/ether.c Normal file
View File

@ -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);
}

155
sys/lib/libsa/exec.c Normal file
View File

@ -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);
}

View File

@ -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();
}

28
sys/lib/libsa/globals.c Normal file
View File

@ -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 */

82
sys/lib/libsa/in_cksum.c Normal file
View File

@ -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);
}

View File

@ -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);
}

54
sys/lib/libsa/iodesc.h Normal file
View File

@ -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 */

393
sys/lib/libsa/net.c Normal file
View File

@ -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);
}

98
sys/lib/libsa/net.h Normal file
View File

@ -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));

329
sys/lib/libsa/netif.c Normal file
View File

@ -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);
}

63
sys/lib/libsa/netif.h Normal file
View File

@ -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 */

720
sys/lib/libsa/nfs.c Normal file
View File

@ -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);
}

43
sys/lib/libsa/nfs.h Normal file
View File

@ -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));

View File

@ -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;
}

137
sys/lib/libsa/rarp.c Normal file
View File

@ -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);
}

251
sys/lib/libsa/rpc.c Normal file
View File

@ -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);
}

84
sys/lib/libsa/rpc.h Normal file
View File

@ -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));

View File

@ -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));