Statistics
| Branch: | Revision:

root / slirp / slirp.c @ 9c22a623

History | View | Annotate | Download (27.6 kB)

1 d75a0b97 bellard
/*
2 d75a0b97 bellard
 * libslirp glue
3 d75a0b97 bellard
 *
4 d75a0b97 bellard
 * Copyright (c) 2004-2008 Fabrice Bellard
5 d75a0b97 bellard
 *
6 d75a0b97 bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 d75a0b97 bellard
 * of this software and associated documentation files (the "Software"), to deal
8 d75a0b97 bellard
 * in the Software without restriction, including without limitation the rights
9 d75a0b97 bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 d75a0b97 bellard
 * copies of the Software, and to permit persons to whom the Software is
11 d75a0b97 bellard
 * furnished to do so, subject to the following conditions:
12 d75a0b97 bellard
 *
13 d75a0b97 bellard
 * The above copyright notice and this permission notice shall be included in
14 d75a0b97 bellard
 * all copies or substantial portions of the Software.
15 d75a0b97 bellard
 *
16 d75a0b97 bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 d75a0b97 bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 d75a0b97 bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 d75a0b97 bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 d75a0b97 bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 d75a0b97 bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 d75a0b97 bellard
 * THE SOFTWARE.
23 d75a0b97 bellard
 */
24 e1c5a2b3 aliguori
#include "qemu-common.h"
25 0580ac91 blueswir1
#include "qemu-char.h"
26 f0cbd3ec bellard
#include "slirp.h"
27 062e5527 aliguori
#include "hw/hw.h"
28 f0cbd3ec bellard
29 f0cbd3ec bellard
/* host address */
30 f0cbd3ec bellard
struct in_addr our_addr;
31 f0cbd3ec bellard
/* host dns address */
32 f0cbd3ec bellard
struct in_addr dns_addr;
33 f0cbd3ec bellard
/* host loopback address */
34 f0cbd3ec bellard
struct in_addr loopback_addr;
35 f0cbd3ec bellard
36 f0cbd3ec bellard
/* address for slirp virtual addresses */
37 f0cbd3ec bellard
struct in_addr special_addr;
38 8dbca8dd bellard
/* virtual address alias for host */
39 8dbca8dd bellard
struct in_addr alias_addr;
40 f0cbd3ec bellard
41 9634d903 blueswir1
static const uint8_t special_ethaddr[6] = {
42 f0cbd3ec bellard
    0x52, 0x54, 0x00, 0x12, 0x35, 0x00
43 f0cbd3ec bellard
};
44 f0cbd3ec bellard
45 de806f07 bellard
/* ARP cache for the guest IP addresses (XXX: allow many entries) */
46 f0cbd3ec bellard
uint8_t client_ethaddr[6];
47 de806f07 bellard
static struct in_addr client_ipaddr;
48 de806f07 bellard
49 de806f07 bellard
static const uint8_t zero_ethaddr[6] = { 0, 0, 0, 0, 0, 0 };
50 f0cbd3ec bellard
51 0580ac91 blueswir1
const char *slirp_special_ip = CTL_SPECIAL;
52 a9ba3a85 aliguori
int slirp_restrict;
53 511d2b14 blueswir1
static int do_slowtimo;
54 f0cbd3ec bellard
int link_up;
55 f0cbd3ec bellard
struct timeval tt;
56 f0cbd3ec bellard
FILE *lfd;
57 a3d4af03 bellard
struct ex_list *exec_list;
58 f0cbd3ec bellard
59 f0cbd3ec bellard
/* XXX: suppress those select globals */
60 f0cbd3ec bellard
fd_set *global_readfds, *global_writefds, *global_xfds;
61 f0cbd3ec bellard
62 3f423c9c bellard
char slirp_hostname[33];
63 115defd1 pbrook
64 f0cbd3ec bellard
#ifdef _WIN32
65 f0cbd3ec bellard
66 f0cbd3ec bellard
static int get_dns_addr(struct in_addr *pdns_addr)
67 f0cbd3ec bellard
{
68 379ff53d bellard
    FIXED_INFO *FixedInfo=NULL;
69 379ff53d bellard
    ULONG    BufLen;
70 379ff53d bellard
    DWORD    ret;
71 379ff53d bellard
    IP_ADDR_STRING *pIPAddr;
72 379ff53d bellard
    struct in_addr tmp_addr;
73 3b46e624 ths
74 379ff53d bellard
    FixedInfo = (FIXED_INFO *)GlobalAlloc(GPTR, sizeof(FIXED_INFO));
75 379ff53d bellard
    BufLen = sizeof(FIXED_INFO);
76 3b46e624 ths
77 379ff53d bellard
    if (ERROR_BUFFER_OVERFLOW == GetNetworkParams(FixedInfo, &BufLen)) {
78 379ff53d bellard
        if (FixedInfo) {
79 379ff53d bellard
            GlobalFree(FixedInfo);
80 379ff53d bellard
            FixedInfo = NULL;
81 379ff53d bellard
        }
82 379ff53d bellard
        FixedInfo = GlobalAlloc(GPTR, BufLen);
83 379ff53d bellard
    }
84 5fafdf24 ths
85 379ff53d bellard
    if ((ret = GetNetworkParams(FixedInfo, &BufLen)) != ERROR_SUCCESS) {
86 379ff53d bellard
        printf("GetNetworkParams failed. ret = %08x\n", (u_int)ret );
87 379ff53d bellard
        if (FixedInfo) {
88 379ff53d bellard
            GlobalFree(FixedInfo);
89 379ff53d bellard
            FixedInfo = NULL;
90 379ff53d bellard
        }
91 379ff53d bellard
        return -1;
92 379ff53d bellard
    }
93 3b46e624 ths
94 379ff53d bellard
    pIPAddr = &(FixedInfo->DnsServerList);
95 379ff53d bellard
    inet_aton(pIPAddr->IpAddress.String, &tmp_addr);
96 379ff53d bellard
    *pdns_addr = tmp_addr;
97 379ff53d bellard
#if 0
98 379ff53d bellard
    printf( "DNS Servers:\n" );
99 379ff53d bellard
    printf( "DNS Addr:%s\n", pIPAddr->IpAddress.String );
100 3b46e624 ths

101 379ff53d bellard
    pIPAddr = FixedInfo -> DnsServerList.Next;
102 379ff53d bellard
    while ( pIPAddr ) {
103 379ff53d bellard
            printf( "DNS Addr:%s\n", pIPAddr ->IpAddress.String );
104 379ff53d bellard
            pIPAddr = pIPAddr ->Next;
105 379ff53d bellard
    }
106 379ff53d bellard
#endif
107 379ff53d bellard
    if (FixedInfo) {
108 379ff53d bellard
        GlobalFree(FixedInfo);
109 379ff53d bellard
        FixedInfo = NULL;
110 379ff53d bellard
    }
111 379ff53d bellard
    return 0;
112 f0cbd3ec bellard
}
113 f0cbd3ec bellard
114 f0cbd3ec bellard
#else
115 f0cbd3ec bellard
116 f0cbd3ec bellard
static int get_dns_addr(struct in_addr *pdns_addr)
117 f0cbd3ec bellard
{
118 f0cbd3ec bellard
    char buff[512];
119 363a37d5 blueswir1
    char buff2[257];
120 f0cbd3ec bellard
    FILE *f;
121 f0cbd3ec bellard
    int found = 0;
122 f0cbd3ec bellard
    struct in_addr tmp_addr;
123 3b46e624 ths
124 f0cbd3ec bellard
    f = fopen("/etc/resolv.conf", "r");
125 f0cbd3ec bellard
    if (!f)
126 f0cbd3ec bellard
        return -1;
127 f0cbd3ec bellard
128 31a60e22 blueswir1
#ifdef DEBUG
129 f0cbd3ec bellard
    lprint("IP address of your DNS(s): ");
130 31a60e22 blueswir1
#endif
131 f0cbd3ec bellard
    while (fgets(buff, 512, f) != NULL) {
132 f0cbd3ec bellard
        if (sscanf(buff, "nameserver%*[ \t]%256s", buff2) == 1) {
133 f0cbd3ec bellard
            if (!inet_aton(buff2, &tmp_addr))
134 f0cbd3ec bellard
                continue;
135 f0cbd3ec bellard
            if (tmp_addr.s_addr == loopback_addr.s_addr)
136 f0cbd3ec bellard
                tmp_addr = our_addr;
137 f0cbd3ec bellard
            /* If it's the first one, set it to dns_addr */
138 f0cbd3ec bellard
            if (!found)
139 f0cbd3ec bellard
                *pdns_addr = tmp_addr;
140 31a60e22 blueswir1
#ifdef DEBUG
141 f0cbd3ec bellard
            else
142 f0cbd3ec bellard
                lprint(", ");
143 31a60e22 blueswir1
#endif
144 f0cbd3ec bellard
            if (++found > 3) {
145 31a60e22 blueswir1
#ifdef DEBUG
146 f0cbd3ec bellard
                lprint("(more)");
147 31a60e22 blueswir1
#endif
148 f0cbd3ec bellard
                break;
149 31a60e22 blueswir1
            }
150 31a60e22 blueswir1
#ifdef DEBUG
151 31a60e22 blueswir1
            else
152 f0cbd3ec bellard
                lprint("%s", inet_ntoa(tmp_addr));
153 31a60e22 blueswir1
#endif
154 f0cbd3ec bellard
        }
155 f0cbd3ec bellard
    }
156 1d43a717 bellard
    fclose(f);
157 f0cbd3ec bellard
    if (!found)
158 f0cbd3ec bellard
        return -1;
159 f0cbd3ec bellard
    return 0;
160 f0cbd3ec bellard
}
161 f0cbd3ec bellard
162 f0cbd3ec bellard
#endif
163 f0cbd3ec bellard
164 379ff53d bellard
#ifdef _WIN32
165 9634d903 blueswir1
static void slirp_cleanup(void)
166 379ff53d bellard
{
167 379ff53d bellard
    WSACleanup();
168 379ff53d bellard
}
169 379ff53d bellard
#endif
170 379ff53d bellard
171 062e5527 aliguori
static void slirp_state_save(QEMUFile *f, void *opaque);
172 062e5527 aliguori
static int slirp_state_load(QEMUFile *f, void *opaque, int version_id);
173 062e5527 aliguori
174 511d2b14 blueswir1
void slirp_init(int restricted, char *special_ip)
175 f0cbd3ec bellard
{
176 512176db bellard
    //    debug_init("/tmp/slirp.log", DEBUG_DEFAULT);
177 3b46e624 ths
178 379ff53d bellard
#ifdef _WIN32
179 379ff53d bellard
    {
180 379ff53d bellard
        WSADATA Data;
181 379ff53d bellard
        WSAStartup(MAKEWORD(2,0), &Data);
182 379ff53d bellard
        atexit(slirp_cleanup);
183 379ff53d bellard
    }
184 379ff53d bellard
#endif
185 379ff53d bellard
186 f0cbd3ec bellard
    link_up = 1;
187 511d2b14 blueswir1
    slirp_restrict = restricted;
188 f0cbd3ec bellard
189 f0cbd3ec bellard
    if_init();
190 f0cbd3ec bellard
    ip_init();
191 f0cbd3ec bellard
192 f0cbd3ec bellard
    /* Initialise mbufs *after* setting the MTU */
193 f0cbd3ec bellard
    m_init();
194 f0cbd3ec bellard
195 f0cbd3ec bellard
    /* set default addresses */
196 f0cbd3ec bellard
    inet_aton("127.0.0.1", &loopback_addr);
197 f0cbd3ec bellard
198 f0cbd3ec bellard
    if (get_dns_addr(&dns_addr) < 0) {
199 0f8134bf pbrook
        dns_addr = loopback_addr;
200 0f8134bf pbrook
        fprintf (stderr, "Warning: No DNS servers found\n");
201 f0cbd3ec bellard
    }
202 f0cbd3ec bellard
203 a9ba3a85 aliguori
    if (special_ip)
204 a9ba3a85 aliguori
        slirp_special_ip = special_ip;
205 a9ba3a85 aliguori
206 a9ba3a85 aliguori
    inet_aton(slirp_special_ip, &special_addr);
207 8dbca8dd bellard
    alias_addr.s_addr = special_addr.s_addr | htonl(CTL_ALIAS);
208 f4e15b4b pbrook
    getouraddr();
209 062e5527 aliguori
    register_savevm("slirp", 0, 1, slirp_state_save, slirp_state_load, NULL);
210 f0cbd3ec bellard
}
211 f0cbd3ec bellard
212 f0cbd3ec bellard
#define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
213 f0cbd3ec bellard
#define CONN_CANFRCV(so) (((so)->so_state & (SS_FCANTRCVMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
214 f0cbd3ec bellard
#define UPD_NFDS(x) if (nfds < (x)) nfds = (x)
215 f0cbd3ec bellard
216 f0cbd3ec bellard
/*
217 f0cbd3ec bellard
 * curtime kept to an accuracy of 1ms
218 f0cbd3ec bellard
 */
