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