summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sbin/photurisd/handle_spi_update.c4
-rw-r--r--sbin/photurisd/kernel.c181
-rw-r--r--sbin/photurisd/kernel.h3
-rw-r--r--sbin/photurisd/log.h6
-rw-r--r--sbin/photurisd/photurisd.c8
-rw-r--r--sbin/photurisd/server.c10
-rw-r--r--sbin/photurisd/spi.c201
-rw-r--r--sbin/photurisd/spi.h10
8 files changed, 246 insertions, 177 deletions
diff --git a/sbin/photurisd/handle_spi_update.c b/sbin/photurisd/handle_spi_update.c
index 6fc1ed8df79..19c61296011 100644
--- a/sbin/photurisd/handle_spi_update.c
+++ b/sbin/photurisd/handle_spi_update.c
@@ -34,7 +34,7 @@
*/
#ifndef lint
-static char rcsid[] = "$Id: handle_spi_update.c,v 1.4 2000/12/11 21:21:17 provos Exp $";
+static char rcsid[] = "$Id: handle_spi_update.c,v 1.5 2000/12/14 23:28:57 provos Exp $";
#endif
#include <stdio.h>
@@ -150,8 +150,8 @@ handle_spi_update(u_char *packet, int size, char *address,
#ifdef IPSEC
kernel_unlink_spi(spi);
#endif
- spi_unlink(spi);
spi_value_reset(spi);
+ spi_unlink(spi);
return 0;
}
diff --git a/sbin/photurisd/kernel.c b/sbin/photurisd/kernel.c
index 3dfa10b93ff..d876cf6a114 100644
--- a/sbin/photurisd/kernel.c
+++ b/sbin/photurisd/kernel.c
@@ -39,7 +39,7 @@
*/
#ifndef lint
-static char rcsid[] = "$Id: kernel.c,v 1.14 2000/12/14 18:32:25 provos Exp $";
+static char rcsid[] = "$Id: kernel.c,v 1.15 2000/12/14 23:28:58 provos Exp $";
#endif
#include <time.h>
@@ -91,6 +91,14 @@ static int regsd; /* PFKEY socket for Register and Acquire */
static int pfkey_seq;
static pid_t pfkey_pid;
+struct pfmsg {
+ TAILQ_ENTRY(pfmsg) next;
+
+ struct sadb_msg *smsg;
+};
+
+TAILQ_HEAD(pflist, pfmsg) pfqueue;
+
/*
* Translate a Photuris ID into a data structure for the
* corresponding Kernel transform.
@@ -213,18 +221,20 @@ kernel_valid_auth(attrib_t *auth, u_int8_t *flag, u_int16_t size)
int
init_kernel(void)
{
- if ((sd = socket(PF_KEY, SOCK_RAW, PF_KEY_V2)) == -1)
- log_fatal(__FUNCTION__": socket(PF_KEY) for IPSec keyengine");
- if ((regsd = socket(PF_KEY, SOCK_RAW, PF_KEY_V2)) == -1)
- log_fatal(__FUNCTION__": socket() for PFKEY register");
+ TAILQ_INIT(&pfqueue);
+
+ if ((sd = socket(PF_KEY, SOCK_RAW, PF_KEY_V2)) == -1)
+ log_fatal(__FUNCTION__": socket(PF_KEY) for IPSec keyengine");
+ if ((regsd = socket(PF_KEY, SOCK_RAW, PF_KEY_V2)) == -1)
+ log_fatal(__FUNCTION__": socket() for PFKEY register");
- pfkey_seq = 0;
- pfkey_pid = getpid();
+ pfkey_seq = 0;
+ pfkey_pid = getpid();
- if (kernel_register(regsd) == -1)
- log_fatal(__FUNCTION__": PFKEY socket registration failed");
+ if (kernel_register(regsd) == -1)
+ log_fatal(__FUNCTION__": PFKEY socket registration failed");
- return (1);
+ return (1);
}
int
@@ -289,11 +299,37 @@ kernel_xf_set(int sd, char *buffer, int blen, struct iovec *iov,
return (1);
}
+void
+kernel_queue_msg(struct sadb_msg *smsg)
+{
+ struct pfmsg *pfmsg;
+
+ LOG_DBG((LOG_KERNEL, 50, __FUNCTION__": queuing message type %d",
+ smsg->sadb_msg_type));
+
+ pfmsg = malloc(sizeof(pfmsg));
+ if (pfmsg == NULL) {
+ log_error(__FUNCTION__": malloc");
+ return;
+ }
+
+ pfmsg->smsg = malloc(smsg->sadb_msg_len * 8);
+ if (pfmsg->smsg == NULL) {
+ log_error(__FUNCTION__": malloc");
+ free(pfmsg);
+ return;
+ }
+
+ memcpy(pfmsg->smsg, smsg, smsg->sadb_msg_len * 8);
+
+ TAILQ_INSERT_TAIL(&pfqueue, pfmsg, next);
+}
+
int
kernel_xf_read(int sd, char *buffer, int blen, int seq)
{
struct sadb_msg *sres = (struct sadb_msg *)buffer;
- int len;
+ int len, forus;
/*
* Read in response from the kernel. If seq number and/or PID are
@@ -302,7 +338,7 @@ kernel_xf_read(int sd, char *buffer, int blen, int seq)
*/
do {
if (recv(sd, sres, sizeof(*sres), MSG_PEEK) != sizeof(*sres)) {
- perror("read() in kernel_xf_read()");
+ log_error(__FUNCTION__": read()");
return (0);
}
len = sres->sadb_msg_len * 8;
@@ -314,10 +350,26 @@ kernel_xf_read(int sd, char *buffer, int blen, int seq)
log_error(__FUNCTION__": read()");
return (0);
}
- } while (seq && (sres->sadb_msg_seq != seq ||
- (sres->sadb_msg_pid && sres->sadb_msg_pid != pfkey_pid)
- ));
-
+
+ forus = !(sres->sadb_msg_pid && sres->sadb_msg_pid != pfkey_pid) &&
+ !(seq && sres->sadb_msg_seq != seq);
+
+ if (!forus) {
+ switch (sres->sadb_msg_type) {
+ case SADB_ACQUIRE:
+ case SADB_EXPIRE:
+ kernel_queue_msg(sres);
+ break;
+ default:
+ LOG_DBG((LOG_KERNEL, 50, __FUNCTION__
+ ": skipping message type %d",
+ sres->sadb_msg_type));
+ break;
+ }
+ }
+
+ } while (!forus);
+
if (sres->sadb_msg_errno) {
LOG_DBG((LOG_KERNEL, 40, __FUNCTION__": PFKEYV2 result: %s",
strerror(sres->sadb_msg_errno)));
@@ -325,9 +377,6 @@ kernel_xf_read(int sd, char *buffer, int blen, int seq)
return (0);
}
- if (sres->sadb_msg_pid && sres->sadb_msg_pid != pfkey_pid)
- return (0);
-
return (1);
}
@@ -1054,6 +1103,48 @@ kernel_unlink_spi(struct spiob *ospi)
return (1);
}
+void
+kernel_dispatch_notify(struct sadb_msg *sres)
+{
+ LOG_DBG((LOG_KERNEL, 60, __FUNCTION__": Got PFKEYV2 message: type %d",
+ sres->sadb_msg_type));
+
+ switch (sres->sadb_msg_type) {
+ case SADB_EXPIRE:
+ LOG_DBG((LOG_KERNEL, 55, __FUNCTION__": Got SA Expiration"));
+ kernel_handle_expire(sres);
+ break;
+ case SADB_ACQUIRE:
+ LOG_DBG((LOG_KERNEL, 55, __FUNCTION__
+ ": Got Notify SA Request (SADB_ACQUIRE): %d",
+ sres->sadb_msg_len * 8));
+ LOG_DBG_BUF((LOG_KERNEL, 60, "acquire buf",
+ (u_char *)sres, sres->sadb_msg_len * 8));
+
+
+ kernel_request_sa(sres);
+ break;
+ default:
+ /* discard silently */
+ return;
+ }
+}
+
+void
+kernel_handle_queue()
+{
+ struct pfmsg *pfmsg;
+
+ while (pfmsg = TAILQ_FIRST(&pfqueue)) {
+ TAILQ_REMOVE(&pfqueue, pfmsg, next);
+
+ kernel_dispatch_notify(pfmsg->smsg);
+
+ free(pfmsg->smsg);
+ free(pfmsg);
+ }
+}
+
/*
* Handles Notifies from the kernel, which can include Requests for new
* SAs, soft and hard expirations for already established SAs.
@@ -1062,39 +1153,25 @@ kernel_unlink_spi(struct spiob *ospi)
void
kernel_handle_notify(int sd)
{
- struct sadb_msg *sres = (struct sadb_msg *)buffer;
- size_t len;
-
- if (!kernel_xf_read(regsd, buffer, BUFFER_SIZE, 0))
- return;
-
- LOG_DBG((LOG_KERNEL, 60, __FUNCTION__": Got PFKEYV2 message: type %d",
- sres->sadb_msg_type));
-
- switch (sres->sadb_msg_type) {
- case SADB_EXPIRE:
- LOG_DBG((LOG_KERNEL, 60, __FUNCTION__": Got SA Expiration"));
- kernel_handle_expire(sres);
- break;
- case SADB_ACQUIRE:
- LOG_DBG((LOG_KERNEL, 60, __FUNCTION__
- ": Got Notify SA Request (SADB_ACQUIRE): %d",
- sres->sadb_msg_len * 8));
- LOG_DBG_BUF((LOG_KERNEL, 60, "acquire buf",
- (u_char *)sres, sres->sadb_msg_len * 8));
-
- len = sres->sadb_msg_len * 8;
- sres = malloc(len);
- if (sres) {
- memcpy(sres, buffer, len);
- kernel_request_sa(sres);
- free(sres);
- }
- break;
- default:
- /* discard silently */
- return;
- }
+ struct sadb_msg *sres = (struct sadb_msg *)buffer;
+ size_t len;
+
+ if (!kernel_xf_read(regsd, buffer, BUFFER_SIZE, 0)) {
+ LOG_DBG((LOG_KERNEL, 65, __FUNCTION__": nothing to read"));
+ return;
+ }
+
+ len = sres->sadb_msg_len * 8;
+ sres = malloc(len);
+ if (!sres) {
+ log_error(__FUNCTION__": malloc");
+ return;
+ }
+ memcpy(sres, buffer, len);
+
+ kernel_dispatch_notify(sres);
+
+ free(sres);
}
struct sadb_msg *
diff --git a/sbin/photurisd/kernel.h b/sbin/photurisd/kernel.h
index 7a6c54ada86..194eb181a9c 100644
--- a/sbin/photurisd/kernel.h
+++ b/sbin/photurisd/kernel.h
@@ -27,7 +27,7 @@
* (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: kernel.h,v 1.8 2000/12/14 18:32:25 provos Exp $ */
+/* $Id: kernel.h,v 1.9 2000/12/14 23:28:58 provos Exp $ */
/*
* kernel.h:
* security paramter index creation.
@@ -115,5 +115,6 @@ EXTERN int kernel_get_socket(void);
EXTERN void kernel_set_socket_policy(int sd);
EXTERN void kernel_handle_notify(int sd);
EXTERN void kernel_notify_result(struct stateob *, struct spiob *, int);
+EXTERN void kernel_handle_queue(void);
#endif /* _KERNEL_H */
diff --git a/sbin/photurisd/log.h b/sbin/photurisd/log.h
index 2b395cad014..43d5379ded9 100644
--- a/sbin/photurisd/log.h
+++ b/sbin/photurisd/log.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: log.h,v 1.1 2000/12/11 21:21:18 provos Exp $ */
+/* $OpenBSD: log.h,v 1.2 2000/12/14 23:28:58 provos Exp $ */
/* $EOM: log.h,v 1.19 2000/03/30 14:27:23 ho Exp $ */
/*
@@ -47,11 +47,11 @@
#define LOG_SIZE 200
enum log_classes {
- LOG_MISC, LOG_TRANSPORT, LOG_CRYPTO, LOG_TIMER, LOG_SA, LOG_KERNEL,
+ LOG_MISC, LOG_TRANSPORT, LOG_CRYPTO, LOG_TIMER, LOG_SPI, LOG_KERNEL,
LOG_ENDCLASS
};
#define LOG_CLASSES_TEXT \
- { "Misc", "Trpt", "Cryp", "Timr", "SA ", "Kern" }
+ { "Misc", "Trpt", "Cryp", "Timr", "SPI ", "Kern" }
/*
* "Class" LOG_REPORT will always be logged to the current log channel,
diff --git a/sbin/photurisd/photurisd.c b/sbin/photurisd/photurisd.c
index 58c09faff95..ab6c29d3576 100644
--- a/sbin/photurisd/photurisd.c
+++ b/sbin/photurisd/photurisd.c
@@ -32,7 +32,7 @@
*/
#ifndef lint
-static char rcsid[] = "$Id: photurisd.c,v 1.6 2000/12/11 21:21:18 provos Exp $";
+static char rcsid[] = "$Id: photurisd.c,v 1.7 2000/12/14 23:28:58 provos Exp $";
#endif
#define _PHOTURIS_C_
@@ -162,6 +162,8 @@ main(int argc, char **argv)
argc -= optind;
argv += optind;
+ spi_init();
+
init_vars();
init_times();
@@ -170,12 +172,12 @@ main(int argc, char **argv)
init_schemes();
-#ifndef DEBUG
+#ifndef USE_DEBUG
init_signals();
if (fork())
exit(0);
daemon_mode = 1;
-#endif
+#endif /* USE_DEBUG */
#ifdef IPSEC
init_kernel();
diff --git a/sbin/photurisd/server.c b/sbin/photurisd/server.c
index 210e090d367..13ac367262d 100644
--- a/sbin/photurisd/server.c
+++ b/sbin/photurisd/server.c
@@ -35,7 +35,7 @@
*/
#ifndef lint
-static char rcsid[] = "$Id: server.c,v 1.5 2000/12/12 01:53:42 provos Exp $";
+static char rcsid[] = "$Id: server.c,v 1.6 2000/12/14 23:28:59 provos Exp $";
#endif
#define _SERVER_C_
@@ -320,6 +320,14 @@ server(void)
}
}
+#ifdef IPSEC
+ /*
+ * Deal with queue acquire and expire message, since we
+ * dont have proper timeout code, it needs to go here.
+ */
+ kernel_handle_queue();
+#endif
+
schedule_process(global_socket);
fflush(stdout);
fflush(stderr);
diff --git a/sbin/photurisd/spi.c b/sbin/photurisd/spi.c
index c8345d6d50a..fb140b3a8f2 100644
--- a/sbin/photurisd/spi.c
+++ b/sbin/photurisd/spi.c
@@ -33,11 +33,13 @@
*/
#ifndef lint
-static char rcsid[] = "$Id: spi.c,v 1.4 2000/12/11 21:21:18 provos Exp $";
+static char rcsid[] = "$Id: spi.c,v 1.5 2000/12/14 23:28:59 provos Exp $";
#endif
#define _SPI_C_
+#include <sys/types.h>
+#include <sys/queue.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -58,13 +60,19 @@ static char rcsid[] = "$Id: spi.c,v 1.4 2000/12/11 21:21:18 provos Exp $";
#endif
-static struct spiob *spiob = NULL;
+TAILQ_HEAD(spilist, spiob) spihead;
+
+void
+spi_init(void)
+{
+ TAILQ_INIT(&spihead);
+}
time_t
getspilifetime(struct stateob *st)
{
/* XXX - destination depend lifetimes */
- return st->spi_lifetime;
+ return (st->spi_lifetime);
}
int
@@ -78,7 +86,7 @@ make_spi(struct stateob *st, char *local_address,
if(*attributes == NULL) { /* We are in need of attributes */
if (select_attrib(st, attributes, attribsize) == -1) {
log_print("select_attrib() in make_spi()");
- return -1;
+ return (-1);
}
}
@@ -102,104 +110,96 @@ make_spi(struct stateob *st, char *local_address,
*lifetime = getspilifetime(st) + (arc4random() & 0x1F);
- return 0;
+ return (0);
}
int
spi_insert(struct spiob *ob)
{
- struct spiob *tmp;
-
- ob->next = NULL;
+ TAILQ_INSERT_TAIL(&spihead, ob, next);
- if(spiob == NULL) {
- spiob = ob;
- return 1;
- }
-
- tmp=spiob;
- while(tmp->next!=NULL)
- tmp = tmp->next;
-
- tmp->next = ob;
- return 1;
+ return (1);
}
int
spi_unlink(struct spiob *ob)
{
- struct spiob *tmp;
- if(spiob == ob) {
- spiob = ob->next;
- free(ob);
- return 1;
- }
+ LOG_DBG((LOG_SPI, 45, __FUNCTION__": unlinking %s spi %x",
+ ob->flags & SPI_OWNER ? "Owner" : "User",
+ ntohl(*(u_int32_t *)ob->SPI)));
- for(tmp=spiob; tmp!=NULL; tmp=tmp->next) {
- if(tmp->next==ob) {
- tmp->next=ob->next;
- free(ob);
- return 1;
- }
- }
- return 0;
+ TAILQ_REMOVE(&spihead, ob, next);
+ free(ob);
+
+ return (1);
}
struct spiob *
spi_new(char *address, u_int8_t *spi)
{
struct spiob *p;
+
if (spi_find(address, spi) != NULL)
- return NULL;
+ return (NULL);
if ((p = calloc(1, sizeof(struct spiob))) == NULL)
- return NULL;
+ return (NULL);
if ((p->address = strdup(address)) == NULL) {
free(p);
- return NULL;
+ return (NULL);
}
bcopy(spi, p->SPI, SPI_SIZE);
- return p;
+ return (p);
}
int
spi_value_reset(struct spiob *ob)
{
- if (ob->address != NULL)
- free(ob->address);
- if (ob->local_address != NULL)
- free(ob->local_address);
- if (ob->attributes != NULL)
- free(ob->attributes);
- if (ob->sessionkey != NULL)
- free(ob->sessionkey);
-
- return 1;
+ if (ob->address != NULL) {
+ free(ob->address);
+ ob->address = NULL;
+ }
+ if (ob->local_address != NULL) {
+ free(ob->local_address);
+ ob->local_address = NULL;
+ }
+ if (ob->attributes != NULL) {
+ free(ob->attributes);
+ ob->attributes = NULL;
+ }
+ if (ob->sessionkey != NULL) {
+ memset(ob->sessionkey, 0, ob->sessionkeysize);
+ free(ob->sessionkey);
+ ob->sessionkey = NULL;
+ }
+
+ return (1);
}
struct spiob *
spi_find_attrib(char *address, u_int8_t *attrib, u_int16_t attribsize)
{
- struct spiob *tmp = spiob;
+ struct spiob *tmp;
u_int16_t i;
- while(tmp!=NULL) {
- if(!strcmp(address, tmp->address)) {
- for(i=0;i<attribsize; i += attrib[i+1]+2) {
- if (attrib[i] == AT_AH_ATTRIB || attrib[i] == AT_ESP_ATTRIB)
- continue;
+ for (tmp = TAILQ_FIRST(&spihead); tmp; tmp = TAILQ_NEXT(tmp, next)) {
+ if (!strcmp(address, tmp->address)) {
+ for (i = 0; i < attribsize; i += attrib[i + 1] + 2) {
+ if (attrib[i] == AT_AH_ATTRIB ||
+ attrib[i] == AT_ESP_ATTRIB)
+ continue;
if (!isinattrib(tmp->attributes, tmp->attribsize, attrib[i]))
break;
}
if (i == attribsize)
- return tmp;
+ return (tmp);
}
- tmp = tmp->next;
}
- return NULL;
+
+ return (NULL);
}
/*
@@ -211,67 +211,48 @@ spi_find_attrib(char *address, u_int8_t *attrib, u_int16_t attribsize)
struct spiob *
spi_find(char *address, u_int8_t *spi)
{
- struct spiob *tmp = spiob;
- while(tmp!=NULL) {
- if ((address == NULL || (tmp->flags & SPI_OWNER ?
- !strcmp(address, tmp->local_address) :
- !strcmp(address, tmp->address))) &&
- !bcmp(spi, tmp->SPI, SPI_SIZE))
- return tmp;
- tmp = tmp->next;
- }
- return NULL;
-}
+ struct spiob *tmp;
-struct spiob *
-spi_root(void)
-{
- return spiob;
-}
+ for (tmp = TAILQ_FIRST(&spihead); tmp; tmp = TAILQ_NEXT(tmp, next)) {
+ if (bcmp(spi, tmp->SPI, SPI_SIZE))
+ continue;
-void
-spi_cleanup()
-{
- struct spiob *p;
- struct spiob *tmp = spiob;
- while(tmp!=NULL) {
- p = tmp;
- tmp = tmp->next;
- spi_value_reset(p);
- free(p);
- }
- spiob = NULL;
+ if (address == NULL)
+ break;
+
+ if (tmp->flags & SPI_OWNER ?
+ !strcmp(address, tmp->local_address) :
+ !strcmp(address, tmp->address))
+ break;
+ }
+
+ return (tmp);
}
void
spi_expire(void)
{
- struct spiob *tmp = spiob, *p;
- time_t tm;
-
- tm = time(NULL);
- while (tmp != NULL) {
- if (tmp->lifetime == -1 ||
- tmp->lifetime + (tmp->flags & SPI_OWNER ?
- CLEANUP_TIMEOUT : 0) > tm) {
- tmp = tmp->next;
- continue;
- }
-#ifdef DEBUG
- {
- int i = BUFFER_SIZE;
- bin2hex(buffer, &i, tmp->SPI, 4);
- printf("Expiring %s spi %s to %s\n",
- tmp->flags & SPI_OWNER ? "Owner" : "User",
- buffer, tmp->address);
- }
-#endif
+ struct spiob *tmp, *next;
+ time_t tm;
+
+ tm = time(NULL);
+ for (tmp = TAILQ_FIRST(&spihead); tmp; tmp = next) {
+ next = TAILQ_NEXT(tmp, next);
+
+ if (tmp->lifetime == -1 ||
+ tmp->lifetime + (tmp->flags & SPI_OWNER ?
+ CLEANUP_TIMEOUT : 0) > tm)
+ continue;
+
+ LOG_DBG((LOG_SPI, 30, __FUNCTION__
+ ": expiring %s spi %x to %s",
+ tmp->flags & SPI_OWNER ? "Owner" : "User",
+ ntohl(*(u_int32_t *)tmp->SPI), tmp->address));
+
#ifdef IPSEC
- kernel_unlink_spi(tmp);
+ kernel_unlink_spi(tmp);
#endif
- p = tmp;
- tmp = tmp->next;
- spi_value_reset(p);
- spi_unlink(p);
- }
+ spi_value_reset(tmp);
+ spi_unlink(tmp);
+ }
}
diff --git a/sbin/photurisd/spi.h b/sbin/photurisd/spi.h
index 19ca0535560..b20224fb4d7 100644
--- a/sbin/photurisd/spi.h
+++ b/sbin/photurisd/spi.h
@@ -27,7 +27,7 @@
* (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: spi.h,v 1.3 2000/12/11 20:32:15 provos Exp $ */
+/* $Id: spi.h,v 1.4 2000/12/14 23:28:59 provos Exp $ */
/*
* spi.h:
* security paramter index creation.
@@ -35,7 +35,7 @@
#ifndef _SPI_H_
#define _SPI_H_
-
+#include <sys/queue.h>
#include "state.h"
#undef EXTERN
@@ -53,7 +53,8 @@
#define SPI_ESP 8 /* Is used for ESP */
struct spiob {
- struct spiob *next; /* Linked list */
+ TAILQ_ENTRY(spiob) next; /* Linked list */
+
char *address;
char *local_address;
int flags;
@@ -66,6 +67,7 @@ struct spiob {
time_t lifetime; /* Lifetime for the SPI */
};
+EXTERN void spi_init(void);
EXTERN time_t getspilifetime(struct stateob *st);
EXTERN int make_spi(struct stateob *st, char *local_address,
u_int8_t *SPI, time_t *lifetime,
@@ -78,8 +80,6 @@ EXTERN int spi_value_reset(struct spiob *);
EXTERN struct spiob *spi_find_attrib(char *address,
u_int8_t *attrib, u_int16_t attribsize);
EXTERN struct spiob *spi_find(char *, u_int8_t *);
-EXTERN struct spiob *spi_root(void);
-EXTERN void spi_cleanup(void);
EXTERN void spi_expire(void);
#endif /* _SPI_H */