219 379ff53d bellard
#ifdef _WIN32
220 379ff53d bellard
static void updtime(void)
221 379ff53d bellard
{
222 379ff53d bellard
    struct _timeb tb;
223 379ff53d bellard
224 379ff53d bellard
    _ftime(&tb);
225 379ff53d bellard
    curtime = (u_int)tb.time * (u_int)1000;
226 379ff53d bellard
    curtime += (u_int)tb.millitm;
227 379ff53d bellard
}
228 379ff53d bellard
#else
229 f0cbd3ec bellard
static void updtime(void)
230 f0cbd3ec bellard
{
231 511d2b14 blueswir1
        gettimeofday(&tt, NULL);
232 5fafdf24 ths
233 f0cbd3ec bellard
        curtime = (u_int)tt.tv_sec * (u_int)1000;
234 f0cbd3ec bellard
        curtime += (u_int)tt.tv_usec / (u_int)1000;
235 5fafdf24 ths
236 f0cbd3ec bellard
        if ((tt.tv_usec % 1000) >= 500)
237 f0cbd3ec bellard
           curtime++;
238 f0cbd3ec bellard
}
239 379ff53d bellard
#endif
240 f0cbd3ec bellard
241 5fafdf24 ths
void slirp_select_fill(int *pnfds,
242 f0cbd3ec bellard
                       fd_set *readfds, fd_set *writefds, fd_set *xfds)
