Statistics
| Branch: | Revision:

root / slirp / udp.c @ 07574baf

History | View | Annotate | Download (9.5 kB)

1 f0cbd3ec bellard
/*
2 f0cbd3ec bellard
 * Copyright (c) 1982, 1986, 1988, 1990, 1993
3 f0cbd3ec bellard
 *        The Regents of the University of California.  All rights reserved.
4 f0cbd3ec bellard
 *
5 f0cbd3ec bellard
 * Redistribution and use in source and binary forms, with or without
6 f0cbd3ec bellard
 * modification, are permitted provided that the following conditions
7 f0cbd3ec bellard
 * are met:
8 f0cbd3ec bellard
 * 1. Redistributions of source code must retain the above copyright
9 f0cbd3ec bellard
 *    notice, this list of conditions and the following disclaimer.
10 f0cbd3ec bellard
 * 2. Redistributions in binary form must reproduce the above copyright
11 f0cbd3ec bellard
 *    notice, this list of conditions and the following disclaimer in the
12 f0cbd3ec bellard
 *    documentation and/or other materials provided with the distribution.
13 2f5f8996 aliguori
 * 3. Neither the name of the University nor the names of its contributors
14 f0cbd3ec bellard
 *    may be used to endorse or promote products derived from this software
15 f0cbd3ec bellard
 *    without specific prior written permission.
16 f0cbd3ec bellard
 *
17 f0cbd3ec bellard
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 f0cbd3ec bellard
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 f0cbd3ec bellard
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 f0cbd3ec bellard
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 f0cbd3ec bellard
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 f0cbd3ec bellard
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 f0cbd3ec bellard
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 f0cbd3ec bellard
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 f0cbd3ec bellard
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 f0cbd3ec bellard
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 f0cbd3ec bellard
 * SUCH DAMAGE.
28 f0cbd3ec bellard
 *
29 f0cbd3ec bellard
 *        @(#)udp_usrreq.c        8.4 (Berkeley) 1/21/94
30 f0cbd3ec bellard
 * udp_usrreq.c,v 1.4 1994/10/02 17:48:45 phk Exp
31 f0cbd3ec bellard
 */
32 f0cbd3ec bellard
33 f0cbd3ec bellard
/*
34 f0cbd3ec bellard
 * Changes and additions relating to SLiRP
35 f0cbd3ec bellard
 * Copyright (c) 1995 Danny Gasparovski.
36 5fafdf24 ths
 *
37 5fafdf24 ths
 * Please read the file COPYRIGHT for the
38 f0cbd3ec bellard
 * terms and conditions of the copyright.
39 f0cbd3ec bellard
 */
40 f0cbd3ec bellard
41 f0cbd3ec bellard
#include <slirp.h>
42 f0cbd3ec bellard
#include "ip_icmp.h"
43 f0cbd3ec bellard
44 9634d903 blueswir1
static u_int8_t udp_tos(struct socket *so);
45 9634d903 blueswir1
46 f0cbd3ec bellard
void
47 460fec67 Jan Kiszka
udp_init(Slirp *slirp)
48 f0cbd3ec bellard
{
49 460fec67 Jan Kiszka
    slirp->udb.so_next = slirp->udb.so_prev = &slirp->udb;
50 460fec67 Jan Kiszka
    slirp->udp_last_so = &slirp->udb;
51 f0cbd3ec bellard
}
52 5fafdf24 ths
/* m->m_data  points at ip packet header
53 5fafdf24 ths
 * m->m_len   length ip packet
54 f0cbd3ec bellard
 * ip->ip_len length data (IPDU)
55 f0cbd3ec bellard
 */
