plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

getnetconn.c (3240B)


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