243 f0cbd3ec bellard
{
244 f0cbd3ec bellard
    struct socket *so, *so_next;
245 f0cbd3ec bellard
    struct timeval timeout;
246 f0cbd3ec bellard
    int nfds;
247 f0cbd3ec bellard
    int tmp_time;
248 f0cbd3ec bellard
249 f0cbd3ec bellard
    /* fail safe */
250 f0cbd3ec bellard
    global_readfds = NULL;
251 f0cbd3ec bellard
    global_writefds = NULL;
252 f0cbd3ec bellard
    global_xfds = NULL;
253 3b46e624 ths
254 f0cbd3ec bellard
    nfds = *pnfds;
255 f0cbd3ec bellard
        /*
256 f0cbd3ec bellard
         * First, TCP sockets
257 f0cbd3ec bellard
         */
258 f0cbd3ec bellard
        do_slowtimo = 0;
259 f0cbd3ec bellard
        if (link_up) {
260 5fafdf24 ths
                /*
261 f0cbd3ec bellard
                 * *_slowtimo needs calling if there are IP fragments
262 f0cbd3ec bellard
                 * in the fragment queue, or there are TCP connections active
263 f0cbd3ec bellard
                 */
264 f0cbd3ec bellard
                do_slowtimo = ((tcb.so_next != &tcb) ||
265 429d0a3d blueswir1
                (&ipq.ip_link != ipq.ip_link.next));
266 3b46e624 ths
267 f0cbd3ec bellard
                for (so = tcb.so_next; so != &tcb; so = so_next) {
268 f0cbd3ec bellard
                        so_next = so->so_next;
269 3b46e624 ths
270 f0cbd3ec bellard
                        /*
271 f0cbd3ec bellard
                         * See if we need a tcp_fasttimo
272 f0cbd3ec bellard
                         */
273 f0cbd3ec bellard
                        if (time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK)
274 f0cbd3ec bellard
                           time_fasttimo = curtime; /* Flag when we want a fasttimo */
275 3b46e624 ths
276 f0cbd3ec bellard
                        /*
277 f0cbd3ec bellard
                         * NOFDREF can include still connecting to local-host,
278 f0cbd3ec bellard
                         * newly socreated() sockets etc. Don't want to select these.
279 f0cbd3ec bellard
                          */
280 f0cbd3ec bellard
                        if (so->so_state & SS_NOFDREF || so->s == -1)
281 f0cbd3ec bellard
                           continue;
282 3b46e624 ths
283 f0cbd3ec bellard
                        /*
284 f0cbd3ec bellard
                         * Set for reading sockets which are accepting
285 f0cbd3ec bellard
                         */
286 f0cbd3ec bellard
                        if (so->so_state & SS_FACCEPTCONN) {
287 f0cbd3ec bellard
                                FD_SET(so->s, readfds);
288 f0cbd3ec bellard
                                UPD_NFDS(so->s);
289 f0cbd3ec bellard
                                continue;
290 f0cbd3ec bellard
                        }
291 3b46e624 ths
292 f0cbd3ec bellard
                        /*
293 f0cbd3ec bellard
                         * Set for writing sockets which are connecting
294 f0cbd3ec bellard
                         */
295 f0cbd3ec bellard
                        if (so->so_state & SS_ISFCONNECTING) {
296 f0cbd3ec bellard
                                FD_SET(so->s, writefds);
297 f0cbd3ec bellard
                                UPD_NFDS(so->s);
298 f0cbd3ec bellard
                                continue;
299 f0cbd3ec bellard
                        }
300 3b46e624 ths
301 f0cbd3ec bellard
                        /*
302 f0cbd3ec bellard
                         * Set for writing if we are connected, can send more, and
303 f0cbd3ec bellard
                         * we have something to send
304 f0cbd3ec bellard
                         */
305 f0cbd3ec bellard
                        if (CONN_CANFSEND(so) && so->so_rcv.sb_cc) {
306 f0cbd3ec bellard
                                FD_SET(so->s, writefds);
307 f0cbd3ec bellard
                                UPD_NFDS(so->s);
308 f0cbd3ec bellard
                        }
309 3b46e624 ths
310 f0cbd3ec bellard
                        /*
311 f0cbd3ec bellard
                         * Set for reading (and urgent data) if we are connected, can
312 f0cbd3ec bellard
                         * receive more, and we have room for it XXX /2 ?
313 f0cbd3ec bellard
                         */
314 f0cbd3ec bellard
                        if (CONN_CANFRCV(so) && (so->so_snd.sb_cc < (so->so_snd.sb_datalen/2))) {
315 f0cbd3ec bellard
                                FD_SET(so->s, readfds);
316 f0cbd3ec bellard
                                FD_SET(so->s, xfds);
317 f0cbd3ec bellard
                                UPD_NFDS(so->s);
318 f0cbd3ec bellard
                        }
319 f0cbd3ec bellard
                }
320 3b46e624 ths
321 f0cbd3ec bellard
                /*
322 f0cbd3ec bellard
                 * UDP sockets
323 f0cbd3ec bellard
                 */
324 f0cbd3ec bellard
                for (so = udb.so_next; so != &udb; so = so_next) {
325 f0cbd3ec bellard
                        so_next = so->so_next;
326 3b46e624 ths
327 f0cbd3ec bellard
                        /*
328 f0cbd3ec bellard
                         * See if it's timed out
329 f0cbd3ec bellard
                         */
330 f0cbd3ec bellard
                        if (so->so_expire) {
331 f0cbd3ec bellard
                                if (so->so_expire <= curtime) {
332 f0cbd3ec bellard
                                        udp_detach(so);
333 f0cbd3ec bellard
                                        continue;
334 f0cbd3ec bellard
                                } else
335 f0cbd3ec bellard
                                        do_slowtimo = 1; /* Let socket expire */
336 f0cbd3ec bellard
                        }
337 3b46e624 ths
338 f0cbd3ec bellard
                        /*
339 f0cbd3ec bellard
                         * When UDP packets are received from over the
340 f0cbd3ec bellard
                         * link, they're sendto()'d straight away, so
341 f0cbd3ec bellard
                         * no need for setting for writing
342 f0cbd3ec bellard
                         * Limit the number of packets queued by this session
343 f0cbd3ec bellard
                         * to 4.  Note that even though we try and limit this
344 f0cbd3ec bellard
                         * to 4 packets, the session could have more queued
345 f0cbd3ec bellard
                         * if the packets needed to be fragmented
346 f0cbd3ec bellard
                         * (XXX <= 4 ?)
347 f0cbd3ec bellard
                         */
348 f0cbd3ec bellard
                        if ((so->so_state & SS_ISFCONNECTED) && so->so_queued <= 4) {
349 f0cbd3ec bellard
                                FD_SET(so->s, readfds);
350 f0cbd3ec bellard
                                UPD_NFDS(so->s);
351 f0cbd3ec bellard
                        }
352 f0cbd3ec bellard
                }
353 f0cbd3ec bellard
        }
354 5fafdf24 ths
355 f0cbd3ec bellard
        /*
356 f0cbd3ec bellard
         * Setup timeout to use minimum CPU usage, especially when idle
357 f0cbd3ec bellard
         */
358 5fafdf24 ths
359 5fafdf24 ths
        /*
360 f0cbd3ec bellard
         * First, see the timeout needed by *timo
361 f0cbd3ec bellard
         */
362 f0cbd3ec bellard
        timeout.tv_sec = 0;
363 f0cbd3ec bellard
        timeout.tv_usec = -1;
364 f0cbd3ec bellard
        /*
365 f0cbd3ec bellard
         * If a slowtimo is needed, set timeout to 500ms from the last
366 f0cbd3ec bellard
         * slow timeout. If a fast timeout is needed, set timeout within
367 f0cbd3ec bellard
         * 200ms of when it was requested.
368 f0cbd3ec bellard
         */
369 f0cbd3ec bellard
        if (do_slowtimo) {
370 f0cbd3ec bellard
                /* XXX + 10000 because some select()'s aren't that accurate */
371 f0cbd3ec bellard
                timeout.tv_usec = ((500 - (curtime - last_slowtimo)) * 1000) + 10000;
372 f0cbd3ec bellard
                if (timeout.tv_usec < 0)
373 f0cbd3ec bellard
                   timeout.tv_usec = 0;
374 f0cbd3ec bellard
                else if (timeout.tv_usec > 510000)
375 f0cbd3ec bellard
                   timeout.tv_usec = 510000;
376 3b46e624 ths
377 f0cbd3ec bellard
                /* Can only fasttimo if we also slowtimo */
378 f0cbd3ec bellard
                if (time_fasttimo) {
379 f0cbd3ec bellard
                        tmp_time = (200 - (curtime - time_fasttimo)) * 1000;
380 f0cbd3ec bellard
                        if (tmp_time < 0)
381 f0cbd3ec bellard
                           tmp_time = 0;
382 3b46e624 ths
383 f0cbd3ec bellard
                        /* Choose the smallest of the 2 */
384 f0cbd3ec bellard
                        if (tmp_time < timeout.tv_usec)
385 f0cbd3ec bellard
                           timeout.tv_usec = (u_int)tmp_time;
386 f0cbd3ec bellard
                }
387 f0cbd3ec bellard
        }
388 f0cbd3ec bellard
        *pnfds = nfds;
389 5fafdf24 ths
}
390 f0cbd3ec bellard
391 f0cbd3ec bellard
void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
392 f0cbd3ec bellard
{
393 f0cbd3ec bellard
    struct socket *so, *so_next;
394 f0cbd3ec bellard
    int ret;
395 f0cbd3ec bellard
396 f0cbd3ec bellard
    global_readfds = readfds;
397 f0cbd3ec bellard
    global_writefds = writefds;
398 f0cbd3ec bellard
    global_xfds = xfds;
399 f0cbd3ec bellard
400 f0cbd3ec bellard
        /* Update time */
401 f0cbd3ec bellard
        updtime();
402 5fafdf24 ths
403 f0cbd3ec bellard
        /*
404 5fafdf24 ths
         * See if anything has timed out
405 f0cbd3ec bellard
         */
406 f0cbd3ec bellard
        if (link_up) {
407 df5f8956 bellard
                if (time_fasttimo && ((curtime - time_fasttimo) >= 2)) {
408 f0cbd3ec bellard
                        tcp_fasttimo();
409 f0cbd3ec bellard
                        time_fasttimo = 0;
410 f0cbd3ec bellard
                }
411 f0cbd3ec bellard
                if (do_slowtimo && ((curtime - last_slowtimo) >= 499)) {
412 f0cbd3ec bellard
                        ip_slowtimo();
413 f0cbd3ec bellard
                        tcp_slowtimo();
414 f0cbd3ec bellard
                        last_slowtimo = curtime;
415 f0cbd3ec bellard
                }
416 f0cbd3ec bellard
        }
417 5fafdf24 ths
418 f0cbd3ec bellard
        /*
419 f0cbd3ec bellard
         * Check sockets
420 f0cbd3ec bellard
         */
421 f0cbd3ec bellard
        if (link_up) {
422 f0cbd3ec bellard
                /*
423 f0cbd3ec bellard
                 * Check TCP sockets
424 f0cbd3ec bellard
                 */
425 f0cbd3ec bellard
                for (so = tcb.so_next; so != &tcb; so = so_next) {
426 f0cbd3ec bellard
                        so_next = so->so_next;
427 3b46e624 ths
428 f0cbd3ec bellard
                        /*
429 f0cbd3ec bellard
                         * FD_ISSET is meaningless on these sockets
430 f0cbd3ec bellard
                         * (and they can crash the program)
431 f0cbd3ec bellard
                         */
432 f0cbd3ec bellard
                        if (so->so_state & SS_NOFDREF || so->s == -1)
433 f0cbd3ec bellard
                           continue;
434 3b46e624 ths
435 f0cbd3ec bellard
                        /*
436 f0cbd3ec bellard
                         * Check for URG data
437 f0cbd3ec bellard
                         * This will soread as well, so no need to
438 f0cbd3ec bellard
                         * test for readfds below if this succeeds
439 f0cbd3ec bellard
                         */
440 f0cbd3ec bellard
                        if (FD_ISSET(so->s, xfds))
441 f0cbd3ec bellard
                           sorecvoob(so);
442 f0cbd3ec bellard
                        /*
443 f0cbd3ec bellard
                         * Check sockets for reading
444 f0cbd3ec bellard
                         */
445 f0cbd3ec bellard
                        else if (FD_ISSET(so->s, readfds)) {
446 f0cbd3ec bellard
                                /*
447 f0cbd3ec bellard
                                 * Check for incoming connections
448 f0cbd3ec bellard
                                 */
449 f0cbd3ec bellard
                                if (so->so_state & SS_FACCEPTCONN) {
450 f0cbd3ec bellard
                                        tcp_connect(so);
451 f0cbd3ec bellard
                                        continue;
452 f0cbd3ec bellard
                                } /* else */
453 f0cbd3ec bellard
                                ret = soread(so);
454 3b46e624 ths
455 f0cbd3ec bellard
                                /* Output it if we read something */
456 f0cbd3ec bellard
                                if (ret > 0)
457 f0cbd3ec bellard
                                   tcp_output(sototcpcb(so));
458 f0cbd3ec bellard
                        }
459 3b46e624 ths
460 f0cbd3ec bellard
                        /*
461 f0cbd3ec bellard
                         * Check sockets for writing
462 f0cbd3ec bellard
                         */
463 f0cbd3ec bellard
                        if (FD_ISSET(so->s, writefds)) {
464 f0cbd3ec bellard
                          /*
465 f0cbd3ec bellard
                           * Check for non-blocking, still-connecting sockets
466 f0cbd3ec bellard
                           */
467 f0cbd3ec bellard
                          if (so->so_state & SS_ISFCONNECTING) {
468 f0cbd3ec bellard
                            /* Connected */
469 f0cbd3ec bellard
                            so->so_state &= ~SS_ISFCONNECTING;
470 3b46e624 ths
471 02d2c54c bellard
                            ret = send(so->s, &ret, 0, 0);
472 f0cbd3ec bellard
                            if (ret < 0) {
473 f0cbd3ec bellard
                              /* XXXXX Must fix, zero bytes is a NOP */
474 f0cbd3ec bellard
                              if (errno == EAGAIN || errno == EWOULDBLOCK ||
475 f0cbd3ec bellard
                                  errno == EINPROGRESS || errno == ENOTCONN)
476 f0cbd3ec bellard
                                continue;
477 3b46e624 ths
478 f0cbd3ec bellard
                              /* else failed */
479 f0cbd3ec bellard
                              so->so_state = SS_NOFDREF;
480 f0cbd3ec bellard
                            }
481 f0cbd3ec bellard
                            /* else so->so_state &= ~SS_ISFCONNECTING; */
482 3b46e624 ths
483 f0cbd3ec bellard
                            /*
484 f0cbd3ec bellard
                             * Continue tcp_input
485 f0cbd3ec bellard
                             */
486 f0cbd3ec bellard
                            tcp_input((struct mbuf *)NULL, sizeof(struct ip), so);
487 f0cbd3ec bellard
                            /* continue; */
488 f0cbd3ec bellard
                          } else
489 f0cbd3ec bellard
                            ret = sowrite(so);
490 f0cbd3ec bellard
                          /*
491 5fafdf24 ths
                           * XXXXX If we wrote something (a lot), there
492 f0cbd3ec bellard
                           * could be a need for a window update.
493 f0cbd3ec bellard
                           * In the worst case, the remote will send
494 f0cbd3ec bellard
                           * a window probe to get things going again
495 f0cbd3ec bellard
                           */
496 f0cbd3ec bellard
                        }
497 3b46e624 ths
498 f0cbd3ec bellard
                        /*
499 f0cbd3ec bellard
                         * Probe a still-connecting, non-blocking socket
500 f0cbd3ec bellard
                         * to check if it's still alive
501 f0cbd3ec bellard
                           */
502 f0cbd3ec bellard
#ifdef PROBE_CONN
503 f0cbd3ec bellard
                        if (so->so_state & SS_ISFCONNECTING) {
504 02d2c54c bellard
                          ret = recv(so->s, (char *)&ret, 0,0);
505 3b46e624 ths
506 f0cbd3ec bellard
                          if (ret < 0) {
507 f0cbd3ec bellard
                            /* XXX */
508 f0cbd3ec bellard
                            if (errno == EAGAIN || errno == EWOULDBLOCK ||
509 f0cbd3ec bellard
                                errno == EINPROGRESS || errno == ENOTCONN)
510 f0cbd3ec bellard
                              continue; /* Still connecting, continue */
511 3b46e624 ths
512 f0cbd3ec bellard
                            /* else failed */
513 f0cbd3ec bellard
                            so->so_state = SS_NOFDREF;
514 3b46e624 ths
515 f0cbd3ec bellard
                            /* tcp_input will take care of it */
516 f0cbd3ec bellard
                          } else {
517 02d2c54c bellard
                            ret = send(so->s, &ret, 0,0);
518 f0cbd3ec bellard
                            if (ret < 0) {
519 f0cbd3ec bellard
                              /* XXX */
520 f0cbd3ec bellard
                              if (errno == EAGAIN || errno == EWOULDBLOCK ||
521 f0cbd3ec bellard
                                  errno == EINPROGRESS || errno == ENOTCONN)
522 f0cbd3ec bellard
                                continue;
523 f0cbd3ec bellard
                              /* else failed */
524 f0cbd3ec bellard
                              so->so_state = SS_NOFDREF;
525 f0cbd3ec bellard
                            } else
526 f0cbd3ec bellard
                              so->so_state &= ~SS_ISFCONNECTING;
527 3b46e624 ths
528 f0cbd3ec bellard
                          }
529 f0cbd3ec bellard
                          tcp_input((struct mbuf *)NULL, sizeof(struct ip),so);
530 f0cbd3ec bellard
                        } /* SS_ISFCONNECTING */
531 f0cbd3ec bellard
#endif
532 f0cbd3ec bellard
                }
533 3b46e624 ths
534 f0cbd3ec bellard
                /*
535 f0cbd3ec bellard
                 * Now UDP sockets.
536 f0cbd3ec bellard
                 * Incoming packets are sent straight away, they're not buffered.
537 f0cbd3ec bellard
                 * Incoming UDP data isn't buffered either.
538 f0cbd3ec bellard
                 */
539 f0cbd3ec bellard
                for (so = udb.so_next; so != &udb; so = so_next) {
540 f0cbd3ec bellard
                        so_next = so->so_next;
541 3b46e624 ths
542 f0cbd3ec bellard
                        if (so->s != -1 && FD_ISSET(so->s, readfds)) {
543 f0cbd3ec bellard
                            sorecvfrom(so);
544 f0cbd3ec bellard
                        }
545 f0cbd3ec bellard
                }
546 f0cbd3ec bellard
        }
547 5fafdf24 ths
548 f0cbd3ec bellard
        /*
549 f0cbd3ec bellard
         * See if we can start outputting
550 f0cbd3ec bellard
         */
551 f0cbd3ec bellard
        if (if_queued && link_up)
552 f0cbd3ec bellard
           if_start();
553 02d2c54c bellard
554 02d2c54c bellard
        /* clear global file descriptor sets.
555 02d2c54c bellard
         * these reside on the stack in vl.c
556 02d2c54c bellard
         * so they're unusable if we're not in
557 02d2c54c bellard
         * slirp_select_fill or slirp_select_poll.
558 02d2c54c bellard
         */
559 02d2c54c bellard
         global_readfds = NULL;
560 02d2c54c bellard
         global_writefds = NULL;
561 02d2c54c bellard
         global_xfds = NULL;
562 f0cbd3ec bellard
}
563 f0cbd3ec bellard
564 f0cbd3ec bellard
#define ETH_ALEN 6
565 f0cbd3ec bellard
#define ETH_HLEN 14
566 f0cbd3ec bellard
567 f0cbd3ec bellard
#define ETH_P_IP        0x0800                /* Internet Protocol packet        */
568 f0cbd3ec bellard
#define ETH_P_ARP        0x0806                /* Address Resolution packet        */
569 f0cbd3ec bellard
570 f0cbd3ec bellard
#define        ARPOP_REQUEST        1                /* ARP request                        */
571 f0cbd3ec bellard
#define        ARPOP_REPLY        2                /* ARP reply                        */
572 f0cbd3ec bellard
573 5fafdf24 ths
struct ethhdr
574 f0cbd3ec bellard
{
575 f0cbd3ec bellard
        unsigned char        h_dest[ETH_ALEN];        /* destination eth addr        */
576 f0cbd3ec bellard
        unsigned char        h_source[ETH_ALEN];        /* source ether addr        */
577 f0cbd3ec bellard
        unsigned short        h_proto;                /* packet type ID field        */
578 f0cbd3ec bellard
};
579 f0cbd3ec bellard
580 f0cbd3ec bellard
struct arphdr
581 f0cbd3ec bellard
{
582 f0cbd3ec bellard
        unsigned short        ar_hrd;                /* format of hardware address        */
583 f0cbd3ec bellard
        unsigned short        ar_pro;                /* format of protocol address        */
584 f0cbd3ec bellard
        unsigned char        ar_hln;                /* length of hardware address        */
585 f0cbd3ec bellard
        unsigned char        ar_pln;                /* length of protocol address        */
586 f0cbd3ec bellard
        unsigned short        ar_op;                /* ARP opcode (command)                */
587 f0cbd3ec bellard
588 f0cbd3ec bellard
         /*
589 f0cbd3ec bellard
          *         Ethernet looks like this : This bit is variable sized however...
590 f0cbd3ec bellard
          */
591 f0cbd3ec bellard
        unsigned char                ar_sha[ETH_ALEN];        /* sender hardware address        */
592 f0cbd3ec bellard
        unsigned char                ar_sip[4];                /* sender IP address                */
593 f0cbd3ec bellard
        unsigned char                ar_tha[ETH_ALEN];        /* target hardware address        */
594 f0cbd3ec bellard
        unsigned char                ar_tip[4];                /* target IP address                */
595 f0cbd3ec bellard
};
596 f0cbd3ec bellard
597 8fcd3692 blueswir1
static void arp_input(const uint8_t *pkt, int pkt_len)
598 f0cbd3ec bellard
{
599 f0cbd3ec bellard
    struct ethhdr *eh = (struct ethhdr *)pkt;
600 f0cbd3ec bellard
    struct arphdr *ah = (struct arphdr *)(pkt + ETH_HLEN);
601 f0cbd3ec bellard
    uint8_t arp_reply[ETH_HLEN + sizeof(struct arphdr)];
602 f0cbd3ec bellard
    struct ethhdr *reh = (struct ethhdr *)arp_reply;
603 f0cbd3ec bellard
    struct arphdr *rah = (struct arphdr *)(arp_reply + ETH_HLEN);
604 f0cbd3ec bellard
    int ar_op;
605 a3d4af03 bellard
    struct ex_list *ex_ptr;
606 f0cbd3ec bellard
607 f0cbd3ec bellard
    ar_op = ntohs(ah->ar_op);
608 f0cbd3ec bellard
    switch(ar_op) {
609 f0cbd3ec bellard
    case ARPOP_REQUEST:
610 a3d4af03 bellard
        if (!memcmp(ah->ar_tip, &special_addr, 3)) {
611 5fafdf24 ths
            if (ah->ar_tip[3] == CTL_DNS || ah->ar_tip[3] == CTL_ALIAS)
612 a3d4af03 bellard
                goto arp_ok;
613 a3d4af03 bellard
            for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
614 a3d4af03 bellard
                if (ex_ptr->ex_addr == ah->ar_tip[3])
615 a3d4af03 bellard
                    goto arp_ok;
616 a3d4af03 bellard
            }
617 a3d4af03 bellard
            return;
618 a3d4af03 bellard
        arp_ok:
619 f0cbd3ec bellard
            /* XXX: make an ARP request to have the client address */
620 f0cbd3ec bellard
            memcpy(client_ethaddr, eh->h_source, ETH_ALEN);
621 f0cbd3ec bellard
622 f0cbd3ec bellard
            /* ARP request for alias/dns mac address */
623 f0cbd3ec bellard
            memcpy(reh->h_dest, pkt + ETH_ALEN, ETH_ALEN);
624 f0cbd3ec bellard
            memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 1);
625 f0cbd3ec bellard
            reh->h_source[5] = ah->ar_tip[3];
626 f0cbd3ec bellard
            reh->h_proto = htons(ETH_P_ARP);
627 f0cbd3ec bellard
628 f0cbd3ec bellard
            rah->ar_hrd = htons(1);
629 f0cbd3ec bellard
            rah->ar_pro = htons(ETH_P_IP);
630 f0cbd3ec bellard
            rah->ar_hln = ETH_ALEN;
631 f0cbd3ec bellard
            rah->ar_pln = 4;
632 f0cbd3ec bellard
            rah->ar_op = htons(ARPOP_REPLY);
633 f0cbd3ec bellard
            memcpy(rah->ar_sha, reh->h_source, ETH_ALEN);
634 f0cbd3ec bellard
            memcpy(rah->ar_sip, ah->ar_tip, 4);
635 f0cbd3ec bellard
            memcpy(rah->ar_tha, ah->ar_sha, ETH_ALEN);
636 f0cbd3ec bellard
            memcpy(rah->ar_tip, ah->ar_sip, 4);
637 f0cbd3ec bellard
            slirp_output(arp_reply, sizeof(arp_reply));
638 f0cbd3ec bellard
        }
