slirp: Factorizing and cleaning solookup()
[qemu/ar7.git] / slirp / socket.c
blob8f73e906e28f0750f19faceb6d715a20b2c92667
1 /*
2 * Copyright (c) 1995 Danny Gasparovski.
4 * Please read the file COPYRIGHT for the
5 * terms and conditions of the copyright.
6 */
8 #include "qemu-common.h"
9 #include <slirp.h>
10 #include "ip_icmp.h"
11 #ifdef __sun__
12 #include <sys/filio.h>
13 #endif
15 static void sofcantrcvmore(struct socket *so);
16 static void sofcantsendmore(struct socket *so);
18 struct socket *
19 solookup(struct socket **last, struct socket *head,
20 struct in_addr laddr, u_int lport,
21 struct in_addr faddr, u_int fport)
23 struct socket *so = *last;
25 /* Optimisation */
26 if (so != head &&
27 so->so_lport == lport &&
28 so->so_laddr.s_addr == laddr.s_addr &&
29 (!faddr.s_addr ||
30 (so->so_faddr.s_addr == faddr.s_addr &&
31 so->so_fport == fport))) {
32 return so;
35 for (so = head->so_next; so != head; so = so->so_next) {
36 if (so->so_lport == lport &&
37 so->so_laddr.s_addr == laddr.s_addr &&
38 (!faddr.s_addr ||
39 (so->so_faddr.s_addr == faddr.s_addr &&
40 so->so_fport == fport))) {
41 *last = so;
42 return so;
46 return (struct socket *)NULL;
50 * Create a new socket, initialise the fields
51 * It is the responsibility of the caller to
52 * insque() it into the correct linked-list
54 struct socket *
55 socreate(Slirp *slirp)
57 struct socket *so;
59 so = (struct socket *)malloc(sizeof(struct socket));
60 if(so) {
61 memset(so, 0, sizeof(struct socket));
62 so->so_state = SS_NOFDREF;
63 so->s = -1;
64 so->slirp = slirp;
65 so->pollfds_idx = -1;
67 return(so);
71 * remque and free a socket, clobber cache
73 void
74 sofree(struct socket *so)
76 Slirp *slirp = so->slirp;
78 if (so->so_emu==EMU_RSH && so->extra) {
79 sofree(so->extra);
80 so->extra=NULL;
82 if (so == slirp->tcp_last_so) {
83 slirp->tcp_last_so = &slirp->tcb;
84 } else if (so == slirp->udp_last_so) {
85 slirp->udp_last_so = &slirp->udb;
86 } else if (so == slirp->icmp_last_so) {
87 slirp->icmp_last_so = &slirp->icmp;
89 m_free(so->so_m);
91 if(so->so_next && so->so_prev)
92 remque(so); /* crashes if so is not in a queue */
94 free(so);
97 size_t sopreprbuf(struct socket *so, struct iovec *iov, int *np)
99 int n, lss, total;
100 struct sbuf *sb = &so->so_snd;
101 int len = sb->sb_datalen - sb->sb_cc;
102 int mss = so->so_tcpcb->t_maxseg;
104 DEBUG_CALL("sopreprbuf");
105 DEBUG_ARG("so = %p", so);
107 if (len <= 0)
108 return 0;
110 iov[0].iov_base = sb->sb_wptr;
111 iov[1].iov_base = NULL;
112 iov[1].iov_len = 0;
113 if (sb->sb_wptr < sb->sb_rptr) {
114 iov[0].iov_len = sb->sb_rptr - sb->sb_wptr;
115 /* Should never succeed, but... */
116 if (iov[0].iov_len > len)
117 iov[0].iov_len = len;
118 if (iov[0].iov_len > mss)
119 iov[0].iov_len -= iov[0].iov_len%mss;
120 n = 1;
121 } else {
122 iov[0].iov_len = (sb->sb_data + sb->sb_datalen) - sb->sb_wptr;
123 /* Should never succeed, but... */
124 if (iov[0].iov_len > len) iov[0].iov_len = len;
125 len -= iov[0].iov_len;
126 if (len) {
127 iov[1].iov_base = sb->sb_data;
128 iov[1].iov_len = sb->sb_rptr - sb->sb_data;
129 if(iov[1].iov_len > len)
130 iov[1].iov_len = len;
131 total = iov[0].iov_len + iov[1].iov_len;
132 if (total > mss) {
133 lss = total%mss;
134 if (iov[1].iov_len > lss) {
135 iov[1].iov_len -= lss;
136 n = 2;
137 } else {
138 lss -= iov[1].iov_len;
139 iov[0].iov_len -= lss;
140 n = 1;
142 } else
143 n = 2;
144 } else {
145 if (iov[0].iov_len > mss)
146 iov[0].iov_len -= iov[0].iov_len%mss;
147 n = 1;
150 if (np)
151 *np = n;
153 return iov[0].iov_len + (n - 1) * iov[1].iov_len;
157 * Read from so's socket into sb_snd, updating all relevant sbuf fields
158 * NOTE: This will only be called if it is select()ed for reading, so
159 * a read() of 0 (or less) means it's disconnected
162 soread(struct socket *so)
164 int n, nn;
165 struct sbuf *sb = &so->so_snd;
166 struct iovec iov[2];
168 DEBUG_CALL("soread");
169 DEBUG_ARG("so = %p", so);
172 * No need to check if there's enough room to read.
173 * soread wouldn't have been called if there weren't
175 sopreprbuf(so, iov, &n);
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 = qemu_recv(so->s, iov[0].iov_base, iov[0].iov_len,0);
182 #endif
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;
194 #ifndef HAVE_READV
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
204 if (n == 2 && nn == iov[0].iov_len) {
205 int ret;
206 ret = qemu_recv(so->s, iov[1].iov_base, iov[1].iov_len,0);
207 if (ret > 0)
208 nn += ret;
211 DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn));
212 #endif
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;
222 int soreadbuf(struct socket *so, const char *buf, int size)
224 int n, nn, copy = size;
225 struct sbuf *sb = &so->so_snd;
226 struct iovec iov[2];
228 DEBUG_CALL("soreadbuf");
229 DEBUG_ARG("so = %p", so);
232 * No need to check if there's enough room to read.
233 * soread wouldn't have been called if there weren't
235 if (sopreprbuf(so, iov, &n) < size)
236 goto err;
238 nn = MIN(iov[0].iov_len, copy);
239 memcpy(iov[0].iov_base, buf, nn);
241 copy -= nn;
242 buf += nn;
244 if (copy == 0)
245 goto done;
247 memcpy(iov[1].iov_base, buf, copy);
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:
258 sofcantrcvmore(so);
259 tcp_sockclosed(sototcpcb(so));
260 fprintf(stderr, "soreadbuf buffer to small");
261 return -1;
265 * Get urgent data
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
271 void
272 sorecvoob(struct socket *so)
274 struct tcpcb *tp = sototcpcb(so);
276 DEBUG_CALL("sorecvoob");
277 DEBUG_ARG("so = %p", so);
280 * We take a guess at how much urgent data has arrived.
281 * In most situations, when urgent data arrives, the next
282 * read() should get all the urgent data. This guess will
283 * be wrong however if more data arrives just after the
284 * urgent data, or the read() doesn't return all the
285 * urgent data.
287 soread(so);
288 tp->snd_up = tp->snd_una + so->so_snd.sb_cc;
289 tp->t_force = 1;
290 tcp_output(tp);
291 tp->t_force = 0;
295 * Send urgent data
296 * There's a lot duplicated code here, but...
299 sosendoob(struct socket *so)
301 struct sbuf *sb = &so->so_rcv;
302 char buff[2048]; /* XXX Shouldn't be sending more oob data than this */
304 int n, len;
306 DEBUG_CALL("sosendoob");
307 DEBUG_ARG("so = %p", so);
308 DEBUG_ARG("sb->sb_cc = %d", sb->sb_cc);
310 if (so->so_urgc > 2048)
311 so->so_urgc = 2048; /* XXXX */
313 if (sb->sb_rptr < sb->sb_wptr) {
314 /* We can send it directly */
315 n = slirp_send(so, sb->sb_rptr, so->so_urgc, (MSG_OOB)); /* |MSG_DONTWAIT)); */
316 so->so_urgc -= n;
318 DEBUG_MISC((dfd, " --- sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc));
319 } else {
321 * Since there's no sendv or sendtov like writev,
322 * we must copy all data to a linear buffer then
323 * send it all
325 len = (sb->sb_data + sb->sb_datalen) - sb->sb_rptr;
326 if (len > so->so_urgc) len = so->so_urgc;
327 memcpy(buff, sb->sb_rptr, len);
328 so->so_urgc -= len;
329 if (so->so_urgc) {
330 n = sb->sb_wptr - sb->sb_data;
331 if (n > so->so_urgc) n = so->so_urgc;
332 memcpy((buff + len), sb->sb_data, n);
333 so->so_urgc -= n;
334 len += n;
336 n = slirp_send(so, buff, len, (MSG_OOB)); /* |MSG_DONTWAIT)); */
337 #ifdef DEBUG
338 if (n != len)
339 DEBUG_ERROR((dfd, "Didn't send all data urgently XXXXX\n"));
340 #endif
341 DEBUG_MISC((dfd, " ---2 sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc));
344 sb->sb_cc -= n;
345 sb->sb_rptr += n;
346 if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen))
347 sb->sb_rptr -= sb->sb_datalen;
349 return n;
353 * Write data from so_rcv to so's socket,
354 * updating all sbuf field as necessary
357 sowrite(struct socket *so)
359 int n,nn;
360 struct sbuf *sb = &so->so_rcv;
361 int len = sb->sb_cc;
362 struct iovec iov[2];
364 DEBUG_CALL("sowrite");
365 DEBUG_ARG("so = %p", so);
367 if (so->so_urgc) {
368 sosendoob(so);
369 if (sb->sb_cc == 0)
370 return 0;
374 * No need to check if there's something to write,
375 * sowrite wouldn't have been called otherwise
378 iov[0].iov_base = sb->sb_rptr;
379 iov[1].iov_base = NULL;
380 iov[1].iov_len = 0;
381 if (sb->sb_rptr < sb->sb_wptr) {
382 iov[0].iov_len = sb->sb_wptr - sb->sb_rptr;
383 /* Should never succeed, but... */
384 if (iov[0].iov_len > len) iov[0].iov_len = len;
385 n = 1;
386 } else {
387 iov[0].iov_len = (sb->sb_data + sb->sb_datalen) - sb->sb_rptr;
388 if (iov[0].iov_len > len) iov[0].iov_len = len;
389 len -= iov[0].iov_len;
390 if (len) {
391 iov[1].iov_base = sb->sb_data;
392 iov[1].iov_len = sb->sb_wptr - sb->sb_data;
393 if (iov[1].iov_len > len) iov[1].iov_len = len;
394 n = 2;
395 } else
396 n = 1;
398 /* Check if there's urgent data to send, and if so, send it */
400 #ifdef HAVE_READV
401 nn = writev(so->s, (const struct iovec *)iov, n);
403 DEBUG_MISC((dfd, " ... wrote nn = %d bytes\n", nn));
404 #else
405 nn = slirp_send(so, iov[0].iov_base, iov[0].iov_len,0);
406 #endif
407 /* This should never happen, but people tell me it does *shrug* */
408 if (nn < 0 && (errno == EAGAIN || errno == EINTR))
409 return 0;
411 if (nn <= 0) {
412 DEBUG_MISC((dfd, " --- sowrite disconnected, so->so_state = %x, errno = %d\n",
413 so->so_state, errno));
414 sofcantsendmore(so);
415 tcp_sockclosed(sototcpcb(so));
416 return -1;
419 #ifndef HAVE_READV
420 if (n == 2 && nn == iov[0].iov_len) {
421 int ret;
422 ret = slirp_send(so, iov[1].iov_base, iov[1].iov_len,0);
423 if (ret > 0)
424 nn += ret;
426 DEBUG_MISC((dfd, " ... wrote nn = %d bytes\n", nn));
427 #endif
429 /* Update sbuf */
430 sb->sb_cc -= nn;
431 sb->sb_rptr += nn;
432 if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen))
433 sb->sb_rptr -= sb->sb_datalen;
436 * If in DRAIN mode, and there's no more data, set
437 * it CANTSENDMORE
439 if ((so->so_state & SS_FWDRAIN) && sb->sb_cc == 0)
440 sofcantsendmore(so);
442 return nn;
446 * recvfrom() a UDP socket
448 void
449 sorecvfrom(struct socket *so)
451 struct sockaddr_storage addr;
452 struct sockaddr_storage saddr, daddr;
453 socklen_t addrlen = sizeof(struct sockaddr_storage);
455 DEBUG_CALL("sorecvfrom");
456 DEBUG_ARG("so = %p", so);
458 if (so->so_type == IPPROTO_ICMP) { /* This is a "ping" reply */
459 char buff[256];
460 int len;
462 len = recvfrom(so->s, buff, 256, 0,
463 (struct sockaddr *)&addr, &addrlen);
464 /* XXX Check if reply is "correct"? */
466 if(len == -1 || len == 0) {
467 u_char code=ICMP_UNREACH_PORT;
469 if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST;
470 else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET;
472 DEBUG_MISC((dfd," udp icmp rx errno = %d-%s\n",
473 errno,strerror(errno)));
474 icmp_error(so->so_m, ICMP_UNREACH,code, 0,strerror(errno));
475 } else {
476 icmp_reflect(so->so_m);
477 so->so_m = NULL; /* Don't m_free() it again! */
479 /* No need for this socket anymore, udp_detach it */
480 udp_detach(so);
481 } else { /* A "normal" UDP packet */
482 struct mbuf *m;
483 int len;
484 #ifdef _WIN32
485 unsigned long n;
486 #else
487 int n;
488 #endif
490 m = m_get(so->slirp);
491 if (!m) {
492 return;
494 m->m_data += IF_MAXLINKHDR;
497 * XXX Shouldn't FIONREAD packets destined for port 53,
498 * but I don't know the max packet size for DNS lookups
500 len = M_FREEROOM(m);
501 /* if (so->so_fport != htons(53)) { */
502 ioctlsocket(so->s, FIONREAD, &n);
504 if (n > len) {
505 n = (m->m_data - m->m_dat) + m->m_len + n + 1;
506 m_inc(m, n);
507 len = M_FREEROOM(m);
509 /* } */
511 m->m_len = recvfrom(so->s, m->m_data, len, 0,
512 (struct sockaddr *)&addr, &addrlen);
513 DEBUG_MISC((dfd, " did recvfrom %d, errno = %d-%s\n",
514 m->m_len, errno,strerror(errno)));
515 if(m->m_len<0) {
516 u_char code=ICMP_UNREACH_PORT;
518 if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST;
519 else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET;
521 DEBUG_MISC((dfd," rx error, tx icmp ICMP_UNREACH:%i\n", code));
522 icmp_error(so->so_m, ICMP_UNREACH,code, 0,strerror(errno));
523 m_free(m);
524 } else {
526 * Hack: domain name lookup will be used the most for UDP,
527 * and since they'll only be used once there's no need
528 * for the 4 minute (or whatever) timeout... So we time them
529 * out much quicker (10 seconds for now...)
531 if (so->so_expire) {
532 if (so->so_fport == htons(53))
533 so->so_expire = curtime + SO_EXPIREFAST;
534 else
535 so->so_expire = curtime + SO_EXPIRE;
539 * If this packet was destined for CTL_ADDR,
540 * make it look like that's where it came from
542 saddr = addr;
543 sotranslate_in(so, &saddr);
544 daddr = so->lhost.ss;
546 switch (so->so_ffamily) {
547 case AF_INET:
548 udp_output(so, m, (struct sockaddr_in *) &saddr,
549 (struct sockaddr_in *) &daddr,
550 so->so_iptos);
551 break;
552 default:
553 break;
555 } /* rx error */
556 } /* if ping packet */
560 * sendto() a socket
563 sosendto(struct socket *so, struct mbuf *m)
565 int ret;
566 struct sockaddr_storage addr;
568 DEBUG_CALL("sosendto");
569 DEBUG_ARG("so = %p", so);
570 DEBUG_ARG("m = %p", m);
572 addr = so->fhost.ss;
573 DEBUG_CALL(" sendto()ing)");
574 sotranslate_out(so, &addr);
576 /* Don't care what port we get */
577 ret = sendto(so->s, m->m_data, m->m_len, 0,
578 (struct sockaddr *)&addr, sizeof(addr));
579 if (ret < 0)
580 return -1;
583 * Kill the socket if there's no reply in 4 minutes,
584 * but only if it's an expirable socket
586 if (so->so_expire)
587 so->so_expire = curtime + SO_EXPIRE;
588 so->so_state &= SS_PERSISTENT_MASK;
589 so->so_state |= SS_ISFCONNECTED; /* So that it gets select()ed */
590 return 0;
594 * Listen for incoming TCP connections
596 struct socket *
597 tcp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr,
598 u_int lport, int flags)
600 struct sockaddr_in addr;
601 struct socket *so;
602 int s, opt = 1;
603 socklen_t addrlen = sizeof(addr);
604 memset(&addr, 0, addrlen);
606 DEBUG_CALL("tcp_listen");
607 DEBUG_ARG("haddr = %x", haddr);
608 DEBUG_ARG("hport = %d", hport);
609 DEBUG_ARG("laddr = %x", laddr);
610 DEBUG_ARG("lport = %d", lport);
611 DEBUG_ARG("flags = %x", flags);
613 so = socreate(slirp);
614 if (!so) {
615 return NULL;
618 /* Don't tcp_attach... we don't need so_snd nor so_rcv */
619 if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL) {
620 free(so);
621 return NULL;
623 insque(so, &slirp->tcb);
626 * SS_FACCEPTONCE sockets must time out.
628 if (flags & SS_FACCEPTONCE)
629 so->so_tcpcb->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT*2;
631 so->so_state &= SS_PERSISTENT_MASK;
632 so->so_state |= (SS_FACCEPTCONN | flags);
633 so->so_lfamily = AF_INET;
634 so->so_lport = lport; /* Kept in network format */
635 so->so_laddr.s_addr = laddr; /* Ditto */
637 addr.sin_family = AF_INET;
638 addr.sin_addr.s_addr = haddr;
639 addr.sin_port = hport;
641 if (((s = qemu_socket(AF_INET,SOCK_STREAM,0)) < 0) ||
642 (socket_set_fast_reuse(s) < 0) ||
643 (bind(s,(struct sockaddr *)&addr, sizeof(addr)) < 0) ||
644 (listen(s,1) < 0)) {
645 int tmperrno = errno; /* Don't clobber the real reason we failed */
647 close(s);
648 sofree(so);
649 /* Restore the real errno */
650 #ifdef _WIN32
651 WSASetLastError(tmperrno);
652 #else
653 errno = tmperrno;
654 #endif
655 return NULL;
657 qemu_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int));
659 getsockname(s,(struct sockaddr *)&addr,&addrlen);
660 so->so_ffamily = AF_INET;
661 so->so_fport = addr.sin_port;
662 if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr)
663 so->so_faddr = slirp->vhost_addr;
664 else
665 so->so_faddr = addr.sin_addr;
667 so->s = s;
668 return so;
672 * Various session state calls
673 * XXX Should be #define's
674 * The socket state stuff needs work, these often get call 2 or 3
675 * times each when only 1 was needed
677 void
678 soisfconnecting(struct socket *so)
680 so->so_state &= ~(SS_NOFDREF|SS_ISFCONNECTED|SS_FCANTRCVMORE|
681 SS_FCANTSENDMORE|SS_FWDRAIN);
682 so->so_state |= SS_ISFCONNECTING; /* Clobber other states */
685 void
686 soisfconnected(struct socket *so)
688 so->so_state &= ~(SS_ISFCONNECTING|SS_FWDRAIN|SS_NOFDREF);
689 so->so_state |= SS_ISFCONNECTED; /* Clobber other states */
692 static void
693 sofcantrcvmore(struct socket *so)
695 if ((so->so_state & SS_NOFDREF) == 0) {
696 shutdown(so->s,0);
698 so->so_state &= ~(SS_ISFCONNECTING);
699 if (so->so_state & SS_FCANTSENDMORE) {
700 so->so_state &= SS_PERSISTENT_MASK;
701 so->so_state |= SS_NOFDREF; /* Don't select it */
702 } else {
703 so->so_state |= SS_FCANTRCVMORE;
707 static void
708 sofcantsendmore(struct socket *so)
710 if ((so->so_state & SS_NOFDREF) == 0) {
711 shutdown(so->s,1); /* send FIN to fhost */
713 so->so_state &= ~(SS_ISFCONNECTING);
714 if (so->so_state & SS_FCANTRCVMORE) {
715 so->so_state &= SS_PERSISTENT_MASK;
716 so->so_state |= SS_NOFDREF; /* as above */
717 } else {
718 so->so_state |= SS_FCANTSENDMORE;
723 * Set write drain mode
724 * Set CANTSENDMORE once all data has been write()n
726 void
727 sofwdrain(struct socket *so)
729 if (so->so_rcv.sb_cc)
730 so->so_state |= SS_FWDRAIN;
731 else
732 sofcantsendmore(so);
736 * Translate addr in host addr when it is a virtual address
738 void sotranslate_out(struct socket *so, struct sockaddr_storage *addr)
740 Slirp *slirp = so->slirp;
741 struct sockaddr_in *sin = (struct sockaddr_in *)addr;
743 switch (addr->ss_family) {
744 case AF_INET:
745 if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==
746 slirp->vnetwork_addr.s_addr) {
747 /* It's an alias */
748 if (so->so_faddr.s_addr == slirp->vnameserver_addr.s_addr) {
749 if (get_dns_addr(&sin->sin_addr) < 0) {
750 sin->sin_addr = loopback_addr;
752 } else {
753 sin->sin_addr = loopback_addr;
757 DEBUG_MISC((dfd, " addr.sin_port=%d, "
758 "addr.sin_addr.s_addr=%.16s\n",
759 ntohs(sin->sin_port), inet_ntoa(sin->sin_addr)));
760 break;
762 default:
763 break;
767 void sotranslate_in(struct socket *so, struct sockaddr_storage *addr)
769 Slirp *slirp = so->slirp;
770 struct sockaddr_in *sin = (struct sockaddr_in *)addr;
772 switch (addr->ss_family) {
773 case AF_INET:
774 if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==
775 slirp->vnetwork_addr.s_addr) {
776 uint32_t inv_mask = ~slirp->vnetwork_mask.s_addr;
778 if ((so->so_faddr.s_addr & inv_mask) == inv_mask) {
779 sin->sin_addr = slirp->vhost_addr;
780 } else if (sin->sin_addr.s_addr == loopback_addr.s_addr ||
781 so->so_faddr.s_addr != slirp->vhost_addr.s_addr) {
782 sin->sin_addr = so->so_faddr;
785 break;
787 default:
788 break;
793 * Translate connections from localhost to the real hostname
795 void sotranslate_accept(struct socket *so)
797 Slirp *slirp = so->slirp;
799 switch (so->so_ffamily) {
800 case AF_INET:
801 if (so->so_faddr.s_addr == INADDR_ANY ||
802 (so->so_faddr.s_addr & loopback_mask) ==
803 (loopback_addr.s_addr & loopback_mask)) {
804 so->so_faddr = slirp->vhost_addr;
806 break;
808 default:
809 break;