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