56 f0cbd3ec bellard
void
57 aeed97c4 blueswir1
udp_input(register struct mbuf *m, int iphlen)
58 f0cbd3ec bellard
{
59 460fec67 Jan Kiszka
        Slirp *slirp = m->slirp;
60 f0cbd3ec bellard
        register struct ip *ip;
61 f0cbd3ec bellard
        register struct udphdr *uh;
62 f0cbd3ec bellard
        int len;
63 5fafdf24 ths
        struct ip save_ip;
64 f0cbd3ec bellard
        struct socket *so;
65 5fafdf24 ths
66 f0cbd3ec bellard
        DEBUG_CALL("udp_input");
67 f0cbd3ec bellard
        DEBUG_ARG("m = %lx", (long)m);
68 f0cbd3ec bellard
        DEBUG_ARG("iphlen = %d", iphlen);
69 5fafdf24 ths
70 f0cbd3ec bellard
        /*
71 f0cbd3ec bellard
         * Strip IP options, if any; should skip this,
72 f0cbd3ec bellard
         * make available to user, and use on returned packets,
73 f0cbd3ec bellard
         * but we don't yet have a way to check the checksum
74 f0cbd3ec bellard
         * with options still present.
75 f0cbd3ec bellard
         */
76 f0cbd3ec bellard
        if(iphlen > sizeof(struct ip)) {
77 f0cbd3ec bellard
                ip_stripoptions(m, (struct mbuf *)0);
78 f0cbd3ec bellard
                iphlen = sizeof(struct ip);
79 f0cbd3ec bellard
        }
80 f0cbd3ec bellard
81 f0cbd3ec bellard
        /*
82 f0cbd3ec bellard
         * Get IP and UDP header together in first mbuf.
83 f0cbd3ec bellard
         */
84 f0cbd3ec bellard
        ip = mtod(m, struct ip *);
85 f0cbd3ec bellard
        uh = (struct udphdr *)((caddr_t)ip + iphlen);
86 f0cbd3ec bellard
87 f0cbd3ec bellard
        /*
88 f0cbd3ec bellard
         * Make mbuf data length reflect UDP length.
89 f0cbd3ec bellard
         * If not enough data to reflect UDP length, drop.
90 f0cbd3ec bellard
         */
91 f0cbd3ec bellard
        len = ntohs((u_int16_t)uh->uh_ulen);
92 f0cbd3ec bellard
93 f0cbd3ec bellard
        if (ip->ip_len != len) {
94 f0cbd3ec bellard
                if (len > ip->ip_len) {
95 f0cbd3ec bellard
                        goto bad;
96 f0cbd3ec bellard
                }
97 f0cbd3ec bellard
                m_adj(m, len - ip->ip_len);
98 f0cbd3ec bellard
                ip->ip_len = len;
99 f0cbd3ec bellard
        }
100 5fafdf24 ths
101 f0cbd3ec bellard
        /*
102 f0cbd3ec bellard
         * Save a copy of the IP header in case we want restore it
103 f0cbd3ec bellard
         * for sending an ICMP error message in response.
104 f0cbd3ec bellard
         */
105 5fafdf24 ths
        save_ip = *ip;
106 f0cbd3ec bellard
        save_ip.ip_len+= iphlen;         /* tcp_input subtracts this */
107 f0cbd3ec bellard
108 f0cbd3ec bellard
        /*
109 f0cbd3ec bellard
         * Checksum extended UDP header and data.
110 f0cbd3ec bellard
         */
111 0d62c4cf Jan Kiszka
        if (uh->uh_sum) {
112 429d0a3d blueswir1
      memset(&((struct ipovly *)ip)->ih_mbuf, 0, sizeof(struct mbuf_ptr));
113 f0cbd3ec bellard
          ((struct ipovly *)ip)->ih_x1 = 0;
114 f0cbd3ec bellard
          ((struct ipovly *)ip)->ih_len = uh->uh_ulen;
115 f0cbd3ec bellard
          if(cksum(m, len + sizeof(struct ip))) {
116 f0cbd3ec bellard
            goto bad;
117 f0cbd3ec bellard
          }
118 f0cbd3ec bellard
        }
119 f0cbd3ec bellard
120 f0cbd3ec bellard
        /*
121 f0cbd3ec bellard
         *  handle DHCP/BOOTP
122 f0cbd3ec bellard
         */
123 f0cbd3ec bellard
        if (ntohs(uh->uh_dport) == BOOTP_SERVER) {
124 f0cbd3ec bellard
            bootp_input(m);
125 f0cbd3ec bellard
            goto bad;
126 f0cbd3ec bellard
        }
127 f0cbd3ec bellard
128 460fec67 Jan Kiszka
        if (slirp->restricted) {
129 a9ba3a85 aliguori
            goto bad;
130 460fec67 Jan Kiszka
        }
131 a9ba3a85 aliguori
132 c7f74643 bellard
        /*
133 c7f74643 bellard
         *  handle TFTP
134 c7f74643 bellard
         */
135 c7f74643 bellard
        if (ntohs(uh->uh_dport) == TFTP_SERVER) {
136 c7f74643 bellard
            tftp_input(m);
137 c7f74643 bellard
            goto bad;
138 c7f74643 bellard
        }
139 c7f74643 bellard
140 f0cbd3ec bellard
        /*
141 f0cbd3ec bellard
         * Locate pcb for datagram.
142 f0cbd3ec bellard
         */
143 460fec67 Jan Kiszka
        so = slirp->udp_last_so;
144 f0cbd3ec bellard
        if (so->so_lport != uh->uh_sport ||
145 f0cbd3ec bellard
            so->so_laddr.s_addr != ip->ip_src.s_addr) {
146 f0cbd3ec bellard
                struct socket *tmp;
147 3b46e624 ths
148 460fec67 Jan Kiszka
                for (tmp = slirp->udb.so_next; tmp != &slirp->udb;
149 460fec67 Jan Kiszka
                     tmp = tmp->so_next) {
150 f0cbd3ec bellard
                        if (tmp->so_lport == uh->uh_sport &&
151 f0cbd3ec bellard
                            tmp->so_laddr.s_addr == ip->ip_src.s_addr) {
152 f0cbd3ec bellard
                                so = tmp;
153 f0cbd3ec bellard
                                break;
154 f0cbd3ec bellard
                        }
155 f0cbd3ec bellard
                }
156 460fec67 Jan Kiszka
                if (tmp == &slirp->udb) {
157 f0cbd3ec bellard
                  so = NULL;
158 f0cbd3ec bellard
                } else {
159 460fec67 Jan Kiszka
                  slirp->udp_last_so = so;
160 f0cbd3ec bellard
                }
161 f0cbd3ec bellard
        }
162 5fafdf24 ths
163 f0cbd3ec bellard
        if (so == NULL) {
164 f0cbd3ec bellard
          /*
165 f0cbd3ec bellard
           * If there's no socket for this packet,
166 f0cbd3ec bellard
           * create one
167 f0cbd3ec bellard
           */
168 460fec67 Jan Kiszka
          so = socreate(slirp);
169 460fec67 Jan Kiszka
          if (!so) {
170 460fec67 Jan Kiszka
              goto bad;
171 460fec67 Jan Kiszka
          }
172 f0cbd3ec bellard
          if(udp_attach(so) == -1) {
173 5fafdf24 ths
            DEBUG_MISC((dfd," udp_attach errno = %d-%s\n",
174 f0cbd3ec bellard
                        errno,strerror(errno)));
175 f0cbd3ec bellard
            sofree(so);
176 f0cbd3ec bellard
            goto bad;
177 f0cbd3ec bellard
          }
178 3b46e624 ths
179 f0cbd3ec bellard
          /*
180 f0cbd3ec bellard
           * Setup fields
181 f0cbd3ec bellard
           */
182 f0cbd3ec bellard
          so->so_laddr = ip->ip_src;
183 f0cbd3ec bellard
          so->so_lport = uh->uh_sport;
184 3b46e624 ths
185 f0cbd3ec bellard
          if ((so->so_iptos = udp_tos(so)) == 0)
186 f0cbd3ec bellard
            so->so_iptos = ip->ip_tos;
187 3b46e624 ths
188 f0cbd3ec bellard
          /*
189 f0cbd3ec bellard
           * XXXXX Here, check if it's in udpexec_list,
190 f0cbd3ec bellard
           * and if it is, do the fork_exec() etc.
191 f0cbd3ec bellard
           */
192 f0cbd3ec bellard
        }
193 f0cbd3ec bellard
194 54fd9cdf ths
        so->so_faddr = ip->ip_dst; /* XXX */
195 54fd9cdf ths
        so->so_fport = uh->uh_dport; /* XXX */
196 54fd9cdf ths
197 f0cbd3ec bellard
        iphlen += sizeof(struct udphdr);
198 f0cbd3ec bellard
        m->m_len -= iphlen;
199 f0cbd3ec bellard
        m->m_data += iphlen;
200 f0cbd3ec bellard
201 f0cbd3ec bellard
        /*
202 f0cbd3ec bellard
         * Now we sendto() the packet.
203 f0cbd3ec bellard
         */
204 f0cbd3ec bellard
        if(sosendto(so,m) == -1) {
205 f0cbd3ec bellard
          m->m_len += iphlen;
206 f0cbd3ec bellard
          m->m_data -= iphlen;
207 f0cbd3ec bellard
          *ip=save_ip;
208 f0cbd3ec bellard
          DEBUG_MISC((dfd,"udp tx errno = %d-%s\n",errno,strerror(errno)));
209 3b46e624 ths
          icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno));
