summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndre Oppermann <andre@FreeBSD.org>2004-10-19 15:13:30 +0000
committerAndre Oppermann <andre@FreeBSD.org>2004-10-19 15:13:30 +0000
commit312c75c362ae1871d5a7ac77265fd86e9bb939ef (patch)
tree6ed86bab8d6cc91fa056f60041d4ca61c1f4270e
parent1cf15713ede27d9027aa2df30a50628f726b7e55 (diff)
Notes
-rw-r--r--sys/kern/uipc_domain.c138
-rw-r--r--sys/kern/uipc_sockbuf.c79
-rw-r--r--sys/kern/uipc_socket2.c79
-rw-r--r--sys/sys/protosw.h33
4 files changed, 325 insertions, 4 deletions
diff --git a/sys/kern/uipc_domain.c b/sys/kern/uipc_domain.c
index 5e1b264ee941..c9fe3957a98e 100644
--- a/sys/kern/uipc_domain.c
+++ b/sys/kern/uipc_domain.c
@@ -70,8 +70,22 @@ struct mtx dom_mtx; /* domain list lock */
MTX_SYSINIT(domain, &dom_mtx, "domain list", MTX_DEF);
/*
+ * Dummy protocol specific user requests function pointer array.
+ * All functions return EOPNOTSUPP.
+ */
+struct pr_usrreqs nousrreqs = {
+ pru_abort_notsupp, pru_accept_notsupp, pru_attach_notsupp,
+ pru_bind_notsupp, pru_connect_notsupp, pru_connect2_notsupp,
+ pru_control_notsupp, pru_detach_notsupp, pru_disconnect_notsupp,
+ pru_listen_notsupp, pru_peeraddr_notsupp, pru_rcvd_notsupp,
+ pru_rcvoob_notsupp, pru_send_notsupp, pru_sense_null,
+ pru_shutdown_notsupp, pru_sockaddr_notsupp, pru_sosend_notsupp,
+ pru_soreceive_notsupp, pru_sopoll_notsupp, pru_sosetlabel_null
+};
+
+/*
* Add a new protocol domain to the list of supported domains
- * Note: you cant unload it again because a socket may be using it.
+ * Note: you cant unload it again because a socket may be using it.
* XXX can't fail at this time.
*/
static void
@@ -98,7 +112,7 @@ net_init_domain(struct domain *dp)
/*
* Add a new protocol domain to the list of supported domains
- * Note: you cant unload it again because a socket may be using it.
+ * Note: you cant unload it again because a socket may be using it.
* XXX can't fail at this time.
*/
void
@@ -190,6 +204,126 @@ found:
return (maybe);
}
+/*
+ * The caller must make sure that the new protocol is fully set up and ready to
+ * accept requests before it is registered.
+ */
+int
+pf_proto_register(family, npr)
+ int family;
+ struct protosw *npr;
+{
+ struct domain *dp;
+ struct protosw *pr, *fpr;
+
+ /* Sanity checks. */
+ if (family == 0)
+ return (EPFNOSUPPORT);
+ if (npr->pr_type == 0)
+ return (EPROTOTYPE);
+ if (npr->pr_protocol == 0)
+ return (EPROTONOSUPPORT);
+ if (npr->pr_usrreqs == NULL)
+ return (ENXIO);
+
+ /* Try to find the specified domain based on the family. */
+ for (dp = domains; dp; dp = dp->dom_next)
+ if (dp->dom_family == family)
+ goto found;
+ return (EPFNOSUPPORT);
+
+found:
+ /* Initialize backpointer to struct domain. */
+ npr->pr_domain = dp;
+ fpr = NULL;
+
+ /* The new protocol must not yet exist. */
+ for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) {
+ if ((pr->pr_type == npr->pr_type) &&
+ (pr->pr_protocol == npr->pr_protocol))
+ return (EEXIST); /* XXX: Check only protocol? */
+ /* While here, remember the first free spacer. */
+ if ((fpr == NULL) && (pr->pr_protocol == PROTO_SPACER))
+ fpr = pr;
+ }
+
+ /* If no free spacer is found we can't add the new protocol. */
+ if (fpr == NULL)
+ return (ENOMEM);
+
+ /* Copy the new struct protosw over the spacer. */
+ bcopy(npr, fpr, sizeof(*fpr));
+
+ /* Initialize and activate the protocol. */
+ if (fpr->pr_init)
+ (fpr->pr_init)();
+
+ return (0);
+}
+
+/*
+ * The caller must make sure the protocol and its functions correctly shut down
+ * all sockets and release all locks and memory references.
+ */
+int
+pf_proto_unregister(family, protocol, type)
+ int family;
+ int protocol;
+ int type;
+{
+ struct domain *dp;
+ struct protosw *pr, *dpr;
+
+ /* Sanity checks. */
+ if (family == 0)
+ return (EPFNOSUPPORT);
+ if (protocol == 0)
+ return (EPROTONOSUPPORT);
+ if (type == 0)
+ return (EPROTOTYPE);
+
+ /* Try to find the specified domain based on the family type. */
+ for (dp = domains; dp; dp = dp->dom_next)
+ if (dp->dom_family == family)
+ goto found;
+ return (EPFNOSUPPORT);
+
+found:
+ dpr = NULL;
+
+ /* The protocol must exist and only once. */
+ for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) {
+ if ((pr->pr_type == type) && (pr->pr_protocol == protocol)) {
+ if (dpr != NULL)
+ return (EMLINK); /* Should not happen! */
+ else
+ dpr = pr;
+ }
+ }
+
+ /* Protocol does not exist. */
+ if (dpr == NULL)
+ return (EPROTONOSUPPORT);
+
+ /* De-orbit the protocol and make the slot available again. */
+ dpr->pr_type = 0;
+ dpr->pr_domain = dp;
+ dpr->pr_protocol = PROTO_SPACER;
+ dpr->pr_flags = 0;
+ dpr->pr_input = NULL;
+ dpr->pr_output = NULL;
+ dpr->pr_ctlinput = NULL;
+ dpr->pr_ctloutput = NULL;
+ dpr->pr_ousrreq = NULL;
+ dpr->pr_init = NULL;
+ dpr->pr_fasttimo = NULL;
+ dpr->pr_slowtimo = NULL;
+ dpr->pr_drain = NULL;
+ dpr->pr_usrreqs = &nousrreqs;
+
+ return (0);
+}
+
void
pfctlinput(cmd, sa)
int cmd;
diff --git a/sys/kern/uipc_sockbuf.c b/sys/kern/uipc_sockbuf.c
index 02b68d868f60..eff3c6f81e8a 100644
--- a/sys/kern/uipc_sockbuf.c
+++ b/sys/kern/uipc_sockbuf.c
@@ -1277,12 +1277,30 @@ sbcreatecontrol(p, size, type, level)
* supported by a protocol. Fill in as needed.
*/
int
+pru_abort_notsupp(struct socket *so)
+{
+ return EOPNOTSUPP;
+}
+
+int
pru_accept_notsupp(struct socket *so, struct sockaddr **nam)
{
return EOPNOTSUPP;
}
int
+pru_attach_notsupp(struct socket *so, int proto, struct thread *td)
+{
+ return EOPNOTSUPP;
+}
+
+int
+pru_bind_notsupp(struct socket *so, struct sockaddr *nam, struct thread *td)
+{
+ return EOPNOTSUPP;
+}
+
+int
pru_connect_notsupp(struct socket *so, struct sockaddr *nam, struct thread *td)
{
return EOPNOTSUPP;
@@ -1296,7 +1314,19 @@ pru_connect2_notsupp(struct socket *so1, struct socket *so2)
int
pru_control_notsupp(struct socket *so, u_long cmd, caddr_t data,
- struct ifnet *ifp, struct thread *td)
+ struct ifnet *ifp, struct thread *td)
+{
+ return EOPNOTSUPP;
+}
+
+int
+pru_detach_notsupp(struct socket *so)
+{
+ return EOPNOTSUPP;
+}
+
+int
+pru_disconnect_notsupp(struct socket *so)
{
return EOPNOTSUPP;
}
@@ -1308,6 +1338,12 @@ pru_listen_notsupp(struct socket *so, struct thread *td)
}
int
+pru_peeraddr_notsupp(struct socket *so, struct sockaddr **nam)
+{
+ return EOPNOTSUPP;
+}
+
+int
pru_rcvd_notsupp(struct socket *so, int flags)
{
return EOPNOTSUPP;
@@ -1319,6 +1355,13 @@ pru_rcvoob_notsupp(struct socket *so, struct mbuf *m, int flags)
return EOPNOTSUPP;
}
+int
+pru_send_notsupp(struct socket *so, int flags, struct mbuf *m,
+ struct sockaddr *addr, struct mbuf *control, struct thread *td)
+{
+ return EOPNOTSUPP;
+}
+
/*
* This isn't really a ``null'' operation, but it's the default one
* and doesn't do anything destructive.
@@ -1330,6 +1373,40 @@ pru_sense_null(struct socket *so, struct stat *sb)
return 0;
}
+int
+pru_shutdown_notsupp(struct socket *so)
+{
+ return EOPNOTSUPP;
+}
+
+int
+pru_sockaddr_notsupp(struct socket *so, struct sockaddr **nam)
+{
+ return EOPNOTSUPP;
+}
+
+int
+pru_sosend_notsupp(struct socket *so, struct sockaddr *addr, struct uio *uio,
+ struct mbuf *top, struct mbuf *control, int flags, struct thread *td)
+{
+ return EOPNOTSUPP;
+}
+
+int
+pru_soreceive_notsupp(struct socket *so, struct sockaddr **paddr,
+ struct uio *uio, struct mbuf **mp0, struct mbuf **controlp,
+ int *flagsp)
+{
+ return EOPNOTSUPP;
+}
+
+int
+pru_sopoll_notsupp(struct socket *so, int events, struct ucred *cred,
+ struct thread *td)
+{
+ return EOPNOTSUPP;
+}
+
/*
* For protocol types that don't keep cached copies of labels in their
* pcbs, provide a null sosetlabel that does a NOOP.
diff --git a/sys/kern/uipc_socket2.c b/sys/kern/uipc_socket2.c
index 02b68d868f60..eff3c6f81e8a 100644
--- a/sys/kern/uipc_socket2.c
+++ b/sys/kern/uipc_socket2.c
@@ -1277,12 +1277,30 @@ sbcreatecontrol(p, size, type, level)
* supported by a protocol. Fill in as needed.
*/
int
+pru_abort_notsupp(struct socket *so)
+{
+ return EOPNOTSUPP;
+}
+
+int
pru_accept_notsupp(struct socket *so, struct sockaddr **nam)
{
return EOPNOTSUPP;
}
int
+pru_attach_notsupp(struct socket *so, int proto, struct thread *td)
+{
+ return EOPNOTSUPP;
+}
+
+int
+pru_bind_notsupp(struct socket *so, struct sockaddr *nam, struct thread *td)
+{
+ return EOPNOTSUPP;
+}
+
+int
pru_connect_notsupp(struct socket *so, struct sockaddr *nam, struct thread *td)
{
return EOPNOTSUPP;
@@ -1296,7 +1314,19 @@ pru_connect2_notsupp(struct socket *so1, struct socket *so2)
int
pru_control_notsupp(struct socket *so, u_long cmd, caddr_t data,
- struct ifnet *ifp, struct thread *td)
+ struct ifnet *ifp, struct thread *td)
+{
+ return EOPNOTSUPP;
+}
+
+int
+pru_detach_notsupp(struct socket *so)
+{
+ return EOPNOTSUPP;
+}
+
+int
+pru_disconnect_notsupp(struct socket *so)
{
return EOPNOTSUPP;
}
@@ -1308,6 +1338,12 @@ pru_listen_notsupp(struct socket *so, struct thread *td)
}
int
+pru_peeraddr_notsupp(struct socket *so, struct sockaddr **nam)
+{
+ return EOPNOTSUPP;
+}
+
+int
pru_rcvd_notsupp(struct socket *so, int flags)
{
return EOPNOTSUPP;
@@ -1319,6 +1355,13 @@ pru_rcvoob_notsupp(struct socket *so, struct mbuf *m, int flags)
return EOPNOTSUPP;
}
+int
+pru_send_notsupp(struct socket *so, int flags, struct mbuf *m,
+ struct sockaddr *addr, struct mbuf *control, struct thread *td)
+{
+ return EOPNOTSUPP;
+}
+
/*
* This isn't really a ``null'' operation, but it's the default one
* and doesn't do anything destructive.
@@ -1330,6 +1373,40 @@ pru_sense_null(struct socket *so, struct stat *sb)
return 0;
}
+int
+pru_shutdown_notsupp(struct socket *so)
+{
+ return EOPNOTSUPP;
+}
+
+int
+pru_sockaddr_notsupp(struct socket *so, struct sockaddr **nam)
+{
+ return EOPNOTSUPP;
+}
+
+int
+pru_sosend_notsupp(struct socket *so, struct sockaddr *addr, struct uio *uio,
+ struct mbuf *top, struct mbuf *control, int flags, struct thread *td)
+{
+ return EOPNOTSUPP;
+}
+
+int
+pru_soreceive_notsupp(struct socket *so, struct sockaddr **paddr,
+ struct uio *uio, struct mbuf **mp0, struct mbuf **controlp,
+ int *flagsp)
+{
+ return EOPNOTSUPP;
+}
+
+int
+pru_sopoll_notsupp(struct socket *so, int events, struct ucred *cred,
+ struct thread *td)
+{
+ return EOPNOTSUPP;
+}
+
/*
* For protocol types that don't keep cached copies of labels in their
* pcbs, provide a null sosetlabel that does a NOOP.
diff --git a/sys/sys/protosw.h b/sys/sys/protosw.h
index 617ab59da89d..f4bb7343c985 100644
--- a/sys/sys/protosw.h
+++ b/sys/sys/protosw.h
@@ -105,6 +105,12 @@ struct protosw {
#define PR_FASTHZ 5 /* 5 fast timeouts per second */
/*
+ * This number should be defined again within each protocol family to avoid
+ * confusion.
+ */
+#define PROTO_SPACER 32767 /* spacer for loadable protocols */
+
+/*
* Values for pr_flags.
* PR_ADDR requires PR_ATOMIC;
* PR_ADDR and PR_CONNREQUIRED are mutually exclusive.
@@ -231,16 +237,41 @@ struct pr_usrreqs {
void (*pru_sosetlabel)(struct socket *so);
};
+/*
+ * The dummy protocol specific user requests function pointer array is
+ * initialized to the functions below. All functions return EOPNOTSUPP.
+ */
+extern struct pr_usrreqs nousrreqs;
+
+int pru_abort_notsupp(struct socket *so);
int pru_accept_notsupp(struct socket *so, struct sockaddr **nam);
+int pru_attach_notsupp(struct socket *so, int proto, struct thread *td);
+int pru_bind_notsupp(struct socket *so, struct sockaddr *nam,
+ struct thread *td);
int pru_connect_notsupp(struct socket *so, struct sockaddr *nam,
struct thread *td);
int pru_connect2_notsupp(struct socket *so1, struct socket *so2);
int pru_control_notsupp(struct socket *so, u_long cmd, caddr_t data,
struct ifnet *ifp, struct thread *td);
+int pru_detach_notsupp(struct socket *so);
+int pru_disconnect_notsupp(struct socket *so);
int pru_listen_notsupp(struct socket *so, struct thread *td);
+int pru_peeraddr_notsupp(struct socket *so, struct sockaddr **nam);
int pru_rcvd_notsupp(struct socket *so, int flags);
int pru_rcvoob_notsupp(struct socket *so, struct mbuf *m, int flags);
+int pru_send_notsupp(struct socket *so, int flags, struct mbuf *m,
+ struct sockaddr *addr, struct mbuf *control, struct thread *td);
int pru_sense_null(struct socket *so, struct stat *sb);
+int pru_shutdown_notsupp(struct socket *so);
+int pru_sockaddr_notsupp(struct socket *so, struct sockaddr **nam);
+int pru_sosend_notsupp(struct socket *so, struct sockaddr *addr,
+ struct uio *uio, struct mbuf *top, struct mbuf *control, int flags,
+ struct thread *td);
+int pru_soreceive_notsupp(struct socket *so, struct sockaddr **paddr,
+ struct uio *uio, struct mbuf **mp0, struct mbuf **controlp,
+ int *flagsp);
+int pru_sopoll_notsupp(struct socket *so, int events, struct ucred *cred,
+ struct thread *td);
void pru_sosetlabel_null(struct socket *so);
#endif /* _KERNEL */
@@ -319,6 +350,8 @@ void pfctlinput(int, struct sockaddr *);
void pfctlinput2(int, struct sockaddr *, void *);
struct protosw *pffindproto(int family, int protocol, int type);
struct protosw *pffindtype(int family, int type);
+int pf_proto_register(int family, struct protosw *npr);
+int pf_proto_unregister(int family, int protocol, int type);
#endif
#endif