PERFORCE change 164441 for review

Jonathan Anderson jona at FreeBSD.org
Mon Jun 15 17:56:17 UTC 2009


http://perforce.freebsd.org/chv.cgi?CH=164441

Change 164441 by jona at jona-trustedbsd-belle-vm on 2009/06/15 17:55:46

	Sandbox/angel RPC to request single files and powerboxes

Affected files ...

.. //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/Makefile#5 edit
.. //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/cap.c#3 edit
.. //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/fdtest.c#4 edit
.. //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/powerbox.c#3 edit
.. //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/powerbox.h#3 edit
.. //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/protocol.c#8 edit
.. //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/protocol.h#7 edit
.. //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/server.c#4 edit
.. //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/test_client.c#4 edit

Differences ...

==== //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/Makefile#5 (text+ko) ====

@@ -1,25 +1,22 @@
-CFLAGS=-g -ggdb --std=c99 -Wall -Werror #-pedantic-errors
+VERSION=dev-pre1
+CFLAGS=-g -ggdb --std=c99 -Wall -Werror -pedantic-errors -DVERSION='"${VERSION}"'
+LDFLAGS=-L/usr/local/lib -lefence
 
-BIN=user_angel test_client fdtest
-AGENT_OBJ = user_angel.o server.o cap.o protocol.o fdcomm.o powerbox.o
-CLIENT_OBJ = test_client.o protocol.o fdcomm.o
+BIN=user_angel test_client
+AGENT_OBJ = user_angel.o server.o cap.o protocol.o powerbox.o
+CLIENT_OBJ = test_client.o protocol.o
 
 
 all: ${BIN}
 
 user_angel: ${AGENT_OBJ}
-	${CC} -o $@ ${AGENT_OBJ}
+	${CC} ${LDFLAGS} -o $@ ${AGENT_OBJ}
 
 test_client: ${CLIENT_OBJ}
-	${CC} -o $@ ${CLIENT_OBJ}
+	${CC} ${LDFLAGS} -o $@ ${CLIENT_OBJ}
 
-fdtest: fdtest.o fdcomm.o protocol.o
-	${CC} -o $@ fdtest.o fdcomm.o protocol.o
-
 
 cap.o: cap.c cap.h
-fdcomm.o: fdcomm.c fdcomm.h
-fdtest.o: fdtest.c protocol.h
 powerbox.o: powerbox.c powerbox.h
 protocol.o: protocol.c protocol.h powerbox.h
 server.o: server.c protocol.h server.h

==== //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/cap.c#3 (text+ko) ====

@@ -47,6 +47,7 @@
 	int cap = cap_new(fd, rights);
 	if(cap < 0) err(EX_SOFTWARE, "failed to create new capability");
 
+	close(fd);
 	return cap;
 }
 

==== //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/fdtest.c#4 (text+ko) ====

@@ -85,7 +85,7 @@
 
 
 	struct cap_wire_datum *d = cap_marshall_string(message, strlen(message));
-	if(cap_send_fd(sock, "message and FDs", d, fds, fdlen) < 0)
+	if(cap_send_fd(sock, d, fds, fdlen) < 0)
 		err(EX_IOERR, "Error sending data/FD");
 
 	free(d);
@@ -94,9 +94,8 @@
 	int fd_array[10];
 	fdlen = 10;
 
-	char *name;
-	if(cap_recv_fd(sock, &name, &d, fd_array, &fdlen) < 0)
-		err(EX_IOERR, "Error receiving data/FD");
+	d = cap_recv_fds(sock, fd_array, &fdlen);
+	if(!d) err(EX_IOERR, "Error receiving data/FD");
 
 	printf("Received datum:\n");
 	printf("  type: %i\n", d->type);

==== //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/powerbox.c#3 (text+ko) ====

@@ -34,12 +34,16 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
+#include <fcntl.h>
 #include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 
 #include "powerbox.h"
 
 
