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