Statistics
| Branch: | Revision:

root / slirp / slirp.c @ ed23fbd9

History | View | Annotate | Download (16.4 kB)

1 f0cbd3ec bellard
#include "slirp.h"
2 f0cbd3ec bellard
3 f0cbd3ec bellard
/* host address */
4 f0cbd3ec bellard
struct in_addr our_addr;
5 f0cbd3ec bellard
/* host dns address */
6 f0cbd3ec bellard
struct in_addr dns_addr;
7 f0cbd3ec bellard
/* host loopback address */
8 f0cbd3ec bellard
struct in_addr loopback_addr;
9 f0cbd3ec bellard
10 f0cbd3ec bellard
/* address for slirp virtual addresses */
11 f0cbd3ec bellard
struct in_addr special_addr;
12 8dbca8dd bellard
/* virtual address alias for host */
13 8dbca8dd bellard
struct in_addr alias_addr;
14 f0cbd3ec bellard
15 9634d903 blueswir1
static const uint8_t special_ethaddr[6] = {
16 f0cbd3ec bellard
    0x52, 0x54, 0x00, 0x12, 0x35, 0x00
17 f0cbd3ec bellard
};
18 f0cbd3ec bellard
19 f0cbd3ec bellard
uint8_t client_ethaddr[6];
20 f0cbd3ec bellard
21 f0cbd3ec bellard
int do_slowtimo;
22 f0cbd3ec bellard
int link_up;
23 f0cbd3ec bellard
struct timeval tt;
24 f0cbd3ec bellard
FILE *lfd;
25 a3d4af03 bellard
struct ex_list *exec_list;
26 f0cbd3ec bellard
27 f0cbd3ec bellard
/* XXX: suppress those select globals */
28 f0cbd3ec bellard
fd_set *global_readfds, *global_writefds, *global_xfds;
29 f0cbd3ec bellard
30 3f423c9c bellard
char slirp_hostname[33];
31 115defd1 pbrook
32 f0cbd3ec bellard
#ifdef _WIN32
33 f0cbd3ec bellard
34 f0cbd3ec bellard
static int get_dns_addr(struct in_addr *pdns_addr)
35 f0cbd3ec bellard
{
36 379ff53d bellard
    FIXED_INFO *FixedInfo=NULL;
37 379ff53d bellard
    ULONG    BufLen;
38 379ff53d bellard
    DWORD    ret;
39 379ff53d bellard
    IP_ADDR_STRING *pIPAddr;
40 379ff53d bellard
    struct in_addr tmp_addr;
41 3b46e624 ths
42 379ff53d bellard
    FixedInfo = (FIXED_INFO *)GlobalAlloc(GPTR, sizeof(FIXED_INFO));
43 379ff53d bellard
    BufLen = sizeof(FIXED_INFO);
44 3b46e624 ths
45 379ff53d bellard
    if (ERROR_BUFFER_OVERFLOW == GetNetworkParams(FixedInfo, &BufLen)) {
46 379ff53d bellard
        if (FixedInfo) {
47 379ff53d bellard
            GlobalFree(FixedInfo);
48 379ff53d bellard
            FixedInfo = NULL;
49 379ff53d bellard
        }
50 379ff53d bellard
        FixedInfo = GlobalAlloc(GPTR, BufLen);
51 379ff53d bellard
    }
52 5fafdf24 ths
53 379ff53d bellard
    if ((ret = GetNetworkParams(FixedInfo, &BufLen)) != ERROR_SUCCESS) {
54 379ff53d bellard
        printf("GetNetworkParams failed. ret = %08x\n", (u_int)ret );
55 379ff53d bellard
        if (FixedInfo) {
56 379ff53d bellard
            GlobalFree(FixedInfo);
57 379ff53d bellard
            FixedInfo = NULL;
58 379ff53d bellard
        }
59 379ff53d bellard
        return -1;
60 379ff53d bellard
    }
61 3b46e624 ths
62 379ff53d bellard
    pIPAddr = &(FixedInfo->DnsServerList);
63 379ff53d bellard
    inet_aton(pIPAddr->IpAddress.String, &tmp_addr);
64 379ff53d bellard
    *pdns_addr = tmp_addr;
65 379ff53d bellard
#if 0
66 379ff53d bellard
    printf( "DNS Servers:\n" );
67 379ff53d bellard
    printf( "DNS Addr:%s\n", pIPAddr->IpAddress.String );
68 3b46e624 ths

69 379ff53d bellard
    pIPAddr = FixedInfo -> DnsServerList.Next;
70 379ff53d bellard
    while ( pIPAddr ) {
71 379ff53d bellard
            printf( "DNS Addr:%s\n", pIPAddr ->IpAddress.String );
72 379ff53d bellard
            pIPAddr = pIPAddr ->Next;
73 379ff53d bellard
    }
74 379ff53d bellard
#endif
75 379ff53d bellard
    if (FixedInfo) {
76 379ff53d bellard
        GlobalFree(FixedInfo);
77 379ff53d bellard
        FixedInfo = NULL;
78 379ff53d bellard
    }
79 379ff53d bellard
    return 0;
80 f0cbd3ec bellard
}
81 f0cbd3ec bellard
82 f0cbd3ec bellard
#else
83 f0cbd3ec bellard
84 f0cbd3ec bellard
static int get_dns_addr(struct in_addr *pdns_addr)
85 f0cbd3ec bellard
{
86 f0cbd3ec bellard
    char buff[512];
87 363a37d5 blueswir1
    char buff2[257];
88 f0cbd3ec bellard
    FILE *f;
89 f0cbd3ec bellard
    int found = 0;
90 f0cbd3ec bellard
    struct in_addr tmp_addr;
91 3b46e624 ths
92 f0cbd3ec bellard
    f = fopen("/etc/resolv.conf", "r");
93 f0cbd3ec bellard
    if (!f)
94 f0cbd3ec bellard
        return -1;
95 f0cbd3ec bellard
96 31a60e22 blueswir1
#ifdef DEBUG
97 f0cbd3ec bellard
    lprint("IP address of your DNS(s): ");
98 31a60e22 blueswir1
#endif
99 f0cbd3ec bellard
    while (fgets(buff, 512, f) != NULL) {
100 f0cbd3ec bellard
        if (sscanf(buff, "nameserver%*[ \t]%256s", buff2) == 1) {
101 f0cbd3ec bellard
            if (!inet_aton(buff2, &tmp_addr))
102 f0cbd3ec bellard
                continue;
103 f0cbd3ec bellard
            if (tmp_addr.s_addr == loopback_addr.s_addr)
104 f0cbd3ec bellard
                tmp_addr = our_addr;
105 f0cbd3ec bellard
            /* If it's the first one, set it to dns_addr */
106 f0cbd3ec bellard
            if (!found)
107 f0cbd3ec bellard
                *pdns_addr = tmp_addr;
108 31a60e22 blueswir1
#ifdef DEBUG
109 f0cbd3ec bellard
            else
110 f0cbd3ec bellard
                lprint(", ");
111 31a60e22 blueswir1
#endif
112 f0cbd3ec bellard
            if (++found > 3) {
113 31a60e22 blueswir1
#ifdef DEBUG
114 f0cbd3ec bellard
                lprint("(more)");
115 31a60e22 blueswir1
#endif
116 f0cbd3ec bellard
                break;
117 31a60e22 blueswir1
            }
118 31a60e22 blueswir1
#ifdef DEBUG
119 31a60e22 blueswir1
            else
120 f0cbd3ec bellard
                lprint("%s", inet_ntoa(tmp_addr));
121 31a60e22 blueswir1
#endif
122 f0cbd3ec bellard
        }
123 f0cbd3ec bellard
    }
124 1d43a717 bellard
    fclose(f);
125 f0cbd3ec bellard
    if (!found)
126 f0cbd3ec bellard
        return -1;
127 f0cbd3ec bellard
    return 0;
128 f0cbd3ec bellard
}
129 f0cbd3ec bellard
130 f0cbd3ec bellard
#endif
131 f0cbd3ec bellard
132 379ff53d bellard
#ifdef _WIN32
133 9634d903 blueswir1
static void slirp_cleanup(void)
134 379ff53d bellard
{
135 379ff53d bellard
    WSACleanup();
136 379ff53d bellard
}
137 379ff53d bellard
#endif
138 379ff53d bellard
139 f0cbd3ec bellard
void slirp_init(void)
140 f0cbd3ec bellard
{
141 512176db bellard
    //    debug_init("/tmp/slirp.log", DEBUG_DEFAULT);
142 3b46e624 ths
143 379ff53d bellard
#ifdef _WIN32
144 379ff53d bellard
    {
145 379ff53d bellard
        WSADATA Data;
146 379ff53d bellard
        WSAStartup(MAKEWORD(2,0), &Data);
147 379ff53d bellard
        atexit(slirp_cleanup);
148 379ff53d bellard
    }
149 379ff53d bellard
#endif
150 379ff53d bellard
151 f0cbd3ec bellard
    link_up = 1;
152 f0cbd3ec bellard
153 f0cbd3ec bellard
    if_init();
154 f0cbd3ec bellard
    ip_init();
155 f0cbd3ec bellard
156 f0cbd3ec bellard
    /* Initialise mbufs *after* setting the MTU */
157 f0cbd3ec bellard
    m_init();
158 f0cbd3ec bellard
159 f0cbd3ec bellard
    /* set default addresses */
160 f0cbd3ec bellard
    inet_aton("127.0.0.1", &loopback_addr);
161 f0cbd3ec bellard
162 f0cbd3ec bellard
    if (get_dns_addr(&dns_addr) < 0) {
163 0f8134bf pbrook
        dns_addr = loopback_addr;
164 0f8134bf pbrook
        fprintf (stderr, "Warning: No DNS servers found\n");
165 f0cbd3ec bellard
    }
166 f0cbd3ec bellard
167 f0cbd3ec bellard
    inet_aton(CTL_SPECIAL, &special_addr);
168 8dbca8dd bellard
    alias_addr.s_addr = special_addr.s_addr | htonl(CTL_ALIAS);
169 f4e15b4b pbrook
    getouraddr();
170 f0cbd3ec bellard
}
171 f0cbd3ec bellard
172 f0cbd3ec bellard
#define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
173 f0cbd3ec bellard
#define CONN_CANFRCV(so) (((so)->so_state & (SS_FCANTRCVMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
174 f0cbd3ec bellard
#define UPD_NFDS(x) if (nfds < (x)) nfds = (x)
175 f0cbd3ec bellard
176 f0cbd3ec bellard
/*
177 f0cbd3ec bellard
 * curtime kept to an accuracy of 1ms
178 f0cbd3ec bellard
 */
