VirtualBox

source: vbox/trunk/src/VBox/Devices/Network/slirp/socket.c@ 13733

Last change on this file since 13733 was 13733, checked in by vboxsync, 16 years ago

The rest of macro replacment was added

  • Property svn:eol-style set to native
File size: 21.6 KB
Line 
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#include <slirp.h>
10#include "ip_icmp.h"
11#include "main.h"
12#ifdef __sun__
13#include <sys/filio.h>
14#endif
15
16#ifdef VBOX_WITH_SYNC_SLIRP
17#include <iprt/semaphore.h>
18#endif
19
20void
21so_init()
22{
23 /* Nothing yet */
24}
25
26
27struct socket *
28solookup(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;
36
37 for (so = head->so_next; so != head; so = so->so_next) {
38 if (so->so_lport == lport &&
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 }
44
45 if (so == head)
46 return (struct socket *)NULL;
47 return so;
48
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 */
56struct socket *
57socreate()
58{
59 struct socket *so;
60
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 VBOX_SLIRP_LOCK_CREATE(&so->so_mutex);
67 }
68 return(so);
69}
70
71/*
72 * remque and free a socket, clobber cache
73 */
74void
75sofree(PNATState pData, struct socket *so)
76{
77#ifndef VBOX_WITH_SYNC_SLIRP
78 if (so->so_emu==EMU_RSH && so->extra) {
79 sofree(pData, so->extra);
80 so->extra=NULL;
81 }
82 if (so == tcp_last_so)
83 tcp_last_so = &tcb;
84 else if (so == udp_last_so)
85 udp_last_so = &udb;
86
87 m_free(pData, so->so_m);
88
89 if(so->so_next && so->so_prev)
90 remque(pData, so); /* crashes if so is not in a queue */
91#else
92 /*Take global mutexes of udb and tcb, because we dont know which is mutex */
93 /*XXX: don't forget to set correct so_type in corresponded attach operation */
94 VBOX_SLIRP_LOCK(so->so_mutex);
95 if (so->so_emu==EMU_RSH && so->extra) {
96 sofree(pData, so->extra);
97 so->extra=NULL;
98 }
99
100 if (so->so_type == IPPROTO_UDP) {
101 VBOX_SLIRP_LOCK(pData->udp_last_so_mutex);
102 }
103 else if (so->so_type == IPPROTO_TCP) {
104 VBOX_SLIRP_LOCK(pData->tcp_last_so_mutex);
105 }
106 else {
107 Assert(!"unknown type");
108 }
109
110 if (so == tcp_last_so)
111 tcp_last_so = &tcb;
112 else if (so == udp_last_so)
113 udp_last_so = &udb;
114
115 AssertRelease(so->so_next != NULL && so->so_prev != NULL);
116 if(so->so_next && so->so_prev) {
117 remque(pData, so); /* crashes if so is not in a queue */
118 }
119#ifdef VBOX_SLIRP_LOCK
120 else {
121 Assert(!"shouldn't happens");
122 }
123#endif
124
125 if (so->so_type == IPPROTO_UDP) {
126 VBOX_SLIRP_UNLOCK(pData->udp_last_so_mutex);
127 }
128 else if (so->so_type == IPPROTO_TCP) {
129 VBOX_SLIRP_UNLOCK(pData->tcp_last_so_mutex);
130 }
131 else {
132 Assert(!"unknown type");
133 }
134 /* socket's mutex could be released because socket none accessible via queue anymore*/
135
136 m_free(pData, so->so_m);
137
138
139 VBOX_SLIRP_UNLOCK(so->so_mutex);
140#endif
141
142 free(so);
143#ifdef VBOX_WITH_SYNC_SLIRP
144 so = NULL;
145#endif
146}
147
148/*
149 * Read from so's socket into sb_snd, updating all relevant sbuf fields
150 * NOTE: This will only be called if it is select()ed for reading, so
151 * a read() of 0 (or less) means it's disconnected
152 */
153int
154soread(PNATState pData, struct socket *so)
155{
156 int n, nn, lss, total;
157 struct sbuf *sb = &so->so_snd;
158 int len = sb->sb_datalen - sb->sb_cc;
159 struct iovec iov[2];
160 int mss = so->so_tcpcb->t_maxseg;
161
162 VBOX_SLIRP_LOCK(so->so_mutex);
163 DEBUG_CALL("soread");
164 DEBUG_ARG("so = %lx", (long )so);
165
166 /*
167 * No need to check if there's enough room to read.
168 * soread wouldn't have been called if there weren't
169 */
170
171 len = sb->sb_datalen - sb->sb_cc;
172
173 iov[0].iov_base = sb->sb_wptr;
174 iov[1].iov_base = 0;
175 iov[1].iov_len = 0;
176 if (sb->sb_wptr < sb->sb_rptr) {
177 iov[0].iov_len = sb->sb_rptr - sb->sb_wptr;
178 /* Should never succeed, but... */
179 if (iov[0].iov_len > len)
180 iov[0].iov_len = len;
181 if (iov[0].iov_len > mss)
182 iov[0].iov_len -= iov[0].iov_len%mss;
183 n = 1;
184 } else {
185 iov[0].iov_len = (sb->sb_data + sb->sb_datalen) - sb->sb_wptr;
186 /* Should never succeed, but... */
187 if (iov[0].iov_len > len) iov[0].iov_len = len;
188 len -= iov[0].iov_len;
189 if (len) {
190 iov[1].iov_base = sb->sb_data;
191 iov[1].iov_len = sb->sb_rptr - sb->sb_data;
192 if(iov[1].iov_len > len)
193 iov[1].iov_len = len;
194 total = iov[0].iov_len + iov[1].iov_len;
195 if (total > mss) {
196 lss = total%mss;
197 if (iov[1].iov_len > lss) {
198 iov[1].iov_len -= lss;
199 n = 2;
200 } else {
201 lss -= iov[1].iov_len;
202 iov[0].iov_len -= lss;
203 n = 1;
204 }
205 } else
206 n = 2;
207 } else {
208 if (iov[0].iov_len > mss)
209 iov[0].iov_len -= iov[0].iov_len%mss;
210 n = 1;
211 }
212 }
213
214#ifdef HAVE_READV
215 nn = readv(so->s, (struct iovec *)iov, n);
216 DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn));
217#else
218 nn = recv(so->s, iov[0].iov_base, iov[0].iov_len,0);
219#endif
220 if (nn <= 0) {
221 if (nn < 0 && (errno == EINTR || errno == EAGAIN)) {
222 VBOX_SLIRP_UNLOCK(so->so_mutex);
223 return 0;
224 }
225 else {
226 DEBUG_MISC((dfd, " --- soread() disconnected, nn = %d, errno = %d-%s\n", nn, errno,strerror(errno)));
227 sofcantrcvmore(so);
228 tcp_sockclosed(pData, sototcpcb(so));
229 VBOX_SLIRP_UNLOCK(so->so_mutex);
230 return -1;
231 }
232 }
233
234#ifndef HAVE_READV
235 /*
236 * If there was no error, try and read the second time round
237 * We read again if n = 2 (ie, there's another part of the buffer)
238 * and we read as much as we could in the first read
239 * We don't test for <= 0 this time, because there legitimately
240 * might not be any more data (since the socket is non-blocking),
241 * a close will be detected on next iteration.
242 * A return of -1 wont (shouldn't) happen, since it didn't happen above
243 */
244 if (n == 2 && nn == iov[0].iov_len) {
245 int ret;
246 ret = recv(so->s, iov[1].iov_base, iov[1].iov_len,0);
247 if (ret > 0)
248 nn += ret;
249 }
250
251 DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn));
252#endif
253
254 /* Update fields */
255 sb->sb_cc += nn;
256 sb->sb_wptr += nn;
257 if (sb->sb_wptr >= (sb->sb_data + sb->sb_datalen))
258 sb->sb_wptr -= sb->sb_datalen;
259 VBOX_SLIRP_UNLOCK(so->so_mutex);
260 return nn;
261}
262
263/*
264 * Get urgent data
265 *
266 * When the socket is created, we set it SO_OOBINLINE,
267 * so when OOB data arrives, we soread() it and everything
268 * in the send buffer is sent as urgent data
269 */
270void
271sorecvoob(PNATState pData, struct socket *so)
272{
273 struct tcpcb *tp;
274 VBOX_SLIRP_LOCK(so->so_mutex);
275 tp = sototcpcb(so);
276
277 DEBUG_CALL("sorecvoob");
278 DEBUG_ARG("so = %lx", (long)so);
279
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
285 * urgent data, or the read() doesn't return all the
286 * urgent data.
287 */
288 soread(pData, so);
289 tp->snd_up = tp->snd_una + so->so_snd.sb_cc;
290 VBOX_SLIRP_UNLOCK(so->so_mutex);
291 tp->t_force = 1;
292 tcp_output(pData, tp);
293 tp->t_force = 0;
294}
295
296/*
297 * Send urgent data
298 * There's a lot duplicated code here, but...
299 */
300int
301sosendoob(so)
302 struct socket *so;
303{
304 struct sbuf *sb = &so->so_rcv;
305 char buff[2048]; /* XXX Shouldn't be sending more oob data than this */
306
307 int n, len;
308#ifdef VBOX_WITH_SYNC_SLIRP
309 VBOX_SLIRP_LOCK(so->so_mutex);
310#endif
311
312 DEBUG_CALL("sosendoob");
313 DEBUG_ARG("so = %lx", (long)so);
314 DEBUG_ARG("sb->sb_cc = %d", sb->sb_cc);
315
316 if (so->so_urgc > 2048)
317 so->so_urgc = 2048; /* XXXX */
318
319 if (sb->sb_rptr < sb->sb_wptr) {
320 /* We can send it directly */
321 n = send(so->s, sb->sb_rptr, so->so_urgc, (MSG_OOB)); /* |MSG_DONTWAIT)); */
322 so->so_urgc -= n;
323
324 DEBUG_MISC((dfd, " --- sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc));
325 } else {
326 /*
327 * Since there's no sendv or sendtov like writev,
328 * we must copy all data to a linear buffer then
329 * send it all
330 */
331 len = (sb->sb_data + sb->sb_datalen) - sb->sb_rptr;
332 if (len > so->so_urgc) len = so->so_urgc;
333 memcpy(buff, sb->sb_rptr, len);
334 so->so_urgc -= len;
335 if (so->so_urgc) {
336 n = sb->sb_wptr - sb->sb_data;
337 if (n > so->so_urgc) n = so->so_urgc;
338 memcpy((buff + len), sb->sb_data, n);
339 so->so_urgc -= n;
340 len += n;
341 }
342 n = send(so->s, buff, len, (MSG_OOB)); /* |MSG_DONTWAIT)); */
343#ifdef DEBUG
344 if (n != len)
345 DEBUG_ERROR((dfd, "Didn't send all data urgently XXXXX\n"));
346#endif
347 DEBUG_MISC((dfd, " ---2 sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc));
348 }
349
350 sb->sb_cc -= n;
351 sb->sb_rptr += n;
352 if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen))
353 sb->sb_rptr -= sb->sb_datalen;
354
355#ifdef VBOX_WITH_SYNC_SLIRP
356 VBOX_SLIRP_UNLOCK(so->so_mutex);
357#endif
358 return n;
359}
360
361/*
362 * Write data from so_rcv to so's socket,
363 * updating all sbuf field as necessary
364 */
365int
366sowrite(PNATState pData, struct socket *so)
367{
368 int n,nn;
369 struct sbuf *sb = &so->so_rcv;
370 int len = sb->sb_cc;
371 struct iovec iov[2];
372#ifdef VBOX_WITH_SYNC_SLIRP
373 VBOX_SLIRP_LOCK(so->so_mutex);
374#endif
375
376 DEBUG_CALL("sowrite");
377 DEBUG_ARG("so = %lx", (long)so);
378
379 if (so->so_urgc) {
380 sosendoob(so);
381 if (sb->sb_cc == 0)
382#ifdef VBOX_WITH_SYNC_SLIRP
383 VBOX_SLIRP_UNLOCK(so->so_mutex);
384#endif
385 return 0;
386 }
387
388 /*
389 * No need to check if there's something to write,
390 * sowrite wouldn't have been called otherwise
391 */
392
393 len = sb->sb_cc;
394
395 iov[0].iov_base = sb->sb_rptr;
396 iov[1].iov_base = 0;
397 iov[1].iov_len = 0;
398 if (sb->sb_rptr < sb->sb_wptr) {
399 iov[0].iov_len = sb->sb_wptr - sb->sb_rptr;
400 /* Should never succeed, but... */
401 if (iov[0].iov_len > len) iov[0].iov_len = len;
402 n = 1;
403 } else {
404 iov[0].iov_len = (sb->sb_data + sb->sb_datalen) - sb->sb_rptr;
405 if (iov[0].iov_len > len) iov[0].iov_len = len;
406 len -= iov[0].iov_len;
407 if (len) {
408 iov[1].iov_base = sb->sb_data;
409 iov[1].iov_len = sb->sb_wptr - sb->sb_data;
410 if (iov[1].iov_len > len) iov[1].iov_len = len;
411 n = 2;
412 } else
413 n = 1;
414 }
415 /* Check if there's urgent data to send, and if so, send it */
416
417#ifdef HAVE_READV
418 nn = writev(so->s, (const struct iovec *)iov, n);
419
420 DEBUG_MISC((dfd, " ... wrote nn = %d bytes\n", nn));
421#else
422 nn = send(so->s, iov[0].iov_base, iov[0].iov_len,0);
423#endif
424 /* This should never happen, but people tell me it does *shrug* */
425 if (nn < 0 && (errno == EAGAIN || errno == EINTR)) {
426#ifdef VBOX_WITH_SYNC_SLIRP
427 VBOX_SLIRP_UNLOCK(so->so_mutex);
428#endif
429 return 0;
430 }
431
432 if (nn <= 0) {
433 DEBUG_MISC((dfd, " --- sowrite disconnected, so->so_state = %x, errno = %d\n",
434 so->so_state, errno));
435 sofcantsendmore(so);
436 tcp_sockclosed(pData, sototcpcb(so));
437#ifdef VBOX_WITH_SYNC_SLIRP
438 VBOX_SLIRP_UNLOCK(so->so_mutex);
439#endif
440 return -1;
441 }
442
443#ifndef HAVE_READV
444 if (n == 2 && nn == iov[0].iov_len) {
445 int ret;
446 ret = send(so->s, iov[1].iov_base, iov[1].iov_len,0);
447 if (ret > 0)
448 nn += ret;
449 }
450 DEBUG_MISC((dfd, " ... wrote nn = %d bytes\n", nn));
451#endif
452
453 /* Update sbuf */
454 sb->sb_cc -= nn;
455 sb->sb_rptr += nn;
456 if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen))
457 sb->sb_rptr -= sb->sb_datalen;
458
459 /*
460 * If in DRAIN mode, and there's no more data, set
461 * it CANTSENDMORE
462 */
463 if ((so->so_state & SS_FWDRAIN) && sb->sb_cc == 0)
464 sofcantsendmore(so);
465
466#ifdef VBOX_WITH_SYNC_SLIRP
467 VBOX_SLIRP_UNLOCK(so->so_mutex);
468#endif
469 return nn;
470}
471
472/*
473 * recvfrom() a UDP socket
474 */
475void
476sorecvfrom(PNATState pData, struct socket *so)
477{
478 struct sockaddr_in addr;
479 socklen_t addrlen = sizeof(struct sockaddr_in);
480
481 DEBUG_CALL("sorecvfrom");
482 DEBUG_ARG("so = %lx", (long)so);
483
484#ifdef VBOX_WITH_SYNC_SLIRP
485 VBOX_SLIRP_LOCK(so->so_mutex);
486#endif
487
488 if (so->so_type == IPPROTO_ICMP) { /* This is a "ping" reply */
489 char buff[256];
490 int len;
491
492 len = recvfrom(so->s, buff, 256, 0,
493 (struct sockaddr *)&addr, &addrlen);
494 /* XXX Check if reply is "correct"? */
495
496 if(len == -1 || len == 0) {
497 u_char code=ICMP_UNREACH_PORT;
498
499 if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST;
500 else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET;
501
502 DEBUG_MISC((dfd," udp icmp rx errno = %d-%s\n",
503 errno,strerror(errno)));
504 icmp_error(pData, so->so_m, ICMP_UNREACH,code, 0,strerror(errno));
505 } else {
506 icmp_reflect(pData, so->so_m);
507 so->so_m = 0; /* Don't m_free() it again! */
508 }
509 /* No need for this socket anymore, udp_detach it */
510 udp_detach(pData, so);
511 } else { /* A "normal" UDP packet */
512 struct mbuf *m;
513 int len, n;
514
515 if (!(m = m_get(pData))) return;
516 m->m_data += if_maxlinkhdr;
517
518 /*
519 * XXX Shouldn't FIONREAD packets destined for port 53,
520 * but I don't know the max packet size for DNS lookups
521 */
522 len = M_FREEROOM(m);
523 /* if (so->so_fport != htons(53)) { */
524 ioctlsocket(so->s, FIONREAD, &n);
525
526 if (n > len) {
527 n = (m->m_data - m->m_dat) + m->m_len + n + 1;
528 m_inc(m, n);
529 len = M_FREEROOM(m);
530 }
531 /* } */
532
533 m->m_len = recvfrom(so->s, m->m_data, len, 0,
534 (struct sockaddr *)&addr, &addrlen);
535 DEBUG_MISC((dfd, " did recvfrom %d, errno = %d-%s\n",
536 m->m_len, errno,strerror(errno)));
537 if(m->m_len<0) {
538 u_char code=ICMP_UNREACH_PORT;
539
540 if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST;
541 else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET;
542
543 DEBUG_MISC((dfd," rx error, tx icmp ICMP_UNREACH:%i\n", code));
544 icmp_error(pData, so->so_m, ICMP_UNREACH,code, 0,strerror(errno));
545 m_free(pData, m);
546 } else {
547 /*
548 * Hack: domain name lookup will be used the most for UDP,
549 * and since they'll only be used once there's no need
550 * for the 4 minute (or whatever) timeout... So we time them
551 * out much quicker (10 seconds for now...)
552 */
553 if (so->so_expire) {
554 if (so->so_fport == htons(53))
555 so->so_expire = curtime + SO_EXPIREFAST;
556 else
557 so->so_expire = curtime + SO_EXPIRE;
558 }
559
560 /* if (m->m_len == len) {
561 * m_inc(m, MINCSIZE);
562 * m->m_len = 0;
563 * }
564 */
565
566 /*
567 * If this packet was destined for CTL_ADDR,
568 * make it look like that's where it came from, done by udp_output
569 */
570 udp_output(pData, so, m, &addr);
571 } /* rx error */
572 } /* if ping packet */
573#ifdef VBOX_WITH_SYNC_SLIRP
574 VBOX_SLIRP_UNLOCK(so->so_mutex);
575#endif
576}
577
578/*
579 * sendto() a socket
580 */
581int
582sosendto(PNATState pData, struct socket *so, struct mbuf *m)
583{
584 int ret;
585 struct sockaddr_in addr;
586#if 0
587 struct sockaddr_in host_addr;
588#endif
589#ifdef VBOX_WITH_SYNC_SLIRP
590 VBOX_SLIRP_LOCK(so->so_mutex);
591#endif
592
593 DEBUG_CALL("sosendto");
594 DEBUG_ARG("so = %lx", (long)so);
595 DEBUG_ARG("m = %lx", (long)m);
596
597 addr.sin_family = AF_INET;
598 if ((so->so_faddr.s_addr & htonl(pData->netmask)) == special_addr.s_addr) {
599 /* It's an alias */
600 uint32_t last_byte = ntohl(so->so_faddr.s_addr) & ~pData->netmask;
601 switch(last_byte) {
602#if 0
603 /* handle this case at 'default:' */
604 case CTL_BROADCAST:
605 addr.sin_addr.s_addr = INADDR_BROADCAST;
606# if 0
607 /* Send the packet to host to fully emulate broadcast */
608 /** @todo r=klaus: on Linux host this causes the host to receive
609 * the packet twice for some reason. And I cannot find any place
610 * in the man pages which states that sending a broadcast does not
611 * reach the host itself. */
612 host_addr.sin_family = AF_INET;
613 host_addr.sin_port = so->so_fport;
614 host_addr.sin_addr = our_addr;
615 sendto(so->s, m->m_data, m->m_len, 0,
616 (struct sockaddr *)&host_addr, sizeof (struct sockaddr));
617# endif
618 break;
619#endif
620 case CTL_DNS:
621 if (!get_dns_addr(pData, &dns_addr))
622 addr.sin_addr = dns_addr;
623 else
624 addr.sin_addr = loopback_addr;
625 break;
626 case CTL_ALIAS:
627 default:
628 if (last_byte == ~pData->netmask)
629 addr.sin_addr.s_addr = INADDR_BROADCAST;
630 else
631 addr.sin_addr = loopback_addr;
632 break;
633 }
634 } else
635 addr.sin_addr = so->so_faddr;
636 addr.sin_port = so->so_fport;
637
638 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)));
639
640 /* Don't care what port we get */
641 ret = sendto(so->s, m->m_data, m->m_len, 0,
642 (struct sockaddr *)&addr, sizeof (struct sockaddr));
643 if (ret < 0) {
644#ifdef VBOX_WITH_SYNC_SLIRP
645 VBOX_SLIRP_UNLOCK(so->so_mutex);
646#endif
647 return -1;
648 }
649
650 /*
651 * Kill the socket if there's no reply in 4 minutes,
652 * but only if it's an expirable socket
653 */
654 if (so->so_expire)
655 so->so_expire = curtime + SO_EXPIRE;
656 so->so_state = SS_ISFCONNECTED; /* So that it gets select()ed */
657#ifdef VBOX_WITH_SYNC_SLIRP
658 VBOX_SLIRP_UNLOCK(so->so_mutex);
659#endif
660 return 0;
661}
662
663/*
664 * XXX This should really be tcp_listen
665 */
666struct socket *
667solisten(PNATState pData, u_int port, u_int32_t laddr, u_int lport, int flags)
668{
669 struct sockaddr_in addr;
670 struct socket *so;
671 socklen_t addrlen = sizeof(addr);
672 int s, opt = 1;
673
674 DEBUG_CALL("solisten");
675 DEBUG_ARG("port = %d", port);
676 DEBUG_ARG("laddr = %x", laddr);
677 DEBUG_ARG("lport = %d", lport);
678 DEBUG_ARG("flags = %x", flags);
679
680 if ((so = socreate()) == NULL) {
681 /* free(so); Not sofree() ??? free(NULL) == NOP */
682 return NULL;
683 }
684
685 /* Don't tcp_attach... we don't need so_snd nor so_rcv */
686 if ((so->so_tcpcb = tcp_newtcpcb(pData, so)) == NULL) {
687 free(so);
688#ifdef VBOX_SLIRP_UNLOCK
689 so = NULL;
690#endif
691 return NULL;
692 }
693#ifndef VBOX_WITH_SYNC_SLIRP
694 insque(pData, so,&tcb);
695#else
696 VBOX_SLIRP_LOCK(so->so_mutex);
697 /*after adding to global queue probably we should keep lock*/
698 VBOX_SLIRP_LOCK(pData->tcb_mutex);
699 insque(pData, so,&tcb);
700 VBOX_SLIRP_UNLOCK(pData->tcb_mutex);
701#endif
702
703 /*
704 * SS_FACCEPTONCE sockets must time out.
705 */
706 if (flags & SS_FACCEPTONCE)
707 so->so_tcpcb->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT*2;
708
709 so->so_state = (SS_FACCEPTCONN|flags);
710 so->so_lport = lport; /* Kept in network format */
711 so->so_laddr.s_addr = laddr; /* Ditto */
712
713 addr.sin_family = AF_INET;
714 addr.sin_addr.s_addr = INADDR_ANY;
715 addr.sin_port = port;
716
717 if (((s = socket(AF_INET,SOCK_STREAM,0)) < 0) ||
718 (setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)) < 0) ||
719 (bind(s,(struct sockaddr *)&addr, sizeof(addr)) < 0) ||
720 (listen(s,1) < 0)) {
721#ifdef RT_OS_WINDOWS
722 int tmperrno = WSAGetLastError(); /* Don't clobber the real reason we failed */
723 closesocket(s);
724 sofree(pData, so);
725 /* Restore the real errno */
726 WSASetLastError(tmperrno);
727#else
728 int tmperrno = errno; /* Don't clobber the real reason we failed */
729 close(s);
730 sofree(pData, so);
731 /* Restore the real errno */
732 errno = tmperrno;
733#endif
734 return NULL;
735 }
736 setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int));
737
738 getsockname(s,(struct sockaddr *)&addr,&addrlen);
739 so->so_fport = addr.sin_port;
740 if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr)
741 so->so_faddr = alias_addr;
742 else
743 so->so_faddr = addr.sin_addr;
744
745 so->s = s;
746#ifdef VBOX_WITH_SYNC_SLIRP
747 VBOX_SLIRP_UNLOCK(so->so_mutex);
748#endif
749 return so;
750}
751
752/*
753 * Data is available in so_rcv
754 * Just write() the data to the socket
755 * XXX not yet...
756 */
757void
758sorwakeup(so)
759 struct socket *so;
760{
761/* sowrite(so); */
762/* FD_CLR(so->s,&writefds); */
763}
764
765/*
766 * Data has been freed in so_snd
767 * We have room for a read() if we want to
768 * For now, don't read, it'll be done in the main loop
769 */
770void
771sowwakeup(so)
772 struct socket *so;
773{
774 /* Nothing, yet */
775}
776
777/*
778 * Various session state calls
779 * XXX Should be #define's
780 * The socket state stuff needs work, these often get call 2 or 3
781 * times each when only 1 was needed
782 */
783void
784soisfconnecting(so)
785 register struct socket *so;
786{
787#ifdef VBOX_WITH_SYNC_SLIRP
788 VBOX_SLIRP_LOCK(so->so_mutex);
789#endif
790 so->so_state &= ~(SS_NOFDREF|SS_ISFCONNECTED|SS_FCANTRCVMORE|
791 SS_FCANTSENDMORE|SS_FWDRAIN);
792 so->so_state |= SS_ISFCONNECTING; /* Clobber other states */
793#ifdef VBOX_WITH_SYNC_SLIRP
794 VBOX_SLIRP_UNLOCK(so->so_mutex);
795#endif
796}
797
798void
799soisfconnected(so)
800 register struct socket *so;
801{
802#ifdef VBOX_WITH_SYNC_SLIRP
803 VBOX_SLIRP_LOCK(so->so_mutex);
804#endif
805 so->so_state &= ~(SS_ISFCONNECTING|SS_FWDRAIN|SS_NOFDREF);
806 so->so_state |= SS_ISFCONNECTED; /* Clobber other states */
807#ifdef VBOX_WITH_SYNC_SLIRP
808 VBOX_SLIRP_UNLOCK(so->so_mutex);
809#endif
810}
811
812void
813sofcantrcvmore(so)
814 struct socket *so;
815{
816#ifdef VBOX_WITH_SYNC_SLIRP
817 VBOX_SLIRP_LOCK(so->so_mutex);
818#endif
819 if ((so->so_state & SS_NOFDREF) == 0) {
820 shutdown(so->s,0);
821 }
822 so->so_state &= ~(SS_ISFCONNECTING);
823 if (so->so_state & SS_FCANTSENDMORE)
824 so->so_state = SS_NOFDREF; /* Don't select it */ /* XXX close() here as well? */
825 else
826 so->so_state |= SS_FCANTRCVMORE;
827#ifdef VBOX_WITH_SYNC_SLIRP
828 VBOX_SLIRP_UNLOCK(so->so_mutex);
829#endif
830}
831
832void
833sofcantsendmore(so)
834 struct socket *so;
835{
836#ifdef VBOX_WITH_SYNC_SLIRP
837 VBOX_SLIRP_LOCK(so->so_mutex);
838#endif
839 if ((so->so_state & SS_NOFDREF) == 0) {
840 shutdown(so->s,1); /* send FIN to fhost */
841 }
842 so->so_state &= ~(SS_ISFCONNECTING);
843 if (so->so_state & SS_FCANTRCVMORE)
844 so->so_state = SS_NOFDREF; /* as above */
845 else
846 so->so_state |= SS_FCANTSENDMORE;
847#ifdef VBOX_WITH_SYNC_SLIRP
848 VBOX_SLIRP_UNLOCK(so->so_mutex);
849#endif
850}
851
852void
853soisfdisconnected(so)
854 struct socket *so;
855{
856/* so->so_state &= ~(SS_ISFCONNECTING|SS_ISFCONNECTED); */
857/* close(so->s); */
858/* so->so_state = SS_ISFDISCONNECTED; */
859 /*
860 * XXX Do nothing ... ?
861 */
862}
863
864/*
865 * Set write drain mode
866 * Set CANTSENDMORE once all data has been write()n
867 */
868void
869sofwdrain(so)
870 struct socket *so;
871{
872#ifdef VBOX_WITH_SYNC_SLIRP
873 VBOX_SLIRP_LOCK(so->so_mutex);
874#endif
875 if (so->so_rcv.sb_cc)
876 so->so_state |= SS_FWDRAIN;
877 else
878 sofcantsendmore(so);
879#ifdef VBOX_WITH_SYNC_SLIRP
880 VBOX_SLIRP_UNLOCK(so->so_mutex);
881#endif
882}
883
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette