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