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, 0, sizeof(sa)); 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, 0, sizeof(h)); 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, 256); 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 int 294 so_gethostbyname(char *host, char**hostv, int n) 295 { 296 int i; 297 unsigned char buf[32], *p; 298 struct hostent *hp; 299 300 hp = gethostbyname(host); 301 if(hp == 0) 302 return 0; 303 304 for(i = 0; hp->h_addr_list[i] && i < n; i++) { 305 p = hp->h_addr_list[i]; 306 sprint(buf, "%ud.%ud.%ud.%ud", p[0], p[1], p[2], p[3]); 307 hostv[i] = strdup(buf); 308 if(hostv[i] == 0) 309 break; 310 } 311 return i; 312 } 313 314 int 315 so_gethostbyaddr(char *addr, char **hostv, int n) 316 { 317 int i; 318 struct hostent *hp; 319 unsigned long straddr; 320 321 straddr = inet_addr(addr); 322 if(straddr == -1) 323 return 0; 324 325 hp = gethostbyaddr((char *)&straddr, sizeof (straddr), AF_INET); 326 if(hp == 0) 327 return 0; 328 329 hostv[0] = strdup(hp->h_name); 330 if(hostv[0] == 0) 331 return 0; 332 for(i = 1; hp->h_aliases[i-1] && i < n; i++) { 333 hostv[i] = strdup(hp->h_aliases[i-1]); 334 if(hostv[i] == 0) 335 break; 336 } 337 return i; 338 } 339 340 int 341 so_getservbyname(char *service, char *net, char *port) 342 { 343 ushort p; 344 struct servent *s; 345 346 s = getservbyname(service, net); 347 if(s == 0) 348 return -1; 349 p = s->s_port; 350 sprint(port, "%d", nhgets(&p)); 351 return 0; 352 } 353 354 int 355 so_hangup(int fd, int nolinger) 356 { 357 int r; 358 static struct linger l = {1, 0}; 359 360 osenter(); 361 if(nolinger) 362 setsockopt(fd, SOL_SOCKET, SO_LINGER, (char*)&l, sizeof(l)); 363 r = closesocket(fd); 364 osleave(); 365 return r; 366 } 367 368 void 369 arpadd(char *ipaddr, char *eaddr, int n) 370 { 371 error("arp not implemented"); 372 } 373 374 int 375 so_mustbind(int restricted, int port) 376 { 377 USED(restricted); 378 USED(port); 379 /* Windows requires bound sockets, even on port 0 */ 380 return 1; 381 } 382 383 void 384 so_keepalive(int fd, int ms) 385 { 386 int on; 387 388 USED(ms); 389 on = 1; 390 setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char*)&on, sizeof(on)); 391 } 392