Subject: Re: SO_PEERNAME
To: None <tech-kern@netbsd.org>
From: der Mouse <mouse@Rodents.Montreal.QC.CA>
List: tech-kern
Date: 08/27/2001 02:38:48
Okay, I finally sat down with this. I've now got patches that allow
you to set LOCAL_CREDS on a listening socket and get credentials passed
at connect() time, instead of having to wait for a data send. While I
was experimenting, I noticed that if you want credentials on every data
send, there is presently no way to get them; you have to re-enable
LOCAL_CREDS after every send is done. Unfortunately, the credential
passing happens at send time, not at receive time, so unless you're
blocking in a receive, there is no way to tell when a send happens.
And even if you are, there's a race between reenabling LOCAL_CREDS and
the next send. So I added another option, LOCAL_CREDS_STICKY, which
means that if LOCAL_CREDS is set, it isn't cleared when a data send is
done. (Of course, this will not normally be used; it's of use only
when data sends by differently-credentialed processes can occur on the
same socket, and some semantic difference is desired.)
The changes are quite small. These are relative to
/* $NetBSD: un.h,v 1.22 1999/06/24 14:07:44 kleink Exp $ */
/* $NetBSD: unpcb.h,v 1.11 1998/01/07 22:49:47 thorpej Exp $ */
/* $NetBSD: uipc_usrreq.c,v 1.45 1999/06/17 23:17:45 thorpej Exp $ */
(those being the versions I had handy), but given the last-change dates
and the stability of the AF_LOCAL stuff, I would expect that if those
aren't the -current revs, the tweaks are relatively minor.
For your consideration. Use, tweak, ignore, as you wish.
/~\ The ASCII der Mouse
\ / Ribbon Campaign
X Against HTML mouse@rodents.montreal.qc.ca
/ \ Email! 7D C8 61 52 5D E7 2D 39 4E F1 31 3E E8 B3 27 4B
--- OLD/sys/sys/un.h Thu Jan 1 00:00:00 1970
+++ NEW/sys/sys/un.h Thu Jan 1 00:00:00 1970
@@ -38,6 +38,8 @@
#ifndef _SYS_UN_H_
#define _SYS_UN_H_
+#include <sys/types.h>
+
/*
* Definitions for UNIX IPC domain.
*/
@@ -51,7 +53,8 @@
* Socket options for UNIX IPC domain.
*/
#if !defined(_XOPEN_SOURCE)
-#define LOCAL_CREDS 0x0001 /* pass credentials to receiver */
+#define LOCAL_CREDS 0x0001 /* pass credentials to receiver */
+#define LOCAL_CREDS_STICKY 0x0002 /* LOCAL_CREDS is sticky */
#endif
#ifdef _KERNEL
--- OLD/sys/sys/unpcb.h Thu Jan 1 00:00:00 1970
+++ NEW/sys/sys/unpcb.h Thu Jan 1 00:00:00 1970
@@ -86,6 +86,7 @@
/* unp_flags */
#define UNP_WANTCRED 0x0001 /* credentials wanted */
+#define UNP_STICKYCRED 0x0002 /* UNP_WANTCRED is sticky */
#define sotounpcb(so) ((struct unpcb *)((so)->so_pcb))
--- OLD/sys/kern/uipc_usrreq.c Thu Jan 1 00:00:00 1970
+++ NEW/sys/kern/uipc_usrreq.c Thu Jan 1 00:00:00 1970
@@ -212,6 +212,16 @@
case PRU_CONNECT:
error = unp_connect(so, nam, p);
+ if ((error == 0) &&
+ (so->so_type == SOCK_STREAM) &&
+ (unp->unp_conn->unp_flags & UNP_WANTCRED)) {
+ /* Do a zero-length send to get creds sent. */
+ MGETHDR(m, M_WAIT, MT_DATA);
+ m->m_pkthdr.len = 0;
+ m->m_pkthdr.rcvif = 0;
+ m->m_len = 0;
+ error = uipc_usrreq(so, PRU_SEND, m, 0, 0, p);
+ }
break;
case PRU_CONNECT2:
@@ -307,9 +317,10 @@
if (unp->unp_conn->unp_flags & UNP_WANTCRED) {
/*
* Credentials are passed only once on
- * SOCK_STREAM.
+ * SOCK_STREAM, unless sticky.
*/
- unp->unp_conn->unp_flags &= ~UNP_WANTCRED;
+ if (! (unp->unp_conn->unp_flags & UNP_STICKYCRED))
+ unp->unp_conn->unp_flags &= ~UNP_WANTCRED;
control = unp_addsockcred(p, control);
}
/*
@@ -411,6 +422,7 @@
case PRCO_SETOPT:
switch (optname) {
case LOCAL_CREDS:
+ case LOCAL_CREDS_STICKY:
if (m == NULL || m->m_len != sizeof(int))
error = EINVAL;
else {
@@ -425,6 +437,10 @@
case LOCAL_CREDS:
OPTSET(UNP_WANTCRED);
break;
+
+ case LOCAL_CREDS_STICKY:
+ OPTSET(UNP_STICKYCRED);
+ break;
}
}
break;
@@ -441,6 +457,7 @@
case PRCO_GETOPT:
switch (optname) {
case LOCAL_CREDS:
+ case LOCAL_CREDS_STICKY:
*mp = m = m_get(M_WAIT, MT_SOOPTS);
m->m_len = sizeof(int);
switch (optname) {
@@ -449,6 +466,10 @@
case LOCAL_CREDS:
optval = OPTBIT(UNP_WANTCRED);
+ break;
+
+ case LOCAL_CREDS_STICKY:
+ optval = OPTBIT(UNP_STICKYCRED);
break;
}
*mtod(m, int *) = optval;