|
|
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: #include <slirp.h>
10: #include "ip_icmp.h"
1.1.1.2 root 11: #ifdef __sun__
12: #include <sys/filio.h>
13: #endif
1.1 root 14:
1.1.1.3 root 15: static void sofcantrcvmore(struct socket *so);
16: static void sofcantsendmore(struct socket *so);
17:
1.1 root 18: struct socket *
1.1.1.5 root 19: solookup(struct socket *head, struct in_addr laddr, u_int lport,
20: struct in_addr faddr, u_int fport)
1.1 root 21: {
22: struct socket *so;
1.1.1.3 root 23:
1.1 root 24: for (so = head->so_next; so != head; so = so->so_next) {
1.1.1.3 root 25: if (so->so_lport == lport &&
1.1 root 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: }
1.1.1.3 root 31:
1.1 root 32: if (so == head)
33: return (struct socket *)NULL;
34: return so;
1.1.1.3 root 35:
1.1 root 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 *
1.1.1.5 root 44: socreate(Slirp *slirp)
1.1 root 45: {
46: struct socket *so;
1.1.1.3 root 47:
1.1 root 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;
1.1.1.5 root 53: so->slirp = slirp;
1.1 root 54: }
55: return(so);
56: }
57:
58: /*
59: * remque and free a socket, clobber cache
60: */
61: void
1.1.1.5 root 62: sofree(struct socket *so)
1.1 root 63: {
1.1.1.5 root 64: Slirp *slirp = so->slirp;
65:
1.1 root 66: if (so->so_emu==EMU_RSH && so->extra) {
67: sofree(so->extra);
68: so->extra=NULL;
69: }
1.1.1.5 root 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;
1.1.1.8 ! root 74: } else if (so == slirp->icmp_last_so) {
! 75: slirp->icmp_last_so = &slirp->icmp;
1.1.1.5 root 76: }
1.1 root 77: m_free(so->so_m);
1.1.1.3 root 78:
79: if(so->so_next && so->so_prev)
1.1 root 80: remque(so); /* crashes if so is not in a queue */
81:
82: free(so);
83: }
84:
1.1.1.4 root 85: size_t sopreprbuf(struct socket *so, struct iovec *iov, int *np)
1.1 root 86: {
1.1.1.4 root 87: int n, lss, total;
1.1 root 88: struct sbuf *sb = &so->so_snd;
89: int len = sb->sb_datalen - sb->sb_cc;
90: int mss = so->so_tcpcb->t_maxseg;
1.1.1.3 root 91:
1.1.1.4 root 92: DEBUG_CALL("sopreprbuf");
1.1 root 93: DEBUG_ARG("so = %lx", (long )so);
1.1.1.3 root 94:
1.1.1.4 root 95: if (len <= 0)
96: return 0;
97:
1.1 root 98: iov[0].iov_base = sb->sb_wptr;
1.1.1.4 root 99: iov[1].iov_base = NULL;
100: iov[1].iov_len = 0;
1.1 root 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: }
1.1.1.4 root 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
1.1.1.5 root 150: soread(struct socket *so)
1.1.1.4 root 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);
1.1.1.3 root 164:
1.1 root 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
1.1.1.8 ! root 169: nn = qemu_recv(so->s, iov[0].iov_base, iov[0].iov_len,0);
1.1.1.3 root 170: #endif
1.1 root 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: }
1.1.1.3 root 181:
1.1 root 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;
1.1.1.8 ! root 194: ret = qemu_recv(so->s, iov[1].iov_base, iov[1].iov_len,0);
1.1 root 195: if (ret > 0)
196: nn += ret;
197: }
1.1.1.3 root 198:
1.1 root 199: DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn));
200: #endif
1.1.1.3 root 201:
1.1 root 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: }
1.1.1.3 root 209:
1.1.1.4 root 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:
1.1 root 252: /*
253: * Get urgent data
1.1.1.3 root 254: *
1.1 root 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
1.1.1.5 root 260: sorecvoob(struct socket *so)
1.1 root 261: {
262: struct tcpcb *tp = sototcpcb(so);
263:
264: DEBUG_CALL("sorecvoob");
265: DEBUG_ARG("so = %lx", (long)so);
1.1.1.3 root 266:
1.1 root 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
1.1.1.3 root 272: * urgent data, or the read() doesn't return all the
1.1 root 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
1.1.1.5 root 287: sosendoob(struct socket *so)
1.1 root 288: {
289: struct sbuf *sb = &so->so_rcv;
290: char buff[2048]; /* XXX Shouldn't be sending more oob data than this */
1.1.1.3 root 291:
1.1 root 292: int n, len;
1.1.1.3 root 293:
1.1 root 294: DEBUG_CALL("sosendoob");
295: DEBUG_ARG("so = %lx", (long)so);
296: DEBUG_ARG("sb->sb_cc = %d", sb->sb_cc);
1.1.1.3 root 297:
1.1 root 298: if (so->so_urgc > 2048)
299: so->so_urgc = 2048; /* XXXX */
1.1.1.3 root 300:
1.1 root 301: if (sb->sb_rptr < sb->sb_wptr) {
302: /* We can send it directly */
1.1.1.4 root 303: n = slirp_send(so, sb->sb_rptr, so->so_urgc, (MSG_OOB)); /* |MSG_DONTWAIT)); */
1.1 root 304: so->so_urgc -= n;
1.1.1.3 root 305:
1.1 root 306: DEBUG_MISC((dfd, " --- sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc));
307: } else {
1.1.1.3 root 308: /*
1.1 root 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: }
1.1.1.4 root 324: n = slirp_send(so, buff, len, (MSG_OOB)); /* |MSG_DONTWAIT)); */
1.1 root 325: #ifdef DEBUG
326: if (n != len)
327: DEBUG_ERROR((dfd, "Didn't send all data urgently XXXXX\n"));
1.1.1.3 root 328: #endif
1.1 root 329: DEBUG_MISC((dfd, " ---2 sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc));
330: }
1.1.1.3 root 331:
1.1 root 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;
1.1.1.3 root 336:
1.1 root 337: return n;
338: }
339:
340: /*
1.1.1.3 root 341: * Write data from so_rcv to so's socket,
1.1 root 342: * updating all sbuf field as necessary
343: */
344: int
1.1.1.5 root 345: sowrite(struct socket *so)
1.1 root 346: {
347: int n,nn;
348: struct sbuf *sb = &so->so_rcv;
349: int len = sb->sb_cc;
350: struct iovec iov[2];
1.1.1.3 root 351:
1.1 root 352: DEBUG_CALL("sowrite");
353: DEBUG_ARG("so = %lx", (long)so);
1.1.1.3 root 354:
1.1 root 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: */
1.1.1.3 root 365:
1.1 root 366: iov[0].iov_base = sb->sb_rptr;
1.1.1.4 root 367: iov[1].iov_base = NULL;
368: iov[1].iov_len = 0;
1.1 root 369: if (sb->sb_rptr < sb->sb_wptr) {
370: iov[0].iov_len = sb->sb_wptr - sb->sb_rptr;
371: /* Should never succeed, but... */
372: if (iov[0].iov_len > len) iov[0].iov_len = len;
373: n = 1;
374: } else {
375: iov[0].iov_len = (sb->sb_data + sb->sb_datalen) - sb->sb_rptr;
376: if (iov[0].iov_len > len) iov[0].iov_len = len;
377: len -= iov[0].iov_len;
378: if (len) {
379: iov[1].iov_base = sb->sb_data;
380: iov[1].iov_len = sb->sb_wptr - sb->sb_data;
381: if (iov[1].iov_len > len) iov[1].iov_len = len;
382: n = 2;
383: } else
384: n = 1;
385: }
386: /* Check if there's urgent data to send, and if so, send it */
387:
388: #ifdef HAVE_READV
389: nn = writev(so->s, (const struct iovec *)iov, n);
1.1.1.3 root 390:
1.1 root 391: DEBUG_MISC((dfd, " ... wrote nn = %d bytes\n", nn));
392: #else
1.1.1.4 root 393: nn = slirp_send(so, iov[0].iov_base, iov[0].iov_len,0);
1.1 root 394: #endif
395: /* This should never happen, but people tell me it does *shrug* */
396: if (nn < 0 && (errno == EAGAIN || errno == EINTR))
397: return 0;
1.1.1.3 root 398:
1.1 root 399: if (nn <= 0) {
400: DEBUG_MISC((dfd, " --- sowrite disconnected, so->so_state = %x, errno = %d\n",
401: so->so_state, errno));
402: sofcantsendmore(so);
403: tcp_sockclosed(sototcpcb(so));
404: return -1;
405: }
1.1.1.3 root 406:
1.1 root 407: #ifndef HAVE_READV
408: if (n == 2 && nn == iov[0].iov_len) {
409: int ret;
1.1.1.4 root 410: ret = slirp_send(so, iov[1].iov_base, iov[1].iov_len,0);
1.1 root 411: if (ret > 0)
412: nn += ret;
413: }
414: DEBUG_MISC((dfd, " ... wrote nn = %d bytes\n", nn));
415: #endif
1.1.1.3 root 416:
1.1 root 417: /* Update sbuf */
418: sb->sb_cc -= nn;
419: sb->sb_rptr += nn;
420: if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen))
421: sb->sb_rptr -= sb->sb_datalen;
1.1.1.3 root 422:
1.1 root 423: /*
424: * If in DRAIN mode, and there's no more data, set
425: * it CANTSENDMORE
426: */
427: if ((so->so_state & SS_FWDRAIN) && sb->sb_cc == 0)
428: sofcantsendmore(so);
1.1.1.3 root 429:
1.1 root 430: return nn;
431: }
432:
433: /*
434: * recvfrom() a UDP socket
435: */
436: void
1.1.1.5 root 437: sorecvfrom(struct socket *so)
1.1 root 438: {
439: struct sockaddr_in addr;
1.1.1.4 root 440: socklen_t addrlen = sizeof(struct sockaddr_in);
1.1.1.3 root 441:
1.1 root 442: DEBUG_CALL("sorecvfrom");
443: DEBUG_ARG("so = %lx", (long)so);
1.1.1.3 root 444:
1.1 root 445: if (so->so_type == IPPROTO_ICMP) { /* This is a "ping" reply */
446: char buff[256];
447: int len;
1.1.1.3 root 448:
449: len = recvfrom(so->s, buff, 256, 0,
1.1 root 450: (struct sockaddr *)&addr, &addrlen);
451: /* XXX Check if reply is "correct"? */
1.1.1.3 root 452:
1.1 root 453: if(len == -1 || len == 0) {
454: u_char code=ICMP_UNREACH_PORT;
455:
456: if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST;
457: else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET;
1.1.1.3 root 458:
1.1 root 459: DEBUG_MISC((dfd," udp icmp rx errno = %d-%s\n",
460: errno,strerror(errno)));
461: icmp_error(so->so_m, ICMP_UNREACH,code, 0,strerror(errno));
462: } else {
463: icmp_reflect(so->so_m);
1.1.1.5 root 464: so->so_m = NULL; /* Don't m_free() it again! */
1.1 root 465: }
466: /* No need for this socket anymore, udp_detach it */
467: udp_detach(so);
468: } else { /* A "normal" UDP packet */
469: struct mbuf *m;
1.1.1.5 root 470: int len;
471: #ifdef _WIN32
472: unsigned long n;
473: #else
474: int n;
475: #endif
1.1 root 476:
1.1.1.5 root 477: m = m_get(so->slirp);
478: if (!m) {
479: return;
480: }
1.1.1.3 root 481: m->m_data += IF_MAXLINKHDR;
482:
483: /*
1.1 root 484: * XXX Shouldn't FIONREAD packets destined for port 53,
485: * but I don't know the max packet size for DNS lookups
486: */
487: len = M_FREEROOM(m);
488: /* if (so->so_fport != htons(53)) { */
489: ioctlsocket(so->s, FIONREAD, &n);
1.1.1.3 root 490:
1.1 root 491: if (n > len) {
492: n = (m->m_data - m->m_dat) + m->m_len + n + 1;
493: m_inc(m, n);
494: len = M_FREEROOM(m);
495: }
496: /* } */
1.1.1.3 root 497:
1.1 root 498: m->m_len = recvfrom(so->s, m->m_data, len, 0,
499: (struct sockaddr *)&addr, &addrlen);
1.1.1.3 root 500: DEBUG_MISC((dfd, " did recvfrom %d, errno = %d-%s\n",
1.1 root 501: m->m_len, errno,strerror(errno)));
502: if(m->m_len<0) {
503: u_char code=ICMP_UNREACH_PORT;
504:
505: if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST;
506: else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET;
1.1.1.3 root 507:
1.1 root 508: DEBUG_MISC((dfd," rx error, tx icmp ICMP_UNREACH:%i\n", code));
509: icmp_error(so->so_m, ICMP_UNREACH,code, 0,strerror(errno));
510: m_free(m);
511: } else {
512: /*
513: * Hack: domain name lookup will be used the most for UDP,
514: * and since they'll only be used once there's no need
515: * for the 4 minute (or whatever) timeout... So we time them
516: * out much quicker (10 seconds for now...)
517: */
518: if (so->so_expire) {
519: if (so->so_fport == htons(53))
520: so->so_expire = curtime + SO_EXPIREFAST;
521: else
522: so->so_expire = curtime + SO_EXPIRE;
523: }
524:
1.1.1.3 root 525: /*
1.1 root 526: * If this packet was destined for CTL_ADDR,
527: * make it look like that's where it came from, done by udp_output
528: */
529: udp_output(so, m, &addr);
530: } /* rx error */
531: } /* if ping packet */
532: }
533:
534: /*
535: * sendto() a socket
536: */
537: int
1.1.1.5 root 538: sosendto(struct socket *so, struct mbuf *m)
1.1 root 539: {
1.1.1.5 root 540: Slirp *slirp = so->slirp;
1.1 root 541: int ret;
542: struct sockaddr_in addr;
543:
544: DEBUG_CALL("sosendto");
545: DEBUG_ARG("so = %lx", (long)so);
546: DEBUG_ARG("m = %lx", (long)m);
1.1.1.3 root 547:
1.1 root 548: addr.sin_family = AF_INET;
1.1.1.5 root 549: if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==
550: slirp->vnetwork_addr.s_addr) {
1.1 root 551: /* It's an alias */
1.1.1.5 root 552: if (so->so_faddr.s_addr == slirp->vnameserver_addr.s_addr) {
1.1.1.6 root 553: if (get_dns_addr(&addr.sin_addr) < 0)
554: addr.sin_addr = loopback_addr;
1.1.1.5 root 555: } else {
1.1 root 556: addr.sin_addr = loopback_addr;
557: }
558: } else
559: addr.sin_addr = so->so_faddr;
560: addr.sin_port = so->so_fport;
561:
562: 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 563:
1.1 root 564: /* Don't care what port we get */
565: ret = sendto(so->s, m->m_data, m->m_len, 0,
566: (struct sockaddr *)&addr, sizeof (struct sockaddr));
567: if (ret < 0)
568: return -1;
1.1.1.3 root 569:
1.1 root 570: /*
571: * Kill the socket if there's no reply in 4 minutes,
572: * but only if it's an expirable socket
573: */
574: if (so->so_expire)
575: so->so_expire = curtime + SO_EXPIRE;
1.1.1.5 root 576: so->so_state &= SS_PERSISTENT_MASK;
577: so->so_state |= SS_ISFCONNECTED; /* So that it gets select()ed */
1.1 root 578: return 0;
579: }
580:
581: /*
1.1.1.5 root 582: * Listen for incoming TCP connections
1.1 root 583: */
584: struct socket *
1.1.1.7 root 585: tcp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr,
1.1.1.5 root 586: u_int lport, int flags)
1.1 root 587: {
588: struct sockaddr_in addr;
589: struct socket *so;
1.1.1.4 root 590: int s, opt = 1;
591: socklen_t addrlen = sizeof(addr);
1.1.1.7 root 592: memset(&addr, 0, addrlen);
1.1 root 593:
1.1.1.5 root 594: DEBUG_CALL("tcp_listen");
595: DEBUG_ARG("haddr = %x", haddr);
596: DEBUG_ARG("hport = %d", hport);
1.1 root 597: DEBUG_ARG("laddr = %x", laddr);
598: DEBUG_ARG("lport = %d", lport);
599: DEBUG_ARG("flags = %x", flags);
1.1.1.3 root 600:
1.1.1.5 root 601: so = socreate(slirp);
602: if (!so) {
1.1 root 603: return NULL;
604: }
1.1.1.3 root 605:
1.1 root 606: /* Don't tcp_attach... we don't need so_snd nor so_rcv */
607: if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL) {
608: free(so);
609: return NULL;
610: }
1.1.1.5 root 611: insque(so, &slirp->tcb);
1.1.1.3 root 612:
613: /*
1.1 root 614: * SS_FACCEPTONCE sockets must time out.
615: */
616: if (flags & SS_FACCEPTONCE)
617: so->so_tcpcb->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT*2;
1.1.1.3 root 618:
1.1.1.5 root 619: so->so_state &= SS_PERSISTENT_MASK;
620: so->so_state |= (SS_FACCEPTCONN | flags);
1.1 root 621: so->so_lport = lport; /* Kept in network format */
622: so->so_laddr.s_addr = laddr; /* Ditto */
1.1.1.3 root 623:
1.1 root 624: addr.sin_family = AF_INET;
1.1.1.5 root 625: addr.sin_addr.s_addr = haddr;
626: addr.sin_port = hport;
1.1.1.3 root 627:
1.1.1.6 root 628: if (((s = qemu_socket(AF_INET,SOCK_STREAM,0)) < 0) ||
1.1.1.2 root 629: (setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)) < 0) ||
1.1 root 630: (bind(s,(struct sockaddr *)&addr, sizeof(addr)) < 0) ||
631: (listen(s,1) < 0)) {
632: int tmperrno = errno; /* Don't clobber the real reason we failed */
1.1.1.3 root 633:
1.1 root 634: close(s);
635: sofree(so);
636: /* Restore the real errno */
637: #ifdef _WIN32
638: WSASetLastError(tmperrno);
639: #else
640: errno = tmperrno;
641: #endif
642: return NULL;
643: }
644: setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int));
1.1.1.3 root 645:
1.1 root 646: getsockname(s,(struct sockaddr *)&addr,&addrlen);
647: so->so_fport = addr.sin_port;
648: if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr)
1.1.1.5 root 649: so->so_faddr = slirp->vhost_addr;
1.1 root 650: else
651: so->so_faddr = addr.sin_addr;
652:
653: so->s = s;
654: return so;
655: }
656:
657: /*
658: * Various session state calls
659: * XXX Should be #define's
660: * The socket state stuff needs work, these often get call 2 or 3
661: * times each when only 1 was needed
662: */
663: void
1.1.1.5 root 664: soisfconnecting(struct socket *so)
1.1 root 665: {
666: so->so_state &= ~(SS_NOFDREF|SS_ISFCONNECTED|SS_FCANTRCVMORE|
667: SS_FCANTSENDMORE|SS_FWDRAIN);
668: so->so_state |= SS_ISFCONNECTING; /* Clobber other states */
669: }
670:
671: void
1.1.1.5 root 672: soisfconnected(struct socket *so)
1.1 root 673: {
674: so->so_state &= ~(SS_ISFCONNECTING|SS_FWDRAIN|SS_NOFDREF);
675: so->so_state |= SS_ISFCONNECTED; /* Clobber other states */
676: }
677:
1.1.1.3 root 678: static void
679: sofcantrcvmore(struct socket *so)
1.1 root 680: {
681: if ((so->so_state & SS_NOFDREF) == 0) {
682: shutdown(so->s,0);
683: if(global_writefds) {
684: FD_CLR(so->s,global_writefds);
685: }
686: }
687: so->so_state &= ~(SS_ISFCONNECTING);
1.1.1.5 root 688: if (so->so_state & SS_FCANTSENDMORE) {
689: so->so_state &= SS_PERSISTENT_MASK;
690: so->so_state |= SS_NOFDREF; /* Don't select it */
691: } else {
1.1 root 692: so->so_state |= SS_FCANTRCVMORE;
1.1.1.5 root 693: }
1.1 root 694: }
695:
1.1.1.3 root 696: static void
697: sofcantsendmore(struct socket *so)
1.1 root 698: {
699: if ((so->so_state & SS_NOFDREF) == 0) {
700: shutdown(so->s,1); /* send FIN to fhost */
701: if (global_readfds) {
702: FD_CLR(so->s,global_readfds);
703: }
704: if (global_xfds) {
705: FD_CLR(so->s,global_xfds);
706: }
707: }
708: so->so_state &= ~(SS_ISFCONNECTING);
1.1.1.5 root 709: if (so->so_state & SS_FCANTRCVMORE) {
710: so->so_state &= SS_PERSISTENT_MASK;
711: so->so_state |= SS_NOFDREF; /* as above */
712: } else {
1.1 root 713: so->so_state |= SS_FCANTSENDMORE;
1.1.1.5 root 714: }
1.1 root 715: }
716:
717: /*
718: * Set write drain mode
719: * Set CANTSENDMORE once all data has been write()n
720: */
721: void
1.1.1.5 root 722: sofwdrain(struct socket *so)
1.1 root 723: {
724: if (so->so_rcv.sb_cc)
725: so->so_state |= SS_FWDRAIN;
726: else
727: sofcantsendmore(so);
728: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.