summaryrefslogtreecommitdiff
path: root/pfinet/socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'pfinet/socket.c')
-rw-r--r--pfinet/socket.c100
1 files changed, 92 insertions, 8 deletions
diff --git a/pfinet/socket.c b/pfinet/socket.c
index 7cbc0e9f..52bd37ff 100644
--- a/pfinet/socket.c
+++ b/pfinet/socket.c
@@ -1,6 +1,5 @@
-/*
- Copyright (C) 1995 Free Software Foundation, Inc.
- Written by Michael I. Bushnell, p/BSG.
+/*
+ Copyright (C) 1995,2000 Free Software Foundation, Inc.
This file is part of the GNU Hurd.
@@ -18,18 +17,103 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
-#include <linux/net.h>
#include <assert.h>
#include "pfinet.h"
-struct proto_ops *proto_ops;
+#include <linux/socket.h>
+#include <linux/net.h>
+
+#ifndef NPROTO
+#define NPROTO (PF_INET + 1)
+#endif
+struct net_proto_family *net_families[NPROTO];
/* Notice that a protocol family is live; this only works for inet here. */
int
-sock_register (int family, struct proto_ops *ops)
+sock_register (struct net_proto_family *fam)
{
- assert (family == PF_INET);
- proto_ops = ops;
+ assert (fam->family < NPROTO);
+ net_families[fam->family] = fam;
return 0;
}
+
+struct socket *
+sock_alloc (void)
+{
+ struct socket *sock;
+ struct condition *c;
+
+ sock = malloc (sizeof *sock + sizeof (struct condition));
+ if (!sock)
+ return 0;
+ c = (void *) &sock[1];
+ condition_init (c);
+ bzero (sock, sizeof *sock);
+ sock->state = SS_UNCONNECTED;
+ sock->identity = MACH_PORT_NULL;
+ sock->refcnt = 1;
+ sock->wait = (void *) c;
+
+ return sock;
+}
+
+/* Create a sock_user structure, initialized from SOCK and ISROOT.
+ If NOINSTALL is set, don't put it in the portset. */
+struct sock_user *
+make_sock_user (struct socket *sock, int isroot, int noinstall)
+{
+ error_t err;
+ struct sock_user *user;
+
+ assert (sock->refcnt != 0);
+
+ if (noinstall)
+ err = ports_create_port_noinstall (socketport_class, pfinet_bucket,
+ sizeof (struct sock_user), &user);
+ else
+ err = ports_create_port (socketport_class, pfinet_bucket,
+ sizeof (struct sock_user), &user);
+ if (err)
+ return 0;
+
+ /* We maintain a reference count in `struct socket' (a member not
+ in the original Linux structure), because there can be multiple
+ ports (struct sock_user, aka protids) pointing to the same socket.
+ The socket lives until all the ports die. */
+ ++sock->refcnt;
+ user->isroot = isroot;
+ user->sock = sock;
+ return user;
+}
+
+/* This is called from the port cleanup function below, and on
+ a newly allocated socket when something went wrong in its creation. */
+void
+sock_release (struct socket *sock)
+{
+ if (--sock->refcnt != 0)
+ return;
+
+ if (sock->state != SS_UNCONNECTED)
+ sock->state = SS_DISCONNECTING;
+
+ if (sock->ops)
+ sock->ops->release(sock, NULL);
+
+ if (sock->identity != MACH_PORT_NULL)
+ mach_port_destroy (mach_task_self (), sock->identity);
+
+ free (sock);
+}
+
+/* Release the reference on the referenced socket. */
+void
+clean_socketport (void *arg)
+{
+ struct sock_user *const user = arg;
+
+ __mutex_lock (&global_lock);
+ sock_release (user->sock);
+ __mutex_unlock (&global_lock);
+}