aboutsummaryrefslogtreecommitdiff
path: root/lib/libstand
diff options
context:
space:
mode:
authorToomas Soome <tsoome@FreeBSD.org>2017-05-06 20:32:27 +0000
committerToomas Soome <tsoome@FreeBSD.org>2017-05-06 20:32:27 +0000
commitda8fb057e520892de8cd09d883c0efa57c4deb66 (patch)
treea59af8376ca6e14eee2cab02ba85af6fa548377b /lib/libstand
parenta872bf12f8c976591eb3150fcbd0509575b917d0 (diff)
Notes
Diffstat (limited to 'lib/libstand')
-rw-r--r--lib/libstand/arp.c54
-rw-r--r--lib/libstand/bootp.c83
-rw-r--r--lib/libstand/bootp.h4
-rw-r--r--lib/libstand/bootparam.c101
-rw-r--r--lib/libstand/ether.c39
-rw-r--r--lib/libstand/net.c10
-rw-r--r--lib/libstand/net.h11
-rw-r--r--lib/libstand/netif.c57
-rw-r--r--lib/libstand/netif.h8
-rw-r--r--lib/libstand/nfs.c147
-rw-r--r--lib/libstand/rarp.c43
-rw-r--r--lib/libstand/rpc.c81
-rw-r--r--lib/libstand/rpc.h2
-rw-r--r--lib/libstand/tftp.c84
-rw-r--r--lib/libstand/udp.c64
15 files changed, 389 insertions, 399 deletions
diff --git a/lib/libstand/arp.c b/lib/libstand/arp.c
index dac8f90886de..841010c3195c 100644
--- a/lib/libstand/arp.c
+++ b/lib/libstand/arp.c
@@ -65,17 +65,16 @@ int arp_num = 1;
/* Local forwards */
static ssize_t arpsend(struct iodesc *, void *, size_t);
-static ssize_t arprecv(struct iodesc *, void *, size_t, time_t);
+static ssize_t arprecv(struct iodesc *, void **, void **, time_t);
/* Broadcast an ARP packet, asking who has addr on interface d */
u_char *
-arpwhohas(d, addr)
- struct iodesc *d;
- struct in_addr addr;
+arpwhohas(struct iodesc *d, struct in_addr addr)
{
int i;
struct ether_arp *ah;
struct arp_list *al;
+ void *pkt;
struct {
struct ether_header eh;
struct {
@@ -83,13 +82,6 @@ arpwhohas(d, addr)
u_char pad[18]; /* 60 - sizeof(...) */
} data;
} wbuf;
- struct {
- struct ether_header eh;
- struct {
- struct ether_arp arp;
- u_char pad[24]; /* extra space */
- } data;
- } rbuf;
/* Try for cached answer first */
for (i = 0, al = arp_list; i < arp_num; ++i, ++al)
@@ -122,20 +114,24 @@ arpwhohas(d, addr)
/* Store ip address in cache (incomplete entry). */
al->addr = addr;
+ pkt = NULL;
+ ah = NULL;
i = sendrecv(d,
arpsend, &wbuf.data, sizeof(wbuf.data),
- arprecv, &rbuf.data, sizeof(rbuf.data));
+ arprecv, &pkt, (void **)&ah);
if (i == -1) {
panic("arp: no response for %s\n",
inet_ntoa(addr));
}
/* Store ethernet address in cache */
- ah = &rbuf.data.arp;
#ifdef ARP_DEBUG
if (debug) {
+ struct ether_header *eh;
+
+ eh = (struct ether_header *)((uintptr_t)pkt + ETHER_ALIGN);
printf("arp: response from %s\n",
- ether_sprintf(rbuf.eh.ether_shost));
+ ether_sprintf(eh->ether_shost));
printf("arp: cacheing %s --> %s\n",
inet_ntoa(addr), ether_sprintf(ah->arp_sha));
}
@@ -143,14 +139,12 @@ arpwhohas(d, addr)
MACPY(ah->arp_sha, al->ea);
++arp_num;
+ free(pkt);
return (al->ea);
}
static ssize_t
-arpsend(d, pkt, len)
- struct iodesc *d;
- void *pkt;
- size_t len;
+arpsend(struct iodesc *d, void *pkt, size_t len)
{
#ifdef ARP_DEBUG
@@ -166,28 +160,27 @@ arpsend(d, pkt, len)
* else -1 (and errno == 0)
*/
static ssize_t
-arprecv(d, pkt, len, tleft)
- struct iodesc *d;
- void *pkt;
- size_t len;
- time_t tleft;
+arprecv(struct iodesc *d, void **pkt, void **payload, time_t tleft)
{
ssize_t n;
struct ether_arp *ah;
u_int16_t etype; /* host order */
+ void *ptr;
#ifdef ARP_DEBUG
if (debug)
printf("arprecv: ");
#endif
- n = readether(d, pkt, len, tleft, &etype);
+ ptr = NULL;
+ n = readether(d, &ptr, (void **)&ah, tleft, &etype);
errno = 0; /* XXX */
if (n == -1 || n < sizeof(struct ether_arp)) {
#ifdef ARP_DEBUG
if (debug)
printf("bad len=%d\n", n);
#endif
+ free(ptr);
return (-1);
}
@@ -196,12 +189,11 @@ arprecv(d, pkt, len, tleft)
if (debug)
printf("not arp type=%d\n", etype);
#endif
+ free(ptr);
return (-1);
}
/* Ethernet address now checked in readether() */
-
- ah = (struct ether_arp *)pkt;
if (ah->arp_hrd != htons(ARPHRD_ETHER) ||
ah->arp_pro != htons(ETHERTYPE_IP) ||
ah->arp_hln != sizeof(ah->arp_sha) ||
@@ -211,6 +203,7 @@ arprecv(d, pkt, len, tleft)
if (debug)
printf("bad hrd/pro/hln/pln\n");
#endif
+ free(ptr);
return (-1);
}
@@ -220,6 +213,7 @@ arprecv(d, pkt, len, tleft)
printf("is request\n");
#endif
arp_reply(d, ah);
+ free(ptr);
return (-1);
}
@@ -228,6 +222,7 @@ arprecv(d, pkt, len, tleft)
if (debug)
printf("not ARP reply\n");
#endif
+ free(ptr);
return (-1);
}
@@ -239,6 +234,7 @@ arprecv(d, pkt, len, tleft)
if (debug)
printf("unwanted address\n");
#endif
+ free(ptr);
return (-1);
}
/* We don't care who the reply was sent to. */
@@ -248,6 +244,8 @@ arprecv(d, pkt, len, tleft)
if (debug)
printf("got it\n");
#endif
+ *pkt = ptr;
+ *payload = ah;
return (n);
}
@@ -256,9 +254,7 @@ arprecv(d, pkt, len, tleft)
* Notes: Re-uses buffer. Pad to length = 46.
*/
void
-arp_reply(d, pkt)
- struct iodesc *d;
- void *pkt; /* the request */
+arp_reply(struct iodesc *d, void *pkt)
{
struct ether_arp *arp = pkt;
diff --git a/lib/libstand/bootp.c b/lib/libstand/bootp.c
index 9fc656f4a99d..ec3cd7b5dc26 100644
--- a/lib/libstand/bootp.c
+++ b/lib/libstand/bootp.c
@@ -38,6 +38,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include <stddef.h>
#include <sys/types.h>
#include <sys/limits.h>
#include <sys/endian.h>
@@ -72,7 +73,7 @@ static char vm_cmu[4] = VM_CMU;
/* Local forwards */
static ssize_t bootpsend(struct iodesc *, void *, size_t);
-static ssize_t bootprecv(struct iodesc *, void *, size_t, time_t);
+static ssize_t bootprecv(struct iodesc *, void **, void **, time_t);
static int vend_rfc1048(u_char *, u_int);
#ifdef BOOTP_VEND_CMU
static void vend_cmu(u_char *);
@@ -89,23 +90,21 @@ static void setenv_(u_char *cp, u_char *ep, struct dhcp_opt *opts);
static char expected_dhcpmsgtype = -1, dhcp_ok;
struct in_addr dhcp_serverip;
#endif
+struct bootp *bootp_response;
+size_t bootp_response_size;
/* Fetch required bootp infomation */
void
-bootp(sock, flag)
- int sock;
- int flag;
+bootp(int sock, int flag)
{
+ void *pkt;
struct iodesc *d;
struct bootp *bp;
struct {
u_char header[HEADER_SIZE];
struct bootp wbootp;
} wbuf;
- struct {
- u_char header[HEADER_SIZE];
- struct bootp rbootp;
- } rbuf;
+ struct bootp *rbootp;
#ifdef BOOTP_DEBUG
if (debug)
@@ -175,8 +174,7 @@ bootp(sock, flag)
if(sendrecv(d,
bootpsend, bp, sizeof(*bp),
- bootprecv, &rbuf.rbootp, sizeof(rbuf.rbootp))
- == -1) {
+ bootprecv, &pkt, (void **)&rbootp) == -1) {
printf("bootp: no reply\n");
return;
}
@@ -187,7 +185,7 @@ bootp(sock, flag)
bp->bp_vend[6] = DHCPREQUEST;
bp->bp_vend[7] = TAG_REQ_ADDR;
bp->bp_vend[8] = 4;
- bcopy(&rbuf.rbootp.bp_yiaddr, &bp->bp_vend[9], 4);
+ bcopy(&rbootp->bp_yiaddr, &bp->bp_vend[9], 4);
bp->bp_vend[13] = TAG_SERVERID;
bp->bp_vend[14] = 4;
bcopy(&dhcp_serverip.s_addr, &bp->bp_vend[15], 4);
@@ -205,20 +203,21 @@ bootp(sock, flag)
expected_dhcpmsgtype = DHCPACK;
+ free(pkt);
if(sendrecv(d,
bootpsend, bp, sizeof(*bp),
- bootprecv, &rbuf.rbootp, sizeof(rbuf.rbootp))
- == -1) {
+ bootprecv, &pkt, (void **)&rbootp) == -1) {
printf("DHCPREQUEST failed\n");
return;
}
}
#endif
- myip = d->myip = rbuf.rbootp.bp_yiaddr;
- servip = rbuf.rbootp.bp_siaddr;
- if(rootip.s_addr == INADDR_ANY) rootip = servip;
- bcopy(rbuf.rbootp.bp_file, bootfile, sizeof(bootfile));
+ myip = d->myip = rbootp->bp_yiaddr;
+ servip = rbootp->bp_siaddr;
+ if (rootip.s_addr == INADDR_ANY)
+ rootip = servip;
+ bcopy(rbootp->bp_file, bootfile, sizeof(bootfile));
bootfile[sizeof(bootfile) - 1] = '\0';
if (!netmask) {
@@ -258,14 +257,12 @@ bootp(sock, flag)
/* Bump xid so next request will be unique. */
++d->xid;
+ free(pkt);
}
/* Transmit a bootp request */
static ssize_t
-bootpsend(d, pkt, len)
- struct iodesc *d;
- void *pkt;
- size_t len;
+bootpsend(struct iodesc *d, void *pkt, size_t len)
{
struct bootp *bp;
@@ -286,30 +283,25 @@ bootpsend(d, pkt, len)
}
static ssize_t
-bootprecv(d, pkt, len, tleft)
-struct iodesc *d;
-void *pkt;
-size_t len;
-time_t tleft;
+bootprecv(struct iodesc *d, void **pkt, void **payload, time_t tleft)
{
ssize_t n;
struct bootp *bp;
+ void *ptr;
-#ifdef BOOTP_DEBUGx
+#ifdef BOOTP_DEBUG
if (debug)
printf("bootp_recvoffer: called\n");
#endif
- n = readudp(d, pkt, len, tleft);
+ ptr = NULL;
+ n = readudp(d, &ptr, (void **)&bp, tleft);
if (n == -1 || n < sizeof(struct bootp) - BOOTP_VENDSIZE)
goto bad;
- bp = (struct bootp *)pkt;
-
#ifdef BOOTP_DEBUG
if (debug)
- printf("bootprecv: checked. bp = 0x%lx, n = %d\n",
- (long)bp, (int)n);
+ printf("bootprecv: checked. bp = %p, n = %zd\n", bp, n);
#endif
if (bp->bp_xid != htonl(d->xid)) {
#ifdef BOOTP_DEBUG
@@ -328,8 +320,21 @@ time_t tleft;
/* Suck out vendor info */
if (bcmp(vm_rfc1048, bp->bp_vend, sizeof(vm_rfc1048)) == 0) {
- if(vend_rfc1048(bp->bp_vend, sizeof(bp->bp_vend)) != 0)
+ int vsize = n - offsetof(struct bootp, bp_vend);
+ if (vend_rfc1048(bp->bp_vend, vsize) != 0)
goto bad;
+
+ /* Save copy of bootp reply or DHCP ACK message */
+ if (bp->bp_op == BOOTREPLY &&
+ ((dhcp_ok == 1 && expected_dhcpmsgtype == DHCPACK) ||
+ dhcp_ok == 0)) {
+ free(bootp_response);
+ bootp_response = malloc(n);
+ if (bootp_response != NULL) {
+ bootp_response_size = n;
+ bcopy(bp, bootp_response, bootp_response_size);
+ }
+ }
}
#ifdef BOOTP_VEND_CMU
else if (bcmp(vm_cmu, bp->bp_vend, sizeof(vm_cmu)) == 0)
@@ -338,8 +343,11 @@ time_t tleft;
else
printf("bootprecv: unknown vendor 0x%lx\n", (long)bp->bp_vend);
- return(n);
+ *pkt = ptr;
+ *payload = bp;
+ return (n);
bad:
+ free(ptr);
errno = 0;
return (-1);
}
@@ -356,9 +364,7 @@ dhcp_try_rfc1048(u_char *cp, u_int len)
}
static int
-vend_rfc1048(cp, len)
- u_char *cp;
- u_int len;
+vend_rfc1048(u_char *cp, u_int len)
{
u_char *ep;
int size;
@@ -445,8 +451,7 @@ vend_rfc1048(cp, len)
#ifdef BOOTP_VEND_CMU
static void
-vend_cmu(cp)
- u_char *cp;
+vend_cmu(u_char *cp)
{
struct cmu_vend *vp;
diff --git a/lib/libstand/bootp.h b/lib/libstand/bootp.h
index 98358007e07f..9fb746f49163 100644
--- a/lib/libstand/bootp.h
+++ b/lib/libstand/bootp.h
@@ -147,6 +147,10 @@ struct cmu_vend {
/* v_flags values */
#define VF_SMASK 1 /* Subnet mask field contains valid data */
+/* cached bootp response/dhcp ack */
+extern struct bootp *bootp_response;
+extern size_t bootp_response_size;
+
int dhcp_try_rfc1048(u_char *cp, u_int len);
#endif /* _BOOTP_H_ */
diff --git a/lib/libstand/bootparam.c b/lib/libstand/bootparam.c
index e4d2f1022c92..1de2d53d77fe 100644
--- a/lib/libstand/bootparam.c
+++ b/lib/libstand/bootparam.c
@@ -104,8 +104,7 @@ int xdr_string_decode(char **p, char *str, int *len_p);
* know about us (don't want to broadcast a getport call).
*/
int
-bp_whoami(sockfd)
- int sockfd;
+bp_whoami(int sockfd)
{
/* RPC structures for PMAPPROC_CALLIT */
struct args {
@@ -126,22 +125,19 @@ bp_whoami(sockfd)
n_long h[RPC_HEADER_WORDS];
struct args d;
} sdata;
- struct {
- n_long h[RPC_HEADER_WORDS];
- struct repl d;
- } rdata;
char *send_tail, *recv_head;
struct iodesc *d;
- int len, x;
+ void *pkt;
+ int len, x, rc;
RPC_PRINTF(("bp_whoami: myip=%s\n", inet_ntoa(myip)));
+ rc = -1;
if (!(d = socktodesc(sockfd))) {
RPC_PRINTF(("bp_whoami: bad socket. %d\n", sockfd));
- return (-1);
+ return (rc);
}
args = &sdata.d;
- repl = &rdata.d;
/*
* Build request args for PMAPPROC_CALLIT.
@@ -156,19 +152,19 @@ bp_whoami(sockfd)
* append encapsulated data (client IP address)
*/
if (xdr_inaddr_encode(&send_tail, myip))
- return (-1);
+ return (rc);
/* RPC: portmap/callit */
d->myport = htons(--rpc_port);
d->destip.s_addr = INADDR_BROADCAST; /* XXX: subnet bcast? */
/* rpc_call will set d->destport */
+ pkt = NULL;
len = rpc_call(d, PMAPPROG, PMAPVERS, PMAPPROC_CALLIT,
- args, send_tail - (char*)args,
- repl, sizeof(*repl));
+ args, send_tail - (char*)args, (void **)&repl, &pkt);
if (len < 8) {
printf("bootparamd: 'whoami' call failed\n");
- return (-1);
+ goto done;
}
/* Save bootparam server address (from IP header). */
@@ -196,7 +192,7 @@ bp_whoami(sockfd)
x = ntohl(repl->encap_len);
if (len < x) {
printf("bp_whoami: short reply, %d < %d\n", len, x);
- return (-1);
+ goto done;
}
recv_head = (char*) repl->capsule;
@@ -204,24 +200,27 @@ bp_whoami(sockfd)
hostnamelen = MAXHOSTNAMELEN-1;
if (xdr_string_decode(&recv_head, hostname, &hostnamelen)) {
RPC_PRINTF(("bp_whoami: bad hostname\n"));
- return (-1);
+ goto done;
}
/* domain name */
domainnamelen = MAXHOSTNAMELEN-1;
if (xdr_string_decode(&recv_head, domainname, &domainnamelen)) {
RPC_PRINTF(("bp_whoami: bad domainname\n"));
- return (-1);
+ goto done;
}
/* gateway address */
if (xdr_inaddr_decode(&recv_head, &gateip)) {
RPC_PRINTF(("bp_whoami: bad gateway\n"));
- return (-1);
+ goto done;
}
/* success */
- return(0);
+ rc = 0;
+done:
+ free(pkt);
+ return (rc);
}
@@ -233,25 +232,18 @@ bp_whoami(sockfd)
* server pathname
*/
int
-bp_getfile(sockfd, key, serv_addr, pathname)
- int sockfd;
- char *key;
- char *pathname;
- struct in_addr *serv_addr;
+bp_getfile(int sockfd, char *key, struct in_addr *serv_addr, char *pathname)
{
struct {
n_long h[RPC_HEADER_WORDS];
n_long d[64];
} sdata;
- struct {
- n_long h[RPC_HEADER_WORDS];
- n_long d[128];
- } rdata;
+ void *pkt;
char serv_name[FNAME_SIZE];
- char *send_tail, *recv_head;
+ char *rdata, *send_tail;
/* misc... */
struct iodesc *d;
- int sn_len, path_len, rlen;
+ int rc = -1, sn_len, path_len, rlen;
if (!(d = socktodesc(sockfd))) {
RPC_PRINTF(("bp_getfile: bad socket. %d\n", sockfd));
@@ -259,7 +251,6 @@ bp_getfile(sockfd, key, serv_addr, pathname)
}
send_tail = (char*) sdata.d;
- recv_head = (char*) rdata.d;
/*
* Build request message.
@@ -281,17 +272,16 @@ bp_getfile(sockfd, key, serv_addr, pathname)
d->myport = htons(--rpc_port);
d->destip = bp_server_addr;
/* rpc_call will set d->destport */
-
+ pkt = NULL;
rlen = rpc_call(d,
BOOTPARAM_PROG, BOOTPARAM_VERS, BOOTPARAM_GETFILE,
sdata.d, send_tail - (char*)sdata.d,
- rdata.d, sizeof(rdata.d));
+ (void **)&rdata, &pkt);
if (rlen < 4) {
RPC_PRINTF(("bp_getfile: short reply\n"));
errno = EBADRPC;
- return (-1);
+ goto done;
}
- recv_head = (char*) rdata.d;
/*
* Parse result message.
@@ -299,26 +289,29 @@ bp_getfile(sockfd, key, serv_addr, pathname)
/* server name */
sn_len = FNAME_SIZE-1;
- if (xdr_string_decode(&recv_head, serv_name, &sn_len)) {
+ if (xdr_string_decode(&rdata, serv_name, &sn_len)) {
RPC_PRINTF(("bp_getfile: bad server name\n"));
- return (-1);
+ goto done;
}
/* server IP address (mountd/NFS) */
- if (xdr_inaddr_decode(&recv_head, serv_addr)) {
+ if (xdr_inaddr_decode(&rdata, serv_addr)) {
RPC_PRINTF(("bp_getfile: bad server addr\n"));
- return (-1);
+ goto done;
}
/* server pathname */
path_len = MAXPATHLEN-1;
- if (xdr_string_decode(&recv_head, pathname, &path_len)) {
+ if (xdr_string_decode(&rdata, pathname, &path_len)) {
RPC_PRINTF(("bp_getfile: bad server path\n"));
- return (-1);
+ goto done;
}
/* success */
- return(0);
+ rc = 0;
+done:
+ free(pkt);
+ return (rc);
}
@@ -329,17 +322,14 @@ bp_getfile(sockfd, key, serv_addr, pathname)
int
-xdr_string_encode(pkt, str, len)
- char **pkt;
- char *str;
- int len;
+xdr_string_encode(char **pkt, char *str, int len)
{
- u_int32_t *lenp;
+ uint32_t *lenp;
char *datap;
int padlen = (len + 3) & ~3; /* padded length */
/* The data will be int aligned. */
- lenp = (u_int32_t*) *pkt;
+ lenp = (uint32_t *) *pkt;
*pkt += sizeof(*lenp);
*lenp = htonl(len);
@@ -351,18 +341,15 @@ xdr_string_encode(pkt, str, len)
}
int
-xdr_string_decode(pkt, str, len_p)
- char **pkt;
- char *str;
- int *len_p; /* bufsize - 1 */
+xdr_string_decode(char **pkt, char *str, int *len_p)
{
- u_int32_t *lenp;
+ uint32_t *lenp;
char *datap;
int slen; /* string length */
int plen; /* padded length */
/* The data will be int aligned. */
- lenp = (u_int32_t*) *pkt;
+ lenp = (uint32_t *) *pkt;
*pkt += sizeof(*lenp);
slen = ntohl(*lenp);
plen = (slen + 3) & ~3;
@@ -381,9 +368,7 @@ xdr_string_decode(pkt, str, len_p)
int
-xdr_inaddr_encode(pkt, ia)
- char **pkt;
- struct in_addr ia; /* network order */
+xdr_inaddr_encode(char **pkt, struct in_addr ia)
{
struct xdr_inaddr *xi;
u_char *cp;
@@ -414,9 +399,7 @@ xdr_inaddr_encode(pkt, ia)
}
int
-xdr_inaddr_decode(pkt, ia)
- char **pkt;
- struct in_addr *ia; /* network order */
+xdr_inaddr_decode(char **pkt, struct in_addr *ia)
{
struct xdr_inaddr *xi;
u_char *cp;
diff --git a/lib/libstand/ether.c b/lib/libstand/ether.c
index df42f31a8b71..3616777e7955 100644
--- a/lib/libstand/ether.c
+++ b/lib/libstand/ether.c
@@ -54,12 +54,7 @@ __FBSDID("$FreeBSD$");
/* Caller must leave room for ethernet header in front!! */
ssize_t
-sendether(d, pkt, len, dea, etype)
- struct iodesc *d;
- void *pkt;
- size_t len;
- u_char *dea;
- int etype;
+sendether(struct iodesc *d, void *pkt, size_t len, uint8_t *dea, int etype)
{
ssize_t n;
struct ether_header *eh;
@@ -86,32 +81,31 @@ sendether(d, pkt, len, dea, etype)
/*
* Get a packet of any Ethernet type, with our address or
- * the broadcast address. Save the Ether type in arg 5.
- * NOTE: Caller must leave room for the Ether header.
+ * the broadcast address. Save the Ether type in etype.
+ * Unless there is an error, we pass the whole packet and the unencapsulated
+ * data.
*/
ssize_t
-readether(d, pkt, len, tleft, etype)
- struct iodesc *d;
- void *pkt;
- size_t len;
- time_t tleft;
- u_int16_t *etype;
+readether(struct iodesc *d, void **pkt, void **payload, time_t tleft,
+ uint16_t *etype)
{
ssize_t n;
struct ether_header *eh;
+ void *ptr;
#ifdef ETHER_DEBUG
if (debug)
printf("readether: called\n");
#endif
- eh = (struct ether_header *)pkt - 1;
- len += sizeof(*eh);
-
- n = netif_get(d, eh, len, tleft);
- if (n == -1 || n < sizeof(*eh))
+ ptr = NULL;
+ n = netif_get(d, &ptr, tleft);
+ if (n == -1 || n < sizeof(*eh)) {
+ free(ptr);
return (-1);
+ }
+ eh = (struct ether_header *)((uintptr_t)ptr + ETHER_ALIGN);
/* Validate Ethernet address. */
if (bcmp(d->myea, eh->ether_dhost, 6) != 0 &&
bcmp(bcea, eh->ether_dhost, 6) != 0) {
@@ -120,8 +114,12 @@ readether(d, pkt, len, tleft, etype)
printf("readether: not ours (ea=%s)\n",
ether_sprintf(eh->ether_dhost));
#endif
+ free(ptr);
return (-1);
}
+
+ *pkt = ptr;
+ *payload = (void *)((uintptr_t)eh + sizeof(*eh));
*etype = ntohs(eh->ether_type);
n -= sizeof(*eh);
@@ -133,8 +131,7 @@ readether(d, pkt, len, tleft, etype)
*/
static char digits[] = "0123456789abcdef";
char *
-ether_sprintf(ap)
- u_char *ap;
+ether_sprintf(u_char *ap)
{
int i;
static char etherbuf[18];
diff --git a/lib/libstand/net.c b/lib/libstand/net.c
index 38759a802273..ae6e74511e12 100644
--- a/lib/libstand/net.c
+++ b/lib/libstand/net.c
@@ -70,10 +70,10 @@ __FBSDID("$FreeBSD$");
*/
ssize_t
sendrecv(struct iodesc *d,
- ssize_t (*sproc)(struct iodesc *, void *, size_t),
- void *sbuf, size_t ssize,
- ssize_t (*rproc)(struct iodesc *, void *, size_t, time_t),
- void *rbuf, size_t rsize)
+ ssize_t (*sproc)(struct iodesc *, void *, size_t),
+ void *sbuf, size_t ssize,
+ ssize_t (*rproc)(struct iodesc *, void **, void **, time_t),
+ void **pkt, void **payload)
{
ssize_t cc;
time_t t, tmo, tlast;
@@ -116,7 +116,7 @@ sendrecv(struct iodesc *d,
}
/* Try to get a packet and process it. */
- cc = (*rproc)(d, rbuf, rsize, tleft);
+ cc = (*rproc)(d, pkt, payload, tleft);
/* Return on data, EOF or real error. */
if (cc != -1 || errno != 0)
return (cc);
diff --git a/lib/libstand/net.h b/lib/libstand/net.h
index 5221885a266b..740b5d970f87 100644
--- a/lib/libstand/net.h
+++ b/lib/libstand/net.h
@@ -106,16 +106,15 @@ int rarp_getipaddress(int);
/* Link functions: */
ssize_t sendether(struct iodesc *d, void *pkt, size_t len,
u_char *dea, int etype);
-ssize_t readether(struct iodesc *d, void *pkt, size_t len,
- time_t tleft, u_int16_t *etype);
+ssize_t readether(struct iodesc *, void **, void **, time_t, uint16_t *);
ssize_t sendudp(struct iodesc *, void *, size_t);
-ssize_t readudp(struct iodesc *, void *, size_t, time_t);
+ssize_t readudp(struct iodesc *, void **, void **, time_t);
ssize_t sendrecv(struct iodesc *,
- ssize_t (*)(struct iodesc *, void *, size_t),
+ ssize_t (*)(struct iodesc *, void *, size_t),
void *, size_t,
- ssize_t (*)(struct iodesc *, void *, size_t, time_t),
- void *, size_t);
+ ssize_t (*)(struct iodesc *, void **, void **, time_t),
+ void **, void **);
/* bootp/DHCP */
void bootp(int, int);
diff --git a/lib/libstand/netif.c b/lib/libstand/netif.c
index c260690c503c..105f9a31ab5d 100644
--- a/lib/libstand/netif.c
+++ b/lib/libstand/netif.c
@@ -59,7 +59,7 @@ int netif_debug = 0;
*/
void
-netif_init()
+netif_init(void)
{
struct netif_driver *drv;
int d, i;
@@ -76,13 +76,11 @@ netif_init()
}
int
-netif_match(nif, machdep_hint)
- struct netif *nif;
- void *machdep_hint;
+netif_match(struct netif *nif, void *machdep_hint)
{
struct netif_driver *drv = nif->nif_driver;
-#if 0
+#if NETIF_DEBUG
if (netif_debug)
printf("%s%d: netif_match (%d)\n", drv->netif_bname,
nif->nif_unit, nif->nif_sel);
@@ -91,8 +89,7 @@ netif_match(nif, machdep_hint)
}
struct netif *
-netif_select(machdep_hint)
- void *machdep_hint;
+netif_select(void *machdep_hint)
{
int d, u, unit_done, s;
struct netif_driver *drv;
@@ -162,9 +159,7 @@ netif_select(machdep_hint)
}
int
-netif_probe(nif, machdep_hint)
- struct netif *nif;
- void *machdep_hint;
+netif_probe(struct netif *nif, void *machdep_hint)
{
struct netif_driver *drv = nif->nif_driver;
@@ -176,10 +171,7 @@ netif_probe(nif, machdep_hint)
}
void
-netif_attach(nif, desc, machdep_hint)
- struct netif *nif;
- struct iodesc *desc;
- void *machdep_hint;
+netif_attach(struct netif *nif, struct iodesc *desc, void *machdep_hint)
{
struct netif_driver *drv = nif->nif_driver;
@@ -199,8 +191,7 @@ netif_attach(nif, desc, machdep_hint)
}
void
-netif_detach(nif)
- struct netif *nif;
+netif_detach(struct netif *nif)
{
struct netif_driver *drv = nif->nif_driver;
@@ -217,11 +208,7 @@ netif_detach(nif)
}
ssize_t
-netif_get(desc, pkt, len, timo)
- struct iodesc *desc;
- void *pkt;
- size_t len;
- time_t timo;
+netif_get(struct iodesc *desc, void **pkt, time_t timo)
{
#ifdef NETIF_DEBUG
struct netif *nif = desc->io_netif;
@@ -238,20 +225,17 @@ netif_get(desc, pkt, len, timo)
panic("%s%d: no netif_get support\n", drv->netif_bname,
nif->nif_unit);
#endif
- rv = drv->netif_get(desc, pkt, len, timo);
+ rv = drv->netif_get(desc, pkt, timo);
#ifdef NETIF_DEBUG
if (netif_debug)
printf("%s%d: netif_get returning %d\n", drv->netif_bname,
nif->nif_unit, (int)rv);
#endif
- return rv;
+ return (rv);
}
ssize_t
-netif_put(desc, pkt, len)
- struct iodesc *desc;
- void *pkt;
- size_t len;
+netif_put(struct iodesc *desc, void *pkt, size_t len)
{
#ifdef NETIF_DEBUG
struct netif *nif = desc->io_netif;
@@ -274,12 +258,11 @@ netif_put(desc, pkt, len)
printf("%s%d: netif_put returning %d\n", drv->netif_bname,
nif->nif_unit, (int)rv);
#endif
- return rv;
+ return (rv);
}
struct iodesc *
-socktodesc(sock)
- int sock;
+socktodesc(int sock)
{
if (sock >= SOPEN_MAX) {
errno = EBADF;
@@ -289,8 +272,7 @@ socktodesc(sock)
}
int
-netif_open(machdep_hint)
- void *machdep_hint;
+netif_open(void *machdep_hint)
{
int fd;
struct iodesc *s;
@@ -313,23 +295,22 @@ fnd:
printf("netboot: couldn't probe %s%d\n",
nif->nif_driver->netif_bname, nif->nif_unit);
errno = EINVAL;
- return(-1);
+ return (-1);
}
netif_attach(nif, s, machdep_hint);
- return(fd);
+ return (fd);
}
int
-netif_close(sock)
- int sock;
+netif_close(int sock)
{
if (sock >= SOPEN_MAX) {
errno = EBADF;
- return(-1);
+ return (-1);
}
netif_detach(sockets[sock].io_netif);
sockets[sock].io_netif = (struct netif *)0;
- return(0);
+ return (0);
}
diff --git a/lib/libstand/netif.h b/lib/libstand/netif.h
index dac285107a73..44165ab0d88a 100644
--- a/lib/libstand/netif.h
+++ b/lib/libstand/netif.h
@@ -6,15 +6,13 @@
#define __SYS_LIBNETBOOT_NETIF_H
#include "iodesc.h"
-#define NENTS(x) sizeof(x)/sizeof(x[0])
-
struct netif_driver {
const char *netif_bname;
int (*netif_match)(struct netif *, void *);
int (*netif_probe)(struct netif *, void *);
void (*netif_init)(struct iodesc *, void *);
- int (*netif_get)(struct iodesc *, void *, size_t, time_t);
- int (*netif_put)(struct iodesc *, void *, size_t);
+ ssize_t (*netif_get)(struct iodesc *, void **, time_t);
+ ssize_t (*netif_put)(struct iodesc *, void *, size_t);
void (*netif_end)(struct netif *);
struct netif_dif *netif_ifs;
int netif_nifs;
@@ -56,7 +54,7 @@ struct netif *netif_select(void *);
int netif_probe(struct netif *, void *);
void netif_attach(struct netif *, struct iodesc *, void *);
void netif_detach(struct netif *);
-ssize_t netif_get(struct iodesc *, void *, size_t, time_t);
+ssize_t netif_get(struct iodesc *, void **, time_t);
ssize_t netif_put(struct iodesc *, void *, size_t);
int netif_open(void *);
diff --git a/lib/libstand/nfs.c b/lib/libstand/nfs.c
index 8a7e111fcdd7..6c387b8d8ef7 100644
--- a/lib/libstand/nfs.c
+++ b/lib/libstand/nfs.c
@@ -185,6 +185,7 @@ set_nfs_read_size(void)
int
nfs_getrootfh(struct iodesc *d, char *path, uint32_t *fhlenp, u_char *fhp)
{
+ void *pkt = NULL;
int len;
struct args {
uint32_t len;
@@ -201,10 +202,6 @@ nfs_getrootfh(struct iodesc *d, char *path, uint32_t *fhlenp, u_char *fhp)
uint32_t h[RPC_HEADER_WORDS];
struct args d;
} sdata;
- struct {
- uint32_t h[RPC_HEADER_WORDS];
- struct repl d;
- } rdata;
size_t cc;
#ifdef NFS_DEBUG
@@ -213,7 +210,6 @@ nfs_getrootfh(struct iodesc *d, char *path, uint32_t *fhlenp, u_char *fhp)
#endif
args = &sdata.d;
- repl = &rdata.d;
bzero(args, sizeof(*args));
len = strlen(path);
@@ -224,18 +220,25 @@ nfs_getrootfh(struct iodesc *d, char *path, uint32_t *fhlenp, u_char *fhp)
len = sizeof(uint32_t) + roundup(len, sizeof(uint32_t));
cc = rpc_call(d, RPCPROG_MNT, RPCMNT_VER3, RPCMNT_MOUNT,
- args, len, repl, sizeof(*repl));
- if (cc == -1)
+ args, len, (void **)&repl, &pkt);
+ if (cc == -1) {
+ free(pkt);
/* errno was set by rpc_call */
return (errno);
- if (cc < 2 * sizeof (uint32_t))
+ }
+ if (cc < 2 * sizeof (uint32_t)) {
+ free(pkt);
return (EBADRPC);
- if (repl->errno != 0)
+ }
+ if (repl->errno != 0) {
+ free(pkt);
return (ntohl(repl->errno));
+ }
*fhlenp = ntohl(repl->fhsize);
bcopy(repl->fh, fhp, *fhlenp);
set_nfs_read_size();
+ free(pkt);
return (0);
}
@@ -246,6 +249,7 @@ nfs_getrootfh(struct iodesc *d, char *path, uint32_t *fhlenp, u_char *fhp)
int
nfs_lookupfh(struct nfs_iodesc *d, const char *name, struct nfs_iodesc *newfd)
{
+ void *pkt = NULL;
int len, rlen, pos;
struct args {
uint32_t fhsize;
@@ -263,10 +267,6 @@ nfs_lookupfh(struct nfs_iodesc *d, const char *name, struct nfs_iodesc *newfd)
uint32_t h[RPC_HEADER_WORDS];
struct args d;
} sdata;
- struct {
- uint32_t h[RPC_HEADER_WORDS];
- struct repl d;
- } rdata;
ssize_t cc;
#ifdef NFS_DEBUG
@@ -275,7 +275,6 @@ nfs_lookupfh(struct nfs_iodesc *d, const char *name, struct nfs_iodesc *newfd)
#endif
args = &sdata.d;
- repl = &rdata.d;
bzero(args, sizeof(*args));
args->fhsize = htonl(d->fhsize);
@@ -289,23 +288,30 @@ nfs_lookupfh(struct nfs_iodesc *d, const char *name, struct nfs_iodesc *newfd)
len = sizeof(uint32_t) + pos * sizeof(uint32_t) +
roundup(len, sizeof(uint32_t));
- rlen = sizeof(*repl);
-
cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER3, NFSPROCV3_LOOKUP,
- args, len, repl, rlen);
- if (cc == -1)
+ args, len, (void **)&repl, &pkt);
+ if (cc == -1) {
+ free(pkt);
return (errno); /* XXX - from rpc_call */
- if (cc < 2 * sizeof(uint32_t))
+ }
+ if (cc < 2 * sizeof(uint32_t)) {
+ free(pkt);
return (EIO);
- if (repl->errno != 0)
+ }
+ if (repl->errno != 0) {
+ free(pkt);
/* saerrno.h now matches NFS error numbers. */
return (ntohl(repl->errno));
+ }
newfd->fhsize = ntohl(repl->fhsize);
bcopy(repl->fhplusattr, &newfd->fh, newfd->fhsize);
pos = roundup(newfd->fhsize, sizeof(uint32_t)) / sizeof(uint32_t);
- if (repl->fhplusattr[pos++] == 0)
+ if (repl->fhplusattr[pos++] == 0) {
+ free(pkt);
return (EIO);
+ }
bcopy(&repl->fhplusattr[pos], &newfd->fa, sizeof(newfd->fa));
+ free(pkt);
return (0);
}
@@ -316,6 +322,7 @@ nfs_lookupfh(struct nfs_iodesc *d, const char *name, struct nfs_iodesc *newfd)
int
nfs_readlink(struct nfs_iodesc *d, char *buf)
{
+ void *pkt = NULL;
struct args {
uint32_t fhsize;
u_char fh[NFS_V3MAXFHSIZE];
@@ -331,11 +338,8 @@ nfs_readlink(struct nfs_iodesc *d, char *buf)
uint32_t h[RPC_HEADER_WORDS];
struct args d;
} sdata;
- struct {
- uint32_t h[RPC_HEADER_WORDS];
- struct repl d;
- } rdata;
ssize_t cc;
+ int rc = 0;
#ifdef NFS_DEBUG
if (debug)
@@ -343,32 +347,41 @@ nfs_readlink(struct nfs_iodesc *d, char *buf)
#endif
args = &sdata.d;
- repl = &rdata.d;
bzero(args, sizeof(*args));
args->fhsize = htonl(d->fhsize);
bcopy(d->fh, args->fh, d->fhsize);
cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER3, NFSPROCV3_READLINK,
args, sizeof(uint32_t) + roundup(d->fhsize, sizeof(uint32_t)),
- repl, sizeof(*repl));
+ (void **)&repl, &pkt);
if (cc == -1)
return (errno);
- if (cc < 2 * sizeof(uint32_t))
- return (EIO);
+ if (cc < 2 * sizeof(uint32_t)) {
+ rc = EIO;
+ goto done;
+ }
- if (repl->errno != 0)
- return (ntohl(repl->errno));
+ if (repl->errno != 0) {
+ rc = ntohl(repl->errno);
+ goto done;
+ }
- if (repl->ok == 0)
- return (EIO);
+ if (repl->ok == 0) {
+ rc = EIO;
+ goto done;
+ }
repl->len = ntohl(repl->len);
- if (repl->len > NFS_MAXPATHLEN)
- return (ENAMETOOLONG);
+ if (repl->len > NFS_MAXPATHLEN) {
+ rc = ENAMETOOLONG;
+ goto done;
+ }
bcopy(repl->path, buf, repl->len);
buf[repl->len] = 0;
+done:
+ free(pkt);
return (0);
}
#endif
@@ -380,6 +393,7 @@ nfs_readlink(struct nfs_iodesc *d, char *buf)
ssize_t
nfs_readdata(struct nfs_iodesc *d, off_t off, void *addr, size_t len)
{
+ void *pkt = NULL;
struct args {
uint32_t fhsize;
uint32_t fhoffcnt[NFS_V3MAXFHSIZE / sizeof(uint32_t) + 3];
@@ -397,16 +411,11 @@ nfs_readdata(struct nfs_iodesc *d, off_t off, void *addr, size_t len)
uint32_t h[RPC_HEADER_WORDS];
struct args d;
} sdata;
- struct {
- uint32_t h[RPC_HEADER_WORDS];
- struct repl d;
- } rdata;
size_t cc;
long x;
int hlen, rlen, pos;
args = &sdata.d;
- repl = &rdata.d;
bzero(args, sizeof(*args));
args->fhsize = htonl(d->fhsize);
@@ -421,16 +430,19 @@ nfs_readdata(struct nfs_iodesc *d, off_t off, void *addr, size_t len)
cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER3, NFSPROCV3_READ,
args, 4 * sizeof(uint32_t) + roundup(d->fhsize, sizeof(uint32_t)),
- repl, sizeof(*repl));
- if (cc == -1)
+ (void **)&repl, &pkt);
+ if (cc == -1) {
/* errno was already set by rpc_call */
return (-1);
+ }
if (cc < hlen) {
errno = EBADRPC;
+ free(pkt);
return (-1);
}
if (repl->errno != 0) {
errno = ntohl(repl->errno);
+ free(pkt);
return (-1);
}
rlen = cc - hlen;
@@ -438,9 +450,11 @@ nfs_readdata(struct nfs_iodesc *d, off_t off, void *addr, size_t len)
if (rlen < x) {
printf("nfsread: short packet, %d < %ld\n", rlen, x);
errno = EBADRPC;
+ free(pkt);
return (-1);
}
bcopy(repl->data, addr, x);
+ free(pkt);
return (x);
}
@@ -481,17 +495,8 @@ nfs_open(const char *upath, struct open_file *f)
return (ENXIO);
}
- /*
- * This is silly - we should look at dv_type but that value is
- * arch dependant and we can't use it here.
- */
-#ifndef __i386__
- if (strcmp(f->f_dev->dv_name, "net") != 0)
- return (EINVAL);
-#else
- if (strcmp(f->f_dev->dv_name, "pxe") != 0)
+ if (f->f_dev->dv_type != DEVT_NET)
return (EINVAL);
-#endif
if (!(desc = socktodesc(*(int *)(f->f_devdata))))
return (EINVAL);
@@ -660,9 +665,8 @@ nfs_close(struct open_file *f)
printf("nfs_close: fp=0x%lx\n", (u_long)fp);
#endif
- if (fp)
- free(fp);
- f->f_fsdata = (void *)0;
+ free(fp);
+ f->f_fsdata = NULL;
return (0);
}
@@ -773,11 +777,12 @@ nfs_readdir(struct open_file *f, struct dirent *d)
struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata;
struct nfsv3_readdir_repl *repl;
struct nfsv3_readdir_entry *rent;
+ static void *pkt = NULL;
static char *buf;
static struct nfs_iodesc *pfp = NULL;
static uint64_t cookie = 0;
size_t cc;
- int pos;
+ int pos, rc;
struct args {
uint32_t fhsize;
@@ -787,14 +792,12 @@ nfs_readdir(struct open_file *f, struct dirent *d)
uint32_t h[RPC_HEADER_WORDS];
struct args d;
} sdata;
- static struct {
- uint32_t h[RPC_HEADER_WORDS];
- u_char d[NFS_READDIRSIZE];
- } rdata;
if (fp != pfp || fp->off != cookie) {
pfp = NULL;
refill:
+ free(pkt);
+ pkt = NULL;
args = &sdata.d;
bzero(args, sizeof(*args));
@@ -810,11 +813,16 @@ nfs_readdir(struct open_file *f, struct dirent *d)
cc = rpc_call(fp->iodesc, NFS_PROG, NFS_VER3, NFSPROCV3_READDIR,
args, 6 * sizeof(uint32_t) +
roundup(fp->fhsize, sizeof(uint32_t)),
- rdata.d, sizeof(rdata.d));
- buf = rdata.d;
+ (void **)&buf, &pkt);
+ if (cc == -1) {
+ rc = errno;
+ goto err;
+ }
repl = (struct nfsv3_readdir_repl *)buf;
- if (repl->errno != 0)
- return (ntohl(repl->errno));
+ if (repl->errno != 0) {
+ rc = ntohl(repl->errno);
+ goto err;
+ }
pfp = fp;
cookie = fp->off;
fp->cookie = ((uint64_t)ntohl(repl->cookiev0) << 32) |
@@ -826,8 +834,8 @@ nfs_readdir(struct open_file *f, struct dirent *d)
if (rent->follows == 0) {
/* fid0 is actually eof */
if (rent->fid0 != 0) {
- cookie = 0;
- return (ENOENT);
+ rc = ENOENT;
+ goto err;
}
goto refill;
}
@@ -842,4 +850,11 @@ nfs_readdir(struct open_file *f, struct dirent *d)
pos += 2;
buf = (u_char *)&rent->nameplus[pos];
return (0);
+
+err:
+ free(pkt);
+ pkt = NULL;
+ pfp = NULL;
+ cookie = 0;
+ return (rc);
}
diff --git a/lib/libstand/rarp.c b/lib/libstand/rarp.c
index 9ec050da1fbf..8d996d04a3f6 100644
--- a/lib/libstand/rarp.c
+++ b/lib/libstand/rarp.c
@@ -54,17 +54,17 @@ __FBSDID("$FreeBSD$");
static ssize_t rarpsend(struct iodesc *, void *, size_t);
-static ssize_t rarprecv(struct iodesc *, void *, size_t, time_t);
+static ssize_t rarprecv(struct iodesc *, void **, void **, time_t);
/*
* Ethernet (Reverse) Address Resolution Protocol (see RFC 903, and 826).
*/
int
-rarp_getipaddress(sock)
- int sock;
+rarp_getipaddress(int sock)
{
struct iodesc *d;
struct ether_arp *ap;
+ void *pkt;
struct {
u_char header[ETHER_SIZE];
struct {
@@ -72,13 +72,6 @@ rarp_getipaddress(sock)
u_char pad[18]; /* 60 - sizeof(arp) */
} data;
} wbuf;
- struct {
- u_char header[ETHER_SIZE];
- struct {
- struct ether_arp arp;
- u_char pad[24]; /* extra space */
- } data;
- } rbuf;
#ifdef RARP_DEBUG
if (debug)
@@ -102,21 +95,21 @@ rarp_getipaddress(sock)
ap->arp_op = htons(ARPOP_REVREQUEST);
bcopy(d->myea, ap->arp_sha, 6);
bcopy(d->myea, ap->arp_tha, 6);
+ pkt = NULL;
if (sendrecv(d,
rarpsend, &wbuf.data, sizeof(wbuf.data),
- rarprecv, &rbuf.data, sizeof(rbuf.data)) < 0)
- {
+ rarprecv, &pkt, (void *)&ap) < 0) {
printf("No response for RARP request\n");
return (-1);
}
- ap = &rbuf.data.arp;
bcopy(ap->arp_tpa, (char *)&myip, sizeof(myip));
#if 0
/* XXX - Can NOT assume this is our root server! */
bcopy(ap->arp_spa, (char *)&rootip, sizeof(rootip));
#endif
+ free(pkt);
/* Compute our "natural" netmask. */
if (IN_CLASSA(myip.s_addr))
@@ -134,10 +127,7 @@ rarp_getipaddress(sock)
* Broadcast a RARP request (i.e. who knows who I am)
*/
static ssize_t
-rarpsend(d, pkt, len)
- struct iodesc *d;
- void *pkt;
- size_t len;
+rarpsend(struct iodesc *d, void *pkt, size_t len)
{
#ifdef RARP_DEBUG
@@ -153,28 +143,26 @@ rarpsend(d, pkt, len)
* else -1 (and errno == 0)
*/
static ssize_t
-rarprecv(d, pkt, len, tleft)
- struct iodesc *d;
- void *pkt;
- size_t len;
- time_t tleft;
+rarprecv(struct iodesc *d, void **pkt, void **payload, time_t tleft)
{
ssize_t n;
struct ether_arp *ap;
- u_int16_t etype; /* host order */
+ void *ptr = NULL;
+ uint16_t etype; /* host order */
#ifdef RARP_DEBUG
if (debug)
printf("rarprecv: ");
#endif
- n = readether(d, pkt, len, tleft, &etype);
+ n = readether(d, ptr, (void **)&ap, tleft, &etype);
errno = 0; /* XXX */
if (n == -1 || n < sizeof(struct ether_arp)) {
#ifdef RARP_DEBUG
if (debug)
printf("bad len=%d\n", n);
#endif
+ free(ptr);
return (-1);
}
@@ -183,10 +171,10 @@ rarprecv(d, pkt, len, tleft)
if (debug)
printf("bad type=0x%x\n", etype);
#endif
+ free(ptr);
return (-1);
}
- ap = (struct ether_arp *)pkt;
if (ap->arp_hrd != htons(ARPHRD_ETHER) ||
ap->arp_pro != htons(ETHERTYPE_IP) ||
ap->arp_hln != sizeof(ap->arp_sha) ||
@@ -196,6 +184,7 @@ rarprecv(d, pkt, len, tleft)
if (debug)
printf("bad hrd/pro/hln/pln\n");
#endif
+ free(ptr);
return (-1);
}
@@ -204,6 +193,7 @@ rarprecv(d, pkt, len, tleft)
if (debug)
printf("bad op=0x%x\n", ntohs(ap->arp_op));
#endif
+ free(ptr);
return (-1);
}
@@ -213,6 +203,7 @@ rarprecv(d, pkt, len, tleft)
if (debug)
printf("unwanted address\n");
#endif
+ free(ptr);
return (-1);
}
@@ -221,5 +212,7 @@ rarprecv(d, pkt, len, tleft)
if (debug)
printf("got it\n");
#endif
+ *pkt = ptr;
+ *payload = ap;
return (n);
}
diff --git a/lib/libstand/rpc.c b/lib/libstand/rpc.c
index 79ee45af0ed5..932fdc98b903 100644
--- a/lib/libstand/rpc.c
+++ b/lib/libstand/rpc.c
@@ -97,7 +97,7 @@ struct rpc_reply {
};
/* Local forwards */
-static ssize_t recvrpc(struct iodesc *, void *, size_t, time_t);
+static ssize_t recvrpc(struct iodesc *, void **, void **, time_t);
static int rpc_getport(struct iodesc *, n_long, n_long);
int rpc_xid;
@@ -109,14 +109,14 @@ int rpc_port = 0x400; /* predecrement */
*/
ssize_t
rpc_call(struct iodesc *d, n_long prog, n_long vers, n_long proc,
- void *sdata, size_t slen, void *rdata, size_t rlen)
+ void *sdata, size_t slen, void **rdata, void **pkt)
{
- ssize_t cc;
+ ssize_t cc, rsize;
struct auth_info *auth;
struct rpc_call *call;
struct rpc_reply *reply;
char *send_head, *send_tail;
- char *recv_head, *recv_tail;
+ void *ptr;
n_long x;
int port; /* host order */
@@ -145,7 +145,6 @@ rpc_call(struct iodesc *d, n_long prog, n_long vers, n_long proc,
auth->authtype = htonl(RPCAUTH_NULL);
auth->authlen = 0;
-#if 1
/* Auth credentials: always auth unix (as root) */
send_head -= sizeof(struct auth_unix);
bzero(send_head, sizeof(struct auth_unix));
@@ -153,13 +152,6 @@ rpc_call(struct iodesc *d, n_long prog, n_long vers, n_long proc,
auth = (struct auth_info *)send_head;
auth->authtype = htonl(RPCAUTH_UNIX);
auth->authlen = htonl(sizeof(struct auth_unix));
-#else
- /* Auth credentials: always auth_null (XXX OK?) */
- send_head -= sizeof(*auth);
- auth = send_head;
- auth->authtype = htonl(RPCAUTH_NULL);
- auth->authlen = 0;
-#endif
/* RPC call structure. */
send_head -= sizeof(*call);
@@ -172,34 +164,28 @@ rpc_call(struct iodesc *d, n_long prog, n_long vers, n_long proc,
call->rp_vers = htonl(vers);
call->rp_proc = htonl(proc);
- /* Make room for the rpc_reply header. */
- recv_head = rdata;
- recv_tail = (char *)rdata + rlen;
- recv_head -= sizeof(*reply);
-
+ ptr = NULL;
cc = sendrecv(d,
sendudp, send_head, send_tail - send_head,
- recvrpc, recv_head, recv_tail - recv_head);
+ recvrpc, &ptr, (void **)&reply);
#ifdef RPC_DEBUG
if (debug)
- printf("callrpc: cc=%ld rlen=%lu\n", (long)cc, (u_long)rlen);
+ printf("callrpc: cc=%zd\n", cc);
#endif
if (cc == -1)
return (-1);
if (cc <= sizeof(*reply)) {
errno = EBADRPC;
+ free(ptr);
return (-1);
}
- recv_tail = recv_head + cc;
-
/*
* Check the RPC reply status.
* The xid, dir, astatus were already checked.
*/
- reply = (struct rpc_reply *)recv_head;
auth = &reply->rp_u.rpu_rok.rok_auth;
x = ntohl(auth->authlen);
if (x != 0) {
@@ -208,17 +194,21 @@ rpc_call(struct iodesc *d, n_long prog, n_long vers, n_long proc,
printf("callrpc: reply auth != NULL\n");
#endif
errno = EBADRPC;
- return(-1);
+ free(ptr);
+ return (-1);
}
x = ntohl(reply->rp_u.rpu_rok.rok_status);
if (x != 0) {
printf("callrpc: error = %ld\n", (long)x);
errno = EBADRPC;
- return(-1);
+ free(ptr);
+ return (-1);
}
- recv_head += sizeof(*reply);
- return (ssize_t)(recv_tail - recv_head);
+ rsize = cc - sizeof(*reply);
+ *rdata = (void *)((uintptr_t)reply + sizeof(*reply));
+ *pkt = ptr;
+ return (rsize);
}
/*
@@ -227,8 +217,9 @@ rpc_call(struct iodesc *d, n_long prog, n_long vers, n_long proc,
* Remaining checks are done by callrpc
*/
static ssize_t
-recvrpc(struct iodesc *d, void *pkt, size_t len, time_t tleft)
+recvrpc(struct iodesc *d, void **pkt, void **payload, time_t tleft)
{
+ void *ptr;
struct rpc_reply *reply;
ssize_t n;
int x;
@@ -236,14 +227,15 @@ recvrpc(struct iodesc *d, void *pkt, size_t len, time_t tleft)
errno = 0;
#ifdef RPC_DEBUG
if (debug)
- printf("recvrpc: called len=%lu\n", (u_long)len);
+ printf("recvrpc: called\n");
#endif
- n = readudp(d, pkt, len, tleft);
- if (n <= (4 * 4))
- return -1;
-
- reply = (struct rpc_reply *)pkt;
+ ptr = NULL;
+ n = readudp(d, &ptr, (void **)&reply, tleft);
+ if (n <= (4 * 4)) {
+ free(ptr);
+ return (-1);
+ }
x = ntohl(reply->rp_xid);
if (x != rpc_xid) {
@@ -251,7 +243,8 @@ recvrpc(struct iodesc *d, void *pkt, size_t len, time_t tleft)
if (debug)
printf("recvrpc: rp_xid %d != xid %d\n", x, rpc_xid);
#endif
- return -1;
+ free(ptr);
+ return (-1);
}
x = ntohl(reply->rp_direction);
@@ -260,16 +253,20 @@ recvrpc(struct iodesc *d, void *pkt, size_t len, time_t tleft)
if (debug)
printf("recvrpc: rp_direction %d != REPLY\n", x);
#endif
- return -1;
+ free(ptr);
+ return (-1);
}
x = ntohl(reply->rp_astatus);
if (x != RPC_MSGACCEPTED) {
errno = ntohl(reply->rp_u.rpu_errno);
printf("recvrpc: reject, astat=%d, errno=%d\n", x, errno);
- return -1;
+ free(ptr);
+ return (-1);
}
+ *pkt = ptr;
+ *payload = reply;
/* Return data count (thus indicating success) */
return (n);
}
@@ -387,11 +384,7 @@ rpc_getport(struct iodesc *d, n_long prog, n_long vers)
n_long h[RPC_HEADER_WORDS];
struct args d;
} sdata;
- struct {
- n_long h[RPC_HEADER_WORDS];
- struct res d;
- n_long pad;
- } rdata;
+ void *pkt;
ssize_t cc;
int port;
@@ -416,16 +409,18 @@ rpc_getport(struct iodesc *d, n_long prog, n_long vers)
args->vers = htonl(vers);
args->proto = htonl(IPPROTO_UDP);
args->port = 0;
- res = &rdata.d;
+ pkt = NULL;
cc = rpc_call(d, PMAPPROG, PMAPVERS, PMAPPROC_GETPORT,
- args, sizeof(*args), res, sizeof(*res));
+ args, sizeof(*args), (void **)&res, &pkt);
if (cc < sizeof(*res)) {
printf("getport: %s", strerror(errno));
errno = EBADRPC;
+ free(pkt);
return (-1);
}
port = (int)ntohl(res->port);
+ free(pkt);
rpc_pmap_putcache(d->destip, prog, vers, port);
diff --git a/lib/libstand/rpc.h b/lib/libstand/rpc.h
index a892a6939dd2..5efe83210142 100644
--- a/lib/libstand/rpc.h
+++ b/lib/libstand/rpc.h
@@ -48,7 +48,7 @@
/* RPC functions: */
ssize_t rpc_call(struct iodesc *, n_long, n_long, n_long,
- void *, size_t, void *, size_t);
+ void *, size_t, void **, void **);
void rpc_fromaddr(void *, struct in_addr *, u_short *);
int rpc_pmap_getcache(struct in_addr, u_int, u_int);
void rpc_pmap_putcache(struct in_addr, u_int, u_int, int);
diff --git a/lib/libstand/tftp.c b/lib/libstand/tftp.c
index b3d2da7b0ed9..922142c2a807 100644
--- a/lib/libstand/tftp.c
+++ b/lib/libstand/tftp.c
@@ -73,8 +73,8 @@ static int tftp_stat(struct open_file *f, struct stat *sb);
static ssize_t sendrecv_tftp(struct tftp_handle *h,
ssize_t (*sproc)(struct iodesc *, void *, size_t),
void *sbuf, size_t ssize,
- ssize_t (*rproc)(struct tftp_handle *h, void *, ssize_t, time_t, unsigned short *),
- void *rbuf, size_t rsize, unsigned short *rtype);
+ ssize_t (*rproc)(struct tftp_handle *h, void **, void **, time_t, unsigned short *),
+ void **, void **, unsigned short *rtype);
struct fs_ops tftp_fsops = {
"tftp",
@@ -114,11 +114,8 @@ struct tftp_handle {
char *path; /* saved for re-requests */
unsigned int tftp_blksize;
unsigned long tftp_tsize;
- struct {
- u_char header[HEADER_SIZE];
- struct tftphdr t;
- u_char space[TFTP_MAX_BLKSIZE];
- } __packed __aligned(4) lastdata;
+ void *pkt;
+ struct tftphdr *tftp_hdr;
};
#define TFTP_MAX_ERRCODE EOPTNEG
@@ -181,20 +178,23 @@ tftp_sendack(struct tftp_handle *h)
}
static ssize_t
-recvtftp(struct tftp_handle *h, void *pkt, ssize_t len, time_t tleft,
+recvtftp(struct tftp_handle *h, void **pkt, void **payload, time_t tleft,
unsigned short *rtype)
{
struct iodesc *d = h->iodesc;
struct tftphdr *t;
+ void *ptr = NULL;
+ ssize_t len;
errno = 0;
- len = readudp(d, pkt, len, tleft);
+ len = readudp(d, &ptr, (void **)&t, tleft);
- if (len < 4)
+ if (len < 4) {
+ free(ptr);
return (-1);
+ }
- t = (struct tftphdr *) pkt;
*rtype = ntohs(t->th_opcode);
switch (ntohs(t->th_opcode)) {
case DATA: {
@@ -204,6 +204,7 @@ recvtftp(struct tftp_handle *h, void *pkt, ssize_t len, time_t tleft,
/*
* Expected block?
*/
+ free(ptr);
return (-1);
}
if (d->xid == 1) {
@@ -211,11 +212,13 @@ recvtftp(struct tftp_handle *h, void *pkt, ssize_t len, time_t tleft,
* First data packet from new port.
*/
struct udphdr *uh;
- uh = (struct udphdr *) pkt - 1;
+ uh = (struct udphdr *) t - 1;
d->destport = uh->uh_sport;
} /* else check uh_sport has not changed??? */
- got = len - (t->th_data - (char *) t);
- return got;
+ got = len - (t->th_data - (char *)t);
+ *pkt = ptr;
+ *payload = t;
+ return (got);
}
case ERROR:
if ((unsigned) ntohs(t->th_code) > TFTP_MAX_ERRCODE) {
@@ -227,6 +230,7 @@ recvtftp(struct tftp_handle *h, void *pkt, ssize_t len, time_t tleft,
#endif
errno = tftperrors[ntohs(t->th_code)];
}
+ free(ptr);
return (-1);
case OACK: {
struct udphdr *uh;
@@ -237,6 +241,7 @@ recvtftp(struct tftp_handle *h, void *pkt, ssize_t len, time_t tleft,
* Drop the pkt.
*/
if (d->xid != 1) {
+ free(ptr);
return (-1);
}
@@ -244,7 +249,7 @@ recvtftp(struct tftp_handle *h, void *pkt, ssize_t len, time_t tleft,
* Remember which port this OACK came from, because we need
* to send the ACK or errors back to it.
*/
- uh = (struct udphdr *) pkt - 1;
+ uh = (struct udphdr *) t - 1;
d->destport = uh->uh_sport;
/* Parse options ACK-ed by the server. */
@@ -252,14 +257,18 @@ recvtftp(struct tftp_handle *h, void *pkt, ssize_t len, time_t tleft,
if (tftp_parse_oack(h, t->th_u.tu_stuff, tftp_oack_len) != 0) {
tftp_senderr(h, EOPTNEG, "Malformed OACK");
errno = EIO;
+ free(ptr);
return (-1);
}
+ *pkt = ptr;
+ *payload = t;
return (0);
}
default:
#ifdef TFTP_DEBUG
printf("tftp type %d not handled\n", ntohs(t->th_opcode));
#endif
+ free(ptr);
return (-1);
}
}
@@ -276,6 +285,7 @@ tftp_makereq(struct tftp_handle *h)
char *wtail;
int l;
ssize_t res;
+ void *pkt;
struct tftphdr *t;
char *tftp_blksize = NULL;
int blksize_l;
@@ -314,8 +324,6 @@ tftp_makereq(struct tftp_handle *h)
bcopy("0", wtail, 2);
wtail += 2;
- t = &h->lastdata.t;
-
/* h->iodesc->myport = htons(--tftpport); */
h->iodesc->myport = htons(tftpport + (getsecs() & 0x3ff));
h->iodesc->destport = htons(IPPORT_TFTP);
@@ -325,8 +333,17 @@ tftp_makereq(struct tftp_handle *h)
h->islastblock = 0;
h->validsize = 0;
+ pkt = NULL;
res = sendrecv_tftp(h, &sendudp, &wbuf.t, wtail - (char *) &wbuf.t,
- &recvtftp, t, sizeof(*t) + h->tftp_blksize, &rtype);
+ &recvtftp, &pkt, (void **)&t, &rtype);
+ if (res == -1) {
+ free(pkt);
+ return (errno);
+ }
+
+ free(h->pkt);
+ h->pkt = pkt;
+ h->tftp_hdr = t;
if (rtype == OACK)
return (tftp_getnextblock(h));
@@ -362,6 +379,7 @@ tftp_getnextblock(struct tftp_handle *h)
} __packed __aligned(4) wbuf;
char *wtail;
int res;
+ void *pkt;
struct tftphdr *t;
unsigned short rtype = 0;
wbuf.t.th_opcode = htons((u_short) ACK);
@@ -369,16 +387,20 @@ tftp_getnextblock(struct tftp_handle *h)
wbuf.t.th_block = htons((u_short) h->currblock);
wtail += 2;
- t = &h->lastdata.t;
-
h->iodesc->xid = h->currblock + 1; /* expected block */
+ pkt = NULL;
res = sendrecv_tftp(h, &sendudp, &wbuf.t, wtail - (char *) &wbuf.t,
- &recvtftp, t, sizeof(*t) + h->tftp_blksize, &rtype);
+ &recvtftp, &pkt, (void **)&t, &rtype);
- if (res == -1) /* 0 is OK! */
+ if (res == -1) { /* 0 is OK! */
+ free(pkt);
return (errno);
+ }
+ free(h->pkt);
+ h->pkt = pkt;
+ h->tftp_hdr = t;
h->currblock++;
h->validsize = res;
if (res < h->tftp_blksize)
@@ -405,14 +427,8 @@ tftp_open(const char *path, struct open_file *f)
if (netproto != NET_TFTP)
return (EINVAL);
- if (strcmp(f->f_dev->dv_name, "net") != 0) {
-#ifdef __i386__
- if (strcmp(f->f_dev->dv_name, "pxe") != 0)
- return (EINVAL);
-#else
+ if (f->f_dev->dv_type != DEVT_NET)
return (EINVAL);
-#endif
- }
if (is_open)
return (EBUSY);
@@ -507,7 +523,7 @@ tftp_read(struct open_file *f, void *addr, size_t size,
return (EINVAL);
}
count = (size < inbuffer ? size : inbuffer);
- bcopy(tftpfile->lastdata.t.th_data + offinblock,
+ bcopy(tftpfile->tftp_hdr->th_data + offinblock,
addr, count);
addr = (char *)addr + count;
@@ -540,6 +556,7 @@ tftp_close(struct open_file *f)
if (tftpfile) {
free(tftpfile->path);
+ free(tftpfile->pkt);
free(tftpfile);
}
is_open = 0;
@@ -591,8 +608,9 @@ static ssize_t
sendrecv_tftp(struct tftp_handle *h,
ssize_t (*sproc)(struct iodesc *, void *, size_t),
void *sbuf, size_t ssize,
- ssize_t (*rproc)(struct tftp_handle *, void *, ssize_t, time_t, unsigned short *),
- void *rbuf, size_t rsize, unsigned short *rtype)
+ ssize_t (*rproc)(struct tftp_handle *, void **, void **, time_t,
+ unsigned short *),
+ void **pkt, void **payload, unsigned short *rtype)
{
struct iodesc *d = h->iodesc;
ssize_t cc;
@@ -624,7 +642,7 @@ sendrecv_tftp(struct tftp_handle *h,
recvnext:
/* Try to get a packet and process it. */
- cc = (*rproc)(h, rbuf, rsize, tleft, rtype);
+ cc = (*rproc)(h, pkt, payload, tleft, rtype);
/* Return on data, EOF or real error. */
if (cc != -1 || errno != 0)
return (cc);
diff --git a/lib/libstand/udp.c b/lib/libstand/udp.c
index db5de892e855..2eba7a18eefc 100644
--- a/lib/libstand/udp.c
+++ b/lib/libstand/udp.c
@@ -59,10 +59,7 @@ __FBSDID("$FreeBSD$");
/* Caller must leave room for ethernet, ip and udp headers in front!! */
ssize_t
-sendudp(d, pkt, len)
- struct iodesc *d;
- void *pkt;
- size_t len;
+sendudp(struct iodesc *d, void *pkt, size_t len)
{
ssize_t cc;
struct ip *ip;
@@ -131,32 +128,29 @@ sendudp(d, pkt, len)
/*
* Receive a UDP packet and validate it is for us.
- * Caller leaves room for the headers (Ether, IP, UDP)
*/
ssize_t
-readudp(d, pkt, len, tleft)
- struct iodesc *d;
- void *pkt;
- size_t len;
- time_t tleft;
+readudp(struct iodesc *d, void **pkt, void **payload, time_t tleft)
{
ssize_t n;
size_t hlen;
struct ip *ip;
struct udphdr *uh;
- u_int16_t etype; /* host order */
+ uint16_t etype; /* host order */
+ void *ptr;
#ifdef NET_DEBUG
if (debug)
printf("readudp: called\n");
#endif
- uh = (struct udphdr *)pkt - 1;
- ip = (struct ip *)uh - 1;
-
- n = readether(d, ip, len + sizeof(*ip) + sizeof(*uh), tleft, &etype);
- if (n == -1 || n < sizeof(*ip) + sizeof(*uh))
- return -1;
+ ip = NULL;
+ ptr = NULL;
+ n = readether(d, &ptr, (void **)&ip, tleft, &etype);
+ if (n == -1 || n < sizeof(*ip) + sizeof(*uh)) {
+ free(ptr);
+ return (-1);
+ }
/* Ethernet address checks now in readether() */
@@ -167,7 +161,8 @@ readudp(d, pkt, len, tleft)
/* Send ARP reply */
arp_reply(d, ah);
}
- return -1;
+ free(ptr);
+ return (-1);
}
if (etype != ETHERTYPE_IP) {
@@ -175,7 +170,8 @@ readudp(d, pkt, len, tleft)
if (debug)
printf("readudp: not IP. ether_type=%x\n", etype);
#endif
- return -1;
+ free(ptr);
+ return (-1);
}
/* Check ip header */
@@ -185,7 +181,8 @@ readudp(d, pkt, len, tleft)
if (debug)
printf("readudp: IP version or not UDP. ip_v=%d ip_p=%d\n", ip->ip_v, ip->ip_p);
#endif
- return -1;
+ free(ptr);
+ return (-1);
}
hlen = ip->ip_hl << 2;
@@ -195,7 +192,8 @@ readudp(d, pkt, len, tleft)
if (debug)
printf("readudp: short hdr or bad cksum.\n");
#endif
- return -1;
+ free(ptr);
+ return (-1);
}
if (n < ntohs(ip->ip_len)) {
#ifdef NET_DEBUG
@@ -203,7 +201,8 @@ readudp(d, pkt, len, tleft)
printf("readudp: bad length %d < %d.\n",
(int)n, ntohs(ip->ip_len));
#endif
- return -1;
+ free(ptr);
+ return (-1);
}
if (d->myip.s_addr && ip->ip_dst.s_addr != d->myip.s_addr) {
#ifdef NET_DEBUG
@@ -212,12 +211,14 @@ readudp(d, pkt, len, tleft)
printf("%s\n", inet_ntoa(ip->ip_dst));
}
#endif
- return -1;
+ free(ptr);
+ return (-1);
}
+ uh = (struct udphdr *)((uintptr_t)ip + sizeof (*ip));
/* If there were ip options, make them go away */
if (hlen != sizeof(*ip)) {
- bcopy(((u_char *)ip) + hlen, uh, len - hlen);
+ bcopy(((u_char *)ip) + hlen, uh, uh->uh_ulen - hlen);
ip->ip_len = htons(sizeof(*ip));
n -= hlen - sizeof(*ip);
}
@@ -227,7 +228,8 @@ readudp(d, pkt, len, tleft)
printf("readudp: bad dport %d != %d\n",
d->myport, ntohs(uh->uh_dport));
#endif
- return -1;
+ free(ptr);
+ return (-1);
}
#ifndef UDP_NO_CKSUM
@@ -238,7 +240,8 @@ readudp(d, pkt, len, tleft)
n = ntohs(uh->uh_ulen) + sizeof(*ip);
if (n > RECV_SIZE - ETHER_SIZE) {
printf("readudp: huge packet, udp len %d\n", (int)n);
- return -1;
+ free(ptr);
+ return (-1);
}
/* Check checksum (must save and restore ip header) */
@@ -251,8 +254,8 @@ readudp(d, pkt, len, tleft)
if (debug)
printf("readudp: bad cksum\n");
#endif
- *ip = tip;
- return -1;
+ free(ptr);
+ return (-1);
}
*ip = tip;
}
@@ -263,10 +266,13 @@ readudp(d, pkt, len, tleft)
printf("readudp: bad udp len %d < %d\n",
ntohs(uh->uh_ulen), (int)sizeof(*uh));
#endif
- return -1;
+ free(ptr);
+ return (-1);
}
n = (n > (ntohs(uh->uh_ulen) - sizeof(*uh))) ?
ntohs(uh->uh_ulen) - sizeof(*uh) : n;
+ *pkt = ptr;
+ *payload = (void *)((uintptr_t)uh + sizeof(*uh));
return (n);
}