639 f0cbd3ec bellard
        break;
640 de806f07 bellard
    case ARPOP_REPLY:
641 de806f07 bellard
        /* reply to request of client mac address ? */
642 de806f07 bellard
        if (!memcmp(client_ethaddr, zero_ethaddr, ETH_ALEN) &&
643 de806f07 bellard
            !memcmp(ah->ar_sip, &client_ipaddr.s_addr, 4)) {
644 de806f07 bellard
            memcpy(client_ethaddr, ah->ar_sha, ETH_ALEN);
645 de806f07 bellard
        }
646 de806f07 bellard
        break;
647 f0cbd3ec bellard
    default:
648 f0cbd3ec bellard
        break;
649 f0cbd3ec bellard
    }
650 f0cbd3ec bellard
}
651 f0cbd3ec bellard
652 f0cbd3ec bellard
void slirp_input(const uint8_t *pkt, int pkt_len)
653 f0cbd3ec bellard
{
654 f0cbd3ec bellard
    struct mbuf *m;
655 f0cbd3ec bellard
    int proto;
656 f0cbd3ec bellard
657 f0cbd3ec bellard
    if (pkt_len < ETH_HLEN)
658 f0cbd3ec bellard
        return;
659 3b46e624 ths
660 f0cbd3ec bellard
    proto = ntohs(*(uint16_t *)(pkt + 12));
661 f0cbd3ec bellard
    switch(proto) {
662 f0cbd3ec bellard
    case ETH_P_ARP:
663 f0cbd3ec bellard
        arp_input(pkt, pkt_len);
664 f0cbd3ec bellard
        break;
665 f0cbd3ec bellard
    case ETH_P_IP:
666 f0cbd3ec bellard
        m = m_get();
667 f0cbd3ec bellard
        if (!m)
668 f0cbd3ec bellard
            return;
669 38f3e7c2 bellard
        /* Note: we add to align the IP header */
670 e8e880a7 aurel32
        if (M_FREEROOM(m) < pkt_len + 2) {
671 e8e880a7 aurel32
            m_inc(m, pkt_len + 2);
672 e8e880a7 aurel32
        }
673 38f3e7c2 bellard
        m->m_len = pkt_len + 2;
674 38f3e7c2 bellard
        memcpy(m->m_data + 2, pkt, pkt_len);
675 f0cbd3ec bellard
676 38f3e7c2 bellard
        m->m_data += 2 + ETH_HLEN;
677 38f3e7c2 bellard
        m->m_len -= 2 + ETH_HLEN;
678 f0cbd3ec bellard
679 f0cbd3ec bellard
        ip_input(m);
680 f0cbd3ec bellard
        break;
681 f0cbd3ec bellard
    default:
682 f0cbd3ec bellard
        break;
683 f0cbd3ec bellard
    }
684 f0cbd3ec bellard
}
685 f0cbd3ec bellard
686 f0cbd3ec bellard
/* output the IP packet to the ethernet device */
687 f0cbd3ec bellard
void if_encap(const uint8_t *ip_data, int ip_data_len)
688 f0cbd3ec bellard
{
689 f0cbd3ec bellard
    uint8_t buf[1600];
690 f0cbd3ec bellard
    struct ethhdr *eh = (struct ethhdr *)buf;
691 f0cbd3ec bellard
692 f0cbd3ec bellard
    if (ip_data_len + ETH_HLEN > sizeof(buf))
693 f0cbd3ec bellard
        return;
694 de806f07 bellard
    
695 de806f07 bellard
    if (!memcmp(client_ethaddr, zero_ethaddr, ETH_ALEN)) {
696 de806f07 bellard
        uint8_t arp_req[ETH_HLEN + sizeof(struct arphdr)];
697 de806f07 bellard
        struct ethhdr *reh = (struct ethhdr *)arp_req;
698 de806f07 bellard
        struct arphdr *rah = (struct arphdr *)(arp_req + ETH_HLEN);
699 de806f07 bellard
        const struct ip *iph = (const struct ip *)ip_data;
700 de806f07 bellard
701 de806f07 bellard
        /* If the client addr is not known, there is no point in
702 de806f07 bellard
           sending the packet to it. Normally the sender should have
703 de806f07 bellard
           done an ARP request to get its MAC address. Here we do it
704 de806f07 bellard
           in place of sending the packet and we hope that the sender
705 de806f07 bellard
           will retry sending its packet. */
706 de806f07 bellard
        memset(reh->h_dest, 0xff, ETH_ALEN);
707 de806f07 bellard
        memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 1);
708 de806f07 bellard
        reh->h_source[5] = CTL_ALIAS;
709 de806f07 bellard
        reh->h_proto = htons(ETH_P_ARP);
710 de806f07 bellard
        rah->ar_hrd = htons(1);
711 de806f07 bellard
        rah->ar_pro = htons(ETH_P_IP);
712 de806f07 bellard
        rah->ar_hln = ETH_ALEN;
713 de806f07 bellard
        rah->ar_pln = 4;
714 de806f07 bellard
        rah->ar_op = htons(ARPOP_REQUEST);
715 de806f07 bellard
        /* source hw addr */
716 de806f07 bellard
        memcpy(rah->ar_sha, special_ethaddr, ETH_ALEN - 1);
717 de806f07 bellard
        rah->ar_sha[5] = CTL_ALIAS;
718 de806f07 bellard
        /* source IP */
719 de806f07 bellard
        memcpy(rah->ar_sip, &alias_addr, 4);
720 de806f07 bellard
        /* target hw addr (none) */
721 de806f07 bellard
        memset(rah->ar_tha, 0, ETH_ALEN);
722 de806f07 bellard
        /* target IP */
723 de806f07 bellard
        memcpy(rah->ar_tip, &iph->ip_dst, 4);
724 de806f07 bellard
        client_ipaddr = iph->ip_dst;
725 de806f07 bellard
        slirp_output(arp_req, sizeof(arp_req));
726 de806f07 bellard
    } else {
727 de806f07 bellard
        memcpy(eh->h_dest, client_ethaddr, ETH_ALEN);
728 de806f07 bellard
        memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 1);
