Commit Diff


commit - 18b1814390e9d3bff470de940b448dfddf87187d
commit + 06f4d9201a6552b3c832fccc72ff0627986977e5
blob - /dev/null
blob + 1f2394043cfb1b96df24bf57a12b6a6f578b7fb8 (mode 644)
--- /dev/null
+++ src/lib9/getnetconn.c
@@ -0,0 +1,134 @@
+#include <u.h>
+#define NOPLAN9DEFINES
+#include <libc.h>
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <sys/un.h>
+#include <errno.h>
+
+#undef sun
+#define sun sockun
+
+extern int _p9netfd(char*);
+
+static char *unknown = "unknown";
+
+static int
+convert(int s, struct sockaddr *sa, char **lsys, char **lserv, char **laddr)
+{
+	struct sockaddr_un *sun;
+	struct sockaddr_in *sin;
+	uchar *ip;
+	u32int ipl;
+	socklen_t sn;
+	int n;
+	char *net;
+	
+	switch(sa->sa_family){
+	case AF_INET:
+		sin = (void*)sa;
+		ip = (uchar*)&sin->sin_addr;
+		ipl = *(u32int*)ip;
+		if(ipl == 0)
+			*lsys = strdup("*");
+		else
+			*lsys = smprint("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
+		*lserv = smprint("%d", ntohs(sin->sin_port));
+		sn = sizeof n;
+		if(getsockopt(s, SOL_SOCKET, SO_TYPE, (void*)&n, &sn) < 0)
+			return -1;
+		if(n == SOCK_STREAM)
+			net = "tcp";
+		else if(n == SOCK_DGRAM)
+			net = "udp";
+		else{
+			werrstr("unknown network type");
+			return -1;
+		}
+		*laddr = smprint("%s!%s!%s", net, *lsys, *lserv);
+		if(*lsys == nil || *lserv == nil || *laddr == nil)
+			return -1;
+		return 0;
+	case AF_UNIX:
+		sun = (void*)sa;
+		*lsys = unknown;
+		*lserv = unknown;
+		*laddr = smprint("unix!%s", sun->sun_path);
+		if(*laddr == nil)
+			return -1;
+		return 0;
+	default:
+		werrstr("unknown socket family");
+		return -1;
+	}
+}
+
+NetConnInfo*
+getnetconninfo(char *dir, int fd)
+{
+	socklen_t sn;
+	union {
+		struct sockaddr sa;
+		struct sockaddr_in sin;
+		struct sockaddr_un sun;
+	} u;
+	NetConnInfo *nci;
+
+	if(dir){
+		if((fd = _p9netfd(dir)) < 0){
+			werrstr("no such network connection %s", dir);
+			return nil;
+		}
+	}
+
+	nci = mallocz(sizeof *nci, 1);
+	if(nci == nil)
+		goto err;
+	nci->dir = smprint("/dev/fd/%d", fd);
+	nci->root = strdup("/net");
+	nci->spec = unknown;
+	if(nci->dir == nil || nci->root == nil)
+		goto err;
+	sn = sizeof sn;
+	if(getsockname(fd, &u.sa, &sn) < 0)
+		goto err;
+	if(convert(fd, &u.sa, &nci->lsys, &nci->lserv, &nci->laddr) < 0)
+		goto err;
+	sn = sizeof sn;
+	if(getpeername(fd, &u.sa, &sn) < 0)
+		goto err;
+	if(convert(fd, &u.sa, &nci->rsys, &nci->rserv, &nci->raddr) < 0)
+		goto err;
+	return nci;
+
+err:
+	freenetconninfo(nci);
+	return nil;
+}
+
+static void
+xfree(void *v)
+{
+	if(v != nil && v != unknown)
+		free(v);
+}
+
+void
+freenetconninfo(NetConnInfo *nci)
+{
+	if(nci == nil)
+		return;
+	xfree(nci->dir);
+	xfree(nci->root);
+	xfree(nci->spec);
+	xfree(nci->lsys);
+	xfree(nci->lserv);
+	xfree(nci->rsys);
+	xfree(nci->rserv);
+	xfree(nci->laddr);
+	xfree(nci->raddr);
+	free(nci);
+}
+
blob - d118c47b8fcb8365f6024c17ebf4fec2b16ab0d3
blob + 556be2f0110ce18892f101ca812cf709e9cc6991
--- src/lib9/mkfile
+++ src/lib9/mkfile
@@ -104,6 +104,7 @@ LIB9OFILES=\
 	getcallerpc-$OBJTYPE.$O\
 	getenv.$O\
 	getfields.$O\
+	getnetconn.$O\
 	getns.$O\
 	getuser.$O\
 	getwd.$O\