9base

revived minimalist port of Plan 9 userland to Unix
git clone git://git.suckless.org/9base
Log | Files | Refs | README | LICENSE

getnetconn.c (2498B)


      1 #include <u.h>
      2 #define NOPLAN9DEFINES
      3 #include <libc.h>
      4 
      5 #include <sys/socket.h>
      6 #include <netinet/in.h>
      7 #include <netinet/tcp.h>
      8 #include <sys/un.h>
      9 #include <errno.h>
     10 
     11 #undef sun
     12 #define sun sockun
     13 
     14 extern int _p9netfd(char*);
     15 
     16 static char *unknown = "unknown";
     17 
     18 static int
     19 convert(int s, struct sockaddr *sa, char **lsys, char **lserv, char **laddr)
     20 {
     21 	struct sockaddr_un *sun;
     22 	struct sockaddr_in *sin;
     23 	uchar *ip;
     24 	u32int ipl;
     25 	socklen_t sn;
     26 	int n;
     27 	char *net;
     28 	
     29 	switch(sa->sa_family){
     30 	case AF_INET:
     31 		sin = (void*)sa;
     32 		ip = (uchar*)&sin->sin_addr;
     33 		ipl = *(u32int*)ip;
     34 		if(ipl == 0)
     35 			*lsys = strdup("*");
     36 		else
     37 			*lsys = smprint("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
     38 		*lserv = smprint("%d", ntohs(sin->sin_port));
     39 		sn = sizeof n;
     40 		if(getsockopt(s, SOL_SOCKET, SO_TYPE, (void*)&n, &sn) < 0)
     41 			return -1;
     42 		if(n == SOCK_STREAM)
     43 			net = "tcp";
     44 		else if(n == SOCK_DGRAM)
     45 			net = "udp";
     46 		else{
     47 			werrstr("unknown network type");
     48 			return -1;
     49 		}
     50 		*laddr = smprint("%s!%s!%s", net, *lsys, *lserv);
     51 		if(*lsys == nil || *lserv == nil || *laddr == nil)
     52 			return -1;
     53 		return 0;
     54 	case AF_UNIX:
     55 		sun = (void*)sa;
     56 		*lsys = unknown;
     57 		*lserv = unknown;
     58 		*laddr = smprint("unix!%s", sun->sun_path);
     59 		if(*laddr == nil)
     60 			return -1;
     61 		return 0;
     62 	default:
     63 		werrstr("unknown socket family");
     64 		return -1;
     65 	}
     66 }
     67 
     68 NetConnInfo*
     69 getnetconninfo(char *dir, int fd)
     70 {
     71 	socklen_t sn;
     72 	union {
     73 		struct sockaddr sa;
     74 		struct sockaddr_in sin;
     75 		struct sockaddr_un sun;
     76 	} u;
     77 	NetConnInfo *nci;
     78 
     79 	if(dir){
     80 		if((fd = _p9netfd(dir)) < 0){
     81 			werrstr("no such network connection %s", dir);
     82 			return nil;
     83 		}
     84 	}
     85 
     86 	nci = mallocz(sizeof *nci, 1);
     87 	if(nci == nil)
     88 		goto err;
     89 	nci->dir = smprint("/dev/fd/%d", fd);
     90 	nci->root = strdup("/net");
     91 	nci->spec = unknown;
     92 	if(nci->dir == nil || nci->root == nil)
     93 		goto err;
     94 	sn = sizeof u;
     95 	if(getsockname(fd, &u.sa, &sn) < 0)
     96 		goto err;
     97 	if(convert(fd, &u.sa, &nci->lsys, &nci->lserv, &nci->laddr) < 0)
     98 		goto err;
     99 	sn = sizeof u;
    100 	if(getpeername(fd, &u.sa, &sn) < 0)
    101 		goto err;
    102 	if(convert(fd, &u.sa, &nci->rsys, &nci->rserv, &nci->raddr) < 0)
    103 		goto err;
    104 	return nci;
    105 
    106 err:
    107 	freenetconninfo(nci);
    108 	return nil;
    109 }
    110 
    111 static void
    112 xfree(void *v)
    113 {
    114 	if(v != nil && v != unknown)
    115 		free(v);
    116 }
    117 
    118 void
    119 freenetconninfo(NetConnInfo *nci)
    120 {
    121 	if(nci == nil)
    122 		return;
    123 	xfree(nci->dir);
    124 	xfree(nci->root);
    125 	xfree(nci->spec);
    126 	xfree(nci->lsys);
    127 	xfree(nci->lserv);
    128 	xfree(nci->rsys);
    129 	xfree(nci->rserv);
    130 	xfree(nci->laddr);
    131 	xfree(nci->raddr);
    132 	free(nci);
    133 }
    134