-int capbox_display(struct capbox_options *options)
+int capbox_display(struct capbox_options *options, int fds[], char *names[],
+                   int *len)
 {
 	printf("capbox_display()\n");
 	printf("  options:\n");
@@ -73,8 +77,26 @@
 	if(options->filterlen > 0) printf("%s\n", options->filter);
 	else printf("<none>\n");
 
-	fprintf(stderr, "powerbox not implemented\n");
+	fprintf(stderr, "powerbox not implemented, faking it\n");
+
+	if(*len > 0)
+	{
+		names[0] = (char*) malloc(32);
+		strcpy(names[0], "/etc/hosts");
+
+		fds[0] = open("/etc/hosts", O_RDONLY);
+	}
+
+	if(*len > 1)
+	{
+		names[1] = (char*) malloc(32);
+		strcpy(names[1], "/etc/nsswitch.conf");
+
+		fds[1] = open("/etc/nsswitch.conf", O_RDONLY);
+	}
+
+	if(*len > 2) *len = 2;
 
-	return -1;
+	return 0;
 }
 

==== //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/powerbox.h#3 (text+ko) ====

@@ -48,11 +48,11 @@
 	enum capbox_op_t	operation;     /* operation to perform */
 	char*			window_title;  /* set by user_angel, not sandbox */
 	int			parent_window; /* X11 window to attach to (or 0) */
-	char*			start_path;    /* path to start in (or NULL) */
+	const char*		start_path;    /* path to start in (or NULL) */
 	int			pathlen;       /* length of start path */
 	int			start_fd;      /* FD to start in (or -1) */
 	int			mult;          /* allow multiple selection */
-	char*			filter;        /* filter expression (or NULL) */
+	const char*		filter;        /* filter expression (or NULL) */
 	int			filterlen;     /* length of filter expression */
 };
 
@@ -60,7 +60,8 @@
 /**
  * Open a powerbox.
  *
- * @return  a capability file descriptor or -1
+ * @return  0 on success
  */
-int capbox_display(struct capbox_options *options);
+int capbox_display(struct capbox_options *options, int fds[], char *names[],
+                   int *len);
 

==== //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/protocol.c#8 (text+ko) ====

@@ -45,85 +45,305 @@
 
 
 
-struct cap_wire_datum* cap_marshall_int(int32_t value)
+
+
+void print_datum(const struct cap_wire_datum *d)
+{
+	printf("Datum @ 0x%8x:\n", (unsigned int) d);
+	printf("  type: %i\n", d->type);
+	printf("  length: %i\n", d->length);
+	printf("  data: ");
+	for(int j = 0; j < d->length; j++)
+	{
+		unsigned char *address = ((unsigned char*) d);
+		address += sizeof(struct cap_wire_datum) + j;
+
+		printf("%02x ", *address);
+	}
+	printf("\n");
+}
+
+
+
+
+typedef struct cap_wire_datum wire_datum;
+
+
+char errmsg[256];
+const char* cap_error(void) { return errmsg; }
+
+
+wire_datum* cap_marshall_int(int32_t value)
 {
-	int size = sizeof(struct cap_wire_datum) + sizeof(int32_t);
-	struct cap_wire_datum *d = (struct cap_wire_datum*) malloc(size);
+	int size = sizeof(wire_datum) + sizeof(int32_t);
+	wire_datum *d = (wire_datum*) malloc(size);
 	
 	d->type = INTEGER;
 	d->length = sizeof(int32_t);
-	((int32_t*) d + sizeof(struct cap_wire_datum))[0] = value;
+
+	void *address = ((char*) d) + sizeof(wire_datum);
+	((int32_t*) address)[0] = value;
 
 	return d;
 }
 
 
 
-int cap_unmarshall_int(struct cap_wire_datum *datum, int32_t *value)
+int cap_unmarshall_int(const wire_datum *datum, int32_t *value)
 {
+	if(datum == NULL)
+	{
+		sprintf(errmsg, "Datum is NULL");
+		return -1;
+	}
+
+	if(!(datum->type & INTEGER))
+	{
+		sprintf(errmsg, "Datum's type is %i, not INTEGER (%i)",
+		        datum->type, INTEGER);
+		return -1;
+	}
+
 	if(datum->length != 4)
 	{
-		fprintf(stderr, "Error unmarshalling int: should be 4B long, not %i\n",
-		                datum->length);
+		sprintf(errmsg, "An 32-bit integer should be 4B long, not %i",
+		        datum->length);
 		return -1;
 	}
 
-	memcpy(value, ((void*) datum) + sizeof(struct cap_wire_datum), 4);
+	memcpy(value, ((char*) datum) + sizeof(wire_datum), 4);
 	return datum->length;
 }
 
 
