ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/slirp/socket.c
Revision: 1.5
Committed: 2007-01-22T14:48:40Z (17 years, 9 months ago) by asvitkine
Content type: text/plain
Branch: MAIN
Changes since 1.4: +1 -0 lines
Log Message:
fix compile warnings w/ slirp caused by not including stdlib

File Contents

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