1 #include <sys/types.h> 2 #include <sys/socket.h> 3 #include <netinet/in.h> 4 #include <netinet/tcp.h> 5 #include <netdb.h> 6 #include <arpa/inet.h> 7 8 #include "u.h" 9 #include "lib.h" 10 #include "dat.h" 11 #include "fns.h" 12 #include "error.h" 13 #include "ip.h" 14 15 #include "devip.h" 16 17 #undef listen 18 #undef accept 19 #undef bind 20 21 static int 22 family(unsigned char *addr) 23 { 24 if(isv4(addr)) 25 return AF_INET; 26 return AF_INET6; 27 } 28 29 static int 30 addrlen(struct sockaddr_storage *ss) 31 { 32 switch(ss->ss_family){ 33 case AF_INET: 34 return sizeof(struct sockaddr_in); 35 case AF_INET6: 36 return sizeof(struct sockaddr_in6); 37 } 38 return 0; 39 } 40 41 void 42 osipinit(void) 43 { 44 char buf[1024]; 45 gethostname(buf, sizeof(buf)); 46 kstrdup(&sysname, buf); 47 48 } 49 50 int 51 so_socket(int type, unsigned char *addr) 52 { 53 int fd, one; 54 55 switch(type) { 56 default: 57 error("bad protocol type"); 58 case S_TCP: 59 type = SOCK_STREAM; 60 break; 61 case S_UDP: 62 type = SOCK_DGRAM; 63 break; 64 } 65 66 fd = socket(family(addr), type, 0); 67 if(fd < 0) 68 oserror(); 69 70 one = 1; 71 if(setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char*)&one, sizeof(one)) > 0){ 72 oserrstr(); 73 print("setsockopt: %r"); 74 } 75 76 return fd; 77 } 78 79 void 80 so_connect(int fd, unsigned char *raddr, unsigned short rport) 81 { 82 struct sockaddr_storage ss; 83 84 memset(&ss, 0, sizeof(ss)); 85 86 ss.ss_family = family(raddr); 87 88 switch(ss.ss_family){ 89 case AF_INET: 90 hnputs(&((struct sockaddr_in*)&ss)->sin_port, rport); 91 v6tov4((unsigned char*)&((struct sockaddr_in*)&ss)->sin_addr.s_addr, raddr); 92 break; 93 case AF_INET6: 94 hnputs(&((struct sockaddr_in6*)&ss)->sin6_port, rport); 95 memcpy(&((struct sockaddr_in6*)&ss)->sin6_addr.s6_addr, raddr, sizeof(struct in6_addr)); 96 break; 97 } 98 99 if(connect(fd, (struct sockaddr*)&ss, addrlen(&ss)) < 0) 100 oserror(); 101 } 102 103 void 104 so_getsockname(int fd, unsigned char *laddr, unsigned short *lport) 105 { 106 socklen_t len; 107 struct sockaddr_storage ss; 108 109 len = sizeof(ss); 110 if(getsockname(fd, (struct sockaddr*)&ss, &len) < 0) 111 oserror(); 112 113 switch(ss.ss_family){ 114 case AF_INET: 115 v4tov6(laddr, (unsigned char*)&((struct sockaddr_in*)&ss)->sin_addr.s_addr); 116 *lport = nhgets(&((struct sockaddr_in*)&ss)->sin_port); 117 break; 118 case AF_INET6: 119 memcpy(laddr, &((struct sockaddr_in6*)&ss)->sin6_addr.s6_addr, sizeof(struct in6_addr)); 120 *lport = nhgets(&((struct sockaddr_in6*)&ss)->sin6_port); 121 break; 122 default: 123 error("not AF_INET or AF_INET6"); 124 } 125 } 126 127 void 128 so_listen(int fd) 129 { 130 if(listen(fd, 5) < 0) 131 oserror(); 132 } 133 134 int 135 so_accept(int fd, unsigned char *raddr, unsigned short *rport) 136 { 137 int nfd; 138 socklen_t len; 139 struct sockaddr_storage ss; 140 141 len = sizeof(ss); 142 nfd = accept(fd, (struct sockaddr*)&ss, &len); 143 if(nfd < 0) 144 oserror(); 145 146 switch(ss.ss_family){ 147 case AF_INET: 148 v4tov6(raddr, (unsigned char*)&((struct sockaddr_in*)&ss)->sin_addr.s_addr); 149 *rport = nhgets(&((struct sockaddr_in*)&ss)->sin_port); 150 break; 151 case AF_INET6: 152 memcpy(raddr, &((struct sockaddr_in6*)&ss)->sin6_addr.s6_addr, sizeof(struct in6_addr)); 153 *rport = nhgets(&((struct sockaddr_in6*)&ss)->sin6_port); 154 break; 155 default: 156 error("not AF_INET or AF_INET6"); 157 } 158 return nfd; 159 } 160 161 void 162 so_bind(int fd, int su, unsigned short port, unsigned char *addr) 163 { 164 int i, one; 165 struct sockaddr_storage ss; 166 167 one = 1; 168 if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&one, sizeof(one)) < 0){ 169 oserrstr(); 170 print("setsockopt: %r"); 171 } 172 173 if(su) { 174 for(i = 600; i < 1024; i++) { 175 memset(&ss, 0, sizeof(ss)); 176 ss.ss_family = family(addr); 177 178 switch(ss.ss_family){ 179 case AF_INET: 180 ((struct sockaddr_in*)&ss)->sin_port = i; 181 break; 182 case AF_INET6: 183 ((struct sockaddr_in6*)&ss)->sin6_port = i; 184 break; 185 } 186 187 if(bind(fd, (struct sockaddr*)&ss, addrlen(&ss)) >= 0) 188 return; 189 } 190 oserror(); 191 } 192 193 memset(&ss, 0, sizeof(ss)); 194 ss.ss_family = family(addr); 195 196 switch(ss.ss_family){ 197 case AF_INET: 198 hnputs(&((struct sockaddr_in*)&ss)->sin_port, port); 199 break; 200 case AF_INET6: 201 hnputs(&((struct sockaddr_in6*)&ss)->sin6_port, port); 202 break; 203 } 204 205 if(bind(fd, (struct sockaddr*)&ss, addrlen(&ss)) < 0) 206 oserror(); 207 } 208 209 int 210 so_gethostbyname(char *host, char**hostv, int n) 211 { 212 int i; 213 char buf[32]; 214 unsigned char *p; 215 struct hostent *hp; 216 217 hp = gethostbyname(host); 218 if(hp == 0) 219 return 0; 220 221 for(i = 0; hp->h_addr_list[i] && i < n; i++) { 222 p = (unsigned char*)hp->h_addr_list[i]; 223 sprint(buf, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); 224 hostv[i] = strdup(buf); 225 if(hostv[i] == 0) 226 break; 227 } 228 return i; 229 } 230 231 char* 232 hostlookup(char *host) 233 { 234 char buf[INET6_ADDRSTRLEN]; 235 uchar *p; 236 struct hostent *he; 237 struct addrinfo *result; 238 239 he = gethostbyname(host); 240 if(he != 0 && he->h_addr_list[0]) { 241 p = (uchar*)he->h_addr_list[0]; 242 sprint(buf, "%ud.%ud.%ud.%ud", p[0], p[1], p[2], p[3]); 243 } else if(getaddrinfo(host, NULL, NULL, &result) == 0) { 244 switch (result->ai_family) { 245 case AF_INET: 246 inet_ntop(AF_INET, &((struct sockaddr_in*)result->ai_addr)->sin_addr, buf, sizeof(buf)); 247 break; 248 case AF_INET6: 249 inet_ntop(AF_INET6, &((struct sockaddr_in6*)result->ai_addr)->sin6_addr, buf, sizeof(buf)); 250 break; 251 default: 252 return nil; 253 } 254 } else 255 return nil; 256 257 return strdup(buf); 258 } 259 260 int 261 so_getservbyname(char *service, char *net, char *port) 262 { 263 struct servent *s; 264 265 s = getservbyname(service, net); 266 if(s == 0) 267 return -1; 268 269 sprint(port, "%d", nhgets(&s->s_port)); 270 return 0; 271 } 272 273 int 274 so_send(int fd, void *d, int n, int f) 275 { 276 return send(fd, d, n, f); 277 } 278 279 int 280 so_recv(int fd, void *d, int n, int f) 281 { 282 return recv(fd, d, n, f); 283 } 284