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