210 f0cbd3ec bellard
        }
211 f0cbd3ec bellard
212 f0cbd3ec bellard
        m_free(so->so_m);   /* used for ICMP if error on sorecvfrom */
213 f0cbd3ec bellard
214 f0cbd3ec bellard
        /* restore the orig mbuf packet */
215 f0cbd3ec bellard
        m->m_len += iphlen;
216 f0cbd3ec bellard
        m->m_data -= iphlen;
217 f0cbd3ec bellard
        *ip=save_ip;
218 f0cbd3ec bellard
        so->so_m=m;         /* ICMP backup */
219 f0cbd3ec bellard
220 f0cbd3ec bellard
        return;
221 f0cbd3ec bellard
bad:
222 f0cbd3ec bellard
        m_freem(m);
223 f0cbd3ec bellard
        return;
224 f0cbd3ec bellard
}
225 f0cbd3ec bellard
226 5fafdf24 ths
int udp_output2(struct socket *so, struct mbuf *m,
227 f0cbd3ec bellard
                struct sockaddr_in *saddr, struct sockaddr_in *daddr,
228 f0cbd3ec bellard
                int iptos)
229 f0cbd3ec bellard
{
230 f0cbd3ec bellard
        register struct udpiphdr *ui;
231 f0cbd3ec bellard
        int error = 0;
232 f0cbd3ec bellard
233 f0cbd3ec bellard
        DEBUG_CALL("udp_output");
234 f0cbd3ec bellard
        DEBUG_ARG("so = %lx", (long)so);
235 f0cbd3ec bellard
        DEBUG_ARG("m = %lx", (long)m);
236 f0cbd3ec bellard
        DEBUG_ARG("saddr = %lx", (long)saddr->sin_addr.s_addr);
237 f0cbd3ec bellard
        DEBUG_ARG("daddr = %lx", (long)daddr->sin_addr.s_addr);
238 f0cbd3ec bellard
239 f0cbd3ec bellard
        /*
240 f0cbd3ec bellard
         * Adjust for header
241 f0cbd3ec bellard
         */
242 f0cbd3ec bellard
        m->m_data -= sizeof(struct udpiphdr);
243 f0cbd3ec bellard
        m->m_len += sizeof(struct udpiphdr);
244 5fafdf24 ths
245 f0cbd3ec bellard
        /*
246 f0cbd3ec bellard
         * Fill in mbuf with extended UDP header
247 f0cbd3ec bellard
         * and addresses and length put into network format.
248 f0cbd3ec bellard
         */
249 f0cbd3ec bellard
        ui = mtod(m, struct udpiphdr *);
250 429d0a3d blueswir1
    memset(&ui->ui_i.ih_mbuf, 0 , sizeof(struct mbuf_ptr));
251 f0cbd3ec bellard
        ui->ui_x1 = 0;
252 f0cbd3ec bellard
        ui->ui_pr = IPPROTO_UDP;
253 0d62c4cf Jan Kiszka
        ui->ui_len = htons(m->m_len - sizeof(struct ip));
254 f0cbd3ec bellard
        /* XXXXX Check for from-one-location sockets, or from-any-location sockets */
255 f0cbd3ec bellard
        ui->ui_src = saddr->sin_addr;
256 f0cbd3ec bellard
        ui->ui_dst = daddr->sin_addr;
257 f0cbd3ec bellard
        ui->ui_sport = saddr->sin_port;
258 f0cbd3ec bellard
        ui->ui_dport = daddr->sin_port;
259 f0cbd3ec bellard
        ui->ui_ulen = ui->ui_len;
260 f0cbd3ec bellard
261 f0cbd3ec bellard
        /*
262 f0cbd3ec bellard
         * Stuff checksum and output datagram.
263 f0cbd3ec bellard
         */
264 f0cbd3ec bellard
        ui->ui_sum = 0;
265 0d62c4cf Jan Kiszka
        if ((ui->ui_sum = cksum(m, m->m_len)) == 0)
266 f0cbd3ec bellard
                ui->ui_sum = 0xffff;
267 f0cbd3ec bellard
        ((struct ip *)ui)->ip_len = m->m_len;
268 f0cbd3ec bellard
269 9634d903 blueswir1
        ((struct ip *)ui)->ip_ttl = IPDEFTTL;
270 f0cbd3ec bellard
        ((struct ip *)ui)->ip_tos = iptos;
271 5fafdf24 ths
272 f0cbd3ec bellard
        error = ip_output(so, m);
273 5fafdf24 ths
274 f0cbd3ec bellard
        return (error);
275 f0cbd3ec bellard
}
276 f0cbd3ec bellard
277 5fafdf24 ths
int udp_output(struct socket *so, struct mbuf *m,
278 f0cbd3ec bellard
               struct sockaddr_in *addr)