729 de806f07 bellard
        /* XXX: not correct */
730 de806f07 bellard
        eh->h_source[5] = CTL_ALIAS;
731 de806f07 bellard
        eh->h_proto = htons(ETH_P_IP);
732 de806f07 bellard
        memcpy(buf + sizeof(struct ethhdr), ip_data, ip_data_len);
733 de806f07 bellard
        slirp_output(buf, ip_data_len + ETH_HLEN);
734 de806f07 bellard
    }
735 f0cbd3ec bellard
}
736 9bf05444 bellard
737 5fafdf24 ths
int slirp_redir(int is_udp, int host_port,
738 9bf05444 bellard
                struct in_addr guest_addr, int guest_port)
739 9bf05444 bellard
{
740 9bf05444 bellard
    if (is_udp) {
741 5fafdf24 ths
        if (!udp_listen(htons(host_port), guest_addr.s_addr,
742 9bf05444 bellard
                        htons(guest_port), 0))
743 9bf05444 bellard
            return -1;
744 9bf05444 bellard
    } else {
745 5fafdf24 ths
        if (!solisten(htons(host_port), guest_addr.s_addr,
746 9bf05444 bellard
                      htons(guest_port), 0))
747 9bf05444 bellard
            return -1;
748 9bf05444 bellard
    }
749 9bf05444 bellard
    return 0;
750 9bf05444 bellard
}
751 a3d4af03 bellard
752 e1c5a2b3 aliguori
int slirp_add_exec(int do_pty, const void *args, int addr_low_byte,
753 a3d4af03 bellard
                  int guest_port)