179 379ff53d bellard
#ifdef _WIN32
180 379ff53d bellard
static void updtime(void)
181 379ff53d bellard
{
182 379ff53d bellard
    struct _timeb tb;
183 379ff53d bellard
184 379ff53d bellard
    _ftime(&tb);
185 379ff53d bellard
    curtime = (u_int)tb.time * (u_int)1000;
186 379ff53d bellard
    curtime += (u_int)tb.millitm;
187 379ff53d bellard
}
188 379ff53d bellard
#else
189 f0cbd3ec bellard
static void updtime(void)
190 f0cbd3ec bellard
{
191 f0cbd3ec bellard
        gettimeofday(&tt, 0);
192 5fafdf24 ths
193 f0cbd3ec bellard
        curtime = (u_int)tt.tv_sec * (u_int)1000;
194 f0cbd3ec bellard
        curtime += (u_int)tt.tv_usec / (u_int)1000;
195 5fafdf24 ths
196 f0cbd3ec bellard
        if ((tt.tv_usec % 1000) >= 500)
197 f0cbd3ec bellard
           curtime++;
198 f0cbd3ec bellard
}
199 379ff53d bellard
#endif
200 f0cbd3ec bellard
201 5fafdf24 ths
void slirp_select_fill(int *pnfds,
202 f0cbd3ec bellard
                       fd_set *readfds, fd_set *writefds, fd_set *xfds)
