Blob


1 #include <u.h>
2 #define NOPLAN9DEFINES
3 #include <libc.h>
5 #include <sys/socket.h>
6 #include <netinet/in.h>
7 #include <netinet/tcp.h>
8 #include <sys/un.h>
9 #include <errno.h>
11 #undef sun
12 #define sun sockun
14 extern int _p9netfd(char*);
16 static char *unknown = "unknown";
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;
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 }
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;
79 if(dir){
80 if((fd = _p9netfd(dir)) < 0){
81 werrstr("no such network connection %s", dir);
82 return nil;
83 }
84 }
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 sn;
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 sn;
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;
106 err:
107 freenetconninfo(nci);
108 return nil;
111 static void
112 xfree(void *v)
114 if(v != nil && v != unknown)
115 free(v);
118 void
119 freenetconninfo(NetConnInfo *nci)
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);