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