203 f0cbd3ec bellard
{
204 f0cbd3ec bellard
    struct socket *so, *so_next;
205 f0cbd3ec bellard
    struct timeval timeout;
206 f0cbd3ec bellard
    int nfds;
207 f0cbd3ec bellard
    int tmp_time;
208 f0cbd3ec bellard
209 f0cbd3ec bellard
    /* fail safe */
210 f0cbd3ec bellard
    global_readfds = NULL;
211 f0cbd3ec bellard
    global_writefds = NULL;
212 f0cbd3ec bellard
    global_xfds = NULL;
213 3b46e624 ths
214 f0cbd3ec bellard
    nfds = *pnfds;
215 f0cbd3ec bellard
        /*
216 f0cbd3ec bellard
         * First, TCP sockets
217 f0cbd3ec bellard
         */
218 f0cbd3ec bellard
        do_slowtimo = 0;
219 f0cbd3ec bellard
        if (link_up) {
220 5fafdf24 ths
                /*
221 f0cbd3ec bellard
                 * *_slowtimo needs calling if there are IP fragments
222 f0cbd3ec bellard
                 * in the fragment queue, or there are TCP connections active
223 f0cbd3ec bellard
                 */
224 f0cbd3ec bellard
                do_slowtimo = ((tcb.so_next != &tcb) ||
225 f0cbd3ec bellard
                               ((struct ipasfrag *)&ipq != (struct ipasfrag *)ipq.next));
226 3b46e624 ths
227 f0cbd3ec bellard
                for (so = tcb.so_next; so != &tcb; so = so_next) {
228 f0cbd3ec bellard
                        so_next = so->so_next;
229 3b46e624 ths
230 f0cbd3ec bellard
                        /*
231 f0cbd3ec bellard
                         * See if we need a tcp_fasttimo
232 f0cbd3ec bellard
                         */
233 f0cbd3ec bellard
                        if (time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK)
234 f0cbd3ec bellard
                           time_fasttimo = curtime; /* Flag when we want a fasttimo */
235 3b46e624 ths
236 f0cbd3ec bellard
                        /*
237 f0cbd3ec bellard
                         * NOFDREF can include still connecting to local-host,
238 f0cbd3ec bellard
                         * newly socreated() sockets etc. Don't want to select these.
239 f0cbd3ec bellard
                          */
240 f0cbd3ec bellard
                        if (so->so_state & SS_NOFDREF || so->s == -1)
241 f0cbd3ec bellard
                           continue;
242 3b46e624 ths
243 f0cbd3ec bellard
                        /*
244 f0cbd3ec bellard
                         * Set for reading sockets which are accepting
245 f0cbd3ec bellard
                         */
246 f0cbd3ec bellard
                        if (so->so_state & SS_FACCEPTCONN) {
247 f0cbd3ec bellard
                                FD_SET(so->s, readfds);
248 f0cbd3ec bellard
                                UPD_NFDS(so->s);
249 f0cbd3ec bellard
                                continue;
250 f0cbd3ec bellard
                        }
251 3b46e624 ths
252 f0cbd3ec bellard
                        /*
253 f0cbd3ec bellard
                         * Set for writing sockets which are connecting
254 f0cbd3ec bellard
                         */
255 f0cbd3ec bellard
                        if (so->so_state & SS_ISFCONNECTING) {
256 f0cbd3ec bellard
                                FD_SET(so->s, writefds);
257 f0cbd3ec bellard
                                UPD_NFDS(so->s);
258 f0cbd3ec bellard
                                continue;
259 f0cbd3ec bellard
                        }
260 3b46e624 ths
261 f0cbd3ec bellard
                        /*
262 f0cbd3ec bellard
                         * Set for writing if we are connected, can send more, and
263 f0cbd3ec bellard
                         * we have something to send
264 f0cbd3ec bellard
                         */
265 f0cbd3ec bellard
                        if (CONN_CANFSEND(so) && so->so_rcv.sb_cc) {
266 f0cbd3ec bellard
                                FD_SET(so->s, writefds);
267 f0cbd3ec bellard
                                UPD_NFDS(so->s);
268 f0cbd3ec bellard
                        }
269 3b46e624 ths
270 f0cbd3ec bellard
                        /*
271 f0cbd3ec bellard
                         * Set for reading (and urgent data) if we are connected, can
272 f0cbd3ec bellard
                         * receive more, and we have room for it XXX /2 ?
273 f0cbd3ec bellard
                         */
274 f0cbd3ec bellard
                        if (CONN_CANFRCV(so) && (so->so_snd.sb_cc < (so->so_snd.sb_datalen/2))) {
275 f0cbd3ec bellard
                                FD_SET(so->s, readfds);
276 f0cbd3ec bellard
                                FD_SET(so->s, xfds);
277 f0cbd3ec bellard
                                UPD_NFDS(so->s);
278 f0cbd3ec bellard
                        }
279 f0cbd3ec bellard
                }
280 3b46e624 ths
281 f0cbd3ec bellard
                /*
282 f0cbd3ec bellard
                 * UDP sockets
283 f0cbd3ec bellard
                 */
284 f0cbd3ec bellard
                for (so = udb.so_next; so != &udb; so = so_next) {
285 f0cbd3ec bellard
                        so_next = so->so_next;
286 3b46e624 ths
287 f0cbd3ec bellard
                        /*
288 f0cbd3ec bellard
                         * See if it's timed out
289 f0cbd3ec bellard
                         */
290 f0cbd3ec bellard
                        if (so->so_expire) {
291 f0cbd3ec bellard
                                if (so->so_expire <= curtime) {
292 f0cbd3ec bellard
                                        udp_detach(so);
293 f0cbd3ec bellard
                                        continue;
294 f0cbd3ec bellard
                                } else
295 f0cbd3ec bellard
                                        do_slowtimo = 1; /* Let socket expire */
296 f0cbd3ec bellard
                        }
297 3b46e624 ths
298 f0cbd3ec bellard
                        /*
299 f0cbd3ec bellard
                         * When UDP packets are received from over the
300 f0cbd3ec bellard
                         * link, they're sendto()'d straight away, so
301 f0cbd3ec bellard
                         * no need for setting for writing
302 f0cbd3ec bellard
                         * Limit the number of packets queued by this session
303 f0cbd3ec bellard
                         * to 4.  Note that even though we try and limit this
304 f0cbd3ec bellard
                         * to 4 packets, the session could have more queued
305 f0cbd3ec bellard
                         * if the packets needed to be fragmented
306 f0cbd3ec bellard
                         * (XXX <= 4 ?)
307 f0cbd3ec bellard
                         */
308 f0cbd3ec bellard
                        if ((so->so_state & SS_ISFCONNECTED) && so->so_queued <= 4) {
309 f0cbd3ec bellard
                                FD_SET(so->s, readfds);
310 f0cbd3ec bellard
                                UPD_NFDS(so->s);
311 f0cbd3ec bellard
                        }
312 f0cbd3ec bellard
                }
313 f0cbd3ec bellard
        }
314 5fafdf24 ths
315 f0cbd3ec bellard
        /*
316 f0cbd3ec bellard
         * Setup timeout to use minimum CPU usage, especially when idle
317 f0cbd3ec bellard
         */
318 5fafdf24 ths
319 5fafdf24 ths
        /*
320 f0cbd3ec bellard
         * First, see the timeout needed by *timo
321 f0cbd3ec bellard
         */
322 f0cbd3ec bellard
        timeout.tv_sec = 0;
323 f0cbd3ec bellard
        timeout.tv_usec = -1;
324 f0cbd3ec bellard
        /*
325 f0cbd3ec bellard
         * If a slowtimo is needed, set timeout to 500ms from the last
326 f0cbd3ec bellard
         * slow timeout. If a fast timeout is needed, set timeout within
327 f0cbd3ec bellard
         * 200ms of when it was requested.
328 f0cbd3ec bellard
         */
329 f0cbd3ec bellard
        if (do_slowtimo) {
330 f0cbd3ec bellard
                /* XXX + 10000 because some select()'s aren't that accurate */
331 f0cbd3ec bellard
                timeout.tv_usec = ((500 - (curtime - last_slowtimo)) * 1000) + 10000;
332 f0cbd3ec bellard
                if (timeout.tv_usec < 0)
333 f0cbd3ec bellard
                   timeout.tv_usec = 0;
334 f0cbd3ec bellard
                else if (timeout.tv_usec > 510000)
335 f0cbd3ec bellard
                   timeout.tv_usec = 510000;
336 3b46e624 ths
337 f0cbd3ec bellard
                /* Can only fasttimo if we also slowtimo */
338 f0cbd3ec bellard
                if (time_fasttimo) {
339 f0cbd3ec bellard
                        tmp_time = (200 - (curtime - time_fasttimo)) * 1000;
340 f0cbd3ec bellard
                        if (tmp_time < 0)
341 f0cbd3ec bellard
                           tmp_time = 0;
342 3b46e624 ths
343 f0cbd3ec bellard
                        /* Choose the smallest of the 2 */
344 f0cbd3ec bellard
                        if (tmp_time < timeout.tv_usec)
345 f0cbd3ec bellard
                           timeout.tv_usec = (u_int)tmp_time;
346 f0cbd3ec bellard
                }
347 f0cbd3ec bellard
        }
348 f0cbd3ec bellard
        *pnfds = nfds;
349 5fafdf24 ths
}
350 f0cbd3ec bellard
351 f0cbd3ec bellard
void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
352 f0cbd3ec bellard
{
353 f0cbd3ec bellard
    struct socket *so, *so_next;
354 f0cbd3ec bellard
    int ret;
355 f0cbd3ec bellard
356 f0cbd3ec bellard
    global_readfds = readfds;
357 f0cbd3ec bellard
    global_writefds = writefds;
358 f0cbd3ec bellard
    global_xfds = xfds;
359 f0cbd3ec bellard
360 f0cbd3ec bellard
        /* Update time */
361 f0cbd3ec bellard
        updtime();
362 5fafdf24 ths
363 f0cbd3ec bellard
        /*
364 5fafdf24 ths
         * See if anything has timed out
365 f0cbd3ec bellard
         */
366 f0cbd3ec bellard
        if (link_up) {
367 df5f8956 bellard
                if (time_fasttimo && ((curtime - time_fasttimo) >= 2)) {
368 f0cbd3ec bellard
                        tcp_fasttimo();
369 f0cbd3ec bellard
                        time_fasttimo = 0;
370 f0cbd3ec bellard
                }
371 f0cbd3ec bellard
                if (do_slowtimo && ((curtime - last_slowtimo) >= 499)) {
372 f0cbd3ec bellard
                        ip_slowtimo();
373 f0cbd3ec bellard
                        tcp_slowtimo();
374 f0cbd3ec bellard
                        last_slowtimo = curtime;
375 f0cbd3ec bellard
                }
376 f0cbd3ec bellard
        }
377 5fafdf24 ths
378 f0cbd3ec bellard
        /*
379 f0cbd3ec bellard
         * Check sockets
380 f0cbd3ec bellard
         */
381 f0cbd3ec bellard
        if (link_up) {
382 f0cbd3ec bellard
                /*
383 f0cbd3ec bellard
                 * Check TCP sockets
384 f0cbd3ec bellard
                 */
385 f0cbd3ec bellard
                for (so = tcb.so_next; so != &tcb; so = so_next) {
386 f0cbd3ec bellard
                        so_next = so->so_next;
387 3b46e624 ths
388 f0cbd3ec bellard
                        /*
389 f0cbd3ec bellard
                         * FD_ISSET is meaningless on these sockets
390 f0cbd3ec bellard
                         * (and they can crash the program)
391 f0cbd3ec bellard
                         */
392 f0cbd3ec bellard
                        if (so->so_state & SS_NOFDREF || so->s == -1)
393 f0cbd3ec bellard
                           continue;
394 3b46e624 ths
395 f0cbd3ec bellard
                        /*
396 f0cbd3ec bellard
                         * Check for URG data
397 f0cbd3ec bellard
                         * This will soread as well, so no need to
398 f0cbd3ec bellard
                         * test for readfds below if this succeeds
399 f0cbd3ec bellard
                         */
400 f0cbd3ec bellard
                        if (FD_ISSET(so->s, xfds))
401 f0cbd3ec bellard
                           sorecvoob(so);
402 f0cbd3ec bellard
                        /*
403 f0cbd3ec bellard
                         * Check sockets for reading
404 f0cbd3ec bellard
                         */
405 f0cbd3ec bellard
                        else if (FD_ISSET(so->s, readfds)) {
406 f0cbd3ec bellard
                                /*
407 f0cbd3ec bellard
                                 * Check for incoming connections
408 f0cbd3ec bellard
                                 */
409 f0cbd3ec bellard
                                if (so->so_state & SS_FACCEPTCONN) {
410 f0cbd3ec bellard
                                        tcp_connect(so);
411 f0cbd3ec bellard
                                        continue;
412 f0cbd3ec bellard
                                } /* else */
413 f0cbd3ec bellard
                                ret = soread(so);
414 3b46e624 ths
415 f0cbd3ec bellard
                                /* Output it if we read something */
416 f0cbd3ec bellard
                                if (ret > 0)
417 f0cbd3ec bellard
                                   tcp_output(sototcpcb(so));
418 f0cbd3ec bellard
                        }
419 3b46e624 ths
420 f0cbd3ec bellard
                        /*
421 f0cbd3ec bellard
                         * Check sockets for writing
422 f0cbd3ec bellard
                         */
423 f0cbd3ec bellard
                        if (FD_ISSET(so->s, writefds)) {
424 f0cbd3ec bellard
                          /*
425 f0cbd3ec bellard
                           * Check for non-blocking, still-connecting sockets
426 f0cbd3ec bellard
                           */
427 f0cbd3ec bellard
                          if (so->so_state & SS_ISFCONNECTING) {
428 f0cbd3ec bellard
                            /* Connected */
429 f0cbd3ec bellard
                            so->so_state &= ~SS_ISFCONNECTING;
430 3b46e624 ths
431 02d2c54c bellard
                            ret = send(so->s, &ret, 0, 0);
432 f0cbd3ec bellard
                            if (ret < 0) {
433 f0cbd3ec bellard
                              /* XXXXX Must fix, zero bytes is a NOP */
434 f0cbd3ec bellard
                              if (errno == EAGAIN || errno == EWOULDBLOCK ||
435 f0cbd3ec bellard
                                  errno == EINPROGRESS || errno == ENOTCONN)
436 f0cbd3ec bellard
                                continue;
437 3b46e624 ths
438 f0cbd3ec bellard
                              /* else failed */
439 f0cbd3ec bellard
                              so->so_state = SS_NOFDREF;
440 f0cbd3ec bellard
                            }
441 f0cbd3ec bellard
                            /* else so->so_state &= ~SS_ISFCONNECTING; */
442 3b46e624 ths
443 f0cbd3ec bellard
                            /*
444 f0cbd3ec bellard
                             * Continue tcp_input
445 f0cbd3ec bellard
                             */
446 f0cbd3ec bellard
                            tcp_input((struct mbuf *)NULL, sizeof(struct ip), so);
447 f0cbd3ec bellard
                            /* continue; */
448 f0cbd3ec bellard
                          } else
449 f0cbd3ec bellard
                            ret = sowrite(so);
450 f0cbd3ec bellard
                          /*
451 5fafdf24 ths
                           * XXXXX If we wrote something (a lot), there
452 f0cbd3ec bellard
                           * could be a need for a window update.
453 f0cbd3ec bellard
                           * In the worst case, the remote will send
454 f0cbd3ec bellard
                           * a window probe to get things going again
455 f0cbd3ec bellard
                           */
456 f0cbd3ec bellard
                        }
457 3b46e624 ths
458 f0cbd3ec bellard
                        /*
459 f0cbd3ec bellard
                         * Probe a still-connecting, non-blocking socket
460 f0cbd3ec bellard
                         * to check if it's still alive
461 f0cbd3ec bellard
                           */
462 f0cbd3ec bellard
#ifdef PROBE_CONN
463 f0cbd3ec bellard
                        if (so->so_state & SS_ISFCONNECTING) {
464 02d2c54c bellard
                          ret = recv(so->s, (char *)&ret, 0,0);
465 3b46e624 ths
466 f0cbd3ec bellard
                          if (ret < 0) {
467 f0cbd3ec bellard
                            /* XXX */
468 f0cbd3ec bellard
                            if (errno == EAGAIN || errno == EWOULDBLOCK ||
469 f0cbd3ec bellard
                                errno == EINPROGRESS || errno == ENOTCONN)
470 f0cbd3ec bellard
                              continue; /* Still connecting, continue */
471 3b46e624 ths
472 f0cbd3ec bellard
                            /* else failed */
473 f0cbd3ec bellard
                            so->so_state = SS_NOFDREF;
474 3b46e624 ths
475 f0cbd3ec bellard
                            /* tcp_input will take care of it */
476 f0cbd3ec bellard
                          } else {
477 02d2c54c bellard
                            ret = send(so->s, &ret, 0,0);
478 f0cbd3ec bellard
                            if (ret < 0) {
479 f0cbd3ec bellard
                              /* XXX */
480 f0cbd3ec bellard
                              if (errno == EAGAIN || errno == EWOULDBLOCK ||
481 f0cbd3ec bellard
                                  errno == EINPROGRESS || errno == ENOTCONN)
482 f0cbd3ec bellard
                                continue;
483 f0cbd3ec bellard
                              /* else failed */
484 f0cbd3ec bellard
                              so->so_state = SS_NOFDREF;
485 f0cbd3ec bellard
                            } else
486 f0cbd3ec bellard
                              so->so_state &= ~SS_ISFCONNECTING;
487 3b46e624 ths
488 f0cbd3ec bellard
                          }
489 f0cbd3ec bellard
                          tcp_input((struct mbuf *)NULL, sizeof(struct ip),so);
490 f0cbd3ec bellard
                        } /* SS_ISFCONNECTING */
491 f0cbd3ec bellard
#endif
492 f0cbd3ec bellard
                }
493 3b46e624 ths
494 f0cbd3ec bellard
                /*
495 f0cbd3ec bellard
                 * Now UDP sockets.
496 f0cbd3ec bellard
                 * Incoming packets are sent straight away, they're not buffered.
497 f0cbd3ec bellard
                 * Incoming UDP data isn't buffered either.
498 f0cbd3ec bellard
                 */
499 f0cbd3ec bellard
                for (so = udb.so_next; so != &udb; so = so_next) {
500 f0cbd3ec bellard
                        so_next = so->so_next;
501 3b46e624 ths
502 f0cbd3ec bellard
                        if (so->s != -1 && FD_ISSET(so->s, readfds)) {
503 f0cbd3ec bellard
                            sorecvfrom(so);
504 f0cbd3ec bellard
                        }
505 f0cbd3ec bellard
                }
506 f0cbd3ec bellard
        }
507 5fafdf24 ths
508 f0cbd3ec bellard
        /*
509 f0cbd3ec bellard
         * See if we can start outputting
510 f0cbd3ec bellard
         */
511 f0cbd3ec bellard
        if (if_queued && link_up)
512 f0cbd3ec bellard
           if_start();
513 02d2c54c bellard
514 02d2c54c bellard
        /* clear global file descriptor sets.
515 02d2c54c bellard
         * these reside on the stack in vl.c
516 02d2c54c bellard
         * so they're unusable if we're not in
517 02d2c54c bellard
         * slirp_select_fill or slirp_select_poll.
518 02d2c54c bellard
         */
519 02d2c54c bellard
         global_readfds = NULL;
520 02d2c54c bellard
         global_writefds = NULL;
521 02d2c54c bellard
         global_xfds = NULL;
522 f0cbd3ec bellard
}
523 f0cbd3ec bellard
524 f0cbd3ec bellard
#define ETH_ALEN 6
525 f0cbd3ec bellard
#define ETH_HLEN 14
526 f0cbd3ec bellard
527 f0cbd3ec bellard
#define ETH_P_IP        0x0800                /* Internet Protocol packet        */
528 f0cbd3ec bellard
#define ETH_P_ARP        0x0806                /* Address Resolution packet        */
529 f0cbd3ec bellard
530 f0cbd3ec bellard
#define        ARPOP_REQUEST        1                /* ARP request                        */
531 f0cbd3ec bellard
#define        ARPOP_REPLY        2                /* ARP reply                        */
532 f0cbd3ec bellard
533 5fafdf24 ths
struct ethhdr
534 f0cbd3ec bellard
{
535 f0cbd3ec bellard
        unsigned char        h_dest[ETH_ALEN];        /* destination eth addr        */
536 f0cbd3ec bellard
        unsigned char        h_source[ETH_ALEN];        /* source ether addr        */
537 f0cbd3ec bellard
        unsigned short        h_proto;                /* packet type ID field        */
538 f0cbd3ec bellard
};
539 f0cbd3ec bellard
540 f0cbd3ec bellard
struct arphdr
541 f0cbd3ec bellard
{
542 f0cbd3ec bellard
        unsigned short        ar_hrd;                /* format of hardware address        */
543 f0cbd3ec bellard
        unsigned short        ar_pro;                /* format of protocol address        */
544 f0cbd3ec bellard
        unsigned char        ar_hln;                /* length of hardware address        */
545 f0cbd3ec bellard
        unsigned char        ar_pln;                /* length of protocol address        */
546 f0cbd3ec bellard
        unsigned short        ar_op;                /* ARP opcode (command)                */
547 f0cbd3ec bellard
548 f0cbd3ec bellard
         /*
549 f0cbd3ec bellard
          *         Ethernet looks like this : This bit is variable sized however...
550 f0cbd3ec bellard
          */
551 f0cbd3ec bellard
        unsigned char                ar_sha[ETH_ALEN];        /* sender hardware address        */
552 f0cbd3ec bellard
        unsigned char                ar_sip[4];                /* sender IP address                */
553 f0cbd3ec bellard
        unsigned char                ar_tha[ETH_ALEN];        /* target hardware address        */
554 f0cbd3ec bellard
        unsigned char                ar_tip[4];                /* target IP address                */
555 f0cbd3ec bellard
};
556 f0cbd3ec bellard
557 8fcd3692 blueswir1
static void arp_input(const uint8_t *pkt, int pkt_len)
558 f0cbd3ec bellard
{
559 f0cbd3ec bellard
    struct ethhdr *eh = (struct ethhdr *)pkt;
560 f0cbd3ec bellard
    struct arphdr *ah = (struct arphdr *)(pkt + ETH_HLEN);
561 f0cbd3ec bellard
    uint8_t arp_reply[ETH_HLEN + sizeof(struct arphdr)];
562 f0cbd3ec bellard
    struct ethhdr *reh = (struct ethhdr *)arp_reply;
563 f0cbd3ec bellard
    struct arphdr *rah = (struct arphdr *)(arp_reply + ETH_HLEN);
564 f0cbd3ec bellard
    int ar_op;
565 a3d4af03 bellard
    struct ex_list *ex_ptr;
566 f0cbd3ec bellard
567 f0cbd3ec bellard
    ar_op = ntohs(ah->ar_op);
568 f0cbd3ec bellard
    switch(ar_op) {
569 f0cbd3ec bellard
    case ARPOP_REQUEST:
570 a3d4af03 bellard
        if (!memcmp(ah->ar_tip, &special_addr, 3)) {
571 5fafdf24 ths
            if (ah->ar_tip[3] == CTL_DNS || ah->ar_tip[3] == CTL_ALIAS)
572 a3d4af03 bellard
                goto arp_ok;
573 a3d4af03 bellard
            for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
574 a3d4af03 bellard
                if (ex_ptr->ex_addr == ah->ar_tip[3])
575 a3d4af03 bellard
                    goto arp_ok;
576 a3d4af03 bellard
            }
577 a3d4af03 bellard
            return;
578 a3d4af03 bellard
        arp_ok:
579 f0cbd3ec bellard
            /* XXX: make an ARP request to have the client address */
580 f0cbd3ec bellard
            memcpy(client_ethaddr, eh->h_source, ETH_ALEN);
581 f0cbd3ec bellard
582 f0cbd3ec bellard
            /* ARP request for alias/dns mac address */
583 f0cbd3ec bellard
            memcpy(reh->h_dest, pkt + ETH_ALEN, ETH_ALEN);
584 f0cbd3ec bellard
            memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 1);
585 f0cbd3ec bellard
            reh->h_source[5] = ah->ar_tip[3];
586 f0cbd3ec bellard
            reh->h_proto = htons(ETH_P_ARP);
587 f0cbd3ec bellard
588 f0cbd3ec bellard
            rah->ar_hrd = htons(1);
589 f0cbd3ec bellard
            rah->ar_pro = htons(ETH_P_IP);
590 f0cbd3ec bellard
            rah->ar_hln = ETH_ALEN;
591 f0cbd3ec bellard
            rah->ar_pln = 4;
592 f0cbd3ec bellard
            rah->ar_op = htons(ARPOP_REPLY);
593 f0cbd3ec bellard
            memcpy(rah->ar_sha, reh->h_source, ETH_ALEN);
594 f0cbd3ec bellard
            memcpy(rah->ar_sip, ah->ar_tip, 4);
595 f0cbd3ec bellard
            memcpy(rah->ar_tha, ah->ar_sha, ETH_ALEN);
596 f0cbd3ec bellard
            memcpy(rah->ar_tip, ah->ar_sip, 4);
597 f0cbd3ec bellard
            slirp_output(arp_reply, sizeof(arp_reply));
598 f0cbd3ec bellard
        }
