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