279 f0cbd3ec bellard
280 f0cbd3ec bellard
{
281 460fec67 Jan Kiszka
    Slirp *slirp = so->slirp;
282 f0cbd3ec bellard
    struct sockaddr_in saddr, daddr;
283 f0cbd3ec bellard
284 f0cbd3ec bellard
    saddr = *addr;
285 460fec67 Jan Kiszka
    if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==
286 460fec67 Jan Kiszka
        slirp->vnetwork_addr.s_addr) {
287 460fec67 Jan Kiszka
        uint32_t inv_mask = ~slirp->vnetwork_mask.s_addr;
288 460fec67 Jan Kiszka
289 460fec67 Jan Kiszka
        if ((so->so_faddr.s_addr & inv_mask) == inv_mask) {
290 460fec67 Jan Kiszka
            saddr.sin_addr = slirp->vhost_addr;
291 a13a4126 Jan Kiszka
        } else if (addr->sin_addr.s_addr == loopback_addr.s_addr ||
292 460fec67 Jan Kiszka
                   so->so_faddr.s_addr != slirp->vhost_addr.s_addr) {
293 a13a4126 Jan Kiszka
            saddr.sin_addr = so->so_faddr;
294 a13a4126 Jan Kiszka
        }
295 c904d61f bellard
    }
