PageRenderTime 43ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/BasiliskII/src/slirp/socket.c

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