754 a3d4af03 bellard
{
755 5fafdf24 ths
    return add_exec(&exec_list, do_pty, (char *)args,
756 a3d4af03 bellard
                    addr_low_byte, htons(guest_port));
757 a3d4af03 bellard
}
758 e1c5a2b3 aliguori
759 e1c5a2b3 aliguori
ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags)
760 e1c5a2b3 aliguori
{
761 e1c5a2b3 aliguori
        if (so->s == -1 && so->extra) {
762 e1c5a2b3 aliguori
                qemu_chr_write(so->extra, buf, len);
763 e1c5a2b3 aliguori
                return len;
764 e1c5a2b3 aliguori
        }
765 e1c5a2b3 aliguori
766 e1c5a2b3 aliguori
        return send(so->s, buf, len, flags);
767 e1c5a2b3 aliguori
}
768 e1c5a2b3 aliguori
769 e1c5a2b3 aliguori
static struct socket *slirp_find_ctl_socket(int addr_low_byte, int guest_port)
770 e1c5a2b3 aliguori
{
771 e1c5a2b3 aliguori
        struct socket *so;
772 e1c5a2b3 aliguori
773 e1c5a2b3 aliguori
        for (so = tcb.so_next; so != &tcb; so = so->so_next) {
774 e1c5a2b3 aliguori
                if ((so->so_faddr.s_addr & htonl(0xffffff00)) ==
775 e1c5a2b3 aliguori
                                special_addr.s_addr
776 e1c5a2b3 aliguori
                                && (ntohl(so->so_faddr.s_addr) & 0xff) ==
777 e1c5a2b3 aliguori
                                addr_low_byte
778 e1c5a2b3 aliguori
                                && htons(so->so_fport) == guest_port)
779 e1c5a2b3 aliguori
                        return so;
780 e1c5a2b3 aliguori
        }
781 e1c5a2b3 aliguori
782 e1c5a2b3 aliguori
        return NULL;
783 e1c5a2b3 aliguori
}
784 e1c5a2b3 aliguori
785 e1c5a2b3 aliguori
size_t slirp_socket_can_recv(int addr_low_byte, int guest_port)
786 e1c5a2b3 aliguori
{
787 e1c5a2b3 aliguori
        struct iovec iov[2];
788 e1c5a2b3 aliguori
        struct socket *so;
789 e1c5a2b3 aliguori
790 e1c5a2b3 aliguori
    if (!link_up)
791 e1c5a2b3 aliguori
        return 0;
792 e1c5a2b3 aliguori
793 e1c5a2b3 aliguori
        so = slirp_find_ctl_socket(addr_low_byte, guest_port);
794 e1c5a2b3 aliguori
795 e1c5a2b3 aliguori
        if (!so || so->so_state & SS_NOFDREF)
796 e1c5a2b3 aliguori
                return 0;
797 e1c5a2b3 aliguori
798 e1c5a2b3 aliguori
        if (!CONN_CANFRCV(so) || so->so_snd.sb_cc >= (so->so_snd.sb_datalen/2))
799 e1c5a2b3 aliguori
                return 0;
800 e1c5a2b3 aliguori
801 e1c5a2b3 aliguori
        return sopreprbuf(so, iov, NULL);
802 e1c5a2b3 aliguori
}
803 e1c5a2b3 aliguori
804 e1c5a2b3 aliguori
void slirp_socket_recv(int addr_low_byte, int guest_port, const uint8_t *buf,
805 e1c5a2b3 aliguori
        int size)
