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