296 f0cbd3ec bellard
    daddr.sin_addr = so->so_laddr;
297 f0cbd3ec bellard
    daddr.sin_port = so->so_lport;
298 3b46e624 ths
299 f0cbd3ec bellard
    return udp_output2(so, m, &saddr, &daddr, so->so_iptos);
300 f0cbd3ec bellard
}
301 f0cbd3ec bellard
302 f0cbd3ec bellard
int
303 aeed97c4 blueswir1
udp_attach(struct socket *so)
304 f0cbd3ec bellard
{
305 40ff6d7e Kevin Wolf
  if((so->s = qemu_socket(AF_INET,SOCK_DGRAM,0)) != -1) {
306 97df1ee5 Ed Swierk
    so->so_expire = curtime + SO_EXPIRE;
307 97df1ee5 Ed Swierk
    insque(so, &so->slirp->udb);
308 f0cbd3ec bellard
  }
309 f0cbd3ec bellard
  return(so->s);
310 f0cbd3ec bellard
}
311 f0cbd3ec bellard
312 f0cbd3ec bellard
void
313 aeed97c4 blueswir1
udp_detach(struct socket *so)
314 f0cbd3ec bellard
{
315 379ff53d bellard
        closesocket(so->s);
316 f0cbd3ec bellard
        sofree(so);
317 f0cbd3ec bellard
}
318 f0cbd3ec bellard
319 9634d903 blueswir1
static const struct tos_t udptos[] = {
320 f0cbd3ec bellard
        {0, 53, IPTOS_LOWDELAY, 0},                        /* DNS */
321 f0cbd3ec bellard
        {0, 0, 0, 0}
322 f0cbd3ec bellard
};
323 f0cbd3ec bellard
324 9634d903 blueswir1
static u_int8_t
325 9634d903 blueswir1
udp_tos(struct socket *so)
326 f0cbd3ec bellard
{
327 f0cbd3ec bellard
        int i = 0;
328 5fafdf24 ths
329 f0cbd3ec bellard
        while(udptos[i].tos) {
330 f0cbd3ec bellard
                if ((udptos[i].fport && ntohs(so->so_fport) == udptos[i].fport) ||
331 f0cbd3ec bellard
                    (udptos[i].lport && ntohs(so->so_lport) == udptos[i].lport)) {
332 f0cbd3ec bellard
                            so->so_emu = udptos[i].emu;
333 f0cbd3ec bellard
                        return udptos[i].tos;
334 f0cbd3ec bellard
                }
335 f0cbd3ec bellard
                i++;
336 f0cbd3ec bellard
        }
337 5fafdf24 ths
338 f0cbd3ec bellard
        return 0;
339 f0cbd3ec bellard
}
340 f0cbd3ec bellard
341 f0cbd3ec bellard
struct socket *
342 460fec67 Jan Kiszka
udp_listen(Slirp *slirp, u_int32_t haddr, u_int hport, u_int32_t laddr,
343 460fec67 Jan Kiszka
           u_int lport, int flags)