806 e1c5a2b3 aliguori
{
807 e1c5a2b3 aliguori
    int ret;
808 e1c5a2b3 aliguori
    struct socket *so = slirp_find_ctl_socket(addr_low_byte, guest_port);
809 e1c5a2b3 aliguori
   
810 e1c5a2b3 aliguori
    if (!so)
811 e1c5a2b3 aliguori
        return;
812 e1c5a2b3 aliguori
813 0580ac91 blueswir1
    ret = soreadbuf(so, (const char *)buf, size);
814 e1c5a2b3 aliguori
815 e1c5a2b3 aliguori
    if (ret > 0)
816 e1c5a2b3 aliguori
        tcp_output(sototcpcb(so));
817 e1c5a2b3 aliguori
}
818 062e5527 aliguori
819 062e5527 aliguori
static void slirp_tcp_save(QEMUFile *f, struct tcpcb *tp)
820 062e5527 aliguori
{
821 062e5527 aliguori
    int i;
822 062e5527 aliguori
823 062e5527 aliguori
    qemu_put_sbe16(f, tp->t_state);
824 062e5527 aliguori
    for (i = 0; i < TCPT_NTIMERS; i++)
825 062e5527 aliguori
        qemu_put_sbe16(f, tp->t_timer[i]);
826 062e5527 aliguori
    qemu_put_sbe16(f, tp->t_rxtshift);
827 062e5527 aliguori
    qemu_put_sbe16(f, tp->t_rxtcur);
828 062e5527 aliguori
    qemu_put_sbe16(f, tp->t_dupacks);
829 062e5527 aliguori
    qemu_put_be16(f, tp->t_maxseg);
830 062e5527 aliguori
    qemu_put_sbyte(f, tp->t_force);
831 062e5527 aliguori
    qemu_put_be16(f, tp->t_flags);
832 062e5527 aliguori
    qemu_put_be32(f, tp->snd_una);
833 062e5527 aliguori
    qemu_put_be32(f, tp->snd_nxt);
834 062e5527 aliguori
    qemu_put_be32(f, tp->snd_up);
835 062e5527 aliguori
    qemu_put_be32(f, tp->snd_wl1);
836 062e5527 aliguori
    qemu_put_be32(f, tp->snd_wl2);
837 062e5527 aliguori
    qemu_put_be32(f, tp->iss);
838 062e5527 aliguori
    qemu_put_be32(f, tp->snd_wnd);
839 062e5527 aliguori
    qemu_put_be32(f, tp->rcv_wnd);
840 062e5527 aliguori
    qemu_put_be32(f, tp->rcv_nxt);
841 062e5527 aliguori
    qemu_put_be32(f, tp->rcv_up);
842 062e5527 aliguori
    qemu_put_be32(f, tp->irs);
843 062e5527 aliguori
    qemu_put_be32(f, tp->rcv_adv);
844 062e5527 aliguori
    qemu_put_be32(f, tp->snd_max);
845 062e5527 aliguori
    qemu_put_be32(f, tp->snd_cwnd);
846 062e5527 aliguori
    qemu_put_be32(f, tp->snd_ssthresh);
847 062e5527 aliguori
    qemu_put_sbe16(f, tp->t_idle);
848 062e5527 aliguori
    qemu_put_sbe16(f, tp->t_rtt);
849 062e5527 aliguori
    qemu_put_be32(f, tp->t_rtseq);
850 062e5527 aliguori
    qemu_put_sbe16(f, tp->t_srtt);
851 062e5527 aliguori
    qemu_put_sbe16(f, tp->t_rttvar);
852 062e5527 aliguori
    qemu_put_be16(f, tp->t_rttmin);
853 062e5527 aliguori
    qemu_put_be32(f, tp->max_sndwnd);
854 062e5527 aliguori
    qemu_put_byte(f, tp->t_oobflags);
855 062e5527 aliguori
    qemu_put_byte(f, tp->t_iobc);
856 062e5527 aliguori
    qemu_put_sbe16(f, tp->t_softerror);
857 062e5527 aliguori
    qemu_put_byte(f, tp->snd_scale);
858 062e5527 aliguori
    qemu_put_byte(f, tp->rcv_scale);
859 062e5527 aliguori
    qemu_put_byte(f, tp->request_r_scale);
860 062e5527 aliguori
    qemu_put_byte(f, tp->requested_s_scale);
861 062e5527 aliguori
    qemu_put_be32(f, tp->ts_recent);
862 062e5527 aliguori
    qemu_put_be32(f, tp->ts_recent_age);
863 062e5527 aliguori
    qemu_put_be32(f, tp->last_ack_sent);
864 062e5527 aliguori
}
865 062e5527 aliguori
866 062e5527 aliguori
static void slirp_sbuf_save(QEMUFile *f, struct sbuf *sbuf)
867 062e5527 aliguori
{
868 062e5527 aliguori
    uint32_t off;
869 062e5527 aliguori
870 062e5527 aliguori
    qemu_put_be32(f, sbuf->sb_cc);
871 062e5527 aliguori
    qemu_put_be32(f, sbuf->sb_datalen);
872 062e5527 aliguori
    off = (uint32_t)(sbuf->sb_wptr - sbuf->sb_data);
873 062e5527 aliguori
    qemu_put_sbe32(f, off);
874 062e5527 aliguori
    off = (uint32_t)(sbuf->sb_rptr - sbuf->sb_data);
875 062e5527 aliguori
    qemu_put_sbe32(f, off);
876 062e5527 aliguori
    qemu_put_buffer(f, (unsigned char*)sbuf->sb_data, sbuf->sb_datalen);
877 062e5527 aliguori
}
878 062e5527 aliguori
879 062e5527 aliguori
static void slirp_socket_save(QEMUFile *f, struct socket *so)
880 062e5527 aliguori
{
881 062e5527 aliguori
    qemu_put_be32(f, so->so_urgc);
882 062e5527 aliguori
    qemu_put_be32(f, so->so_faddr.s_addr);
883 062e5527 aliguori
    qemu_put_be32(f, so->so_laddr.s_addr);
884 062e5527 aliguori
    qemu_put_be16(f, so->so_fport);
885 062e5527 aliguori
    qemu_put_be16(f, so->so_lport);
886 062e5527 aliguori
    qemu_put_byte(f, so->so_iptos);
887 062e5527 aliguori
    qemu_put_byte(f, so->so_emu);
888 062e5527 aliguori
    qemu_put_byte(f, so->so_type);
889 062e5527 aliguori
    qemu_put_be32(f, so->so_state);
890 062e5527 aliguori
    slirp_sbuf_save(f, &so->so_rcv);
891 062e5527 aliguori
    slirp_sbuf_save(f, &so->so_snd);
892 062e5527 aliguori
    slirp_tcp_save(f, so->so_tcpcb);
893 062e5527 aliguori
}
894 062e5527 aliguori
895 062e5527 aliguori
static void slirp_state_save(QEMUFile *f, void *opaque)
896 062e5527 aliguori
{
897 062e5527 aliguori
    struct ex_list *ex_ptr;
898 062e5527 aliguori
899 062e5527 aliguori
    for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next)
900 062e5527 aliguori
        if (ex_ptr->ex_pty == 3) {
901 062e5527 aliguori
            struct socket *so;
902 062e5527 aliguori
            so = slirp_find_ctl_socket(ex_ptr->ex_addr, ntohs(ex_ptr->ex_fport));
903 062e5527 aliguori
            if (!so)
904 062e5527 aliguori
                continue;
905 062e5527 aliguori
906 062e5527 aliguori
            qemu_put_byte(f, 42);
907 062e5527 aliguori
            slirp_socket_save(f, so);
908 062e5527 aliguori
        }
909 062e5527 aliguori
    qemu_put_byte(f, 0);