599 f0cbd3ec bellard
        break;
600 f0cbd3ec bellard
    default:
601 f0cbd3ec bellard
        break;
602 f0cbd3ec bellard
    }
603 f0cbd3ec bellard
}
604 f0cbd3ec bellard
605 f0cbd3ec bellard
void slirp_input(const uint8_t *pkt, int pkt_len)
606 f0cbd3ec bellard
{
607 f0cbd3ec bellard
    struct mbuf *m;
608 f0cbd3ec bellard
    int proto;
609 f0cbd3ec bellard
610 f0cbd3ec bellard
    if (pkt_len < ETH_HLEN)
611 f0cbd3ec bellard
        return;
612 3b46e624 ths
613 f0cbd3ec bellard
    proto = ntohs(*(uint16_t *)(pkt + 12));
614 f0cbd3ec bellard
    switch(proto) {
615 f0cbd3ec bellard
    case ETH_P_ARP:
616 f0cbd3ec bellard
        arp_input(pkt, pkt_len);
617 f0cbd3ec bellard
        break;
618 f0cbd3ec bellard
    case ETH_P_IP:
619 f0cbd3ec bellard
        m = m_get();
620 f0cbd3ec bellard
        if (!m)
621 f0cbd3ec bellard
            return;
622 38f3e7c2 bellard
        /* Note: we add to align the IP header */
623 38f3e7c2 bellard
        m->m_len = pkt_len + 2;
624 38f3e7c2 bellard
        memcpy(m->m_data + 2, pkt, pkt_len);
625 f0cbd3ec bellard
626 38f3e7c2 bellard
        m->m_data += 2 + ETH_HLEN;
627 38f3e7c2 bellard
        m->m_len -= 2 + ETH_HLEN;
628 f0cbd3ec bellard
629 f0cbd3ec bellard
        ip_input(m);
630 f0cbd3ec bellard
        break;
631 f0cbd3ec bellard
    default:
632 f0cbd3ec bellard
        break;
633 f0cbd3ec bellard
    }
634 f0cbd3ec bellard
}
635 f0cbd3ec bellard
636 f0cbd3ec bellard
/* output the IP packet to the ethernet device */
637 f0cbd3ec bellard
void if_encap(const uint8_t *ip_data, int ip_data_len)
638 f0cbd3ec bellard
{
639 f0cbd3ec bellard
    uint8_t buf[1600];
640 f0cbd3ec bellard
    struct ethhdr *eh = (struct ethhdr *)buf;
641 f0cbd3ec bellard
642 f0cbd3ec bellard
    if (ip_data_len + ETH_HLEN > sizeof(buf))
643 f0cbd3ec bellard
        return;
644 f0cbd3ec bellard
645 f0cbd3ec bellard
    memcpy(eh->h_dest, client_ethaddr, ETH_ALEN);
646 f0cbd3ec bellard
    memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 1);
