tadd getnetconninfo - plan9port - [fork] Plan 9 from user space | |
git clone git://src.adamsgaard.dk/plan9port | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit 06f4d9201a6552b3c832fccc72ff0627986977e5 | |
parent 18b1814390e9d3bff470de940b448dfddf87187d | |
Author: rsc <devnull@localhost> | |
Date: Sun, 13 Feb 2005 19:25:44 +0000 | |
add getnetconninfo | |
Diffstat: | |
A src/lib9/getnetconn.c | 134 +++++++++++++++++++++++++++++… | |
M src/lib9/mkfile | 1 + | |
2 files changed, 135 insertions(+), 0 deletions(-) | |
--- | |
diff --git a/src/lib9/getnetconn.c b/src/lib9/getnetconn.c | |
t@@ -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… | |
+ *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); | |
+} | |
+ | |
diff --git a/src/lib9/mkfile b/src/lib9/mkfile | |
t@@ -104,6 +104,7 @@ LIB9OFILES=\ | |
getcallerpc-$OBJTYPE.$O\ | |
getenv.$O\ | |
getfields.$O\ | |
+ getnetconn.$O\ | |
getns.$O\ | |
getuser.$O\ | |
getwd.$O\ |