344 f0cbd3ec bellard
{
345 f0cbd3ec bellard
        struct sockaddr_in addr;
346 f0cbd3ec bellard
        struct socket *so;
347 242acf3a balrog
        socklen_t addrlen = sizeof(struct sockaddr_in), opt = 1;
348 5fafdf24 ths
349 460fec67 Jan Kiszka
        so = socreate(slirp);
350 460fec67 Jan Kiszka
        if (!so) {
351 460fec67 Jan Kiszka
            return NULL;
352 f0cbd3ec bellard
        }
353 40ff6d7e Kevin Wolf
        so->s = qemu_socket(AF_INET,SOCK_DGRAM,0);
354 f0cbd3ec bellard
        so->so_expire = curtime + SO_EXPIRE;
355 460fec67 Jan Kiszka
        insque(so, &slirp->udb);
356 f0cbd3ec bellard
357 f0cbd3ec bellard
        addr.sin_family = AF_INET;
358 3c6a0580 Jan Kiszka
        addr.sin_addr.s_addr = haddr;
359 3c6a0580 Jan Kiszka
        addr.sin_port = hport;
360 f0cbd3ec bellard
361 f0cbd3ec bellard
        if (bind(so->s,(struct sockaddr *)&addr, addrlen) < 0) {
362 f0cbd3ec bellard
                udp_detach(so);
363 f0cbd3ec bellard
                return NULL;
364 f0cbd3ec bellard
        }
365 f0cbd3ec bellard
        setsockopt(so->s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int));
366 5fafdf24 ths
367 f0cbd3ec bellard
        getsockname(so->s,(struct sockaddr *)&addr,&addrlen);
368 f0cbd3ec bellard
        so->so_fport = addr.sin_port;
369 a13a4126 Jan Kiszka
        if (addr.sin_addr.s_addr == 0 ||
370 a13a4126 Jan Kiszka
            addr.sin_addr.s_addr == loopback_addr.s_addr) {
371 460fec67 Jan Kiszka
           so->so_faddr = slirp->vhost_addr;
372 a13a4126 Jan Kiszka
        } else {
373 f0cbd3ec bellard
           so->so_faddr = addr.sin_addr;
374 a13a4126 Jan Kiszka
        }
375 f0cbd3ec bellard
        so->so_lport = lport;
376 f0cbd3ec bellard
        so->so_laddr.s_addr = laddr;
377 f0cbd3ec bellard
        if (flags != SS_FACCEPTONCE)
378 f0cbd3ec bellard
           so->so_expire = 0;
379 5fafdf24 ths
380 f932b6ce Jan Kiszka
        so->so_state &= SS_PERSISTENT_MASK;
381 6dd5ffb6 Jan Kiszka
        so->so_state |= SS_ISFCONNECTED | flags;
382 5fafdf24 ths
383 f0cbd3ec bellard
        return so;
384 f0cbd3ec bellard
}