1 #define Unknown win_Unknown 2 #include <windows.h> 3 #include <winbase.h> 4 #include <sys/types.h> 5 #include <winsock.h> 6 #undef Unknown 7 #include "dat.h" 8 #include "fns.h" 9 #include "ip.h" 10 #include "error.h" 11 12 extern int SOCK_SELECT; 13 14 int 15 so_socket(int type) 16 { 17 int fd, one; 18 19 switch(type) { 20 default: 21 error("bad protocol type"); 22 case S_TCP: 23 type = SOCK_STREAM; 24 break; 25 case S_UDP: 26 type = SOCK_DGRAM; 27 break; 28 } 29 fd = socket(AF_INET, type, 0); 30 if(fd < 0) 31 oserror(); 32 if(type == SOCK_DGRAM){ 33 one = 1; 34 setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (char*)&one, sizeof (one)); 35 }else{ 36 one = 1; 37 setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&one, sizeof(one)); 38 } 39 return fd; 40 } 41 42 int 43 so_send(int sock, void *va, int len, void *hdr, int hdrlen) 44 { 45 int r; 46 struct sockaddr sa; 47 struct sockaddr_in *sin; 48 char *h = hdr; 49 50 51 osenter(); 52 if(hdr == 0) 53 r = send(sock, va, len, 0); 54 else { 55 memset(&sa, sizeof(sa), 0); 56 sin = (struct sockaddr_in*)&sa; 57 sin->sin_family = AF_INET; 58 switch(hdrlen){ 59 case OUdphdrlenv4: 60 memmove(&sin->sin_addr, h, 4); 61 memmove(&sin->sin_port, h+8, 2); 62 break; 63 case OUdphdrlen: 64 v6tov4((uchar*)&sin->sin_addr, h); 65 memmove(&sin->sin_port, h+2*IPaddrlen, 2); /* rport */ 66 break; 67 default: 68 v6tov4((uchar*)&sin->sin_addr, h); 69 memmove(&sin->sin_port, h+3*IPaddrlen, 2); 70 break; 71 } 72 r = sendto(sock, va, len, 0, &sa, sizeof(sa)); 73 } 74 osleave(); 75 return r; 76 } 77 78 static int 79 doselect(int sock) 80 { 81 fd_set waitr; 82 struct timeval seltime; 83 84 up->syscall = SOCK_SELECT; 85 FD_ZERO(&waitr); 86 FD_SET(sock, &waitr); 87 for(;;){ 88 int nfds; 89 fd_set in, exc; 90 91 in = waitr; 92 exc = waitr; 93 seltime.tv_sec = 1; 94 seltime.tv_usec = 0L; 95 nfds = select(sizeof(fd_set)*8, &in, (fd_set*)0, &exc, &seltime); 96 if(up->intwait) { 97 up->intwait = 0; 98 return -1; 99 } 100 if(nfds < 0) { 101 print("select error\n"); 102 return 0; 103 } 104 if(FD_ISSET(sock, &in) || FD_ISSET(sock, &exc)){ 105 return 0; 106 } 107 } 108 } 109 110 int 111 so_recv(int sock, void *va, int len, void *hdr, int hdrlen) 112 { 113 int r, l; 114 struct sockaddr sa; 115 struct sockaddr_in *sin; 116 char h[Udphdrlen]; 117 118 osenter(); 119 if(doselect(sock) < 0) { 120 osleave(); 121 return -1; 122 } 123 if(hdr == 0) 124 r = recv(sock, va, len, 0); 125 else { 126 sin = (struct sockaddr_in*)&sa; 127 l = sizeof(sa); 128 r = recvfrom(sock, va, len, 0, &sa, &l); 129 if(r >= 0) { 130 memset(h, sizeof h, 0); 131 switch(hdrlen){ 132 case OUdphdrlenv4: 133 memmove(h, &sin->sin_addr, 4); 134 memmove(h+2*IPv4addrlen, &sin->sin_port, 2); 135 break; 136 case OUdphdrlen: 137 v4tov6(h, (uchar*)&sin->sin_addr); 138 memmove(h+2*IPaddrlen, &sin->sin_port, 2); 139 break; 140 default: 141 v4tov6(h, (uchar*)&sin->sin_addr); 142 memmove(h+3*IPaddrlen, &sin->sin_port, 2); 143 break; 144 } 145 146 /* alas there's no way to get the local addr/port correctly. Pretend. */ 147 getsockname(sock, &sa, &l); 148 switch(hdrlen){ 149 case OUdphdrlenv4: 150 memmove(h+IPv4addrlen, &sin->sin_addr, IPv4addrlen); 151 memmove(h+2*IPv4addrlen+2, &sin->sin_port, 2); 152 break; 153 case OUdphdrlen: 154 v4tov6(h+IPaddrlen, (uchar*)&sin->sin_addr); 155 memmove(h+2*IPaddrlen+2, &sin->sin_port, 2); 156 break; 157 default: 158 v4tov6(h+IPaddrlen, (uchar*)&sin->sin_addr); 159 v4tov6(h+2*IPaddrlen, (uchar*)&sin->sin_addr); /* ifcaddr */ 160 memmove(h+3*IPaddrlen+2, &sin->sin_port, 2); 161 break; 162 } 163 memmove(hdr, h, hdrlen); 164 } 165 } 166 osleave(); 167 return r; 168 } 169 170 void 171 so_close(int sock) 172 { 173 closesocket(sock); 174 } 175 176 void 177 so_connect(int fd, unsigned long raddr, unsigned short rport) 178 { 179 int r; 180 struct sockaddr sa; 181 struct sockaddr_in *sin; 182 183 memset(&sa, 0, sizeof(sa)); 184 sin = (struct sockaddr_in*)&sa; 185 sin->sin_family = AF_INET; 186 hnputs(&sin->sin_port, rport); 187 hnputl(&sin->sin_addr.s_addr, raddr); 188 189 osenter(); 190 r = connect(fd, &sa, sizeof(sa)); 191 osleave(); 192 if(r < 0) 193 oserror(); 194 } 195 196 void 197 so_getsockname(int fd, unsigned long *laddr, unsigned short *lport) 198 { 199 int len; 200 struct sockaddr sa; 201 struct sockaddr_in *sin; 202 203 sin = (struct sockaddr_in*)&sa; 204 205 len = sizeof(sa); 206 if(getsockname(fd, &sa, &len) < 0) 207 oserror(); 208 209 if(sin->sin_family != AF_INET || len != sizeof(*sin)) 210 error("not AF_INET"); 211 212 *laddr = nhgetl(&sin->sin_addr.s_addr); 213 *lport = nhgets(&sin->sin_port); 214 } 215 216 void 217 so_listen(int fd) 218 { 219 int r; 220 221 osenter(); 222 r = listen(fd, 5); 223 osleave(); 224 if(r < 0) 225 oserror(); 226 } 227 228 int 229 so_accept(int fd, unsigned long *raddr, unsigned short *rport) 230 { 231 int nfd, len; 232 struct sockaddr sa; 233 struct sockaddr_in *sin; 234 235 sin = (struct sockaddr_in*)&sa; 236 237 len = sizeof(sa); 238 osenter(); 239 if(doselect(fd) < 0) { 240 osleave(); 241 return -1; 242 } 243 nfd = accept(fd, &sa, &len); 244 osleave(); 245 if(nfd < 0) 246 oserror(); 247 248 if(sin->sin_family != AF_INET || len != sizeof(*sin)) 249 error("not AF_INET"); 250 251 *raddr = nhgetl(&sin->sin_addr.s_addr); 252 *rport = nhgets(&sin->sin_port); 253 return nfd; 254 } 255 256 void 257 so_bind(int fd, int su, unsigned long addr, unsigned short port) 258 { 259 int i, one; 260 struct sockaddr sa; 261 struct sockaddr_in *sin; 262 263 sin = (struct sockaddr_in*)&sa; 264 265 one = 1; 266 // if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&one, sizeof(one)) < 0) { 267 // oserrstr(up->genbuf, sizeof(up->genbuf)); 268 // print("setsockopt: %s", err); 269 // } 270 271 if(su) { 272 for(i = 600; i < 1024; i++) { 273 memset(&sa, 0, sizeof(sa)); 274 sin->sin_family = AF_INET; 275 hnputl(&sin->sin_addr.s_addr, addr); 276 hnputs(&sin->sin_port, i); 277 278 if(bind(fd, &sa, sizeof(sa)) >= 0) 279 return; 280 } 281 oserror(); 282 } 283 284 memset(&sa, 0, sizeof(sa)); 285 sin->sin_family = AF_INET; 286 hnputl(&sin->sin_addr.s_addr, addr); 287 hnputs(&sin->sin_port, port); 288 289 if(bind(fd, &sa, sizeof(sa)) < 0) 290 oserror(); 291 } 292 293 void 294 so_setsockopt(int fd, int opt, int value) 295 { 296 int r; 297 struct linger l; 298 299 if(opt == SO_LINGER){ 300 l.l_onoff = 1; 301 l.l_linger = (short) value; 302 osenter(); 303 r = setsockopt(fd, SOL_SOCKET, opt, (char *)&l, sizeof(l)); 304 osleave(); 305 }else 306 error(Ebadctl); 307 if(r < 0) 308 oserror(); 309 } 310 311 int 312 so_gethostbyname(char *host, char**hostv, int n) 313 { 314 int i; 315 unsigned char buf[32], *p; 316 struct hostent *hp; 317 318 hp = gethostbyname(host); 319 if(hp == 0) 320 return 0; 321 322 for(i = 0; hp->h_addr_list[i] && i < n; i++) { 323 p = hp->h_addr_list[i]; 324 sprint(buf, "%ud.%ud.%ud.%ud", p[0], p[1], p[2], p[3]); 325 hostv[i] = strdup(buf); 326 if(hostv[i] == 0) 327 break; 328 } 329 return i; 330 } 331 332 int 333 so_gethostbyaddr(char *addr, char **hostv, int n) 334 { 335 int i; 336 struct hostent *hp; 337 unsigned long straddr; 338 339 straddr = inet_addr(addr); 340 if(straddr == -1) 341 return 0; 342 343 hp = gethostbyaddr((char *)&straddr, sizeof (straddr), AF_INET); 344 if(hp == 0) 345 return 0; 346 347 hostv[0] = strdup(hp->h_name); 348 if(hostv[0] == 0) 349 return 0; 350 for(i = 1; hp->h_aliases[i-1] && i < n; i++) { 351 hostv[i] = strdup(hp->h_aliases[i-1]); 352 if(hostv[i] == 0) 353 break; 354 } 355 return i; 356 } 357 358 int 359 so_getservbyname(char *service, char *net, char *port) 360 { 361 ushort p; 362 struct servent *s; 363 364 s = getservbyname(service, net); 365 if(s == 0) 366 return -1; 367 p = s->s_port; 368 sprint(port, "%d", nhgets(&p)); 369 return 0; 370 } 371 372 int 373 so_hangup(int fd, int linger) 374 { 375 int r; 376 static struct linger l = {1, 1000}; 377 378 osenter(); 379 if(linger) 380 setsockopt(fd, SOL_SOCKET, SO_LINGER, (char*)&l, sizeof(l)); 381 r = closesocket(fd); 382 osleave(); 383 return r; 384 } 385 386 void 387 arpadd(char *ipaddr, char *eaddr, int n) 388 { 389 error("arp not implemented"); 390 } 391 392 int 393 so_mustbind(int restricted, int port) 394 { 395 USED(restricted); 396 USED(port); 397 /* Windows requires bound sockets, even on port 0 */ 398 return 1; 399 } 400 401 void 402 so_keepalive(int fd, int ms) 403 { 404 int on; 405 406 USED(ms); 407 on = 1; 408 setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char*)&on, sizeof(on)); 409 } 410