-struct cap_wire_datum* cap_marshall_string(char *value, int len)
+wire_datum* cap_marshall_string(const char *value, int len)
 {
-	int size = sizeof(struct cap_wire_datum) + len;
-	struct cap_wire_datum *d = (struct cap_wire_datum*) malloc(size);
+	int size = sizeof(wire_datum) + len;
+	wire_datum *d = (wire_datum*) malloc(size);
 	
 	d->type = STRING;
 	d->length = len;
-	memcpy(((char*) d) + sizeof(struct cap_wire_datum), value, len);
+	memcpy(((char*) d) + sizeof(wire_datum), value, len);
 
 	return d;
 }
 
 
-int cap_unmarshall_string(struct cap_wire_datum *datum, char *value, int *len)
+int cap_unmarshall_string(const wire_datum *datum, char *value, int *len)
 {
+	if(datum == NULL)
+	{
+		sprintf(errmsg, "NULL datum");
+		return -1;
+	}
+	else if(datum->type != STRING)
+	{
+		sprintf(errmsg, "Datum's type is %i, not STRING (%i)",
+		        datum->type, STRING);
+	}
+	else if(datum->length < 0)
+	{
+		sprintf(errmsg, "Datum length should be positive, not %i",
+		                datum->length);
+		return -1;
+	}
+	else if(datum->length >= *len)
+	{
+		sprintf(errmsg, "String in datum is too long (%iB) to fit in buffer (%iB)",
+		        datum->length, *len);
+		return -1;
+	}
+
 	*len = datum->length;
-	if(datum->length < 0)
+	memcpy(value, ((char*) datum) + sizeof(wire_datum), datum->length);
+	value[*len] = '\0';
+
+	return datum->length;
+}
+
+
+wire_datum* cap_marshall_capbox(const struct capbox_options *options)
+{
+	wire_datum *data[6];
+	data[0] = cap_marshall_int(options->ui);
+	data[1] = cap_marshall_int(options->operation);
+	data[2] = cap_marshall_int(options->parent_window);
+	data[3] = cap_marshall_string(options->start_path, options->pathlen);
+	data[4] = cap_marshall_int(options->mult);
+	data[5] = cap_marshall_string(options->filter, options->filterlen);
+
+	int total_size = 0;
+	for(int i = 0; i < 6; i++)
+		if(data[i] == NULL)
+		{
+			sprintf(errmsg, "Capbox datum %i is NULL", i);
+			return NULL;
+		}
+		else total_size += (sizeof(wire_datum) + data[i]->length);
+
+	wire_datum *d = (wire_datum*) malloc(sizeof(wire_datum) + total_size);
+	d->type = CAPBOX_OPTIONS;
+	d->length = total_size;
+
+	char *buffer = ((char*) d) + sizeof(wire_datum);
+	char *head = buffer;
+	for(int i = 0; i < 6; i++)
+	{
+		memcpy(head, data[i], sizeof(wire_datum) + data[i]->length);
+		head += sizeof(wire_datum) + data[i]->length;
+
+		free(data[i]);
+	}
+
+	return d;
+}
+
+
+int cap_unmarshall_capbox(const wire_datum *datum, struct capbox_options *options)
+{
+	if(datum == NULL)
+	{
+		sprintf(errmsg, "NULL datum");
+		return -1;
+	}
+	else if(datum->type != CAPBOX_OPTIONS)
+	{
+		sprintf(errmsg, "Datum's type is %i, not CAPBOX_OPTIONS (%i)",
+		        datum->type, CAPBOX_OPTIONS);
+	}
+	else if(datum->length < 0)
 	{
-		fprintf(stderr, "Error unmarshalling int: should be positive, not %i\n",
+		sprintf(errmsg, "Datum length should be positive, not %i",
 		                datum->length);
 		return -1;
 	}
 
-	memcpy(value, ((void*) datum) + sizeof(struct cap_wire_datum), datum->length);
-	return datum->length;
+	int32_t tmp_int;
+	wire_datum *d = (wire_datum*) (((char*) datum) + sizeof(wire_datum));
+
+	if(cap_unmarshall_int(d, &tmp_int) < 0)
+	{
+		char error[128];
+		sprintf(error, "Error unmarshalling UI type: %s", cap_error());
+		strcpy(errmsg, error);
+		return -1;
+	}
+	options->ui = tmp_int;
+	d = (wire_datum*) (((char*) d) + sizeof(wire_datum) + d->length);
+
+	if(cap_unmarshall_int(d, &tmp_int) < 0)
+	{
+		char error[128];
+		sprintf(error, "Error unmarshalling operation: %s", cap_error());
+		strcpy(errmsg, error);
+		return -1;
+	}
+	options->operation = tmp_int;
+	d = (wire_datum*) (((char*) d) + sizeof(wire_datum) + d->length);
+
+
+	// window title is handled elsewhere
+
+
+	if(cap_unmarshall_int(d, &tmp_int) < 0)
+	{
+		char error[128];
+		sprintf(error, "Error unmarshalling parent: %s", cap_error());
+		strcpy(errmsg, error);
+		return -1;
+	}
+	options->parent_window = tmp_int;
+	d = (wire_datum*) (((char*) d) + sizeof(wire_datum) + d->length);
+
+	options->pathlen = d->length + 1;
+	options->start_path = (char*) malloc(options->pathlen);
+	if(cap_unmarshall_string(d, (char*) options->start_path, &options->pathlen) < 0)
+	{
+		char error[128];
+		sprintf(error, "Error unmarshalling path: %s", cap_error());
+		strcpy(errmsg, error);
+		return -1;
+	}
+	d = (wire_datum*) (((char*) d) + sizeof(wire_datum) + d->length);
+
+
+	// don't do anything about the start_fd file descriptor;
+	// that's handled at the recvmsg() level
+
+
+	if(cap_unmarshall_int(d, &tmp_int) < 0)
+	{
+		char error[128];
+		sprintf(error, "Error unmarshalling 'mult': %s", cap_error());
+		strcpy(errmsg, error);
+		return -1;
+	}
+	options->mult = tmp_int;
+	d = (wire_datum*) (((char*) d) + sizeof(wire_datum) + d->length);
+
+	options->filterlen = d->length + 1;
+	options->filter = (char*) malloc(options->filterlen);
+	if(cap_unmarshall_string(d, (char*) options->filter, &options->filterlen) < 0)
+	{
+		char error[128];
+		sprintf(error, "Error unmarshalling filter: %s", cap_error());
+		strcpy(errmsg, error);
+		return -1;
+	}
+
+
+	return sizeof(wire_datum) + datum->length;
+}
+
+
+
+int cap_send_message(int sock, wire_datum *data[], int len)
+{
+	int total_bytes = 0;
+	for(int i = 0; i < len; i++)
+	{
+		int bytes = cap_send(sock, data[i]);
+
+		if(bytes < 0) return bytes;
+		else total_bytes += bytes;
+	}
+
+	return total_bytes;
+}
+
+
+
+int cap_send(int sock, wire_datum *datum)
+{
+	return cap_send_fd(sock, datum, NULL, 0);
 }
-/*
-int cap_send(int sock, struct cap_wire_datum* datum);
-*/
 
 
 
-int cap_send_fd(int sock, const char *name, struct cap_wire_datum *d,
+int cap_send_fd(int sock, wire_datum *d,
                 int32_t fd_array[], int32_t fdlen)
 {
 	// the datum is the I/O vector
 	struct iovec iov;
 	iov.iov_base = d;
-	iov.iov_len = sizeof(struct cap_wire_datum) + d->length;
+	iov.iov_len = sizeof(wire_datum) + d->length;
 
 
 	// ancilliary data (file descriptors)
-	int cmsghdrlen = sizeof(struct cmsghdr) + fdlen * sizeof(int32_t);
-	struct cmsghdr *anc_hdr = (struct cmsghdr*) malloc(cmsghdrlen);
-	if(!anc_hdr) err(EX_OSERR, "Error creating ancilliary data header");
+	struct cmsghdr *anc_hdr = NULL;
+	if(fdlen > 0)
+	{
+		int cmsghdrlen = sizeof(struct cmsghdr) + fdlen * sizeof(int32_t);
+		anc_hdr = (struct cmsghdr*) malloc(cmsghdrlen);
+		if(!anc_hdr) err(EX_OSERR, "Error creating ancilliary data header");
+
+		anc_hdr->cmsg_len = cmsghdrlen;
+		anc_hdr->cmsg_level = SOL_SOCKET;
+		anc_hdr->cmsg_type = (fdlen ? SCM_RIGHTS : 0);
+		memcpy(((char*) anc_hdr) + sizeof(struct cmsghdr), fd_array,
+		       fdlen * sizeof(int32_t));
+	}
 
-	anc_hdr->cmsg_len = cmsghdrlen;
-	anc_hdr->cmsg_level = SOL_SOCKET;
-	anc_hdr->cmsg_type = SCM_RIGHTS;
-	memcpy(((void*) anc_hdr) + sizeof(struct cmsghdr), fd_array,
-	       fdlen * sizeof(int32_t));
 
 
 	// sendmsg header
@@ -133,7 +353,7 @@
 	header.msg_iov = &iov;
 	header.msg_iovlen = 1;
 	header.msg_control = anc_hdr;
-	header.msg_controllen = anc_hdr->cmsg_len;
+	header.msg_controllen = ((fdlen > 0) ? anc_hdr->cmsg_len : 0);
 	header.msg_flags = 0;
 
 
@@ -142,6 +362,7 @@
 	if(bytes_sent < 0)
 	{
 		perror("Error sending data and file descriptor(s)");
+		free(anc_hdr);
 		return -1;
 	}
 
@@ -151,37 +372,50 @@
 }
 
 
+wire_datum* cap_recv(int sock)
+{
+	int fdlen = 0;
+	return cap_recv_fds(sock, NULL, &fdlen);
+}
+
 
-int cap_recv_fd(int sock, char **name, struct cap_wire_datum **d,
-                int32_t *fd_array, int32_t *fdlen)
+wire_datum* cap_recv_fds(int sock, int32_t fd_array[], int32_t *fdlen)
 {
 	// how much data is there to receive?
-	struct cap_wire_datum peek;
-	int bytes = recv(sock, &peek, sizeof(struct cap_wire_datum), MSG_PEEK); 
-	if(bytes < 0)
+	wire_datum peek;
+	int bytes = recv(sock, &peek, sizeof(wire_datum), MSG_PEEK); 
+
+	if(bytes == 0)
+	{
+		sprintf(errmsg, "Socket closed: %s", strerror(errno));
+		return NULL;
+	}
+	else if(bytes < 0)
 	{
 		perror("Error peeking at socket");
-		return -1;
+		return NULL;
 	}
 
-	int to_receive = sizeof(struct cap_wire_datum) + peek.length;
+	int to_receive = sizeof(wire_datum) + peek.length;
 
 
 	// make room for it
-	*d = (struct cap_wire_datum*) malloc(to_receive);
+	wire_datum *datum = (wire_datum*) malloc(to_receive);
 	struct iovec iov;
-	iov.iov_base = *d;
+	iov.iov_base = datum;
 	iov.iov_len = to_receive;
 
 
 	// prepare to receive file descriptor(s)
-	int size = sizeof(struct cmsghdr) + *fdlen;
+	int size = sizeof(struct cmsghdr) + *fdlen * sizeof(int32_t);
 	struct cmsghdr *anc_hdr = (struct cmsghdr*) malloc(size);
+	bzero(anc_hdr, size);
+	
 	if(!anc_hdr) err(EX_OSERR, "Error creating ancilliary data header");
 	anc_hdr->cmsg_len = size;
 	anc_hdr->cmsg_level = SOL_SOCKET;
-	anc_hdr->cmsg_type = SCM_RIGHTS;
-	memset(anc_hdr + sizeof(struct cmsghdr), 0, *fdlen * sizeof(int32_t));
+	anc_hdr->cmsg_type = (*fdlen ? SCM_RIGHTS : 0);
+	bzero(anc_hdr + sizeof(struct cmsghdr), *fdlen * sizeof(int32_t));
 
 	// recvmsg() options
 	struct msghdr header;
@@ -198,12 +432,16 @@
 	if(bytes < 0)
 	{
 		perror("Error receiving message");
-		return -1;
+		free(anc_hdr);
+		free(datum);
+		return NULL;
 	}
 	else if(bytes == 0)
 	{
 		fprintf(stderr, "Socket closed\n");
-		return -1;
+		free(anc_hdr);
+		free(datum);
+		return NULL;
 	}
 
 
@@ -212,10 +450,12 @@
 
 	if(recv_fdlen < *fdlen) *fdlen = recv_fdlen;
 
-	memcpy(fd_array, ((void*) anc_hdr) + sizeof(struct cmsghdr),
+	memcpy(fd_array, ((char*) anc_hdr) + sizeof(struct cmsghdr),
 	       *fdlen * sizeof(int32_t));
 
-	return 0;
+	free(anc_hdr);
+
+	return datum;
 }
 
 
@@ -282,7 +522,7 @@
 	return total_bytes;
 }
 
-
+/*
 int cap_send_capbox_options(int client, struct capbox_options *options)
 {
 	int bytes, total_bytes = 0;
@@ -302,11 +542,11 @@
 	bytes = cap_send_string(client, options->start_path, options->pathlen);
 	if(bytes <= 0) return bytes;
 	total_bytes += bytes;
-/* TODO: need to do a sendmsg with SCM_RIGHTS
+* TODO: need to do a sendmsg with SCM_RIGHTS
 	bytes = cap_send_int(client, options->start_fd);
 	if(bytes <= 0) return bytes;
 	total_bytes += bytes;
-*/
+*
 	bytes = cap_send_int(client, options->mult);
 	if(bytes <= 0) return bytes;
 	total_bytes += bytes;
@@ -340,11 +580,11 @@
 	total_bytes += bytes;
 
 	options->pathlen = bytes;
-/* TODO: need to do a sendmsg with SCM_RIGHTS
+* TODO: need to do a sendmsg with SCM_RIGHTS
 	bytes = cap_recv_int(client, &options->start_fd);
 	if(bytes <= 0) { perror("Error receiving path FD"); return bytes; }
 	total_bytes += bytes;
-*/
+*
 	options->start_fd = -1;
 
 	bytes = cap_recv_int(client, &options->mult);
@@ -359,4 +599,5 @@
 
 	return total_bytes;
 }
+*/
 

==== //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/protocol.h#7 (text+ko) ====

@@ -35,6 +35,22 @@
 #include "powerbox.h"
 
 
+
+/** Requests that clients can make */
+enum capangel_req_t
+{
+	NO_OP = 0,
+	FD_FROM_PATH,
+	FD_POWERBOX
+};
+
+
+/** The last protocol error */
+const char* cap_error(void);
+
+
+
+/** Represents a single datum "on the wire" */
 struct cap_wire_datum
 {
 	uint32_t type;
@@ -51,49 +67,35 @@
 
 	uint32_t length;
 
-	/* followed by data; */
+	/* immediately followed by actual data; */
 };
 
 
 
-/** Requests that clients can make */
-enum capangel_req_t
-{
-	FD_FROM_PATH,
-	FD_POWERBOX
-};
-
-
-
 /* Unmarshalling functions; calling programs should free the result */
 struct cap_wire_datum* cap_marshall_int(int32_t value);
-struct cap_wire_datum* cap_marshall_string(char *value, int len);
+struct cap_wire_datum* cap_marshall_string(const char *value, int len);
+struct cap_wire_datum* cap_marshall_capbox(const struct capbox_options *options);
+
 
 /* Unmarshalling functions; return the number of bytes unmarshalled (or -1) */
-int cap_unmarshall_int(struct cap_wire_datum *datum, int32_t *value);
-int cap_unmarshall_string(struct cap_wire_datum *datum, char* value, int *len);
+int cap_unmarshall_int(const struct cap_wire_datum *d, int32_t *value);
+int cap_unmarshall_string(const struct cap_wire_datum *d, char* value, int *len);
+int cap_unmarshall_capbox(const struct cap_wire_datum *d, struct capbox_options *options);
+
 
-/* Sending, with or without file descriptors */
-int cap_send(int sock, char *name, struct cap_wire_datum *d);
-int cap_send_fd(int sock, const char *name, struct cap_wire_datum *d,
+/* Sending, with (_fd) or without file descriptors */
+int cap_send(int sock, struct cap_wire_datum *d);
+int cap_send_fd(int sock, struct cap_wire_datum *d,
                 int32_t fd_array[], int32_t fdlen);
+int cap_send_message(int sock, struct cap_wire_datum *data[], int len);
+
 
 /* Receiving, with or without file descriptors */
-int cap_recv(int sock, char **name, struct cap_wire_datum **d);
+struct cap_wire_datum* cap_recv(int sock);
 
 /* You supply the FD array and say how big it is; I'll tell you how many FDs you actually received. */
-int cap_recv_fd(int sock, char **name, struct cap_wire_datum **d,
-                int32_t fd_array[], int32_t *fdlen);
-
+struct cap_wire_datum* cap_recv_fds(int sock, int32_t fd_array[], int32_t *fdlen);
 
 
 
-int cap_send_int(int client, int value);
-int cap_recv_int(int client, int *value);
-
-int cap_send_string(int client, char *value, int len);
-int cap_recv_string(int client, char **value);
-
-int cap_send_capbox_options(int client, struct capbox_options *options);
-int cap_recv_capbox_options(int client, struct capbox_options *options);
-

==== //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/server.c#4 (text+ko) ====

@@ -31,9 +31,6 @@
  * SUCH DAMAGE.
  */
 
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
 #include <sys/capability.h>
 #include <sys/socket.h>
 #include <sys/un.h>
@@ -46,7 +43,6 @@
 #include <unistd.h>
 
 #include "cap.h"
-#include "fdcomm.h"
 #include "protocol.h"
 #include "server.h"
 
@@ -55,9 +51,8 @@
 int shutting_down = 0;
 char control_socket_name[256] = "";
 
-int *clients;
-int clientslen;
-int clientsmaxlen;
+struct fd_set sockets;
+int highest_fd;
 
 
 void user_angel_server_shutdown(void)
@@ -76,15 +71,13 @@
 int bind_to_path(const char *path);
 void accept_client(int fd_server);
 void service_clients(void);
+void serve(int fd_server, struct fd_set *sockets);
+void client_closed(int client);
 
 
 
 int run_server(const char* address)
 {
-	clientslen = 0;
-	clients = (int*) malloc (128 * sizeof(int));
-	clientsmaxlen = 128;
-
 	strcpy(control_socket_name, address);
 	printf("Creating control socket at %s...\n", control_socket_name);
 
@@ -97,12 +90,7 @@
 	}
 
 
-	while(fd_control)
-	{
-		accept_client(fd_control);
-		service_clients();
-	}
-
+	while(fd_control) serve(fd_control, &sockets);
 	user_angel_server_shutdown();
 
 	return 0;
@@ -111,13 +99,15 @@
 
 int bind_to_path(const char *path)
 {
+	FD_ZERO(&sockets);
+
 	struct sockaddr_un addr;
 	addr.sun_family = AF_UNIX;
 	strcpy(addr.sun_path, control_socket_name);
 
 	
 	int fd = socket(AF_UNIX, SOCK_STREAM, 0);
-	if(fd == 0)
+	if(fd < 0)
 	{
 		if(shutting_down) return 0;
 
@@ -126,6 +116,12 @@
 		return -1;
 	}
 
+	highest_fd = fd;
+
+/*
+	TODO: do this?
+		rc = setsockopt(listen_sd, SOL_SOCKET,  SO_REUSEADDR,
+                   (char *)&on, sizeof(on));*/
 
 	if(bind(fd, (struct sockaddr*) &addr, sizeof(struct sockaddr_un)))
 	{
@@ -148,7 +144,7 @@
 
 
 	// non-blocking socket I/O
-	int flags = fcntl(fd, F_GETFL, 0);
+/*	int flags = fcntl(fd, F_GETFL, 0);
 	if(flags < 0)
 	{
 		perror("Error getting flags for control socket");
@@ -159,7 +155,10 @@
 	{
 		perror("Error setting flags on control socket");
 		return -1;
-	}
+	}*/
+
+	FD_SET(fd, &sockets);
+
 
 
 	return fd;
@@ -185,116 +184,208 @@
 		return;
 	}
 
-	printf("Accepted client: FD %i\n", client);
+	printf("Client %4i: Accepted\n", client);
 
-	clients[clientslen++] = client;
+	FD_SET(client, &sockets);
+	if(client > highest_fd) highest_fd = client;
 
-	if(clientslen == clientsmaxlen)
-	{
-		int newsize = 2 * clientsmaxlen;
-		int *newclients = (int*) malloc(newsize * sizeof(int));
+	char hello[80];
+	sprintf(hello, "user_angel v%s", VERSION);
+	struct cap_wire_datum *d = cap_marshall_string(hello, strlen(hello));
 
-		memcpy(newclients, clients, clientslen * sizeof(int));
-		free(clients);
-		clients = newclients;
-		clientslen = newsize;
-	}
+	cap_send(client, d);
+	free(d);
 }
 
 
-void service_clients(void)
+
+void serve(int fd_server, struct fd_set *sockets)
 {
-	enum capangel_req_t req;
+	struct fd_set selected;
+	memcpy(&selected, sockets, sizeof(*sockets));
+ 
 
-	for(int i = 0; i < clientslen; i++)
+	int ready = select(highest_fd + 1, &selected, NULL, NULL, NULL);
+	if(ready < 0)
+	{
+		perror("select() failed");
+		return;
+	}
+	else if(ready == 0)
 	{
-		int client = clients[i];
-		if(client == -1) continue;
+		perror("select() timed out");
+		return;
+	}
 
-		int bytes = cap_recv_int(client, (int*) &req);
-
-		if(bytes > 0)
+	for(int i = 0; (i <= highest_fd) && (ready > 0); i++)
+	{
+		if(FD_ISSET(i, &selected))
 		{
-			if(handle_request(client, req))
+			if(i == fd_server) accept_client(i);
+			else
 			{
-				perror("Error handling client request");
-				close(client);
-				clients[i] = -1;
+				enum capangel_req_t req;
+				struct cap_wire_datum *d = cap_recv(i);
+
+				if(!d)
+				{
+					if((errno == ENOENT) || (errno == ECONNRESET)) client_closed(i);
+					else perror("Error receiving from client");
+
+					continue;
+				}
+
+
+				int bytes = 0;
+				if(sizeof(enum capangel_req_t) == sizeof(int32_t))
+					bytes = cap_unmarshall_int(d, (int32_t*) &req);
+
+				else
+				{
+					fprintf(stderr, "enum size is %iB\n", sizeof(enum capangel_req_t));
+					return;
+				}
+
+				if(bytes < 0)
+				{
+					fprintf(stderr, "Error unmarshalling request: %s\n", cap_error());
+					continue;
+				}
+
+				if(handle_request(i, req))
+				{
+					perror("Error handling client request");
+					client_closed(i);
+				}
 			}
-		}
-		else if(errno == EAGAIN) continue;
-		else
-		{
-			if(shutting_down) return;
 
-			perror("Error recv()'ing from client");
-			break;
+			ready--;
 		}
 	}
 }
 
 
-
 int handle_request(int client, enum capangel_req_t req)
 {
-	printf("Client %i requests ", client);
+	printf("Client %4i: ", client);
+
+	struct cap_wire_datum *d;
+	int pathlen = 256;
+	char path[pathlen];
+	int fds[32];
+	int fdlen;
 
 	switch(req)
 	{
 		case FD_FROM_PATH:

>>> TRUNCATED FOR MAIL (1000 lines) <<<


More information about the p4-projects mailing list