910 062e5527 aliguori
}
911 062e5527 aliguori
912 062e5527 aliguori
static void slirp_tcp_load(QEMUFile *f, struct tcpcb *tp)
913 062e5527 aliguori
{
914 062e5527 aliguori
    int i;
915 062e5527 aliguori
916 062e5527 aliguori
    tp->t_state = qemu_get_sbe16(f);
917 062e5527 aliguori
    for (i = 0; i < TCPT_NTIMERS; i++)
918 062e5527 aliguori
        tp->t_timer[i] = qemu_get_sbe16(f);
919 062e5527 aliguori
    tp->t_rxtshift = qemu_get_sbe16(f);
920 062e5527 aliguori
    tp->t_rxtcur = qemu_get_sbe16(f);
921 062e5527 aliguori
    tp->t_dupacks = qemu_get_sbe16(f);
922 062e5527 aliguori
    tp->t_maxseg = qemu_get_be16(f);
923 062e5527 aliguori
    tp->t_force = qemu_get_sbyte(f);
924 062e5527 aliguori
    tp->t_flags = qemu_get_be16(f);
925 062e5527 aliguori
    tp->snd_una = qemu_get_be32(f);
926 062e5527 aliguori
    tp->snd_nxt = qemu_get_be32(f);
927 062e5527 aliguori
    tp->snd_up = qemu_get_be32(f);
928 062e5527 aliguori
    tp->snd_wl1 = qemu_get_be32(f);
929 062e5527 aliguori
    tp->snd_wl2 = qemu_get_be32(f);
930 062e5527 aliguori
    tp->iss = qemu_get_be32(f);
931 062e5527 aliguori
    tp->snd_wnd = qemu_get_be32(f);
932 062e5527 aliguori
    tp->rcv_wnd = qemu_get_be32(f);
933 062e5527 aliguori
    tp->rcv_nxt = qemu_get_be32(f);
934 062e5527 aliguori
    tp->rcv_up = qemu_get_be32(f);
935 062e5527 aliguori
    tp->irs = qemu_get_be32(f);
936 062e5527 aliguori
    tp->rcv_adv = qemu_get_be32(f);
937 062e5527 aliguori
    tp->snd_max = qemu_get_be32(f);
938 062e5527 aliguori
    tp->snd_cwnd = qemu_get_be32(f);
939 062e5527 aliguori
    tp->snd_ssthresh = qemu_get_be32(f);
940 062e5527 aliguori
    tp->t_idle = qemu_get_sbe16(f);
941 062e5527 aliguori
    tp->t_rtt = qemu_get_sbe16(f);
942 062e5527 aliguori
    tp->t_rtseq = qemu_get_be32(f);
943 062e5527 aliguori
    tp->t_srtt = qemu_get_sbe16(f);
944 062e5527 aliguori
    tp->t_rttvar = qemu_get_sbe16(f);
945 062e5527 aliguori
    tp->t_rttmin = qemu_get_be16(f);
946 062e5527 aliguori
    tp->max_sndwnd = qemu_get_be32(f);
947 062e5527 aliguori
    tp->t_oobflags = qemu_get_byte(f);
948 062e5527 aliguori
    tp->t_iobc = qemu_get_byte(f);
949 062e5527 aliguori
    tp->t_softerror = qemu_get_sbe16(f);
950 062e5527 aliguori
    tp->snd_scale = qemu_get_byte(f);
951 062e5527 aliguori
    tp->rcv_scale = qemu_get_byte(f);
952 062e5527 aliguori
    tp->request_r_scale = qemu_get_byte(f);
953 062e5527 aliguori
    tp->requested_s_scale = qemu_get_byte(f);
954 062e5527 aliguori
    tp->ts_recent = qemu_get_be32(f);
955 062e5527 aliguori
    tp->ts_recent_age = qemu_get_be32(f);
956 062e5527 aliguori
    tp->last_ack_sent = qemu_get_be32(f);
957 062e5527 aliguori
    tcp_template(tp);
958 062e5527 aliguori
}
959 062e5527 aliguori
960 062e5527 aliguori
static int slirp_sbuf_load(QEMUFile *f, struct sbuf *sbuf)
961 062e5527 aliguori
{
962 062e5527 aliguori
    uint32_t off, sb_cc, sb_datalen;
963 062e5527 aliguori
964 062e5527 aliguori
    sb_cc = qemu_get_be32(f);
965 062e5527 aliguori
    sb_datalen = qemu_get_be32(f);
966 062e5527 aliguori
967 062e5527 aliguori
    sbreserve(sbuf, sb_datalen);
968 062e5527 aliguori
969 062e5527 aliguori
    if (sbuf->sb_datalen != sb_datalen)
970 062e5527 aliguori
        return -ENOMEM;
971 062e5527 aliguori
972 062e5527 aliguori
    sbuf->sb_cc = sb_cc;
973 062e5527 aliguori
974 062e5527 aliguori
    off = qemu_get_sbe32(f);
975 062e5527 aliguori
    sbuf->sb_wptr = sbuf->sb_data + off;
976 062e5527 aliguori
    off = qemu_get_sbe32(f);
977 062e5527 aliguori
    sbuf->sb_rptr = sbuf->sb_data + off;
978 062e5527 aliguori
    qemu_get_buffer(f, (unsigned char*)sbuf->sb_data, sbuf->sb_datalen);
979 062e5527 aliguori
980 062e5527 aliguori
    return 0;
981 062e5527 aliguori
}
982 062e5527 aliguori
983 062e5527 aliguori
static int slirp_socket_load(QEMUFile *f, struct socket *so)
984 062e5527 aliguori
{
985 062e5527 aliguori
    if (tcp_attach(so) < 0)
986 062e5527 aliguori
        return -ENOMEM;
987 062e5527 aliguori
988 062e5527 aliguori
    so->so_urgc = qemu_get_be32(f);
989 062e5527 aliguori
    so->so_faddr.s_addr = qemu_get_be32(f);
990 062e5527 aliguori
    so->so_laddr.s_addr = qemu_get_be32(f);
991 062e5527 aliguori
    so->so_fport = qemu_get_be16(f);
992 062e5527 aliguori
    so->so_lport = qemu_get_be16(f);
993 062e5527 aliguori
    so->so_iptos = qemu_get_byte(f);
994 062e5527 aliguori
    so->so_emu = qemu_get_byte(f);
995 062e5527 aliguori
    so->so_type = qemu_get_byte(f);
996 062e5527 aliguori
    so->so_state = qemu_get_be32(f);
997 062e5527 aliguori
    if (slirp_sbuf_load(f, &so->so_rcv) < 0)
998 062e5527 aliguori
        return -ENOMEM;
999 062e5527 aliguori
    if (slirp_sbuf_load(f, &so->so_snd) < 0)
1000 062e5527 aliguori
        return -ENOMEM;
1001 062e5527 aliguori
    slirp_tcp_load(f, so->so_tcpcb);
1002 062e5527 aliguori
1003 062e5527 aliguori
    return 0;
1004 062e5527 aliguori
}
1005 062e5527 aliguori
1006 062e5527 aliguori
static int slirp_state_load(QEMUFile *f, void *opaque, int version_id)
1007 062e5527 aliguori
{
1008 062e5527 aliguori
    struct ex_list *ex_ptr;
1009 062e5527 aliguori
    int r;
1010 062e5527 aliguori
1011 062e5527 aliguori
    while ((r = qemu_get_byte(f))) {
1012 062e5527 aliguori
        int ret;
1013 062e5527 aliguori
        struct socket *so = socreate();
1014 062e5527 aliguori
1015 062e5527 aliguori
        if (!so)
1016 062e5527 aliguori
            return -ENOMEM;
1017 062e5527 aliguori
1018 062e5527 aliguori
        ret = slirp_socket_load(f, so);
1019 062e5527 aliguori
1020 062e5527 aliguori
        if (ret < 0)
1021 062e5527 aliguori
            return ret;
1022 062e5527 aliguori
1023 062e5527 aliguori
        if ((so->so_faddr.s_addr & htonl(0xffffff00)) != special_addr.s_addr)
1024 062e5527 aliguori
            return -EINVAL;
1025 062e5527 aliguori
1026 062e5527 aliguori
        for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next)
1027 062e5527 aliguori
            if (ex_ptr->ex_pty == 3 &&
1028 062e5527 aliguori
                    (ntohl(so->so_faddr.s_addr) & 0xff) == ex_ptr->ex_addr &&
1029 062e5527 aliguori
                    so->so_fport == ex_ptr->ex_fport)
1030 062e5527 aliguori
                break;
1031 062e5527 aliguori
1032 062e5527 aliguori
        if (!ex_ptr)
1033 062e5527 aliguori
            return -EINVAL;
1034 062e5527 aliguori
1035 0580ac91 blueswir1
        so->extra = (void *)ex_ptr->ex_exec;
1036 062e5527 aliguori
    }
1037 062e5527 aliguori
1038 062e5527 aliguori
    return 0;
1039 062e5527 aliguori
}