getnetconn.c - 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 **la… | |
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[… | |
38 *lserv = smprint("%d", ntohs(sin->sin_port)); | |
39 sn = sizeof n; | |
40 if(getsockopt(s, SOL_SOCKET, SO_TYPE, (void*)&n, &sn) < … | |
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 |