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 <arpa/inet.h>
9 #include <sys/un.h>
10 #include <errno.h>
12 #undef sun
13 #define sun sockun
15 extern int _p9netfd(char*);
17 static char *unknown = "unknown";
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;
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 }
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;
106 if(dir){
107 if((fd = _p9netfd(dir)) < 0){
108 werrstr("no such network connection %s", dir);
109 return nil;
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;
133 err:
134 freenetconninfo(nci);
135 return nil;
138 static void
139 xfree(void *v)
141 if(v != nil && v != unknown)
142 free(v);
145 void
146 freenetconninfo(NetConnInfo *nci)
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);