1 /* 2 * Copyright (c) 1995 Danny Gasparovski. 3 * 4 * Please read the file COPYRIGHT for the 5 * terms and conditions of the copyright. 6 */ 7 8 #define WANT_SYS_IOCTL_H 9 #include "qemu-common.h" 10 #include <slirp.h> 11 #include "ip_icmp.h" 12 #include "main.h" 13 #ifdef __sun__ 14 #include <sys/filio.h> 15 #endif 16 #define SLIRP_COMPILATION 1 17 #include "android/sockets.h" 18 #include "proxy_common.h" 19 20 static void sofcantrcvmore(struct socket *so); 21 static void sofcantsendmore(struct socket *so); 22 23 #if 0 24 static void 25 so_init() 26 { 27 /* Nothing yet */ 28 } 29 #endif 30 31 struct socket * 32 solookup(struct socket *head, uint32_t laddr, u_int lport, 33 uint32_t faddr, u_int fport) 34 { 35 struct socket *so; 36 37 for (so = head->so_next; so != head; so = so->so_next) { 38 if (so->so_laddr_port == lport && 39 so->so_laddr_ip == laddr && 40 so->so_faddr_ip == faddr && 41 so->so_faddr_port == fport) 42 break; 43 } 44 45 if (so == head) 46 return (struct socket *)NULL; 47 return so; 48 49 } 50 51 /* 52 * Create a new socket, initialise the fields 53 * It is the responsibility of the caller to 54 * insque() it into the correct linked-list 55 */ 56 struct socket * 57 socreate(void) 58 { 59 struct socket *so; 60 61 so = (struct socket *)malloc(sizeof(struct socket)); 62 if(so) { 63 memset(so, 0, sizeof(struct socket)); 64 so->so_state = SS_NOFDREF; 65 so->s = -1; 66 } 67 return(so); 68 } 69 70 /* 71 * remque and free a socket, clobber cache 72 */ 73 void 74 sofree(struct socket *so) 75 { 76 if (so->so_state & SS_PROXIFIED) 77 proxy_manager_del(so); 78 79 if (so->so_emu==EMU_RSH && so->extra) { 80 sofree(so->extra); 81 so->extra=NULL; 82 } 83 if (so == tcp_last_so) 84 tcp_last_so = &tcb; 85 else if (so == udp_last_so) 86 udp_last_so = &udb; 87 88 m_free(so->so_m); 89 90 if(so->so_next && so->so_prev) 91 remque(so); /* crashes if so is not in a queue */ 92 93 free(so); 94 } 95 96 size_t sopreprbuf(struct socket *so, struct iovec *iov, int *np) 97 { 98 int n, lss, total; 99 struct sbuf *sb = &so->so_snd; 100 int len = sb->sb_datalen - sb->sb_cc; 101 int mss = so->so_tcpcb->t_maxseg; 102 103 DEBUG_CALL("sopreprbuf"); 104 DEBUG_ARG("so = %lx", (long )so); 105 106 len = sb->sb_datalen - sb->sb_cc; 107 108 if (len <= 0) 109 return 0; 110 111 iov[0].iov_base = sb->sb_wptr; 112 iov[1].iov_base = NULL; 113 iov[1].iov_len = 0; 114 if (sb->sb_wptr < sb->sb_rptr) { 115 iov[0].iov_len = sb->sb_rptr - sb->sb_wptr; 116 /* Should never succeed, but... */ 117 if (iov[0].iov_len > len) 118 iov[0].iov_len = len; 119 if (iov[0].iov_len > mss) 120 iov[0].iov_len -= iov[0].iov_len%mss; 121 n = 1; 122 } else { 123 iov[0].iov_len = (sb->sb_data + sb->sb_datalen) - sb->sb_wptr; 124 /* Should never succeed, but... */ 125 if (iov[0].iov_len > len) iov[0].iov_len = len; 126 len -= iov[0].iov_len; 127 if (len) { 128 iov[1].iov_base = sb->sb_data; 129 iov[1].iov_len = sb->sb_rptr - sb->sb_data; 130 if(iov[1].iov_len > len) 131 iov[1].iov_len = len; 132 total = iov[0].iov_len + iov[1].iov_len; 133 if (total > mss) { 134 lss = total%mss; 135 if (iov[1].iov_len > lss) { 136 iov[1].iov_len -= lss; 137 n = 2; 138 } else { 139 lss -= iov[1].iov_len; 140 iov[0].iov_len -= lss; 141 n = 1; 142 } 143 } else 144 n = 2; 145 } else { 146 if (iov[0].iov_len > mss) 147 iov[0].iov_len -= iov[0].iov_len%mss; 148 n = 1; 149 } 150 } 151 if (np) 152 *np = n; 153 154 return iov[0].iov_len + (n - 1) * iov[1].iov_len; 155 } 156 157 /* 158 * Read from so's socket into sb_snd, updating all relevant sbuf fields 159 * NOTE: This will only be called if it is select()ed for reading, so 160 * a read() of 0 (or less) means it's disconnected 161 */ 162 int 163 soread(struct socket *so) 164 { 165 int n, nn; 166 struct sbuf *sb = &so->so_snd; 167 struct iovec iov[2]; 168 169 DEBUG_CALL("soread"); 170 DEBUG_ARG("so = %lx", (long )so); 171 172 /* 173 * No need to check if there's enough room to read. 174 * soread wouldn't have been called if there weren't 175 */ 176 sopreprbuf(so, iov, &n); 177 178 #ifdef HAVE_READV 179 nn = readv(so->s, (struct iovec *)iov, n); 180 DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn)); 181 #else 182 nn = socket_recv(so->s, iov[0].iov_base, iov[0].iov_len); 183 #endif 184 if (nn <= 0) { 185 if (nn < 0 && (errno == EINTR || errno == EAGAIN)) 186 return 0; 187 else { 188 DEBUG_MISC((dfd, " --- soread() disconnected, nn = %d, errno = %d-%s\n", nn, errno,errno_str)); 189 sofcantrcvmore(so); 190 tcp_sockclosed(sototcpcb(so)); 191 return -1; 192 } 193 } 194 195 #ifndef HAVE_READV 196 /* 197 * If there was no error, try and read the second time round 198 * We read again if n = 2 (ie, there's another part of the buffer) 199 * and we read as much as we could in the first read 200 * We don't test for <= 0 this time, because there legitimately 201 * might not be any more data (since the socket is non-blocking), 202 * a close will be detected on next iteration. 203 * A return of -1 wont (shouldn't) happen, since it didn't happen above 204 */ 205 if (n == 2 && nn == iov[0].iov_len) { 206 int ret; 207 ret = socket_recv(so->s, iov[1].iov_base, iov[1].iov_len); 208 if (ret > 0) 209 nn += ret; 210 } 211 212 DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn)); 213 #endif 214 215 /* Update fields */ 216 sb->sb_cc += nn; 217 sb->sb_wptr += nn; 218 if (sb->sb_wptr >= (sb->sb_data + sb->sb_datalen)) 219 sb->sb_wptr -= sb->sb_datalen; 220 return nn; 221 } 222 223 int soreadbuf(struct socket *so, const char *buf, int size) 224 { 225 int n, nn, copy = size; 226 struct sbuf *sb = &so->so_snd; 227 struct iovec iov[2]; 228 229 DEBUG_CALL("soreadbuf"); 230 DEBUG_ARG("so = %lx", (long )so); 231 232 /* 233 * No need to check if there's enough room to read. 234 * soread wouldn't have been called if there weren't 235 */ 236 if (sopreprbuf(so, iov, &n) < size) 237 goto err; 238 239 nn = MIN(iov[0].iov_len, copy); 240 memcpy(iov[0].iov_base, buf, nn); 241 242 copy -= nn; 243 buf += nn; 244 245 if (copy == 0) 246 goto done; 247 248 memcpy(iov[1].iov_base, buf, copy); 249 250 done: 251 /* Update fields */ 252 sb->sb_cc += size; 253 sb->sb_wptr += size; 254 if (sb->sb_wptr >= (sb->sb_data + sb->sb_datalen)) 255 sb->sb_wptr -= sb->sb_datalen; 256 return size; 257 err: 258 259 sofcantrcvmore(so); 260 tcp_sockclosed(sototcpcb(so)); 261 fprintf(stderr, "soreadbuf buffer to small"); 262 return -1; 263 } 264 265 /* 266 * Get urgent data 267 * 268 * When the socket is created, we set it SO_OOBINLINE, 269 * so when OOB data arrives, we soread() it and everything 270 * in the send buffer is sent as urgent data 271 */ 272 void 273 sorecvoob(struct socket *so) 274 { 275 struct tcpcb *tp = sototcpcb(so); 276 277 DEBUG_CALL("sorecvoob"); 278 DEBUG_ARG("so = %lx", (long)so); 279 280 /* 281 * We take a guess at how much urgent data has arrived. 282 * In most situations, when urgent data arrives, the next 283 * read() should get all the urgent data. This guess will 284 * be wrong however if more data arrives just after the 285 * urgent data, or the read() doesn't return all the 286 * urgent data. 287 */ 288 soread(so); 289 tp->snd_up = tp->snd_una + so->so_snd.sb_cc; 290 tp->t_force = 1; 291 tcp_output(tp); 292 tp->t_force = 0; 293 } 294 295 /* 296 * Send urgent data 297 * There's a lot duplicated code here, but... 298 */ 299 int 300 sosendoob(struct socket *so) 301 { 302 struct sbuf *sb = &so->so_rcv; 303 char buff[2048]; /* XXX Shouldn't be sending more oob data than this */ 304 305 int n, len; 306 307 DEBUG_CALL("sosendoob"); 308 DEBUG_ARG("so = %lx", (long)so); 309 DEBUG_ARG("sb->sb_cc = %d", sb->sb_cc); 310 311 if (so->so_urgc > 2048) 312 so->so_urgc = 2048; /* XXXX */ 313 314 if (sb->sb_rptr < sb->sb_wptr) { 315 /* We can send it directly */ 316 n = socket_send_oob(so->s, sb->sb_rptr, so->so_urgc); /* |MSG_DONTWAIT)); */ 317 so->so_urgc -= n; 318 319 DEBUG_MISC((dfd, " --- sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc)); 320 } else { 321 /* 322 * Since there's no sendv or sendtov like writev, 323 * we must copy all data to a linear buffer then 324 * send it all 325 */ 326 len = (sb->sb_data + sb->sb_datalen) - sb->sb_rptr; 327 if (len > so->so_urgc) len = so->so_urgc; 328 memcpy(buff, sb->sb_rptr, len); 329 so->so_urgc -= len; 330 if (so->so_urgc) { 331 n = sb->sb_wptr - sb->sb_data; 332 if (n > so->so_urgc) n = so->so_urgc; 333 memcpy((buff + len), sb->sb_data, n); 334 so->so_urgc -= n; 335 len += n; 336 } 337 n = socket_send_oob(so->s, buff, len); /* |MSG_DONTWAIT)); */ 338 #ifdef DEBUG 339 if (n != len) 340 DEBUG_ERROR((dfd, "Didn't send all data urgently XXXXX\n")); 341 #endif 342 DEBUG_MISC((dfd, " ---2 sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc)); 343 } 344 345 sb->sb_cc -= n; 346 sb->sb_rptr += n; 347 if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen)) 348 sb->sb_rptr -= sb->sb_datalen; 349 350 return n; 351 } 352 353 /* 354 * Write data from so_rcv to so's socket, 355 * updating all sbuf field as necessary 356 */ 357 int 358 sowrite(struct socket *so) 359 { 360 int n,nn; 361 struct sbuf *sb = &so->so_rcv; 362 int len = sb->sb_cc; 363 struct iovec iov[2]; 364 365 DEBUG_CALL("sowrite"); 366 DEBUG_ARG("so = %lx", (long)so); 367 368 if (so->so_urgc) { 369 sosendoob(so); 370 if (sb->sb_cc == 0) 371 return 0; 372 } 373 374 /* 375 * No need to check if there's something to write, 376 * sowrite wouldn't have been called otherwise 377 */ 378 379 len = sb->sb_cc; 380 381 iov[0].iov_base = sb->sb_rptr; 382 iov[1].iov_base = NULL; 383 iov[1].iov_len = 0; 384 if (sb->sb_rptr < sb->sb_wptr) { 385 iov[0].iov_len = sb->sb_wptr - sb->sb_rptr; 386 /* Should never succeed, but... */ 387 if (iov[0].iov_len > len) iov[0].iov_len = len; 388 n = 1; 389 } else { 390 iov[0].iov_len = (sb->sb_data + sb->sb_datalen) - sb->sb_rptr; 391 if (iov[0].iov_len > len) iov[0].iov_len = len; 392 len -= iov[0].iov_len; 393 if (len) { 394 iov[1].iov_base = sb->sb_data; 395 iov[1].iov_len = sb->sb_wptr - sb->sb_data; 396 if (iov[1].iov_len > len) iov[1].iov_len = len; 397 n = 2; 398 } else 399 n = 1; 400 } 401 /* Check if there's urgent data to send, and if so, send it */ 402 403 #ifdef HAVE_READV 404 nn = writev(so->s, (const struct iovec *)iov, n); 405 406 DEBUG_MISC((dfd, " ... wrote nn = %d bytes\n", nn)); 407 #else 408 nn = socket_send(so->s, iov[0].iov_base, iov[0].iov_len); 409 #endif 410 /* This should never happen, but people tell me it does *shrug* */ 411 if (nn < 0 && (errno == EAGAIN || errno == EINTR)) 412 return 0; 413 414 if (nn <= 0) { 415 DEBUG_MISC((dfd, " --- sowrite disconnected, so->so_state = %x, errno = %d\n", 416 so->so_state, errno)); 417 sofcantsendmore(so); 418 tcp_sockclosed(sototcpcb(so)); 419 return -1; 420 } 421 422 #ifndef HAVE_READV 423 if (n == 2 && nn == iov[0].iov_len) { 424 int ret; 425 ret = socket_send(so->s, iov[1].iov_base, iov[1].iov_len); 426 if (ret > 0) 427 nn += ret; 428 } 429 DEBUG_MISC((dfd, " ... wrote nn = %d bytes\n", nn)); 430 #endif 431 432 /* Update sbuf */ 433 sb->sb_cc -= nn; 434 sb->sb_rptr += nn; 435 if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen)) 436 sb->sb_rptr -= sb->sb_datalen; 437 438 /* 439 * If in DRAIN mode, and there's no more data, set 440 * it CANTSENDMORE 441 */ 442 if ((so->so_state & SS_FWDRAIN) && sb->sb_cc == 0) 443 sofcantsendmore(so); 444 445 return nn; 446 } 447 448 /* 449 * recvfrom() a UDP socket 450 */ 451 void 452 sorecvfrom(struct socket *so) 453 { 454 SockAddress addr; 455 456 DEBUG_CALL("sorecvfrom"); 457 DEBUG_ARG("so = %lx", (long)so); 458 459 if (so->so_type == IPPROTO_ICMP) { /* This is a "ping" reply */ 460 char buff[256]; 461 int len; 462 463 len = socket_recvfrom(so->s, buff, 256, &addr); 464 /* XXX Check if reply is "correct"? */ 465 466 if(len == -1 || len == 0) { 467 u_char code=ICMP_UNREACH_PORT; 468 469 if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST; 470 else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET; 471 472 DEBUG_MISC((dfd," udp icmp rx errno = %d-%s\n", 473 errno,errno_str)); 474 icmp_error(so->so_m, ICMP_UNREACH,code, 0,errno_str); 475 } else { 476 icmp_reflect(so->so_m); 477 so->so_m = 0; /* Don't mbuf_free() it again! */ 478 } 479 /* No need for this socket anymore, udp_detach it */ 480 udp_detach(so); 481 } else { /* A "normal" UDP packet */ 482 struct mbuf *m; 483 int len; 484 int n; 485 486 if (!(m = m_get())) return; 487 m->m_data += IF_MAXLINKHDR; 488 489 /* 490 * XXX Shouldn't FIONREAD packets destined for port 53, 491 * but I don't know the max packet size for DNS lookups 492 */ 493 len = M_FREEROOM(m); 494 /* if (so->so_fport != htons(53)) { */ 495 n = socket_can_read(so->s); 496 497 if (n > len) { 498 n = (m->m_data - m->m_dat) + m->m_len + n + 1; 499 m_inc(m, n); 500 len = M_FREEROOM(m); 501 } 502 /* } */ 503 504 m->m_len = socket_recvfrom(so->s, m->m_data, len, &addr); 505 DEBUG_MISC((dfd, " did recvfrom %d, errno = %d-%s\n", 506 m->m_len, errno,errno_str)); 507 if(m->m_len<0) { 508 u_char code=ICMP_UNREACH_PORT; 509 510 if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST; 511 else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET; 512 513 DEBUG_MISC((dfd," rx error, tx icmp ICMP_UNREACH:%i\n", code)); 514 icmp_error(so->so_m, ICMP_UNREACH,code, 0,errno_str); 515 m_free(m); 516 } else { 517 /* 518 * Hack: domain name lookup will be used the most for UDP, 519 * and since they'll only be used once there's no need 520 * for the 4 minute (or whatever) timeout... So we time them 521 * out much quicker (10 seconds for now...) 522 */ 523 if (so->so_expire) { 524 if (so->so_faddr_port == 53) 525 so->so_expire = curtime + SO_EXPIREFAST; 526 else 527 so->so_expire = curtime + SO_EXPIRE; 528 } 529 530 /* if (m->m_len == len) { 531 * m_inc(m, MINCSIZE); 532 * m->m_len = 0; 533 * } 534 */ 535 536 /* 537 * If this packet was destined for CTL_ADDR, 538 * make it look like that's where it came from, done by udp_output 539 */ 540 udp_output_(so, m, &addr); 541 } /* rx error */ 542 } /* if ping packet */ 543 } 544 545 /* 546 * sendto() a socket 547 */ 548 int 549 sosendto(struct socket *so, struct mbuf *m) 550 { 551 int ret; 552 SockAddress addr; 553 uint32_t addr_ip; 554 uint16_t addr_port; 555 556 DEBUG_CALL("sosendto"); 557 DEBUG_ARG("so = %lx", (long)so); 558 DEBUG_ARG("m = %lx", (long)m); 559 560 if ((so->so_faddr_ip & 0xffffff00) == special_addr_ip) { 561 /* It's an alias */ 562 int low = so->so_faddr_ip & 0xff; 563 564 if ( CTL_IS_DNS(low) ) 565 addr_ip = dns_addr[low - CTL_DNS]; 566 else 567 addr_ip = loopback_addr_ip; 568 } else 569 addr_ip = so->so_faddr_ip; 570 571 addr_port = so->so_faddr_port; 572 573 /* 574 * test for generic forwarding; this function replaces the arguments 575 * only on success 576 */ 577 unsigned long faddr = addr_ip; 578 int fport = addr_port; 579 580 if (slirp_should_net_forward(faddr, fport, &faddr, &fport)) { 581 time_t timestamp = time(NULL); 582 slirp_drop_log( 583 "Redirected UDP: src: 0x%08lx:0x%04x org dst: 0x%08lx:0x%04x " 584 "new dst: 0x%08lx:0x%04x %ld\n", 585 so->so_laddr_ip, so->so_laddr_port, 586 addr_ip, addr_port, 587 faddr, fport, timestamp 588 ); 589 } 590 addr_ip = faddr; 591 addr_port = fport; 592 593 594 sock_address_init_inet(&addr, addr_ip, addr_port); 595 596 DEBUG_MISC((dfd, " sendto()ing, addr.sin_port=%d, addr.sin_addr.s_addr=%08x\n", addr_port, addr_ip)); 597 598 /* Don't care what port we get */ 599 ret = socket_sendto(so->s, m->m_data, m->m_len,&addr); 600 if (ret < 0) 601 return -1; 602 603 /* 604 * Kill the socket if there's no reply in 4 minutes, 605 * but only if it's an expirable socket 606 */ 607 if (so->so_expire) 608 so->so_expire = curtime + SO_EXPIRE; 609 so->so_state = SS_ISFCONNECTED; /* So that it gets select()ed */ 610 return 0; 611 } 612 613 /* 614 * XXX This should really be tcp_listen 615 */ 616 struct socket * 617 solisten(u_int port, u_int32_t laddr, u_int lport, int flags) 618 { 619 SockAddress addr; 620 uint32_t addr_ip; 621 struct socket *so; 622 int s; 623 624 DEBUG_CALL("solisten"); 625 DEBUG_ARG("port = %d", port); 626 DEBUG_ARG("laddr = %x", laddr); 627 DEBUG_ARG("lport = %d", lport); 628 DEBUG_ARG("flags = %x", flags); 629 630 if ((so = socreate()) == NULL) { 631 /* free(so); Not sofree() ??? free(NULL) == NOP */ 632 return NULL; 633 } 634 635 /* Don't tcp_attach... we don't need so_snd nor so_rcv */ 636 if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL) { 637 free(so); 638 return NULL; 639 } 640 insque(so,&tcb); 641 642 /* 643 * SS_FACCEPTONCE sockets must time out. 644 */ 645 if (flags & SS_FACCEPTONCE) 646 so->so_tcpcb->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT*2; 647 648 so->so_state = (SS_FACCEPTCONN|flags); 649 so->so_laddr_port = lport; /* Kept in host format */ 650 so->so_laddr_ip = laddr; /* Ditto */ 651 so->so_haddr_port = port; 652 653 s = socket_loopback_server( port, SOCKET_STREAM ); 654 if (s < 0) 655 return NULL; 656 657 socket_get_address(s, &addr); 658 659 so->so_faddr_port = sock_address_get_port(&addr); 660 661 addr_ip = (uint32_t) sock_address_get_ip(&addr); 662 663 if (addr_ip == 0 || addr_ip == loopback_addr_ip) 664 so->so_faddr_ip = alias_addr_ip; 665 else 666 so->so_faddr_ip = addr_ip; 667 668 so->s = s; 669 return so; 670 } 671 672 673 int 674 sounlisten(u_int port) 675 { 676 struct socket *so; 677 678 for (so = tcb.so_next; so != &tcb; so = so->so_next) { 679 if (so->so_haddr_port == port) { 680 break; 681 } 682 } 683 684 if (so == &tcb) { 685 return -1; 686 } 687 688 sofcantrcvmore( so ); 689 sofcantsendmore( so ); 690 close( so->s ); 691 so->s = -1; 692 sofree( so ); 693 return 0; 694 } 695 696 697 #if 0 698 /* 699 * Data is available in so_rcv 700 * Just write() the data to the socket 701 * XXX not yet... 702 */ 703 static void 704 sorwakeup(so) 705 struct socket *so; 706 { 707 /* sowrite(so); */ 708 /* FD_CLR(so->s,&writefds); */ 709 } 710 711 /* 712 * Data has been freed in so_snd 713 * We have room for a read() if we want to 714 * For now, don't read, it'll be done in the main loop 715 */ 716 static void 717 sowwakeup(so) 718 struct socket *so; 719 { 720 /* Nothing, yet */ 721 } 722 #endif 723 724 /* 725 * Various session state calls 726 * XXX Should be #define's 727 * The socket state stuff needs work, these often get call 2 or 3 728 * times each when only 1 was needed 729 */ 730 void 731 soisfconnecting(struct socket *so) 732 { 733 so->so_state &= ~(SS_NOFDREF|SS_ISFCONNECTED|SS_FCANTRCVMORE| 734 SS_FCANTSENDMORE|SS_FWDRAIN); 735 so->so_state |= SS_ISFCONNECTING; /* Clobber other states */ 736 } 737 738 void 739 soisfconnected(struct socket *so) 740 { 741 so->so_state &= ~(SS_ISFCONNECTING|SS_FWDRAIN|SS_NOFDREF); 742 so->so_state |= SS_ISFCONNECTED; /* Clobber other states */ 743 } 744 745 static void 746 sofcantrcvmore(struct socket *so) 747 { 748 if ((so->so_state & SS_NOFDREF) == 0) { 749 shutdown(so->s,0); 750 if(global_writefds) { 751 FD_CLR(so->s,global_writefds); 752 } 753 } 754 so->so_state &= ~(SS_ISFCONNECTING); 755 if (so->so_state & SS_FCANTSENDMORE) 756 so->so_state = SS_NOFDREF; /* Don't select it */ /* XXX close() here as well? */ 757 else 758 so->so_state |= SS_FCANTRCVMORE; 759 } 760 761 static void 762 sofcantsendmore(struct socket *so) 763 { 764 if ((so->so_state & SS_NOFDREF) == 0) { 765 shutdown(so->s,1); /* send FIN to fhost */ 766 if (global_readfds) { 767 FD_CLR(so->s,global_readfds); 768 } 769 if (global_xfds) { 770 FD_CLR(so->s,global_xfds); 771 } 772 } 773 so->so_state &= ~(SS_ISFCONNECTING); 774 if (so->so_state & SS_FCANTRCVMORE) 775 so->so_state = SS_NOFDREF; /* as above */ 776 else 777 so->so_state |= SS_FCANTSENDMORE; 778 } 779 780 void 781 soisfdisconnected(struct socket *so) 782 { 783 /* so->so_state &= ~(SS_ISFCONNECTING|SS_ISFCONNECTED); */ 784 /* close(so->s); */ 785 /* so->so_state = SS_ISFDISCONNECTED; */ 786 /* 787 * XXX Do nothing ... ? 788 */ 789 } 790 791 /* 792 * Set write drain mode 793 * Set CANTSENDMORE once all data has been write()n 794 */ 795 void 796 sofwdrain(struct socket *so) 797 { 798 if (so->so_rcv.sb_cc) 799 so->so_state |= SS_FWDRAIN; 800 else 801 sofcantsendmore(so); 802 } 803