647 a3d4af03 bellard
    /* XXX: not correct */
648 f0cbd3ec bellard
    eh->h_source[5] = CTL_ALIAS;
649 f0cbd3ec bellard
    eh->h_proto = htons(ETH_P_IP);
650 f0cbd3ec bellard
    memcpy(buf + sizeof(struct ethhdr), ip_data, ip_data_len);
651 f0cbd3ec bellard
    slirp_output(buf, ip_data_len + ETH_HLEN);
652 f0cbd3ec bellard
}
653 9bf05444 bellard
654 5fafdf24 ths
int slirp_redir(int is_udp, int host_port,
655 9bf05444 bellard
                struct in_addr guest_addr, int guest_port)
656 9bf05444 bellard
{
657 9bf05444 bellard
    if (is_udp) {
658 5fafdf24 ths
        if (!udp_listen(htons(host_port), guest_addr.s_addr,
659 9bf05444 bellard
                        htons(guest_port), 0))
660 9bf05444 bellard
            return -1;
661 9bf05444 bellard
    } else {
662 5fafdf24 ths
        if (!solisten(htons(host_port), guest_addr.s_addr,
663 9bf05444 bellard
                      htons(guest_port), 0))
664 9bf05444 bellard
            return -1;
665 9bf05444 bellard
    }
666 9bf05444 bellard
    return 0;
667 9bf05444 bellard
}
668 a3d4af03 bellard
669 5fafdf24 ths
int slirp_add_exec(int do_pty, const char *args, int addr_low_byte,
670 a3d4af03 bellard
                  int guest_port)
671 a3d4af03 bellard
{
672 5fafdf24 ths
    return add_exec(&exec_list, do_pty, (char *)args,
673 a3d4af03 bellard
                    addr_low_byte, htons(guest_port));
674 a3d4af03 bellard
}