Statistics
| Branch: | Revision:

root / slirp / slirp.c @ 9634d903

History | View | Annotate | Download (16.4 kB)

1
#include "slirp.h"
2

    
3
/* host address */
4
struct in_addr our_addr;
5
/* host dns address */
6
struct in_addr dns_addr;
7
/* host loopback address */
8
struct in_addr loopback_addr;
9

    
10
/* address for slirp virtual addresses */
11
struct in_addr special_addr;
12
/* virtual address alias for host */
13
struct in_addr alias_addr;
14

    
15
static const uint8_t special_ethaddr[6] = {
16
    0x52, 0x54, 0x00, 0x12, 0x35, 0x00
17
};
18

    
19
uint8_t client_ethaddr[6];
20

    
21
int do_slowtimo;
22
int link_up;
23
struct timeval tt;
24
FILE *lfd;
25
struct ex_list *exec_list;
26

    
27
/* XXX: suppress those select globals */
28
fd_set *global_readfds, *global_writefds, *global_xfds;
29

    
30
char slirp_hostname[33];
31

    
32
#ifdef _WIN32
33

    
34
static int get_dns_addr(struct in_addr *pdns_addr)
35
{
36
    FIXED_INFO *FixedInfo=NULL;
37
    ULONG    BufLen;
38
    DWORD    ret;
39
    IP_ADDR_STRING *pIPAddr;
40
    struct in_addr tmp_addr;
41

    
42
    FixedInfo = (FIXED_INFO *)GlobalAlloc(GPTR, sizeof(FIXED_INFO));
43
    BufLen = sizeof(FIXED_INFO);
44

    
45
    if (ERROR_BUFFER_OVERFLOW == GetNetworkParams(FixedInfo, &BufLen)) {
46
        if (FixedInfo) {
47
            GlobalFree(FixedInfo);
48
            FixedInfo = NULL;
49
        }
50
        FixedInfo = GlobalAlloc(GPTR, BufLen);
51
    }
52

    
53
    if ((ret = GetNetworkParams(FixedInfo, &BufLen)) != ERROR_SUCCESS) {
54
        printf("GetNetworkParams failed. ret = %08x\n", (u_int)ret );
55
        if (FixedInfo) {
56
            GlobalFree(FixedInfo);
57
            FixedInfo = NULL;
58
        }
59
        return -1;
60
    }
61

    
62
    pIPAddr = &(FixedInfo->DnsServerList);
63
    inet_aton(pIPAddr->IpAddress.String, &tmp_addr);
64
    *pdns_addr = tmp_addr;
65
#if 0
66
    printf( "DNS Servers:\n" );
67
    printf( "DNS Addr:%s\n", pIPAddr->IpAddress.String );
68

69
    pIPAddr = FixedInfo -> DnsServerList.Next;
70
    while ( pIPAddr ) {
71
            printf( "DNS Addr:%s\n", pIPAddr ->IpAddress.String );
72
            pIPAddr = pIPAddr ->Next;
73
    }
74
#endif
75
    if (FixedInfo) {
76
        GlobalFree(FixedInfo);
77
        FixedInfo = NULL;
78
    }
79
    return 0;
80
}
81

    
82
#else
83

    
84
static int get_dns_addr(struct in_addr *pdns_addr)
85
{
86
    char buff[512];
87
    char buff2[256];
88
    FILE *f;
89
    int found = 0;
90
    struct in_addr tmp_addr;
91

    
92
    f = fopen("/etc/resolv.conf", "r");
93
    if (!f)
94
        return -1;
95

    
96
#ifdef DEBUG
97
    lprint("IP address of your DNS(s): ");
98
#endif
99
    while (fgets(buff, 512, f) != NULL) {
100
        if (sscanf(buff, "nameserver%*[ \t]%256s", buff2) == 1) {
101
            if (!inet_aton(buff2, &tmp_addr))
102
                continue;
103
            if (tmp_addr.s_addr == loopback_addr.s_addr)
104
                tmp_addr = our_addr;
105
            /* If it's the first one, set it to dns_addr */
106
            if (!found)
107
                *pdns_addr = tmp_addr;
108
#ifdef DEBUG
109
            else
110
                lprint(", ");
111
#endif
112
            if (++found > 3) {
113
#ifdef DEBUG
114
                lprint("(more)");
115
#endif
116
                break;
117
            }
118
#ifdef DEBUG
119
            else
120
                lprint("%s", inet_ntoa(tmp_addr));
121
#endif
122
        }
123
    }
124
    fclose(f);
125
    if (!found)
126
        return -1;
127
    return 0;
128
}
129

    
130
#endif
131

    
132
#ifdef _WIN32
133
static void slirp_cleanup(void)
134
{
135
    WSACleanup();
136
}
137
#endif
138

    
139
void slirp_init(void)
140
{
141
    //    debug_init("/tmp/slirp.log", DEBUG_DEFAULT);
142

    
143
#ifdef _WIN32
144
    {
145
        WSADATA Data;
146
        WSAStartup(MAKEWORD(2,0), &Data);
147
        atexit(slirp_cleanup);
148
    }
149
#endif
150

    
151
    link_up = 1;
152

    
153
    if_init();
154
    ip_init();
155

    
156
    /* Initialise mbufs *after* setting the MTU */
157
    m_init();
158

    
159
    /* set default addresses */
160
    inet_aton("127.0.0.1", &loopback_addr);
161

    
162
    if (get_dns_addr(&dns_addr) < 0) {
163
        dns_addr = loopback_addr;
164
        fprintf (stderr, "Warning: No DNS servers found\n");
165
    }
166

    
167
    inet_aton(CTL_SPECIAL, &special_addr);
168
    alias_addr.s_addr = special_addr.s_addr | htonl(CTL_ALIAS);
169
    getouraddr();
170
}
171

    
172
#define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
173
#define CONN_CANFRCV(so) (((so)->so_state & (SS_FCANTRCVMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
174
#define UPD_NFDS(x) if (nfds < (x)) nfds = (x)
175

    
176
/*
177
 * curtime kept to an accuracy of 1ms
178
 */
179
#ifdef _WIN32
180
static void updtime(void)
181
{
182
    struct _timeb tb;
183

    
184
    _ftime(&tb);
185
    curtime = (u_int)tb.time * (u_int)1000;
186
    curtime += (u_int)tb.millitm;
187
}
188
#else
189
static void updtime(void)
190
{
191
        gettimeofday(&tt, 0);
192

    
193
        curtime = (u_int)tt.tv_sec * (u_int)1000;
194
        curtime += (u_int)tt.tv_usec / (u_int)1000;
195

    
196
        if ((tt.tv_usec % 1000) >= 500)
197
           curtime++;
198
}
199
#endif
200

    
201
void slirp_select_fill(int *pnfds,
202
                       fd_set *readfds, fd_set *writefds, fd_set *xfds)
203
{
204
    struct socket *so, *so_next;
205
    struct timeval timeout;
206
    int nfds;
207
    int tmp_time;
208

    
209
    /* fail safe */
210
    global_readfds = NULL;
211
    global_writefds = NULL;
212
    global_xfds = NULL;
213

    
214
    nfds = *pnfds;
215
        /*
216
         * First, TCP sockets
217
         */
218
        do_slowtimo = 0;
219
        if (link_up) {
220
                /*
221
                 * *_slowtimo needs calling if there are IP fragments
222
                 * in the fragment queue, or there are TCP connections active
223
                 */
224
                do_slowtimo = ((tcb.so_next != &tcb) ||
225
                               ((struct ipasfrag *)&ipq != (struct ipasfrag *)ipq.next));
226

    
227
                for (so = tcb.so_next; so != &tcb; so = so_next) {
228
                        so_next = so->so_next;
229

    
230
                        /*
231
                         * See if we need a tcp_fasttimo
232
                         */
233
                        if (time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK)
234
                           time_fasttimo = curtime; /* Flag when we want a fasttimo */
235

    
236
                        /*
237
                         * NOFDREF can include still connecting to local-host,
238
                         * newly socreated() sockets etc. Don't want to select these.
239
                          */
240
                        if (so->so_state & SS_NOFDREF || so->s == -1)
241
                           continue;
242

    
243
                        /*
244
                         * Set for reading sockets which are accepting
245
                         */
246
                        if (so->so_state & SS_FACCEPTCONN) {
247
                                FD_SET(so->s, readfds);
248
                                UPD_NFDS(so->s);
249
                                continue;
250
                        }
251

    
252
                        /*
253
                         * Set for writing sockets which are connecting
254
                         */
255
                        if (so->so_state & SS_ISFCONNECTING) {
256
                                FD_SET(so->s, writefds);
257
                                UPD_NFDS(so->s);
258
                                continue;
259
                        }
260

    
261
                        /*
262
                         * Set for writing if we are connected, can send more, and
263
                         * we have something to send
264
                         */
265
                        if (CONN_CANFSEND(so) && so->so_rcv.sb_cc) {
266
                                FD_SET(so->s, writefds);
267
                                UPD_NFDS(so->s);
268
                        }
269

    
270
                        /*
271
                         * Set for reading (and urgent data) if we are connected, can
272
                         * receive more, and we have room for it XXX /2 ?
273
                         */
274
                        if (CONN_CANFRCV(so) && (so->so_snd.sb_cc < (so->so_snd.sb_datalen/2))) {
275
                                FD_SET(so->s, readfds);
276
                                FD_SET(so->s, xfds);
277
                                UPD_NFDS(so->s);
278
                        }
279
                }
280

    
281
                /*
282
                 * UDP sockets
283
                 */
284
                for (so = udb.so_next; so != &udb; so = so_next) {
285
                        so_next = so->so_next;
286

    
287
                        /*
288
                         * See if it's timed out
289
                         */
290
                        if (so->so_expire) {
291
                                if (so->so_expire <= curtime) {
292
                                        udp_detach(so);
293
                                        continue;
294
                                } else
295
                                        do_slowtimo = 1; /* Let socket expire */
296
                        }
297

    
298
                        /*
299
                         * When UDP packets are received from over the
300
                         * link, they're sendto()'d straight away, so
301
                         * no need for setting for writing
302
                         * Limit the number of packets queued by this session
303
                         * to 4.  Note that even though we try and limit this
304
                         * to 4 packets, the session could have more queued
305
                         * if the packets needed to be fragmented
306
                         * (XXX <= 4 ?)
307
                         */
308
                        if ((so->so_state & SS_ISFCONNECTED) && so->so_queued <= 4) {
309
                                FD_SET(so->s, readfds);
310
                                UPD_NFDS(so->s);
311
                        }
312
                }
313
        }
314

    
315
        /*
316
         * Setup timeout to use minimum CPU usage, especially when idle
317
         */
318

    
319
        /*
320
         * First, see the timeout needed by *timo
321
         */
322
        timeout.tv_sec = 0;
323
        timeout.tv_usec = -1;
324
        /*
325
         * If a slowtimo is needed, set timeout to 500ms from the last
326
         * slow timeout. If a fast timeout is needed, set timeout within
327
         * 200ms of when it was requested.
328
         */
329
        if (do_slowtimo) {
330
                /* XXX + 10000 because some select()'s aren't that accurate */
331
                timeout.tv_usec = ((500 - (curtime - last_slowtimo)) * 1000) + 10000;
332
                if (timeout.tv_usec < 0)
333
                   timeout.tv_usec = 0;
334
                else if (timeout.tv_usec > 510000)
335
                   timeout.tv_usec = 510000;
336

    
337
                /* Can only fasttimo if we also slowtimo */
338
                if (time_fasttimo) {
339
                        tmp_time = (200 - (curtime - time_fasttimo)) * 1000;
340
                        if (tmp_time < 0)
341
                           tmp_time = 0;
342

    
343
                        /* Choose the smallest of the 2 */
344
                        if (tmp_time < timeout.tv_usec)
345
                           timeout.tv_usec = (u_int)tmp_time;
346
                }
347
        }
348
        *pnfds = nfds;
349
}
350

    
351
void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
352
{
353
    struct socket *so, *so_next;
354
    int ret;
355

    
356
    global_readfds = readfds;
357
    global_writefds = writefds;
358
    global_xfds = xfds;
359

    
360
        /* Update time */
361
        updtime();
362

    
363
        /*
364
         * See if anything has timed out
365
         */
366
        if (link_up) {
367
                if (time_fasttimo && ((curtime - time_fasttimo) >= 2)) {
368
                        tcp_fasttimo();
369
                        time_fasttimo = 0;
370
                }
371
                if (do_slowtimo && ((curtime - last_slowtimo) >= 499)) {
372
                        ip_slowtimo();
373
                        tcp_slowtimo();
374
                        last_slowtimo = curtime;
375
                }
376
        }
377

    
378
        /*
379
         * Check sockets
380
         */
381
        if (link_up) {
382
                /*
383
                 * Check TCP sockets
384
                 */
385
                for (so = tcb.so_next; so != &tcb; so = so_next) {
386
                        so_next = so->so_next;
387

    
388
                        /*
389
                         * FD_ISSET is meaningless on these sockets
390
                         * (and they can crash the program)
391
                         */
392
                        if (so->so_state & SS_NOFDREF || so->s == -1)
393
                           continue;
394

    
395
                        /*
396
                         * Check for URG data
397
                         * This will soread as well, so no need to
398
                         * test for readfds below if this succeeds
399
                         */
400
                        if (FD_ISSET(so->s, xfds))
401
                           sorecvoob(so);
402
                        /*
403
                         * Check sockets for reading
404
                         */
405
                        else if (FD_ISSET(so->s, readfds)) {
406
                                /*
407
                                 * Check for incoming connections
408
                                 */
409
                                if (so->so_state & SS_FACCEPTCONN) {
410
                                        tcp_connect(so);
411
                                        continue;
412
                                } /* else */
413
                                ret = soread(so);
414

    
415
                                /* Output it if we read something */
416
                                if (ret > 0)
417
                                   tcp_output(sototcpcb(so));
418
                        }
419

    
420
                        /*
421
                         * Check sockets for writing
422
                         */
423
                        if (FD_ISSET(so->s, writefds)) {
424
                          /*
425
                           * Check for non-blocking, still-connecting sockets
426
                           */
427
                          if (so->so_state & SS_ISFCONNECTING) {
428
                            /* Connected */
429
                            so->so_state &= ~SS_ISFCONNECTING;
430

    
431
                            ret = send(so->s, &ret, 0, 0);
432
                            if (ret < 0) {
433
                              /* XXXXX Must fix, zero bytes is a NOP */
434
                              if (errno == EAGAIN || errno == EWOULDBLOCK ||
435
                                  errno == EINPROGRESS || errno == ENOTCONN)
436
                                continue;
437

    
438
                              /* else failed */
439
                              so->so_state = SS_NOFDREF;
440
                            }
441
                            /* else so->so_state &= ~SS_ISFCONNECTING; */
442

    
443
                            /*
444
                             * Continue tcp_input
445
                             */
446
                            tcp_input((struct mbuf *)NULL, sizeof(struct ip), so);
447
                            /* continue; */
448
                          } else
449
                            ret = sowrite(so);
450
                          /*
451
                           * XXXXX If we wrote something (a lot), there
452
                           * could be a need for a window update.
453
                           * In the worst case, the remote will send
454
                           * a window probe to get things going again
455
                           */
456
                        }
457

    
458
                        /*
459
                         * Probe a still-connecting, non-blocking socket
460
                         * to check if it's still alive
461
                           */
462
#ifdef PROBE_CONN
463
                        if (so->so_state & SS_ISFCONNECTING) {
464
                          ret = recv(so->s, (char *)&ret, 0,0);
465

    
466
                          if (ret < 0) {
467
                            /* XXX */
468
                            if (errno == EAGAIN || errno == EWOULDBLOCK ||
469
                                errno == EINPROGRESS || errno == ENOTCONN)
470
                              continue; /* Still connecting, continue */
471

    
472
                            /* else failed */
473
                            so->so_state = SS_NOFDREF;
474

    
475
                            /* tcp_input will take care of it */
476
                          } else {
477
                            ret = send(so->s, &ret, 0,0);
478
                            if (ret < 0) {
479
                              /* XXX */
480
                              if (errno == EAGAIN || errno == EWOULDBLOCK ||
481
                                  errno == EINPROGRESS || errno == ENOTCONN)
482
                                continue;
483
                              /* else failed */
484
                              so->so_state = SS_NOFDREF;
485
                            } else
486
                              so->so_state &= ~SS_ISFCONNECTING;
487

    
488
                          }
489
                          tcp_input((struct mbuf *)NULL, sizeof(struct ip),so);
490
                        } /* SS_ISFCONNECTING */
491
#endif
492
                }
493

    
494
                /*
495
                 * Now UDP sockets.
496
                 * Incoming packets are sent straight away, they're not buffered.
497
                 * Incoming UDP data isn't buffered either.
498
                 */
499
                for (so = udb.so_next; so != &udb; so = so_next) {
500
                        so_next = so->so_next;
501

    
502
                        if (so->s != -1 && FD_ISSET(so->s, readfds)) {
503
                            sorecvfrom(so);
504
                        }
505
                }
506
        }
507

    
508
        /*
509
         * See if we can start outputting
510
         */
511
        if (if_queued && link_up)
512
           if_start();
513

    
514
        /* clear global file descriptor sets.
515
         * these reside on the stack in vl.c
516
         * so they're unusable if we're not in
517
         * slirp_select_fill or slirp_select_poll.
518
         */
519
         global_readfds = NULL;
520
         global_writefds = NULL;
521
         global_xfds = NULL;
522
}
523

    
524
#define ETH_ALEN 6
525
#define ETH_HLEN 14
526

    
527
#define ETH_P_IP        0x0800                /* Internet Protocol packet        */
528
#define ETH_P_ARP        0x0806                /* Address Resolution packet        */
529

    
530
#define        ARPOP_REQUEST        1                /* ARP request                        */
531
#define        ARPOP_REPLY        2                /* ARP reply                        */
532

    
533
struct ethhdr
534
{
535
        unsigned char        h_dest[ETH_ALEN];        /* destination eth addr        */
536
        unsigned char        h_source[ETH_ALEN];        /* source ether addr        */
537
        unsigned short        h_proto;                /* packet type ID field        */
538
};
539

    
540
struct arphdr
541
{
542
        unsigned short        ar_hrd;                /* format of hardware address        */
543
        unsigned short        ar_pro;                /* format of protocol address        */
544
        unsigned char        ar_hln;                /* length of hardware address        */
545
        unsigned char        ar_pln;                /* length of protocol address        */
546
        unsigned short        ar_op;                /* ARP opcode (command)                */
547

    
548
         /*
549
          *         Ethernet looks like this : This bit is variable sized however...
550
          */
551
        unsigned char                ar_sha[ETH_ALEN];        /* sender hardware address        */
552
        unsigned char                ar_sip[4];                /* sender IP address                */
553
        unsigned char                ar_tha[ETH_ALEN];        /* target hardware address        */
554
        unsigned char                ar_tip[4];                /* target IP address                */
555
};
556

    
557
void arp_input(const uint8_t *pkt, int pkt_len)
558
{
559
    struct ethhdr *eh = (struct ethhdr *)pkt;
560
    struct arphdr *ah = (struct arphdr *)(pkt + ETH_HLEN);
561
    uint8_t arp_reply[ETH_HLEN + sizeof(struct arphdr)];
562
    struct ethhdr *reh = (struct ethhdr *)arp_reply;
563
    struct arphdr *rah = (struct arphdr *)(arp_reply + ETH_HLEN);
564
    int ar_op;
565
    struct ex_list *ex_ptr;
566

    
567
    ar_op = ntohs(ah->ar_op);
568
    switch(ar_op) {
569
    case ARPOP_REQUEST:
570
        if (!memcmp(ah->ar_tip, &special_addr, 3)) {
571
            if (ah->ar_tip[3] == CTL_DNS || ah->ar_tip[3] == CTL_ALIAS)
572
                goto arp_ok;
573
            for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
574
                if (ex_ptr->ex_addr == ah->ar_tip[3])
575
                    goto arp_ok;
576
            }
577
            return;
578
        arp_ok:
579
            /* XXX: make an ARP request to have the client address */
580
            memcpy(client_ethaddr, eh->h_source, ETH_ALEN);
581

    
582
            /* ARP request for alias/dns mac address */
583
            memcpy(reh->h_dest, pkt + ETH_ALEN, ETH_ALEN);
584
            memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 1);
585
            reh->h_source[5] = ah->ar_tip[3];
586
            reh->h_proto = htons(ETH_P_ARP);
587

    
588
            rah->ar_hrd = htons(1);
589
            rah->ar_pro = htons(ETH_P_IP);
590
            rah->ar_hln = ETH_ALEN;
591
            rah->ar_pln = 4;
592
            rah->ar_op = htons(ARPOP_REPLY);
593
            memcpy(rah->ar_sha, reh->h_source, ETH_ALEN);
594
            memcpy(rah->ar_sip, ah->ar_tip, 4);
595
            memcpy(rah->ar_tha, ah->ar_sha, ETH_ALEN);
596
            memcpy(rah->ar_tip, ah->ar_sip, 4);
597
            slirp_output(arp_reply, sizeof(arp_reply));
598
        }
599
        break;
600
    default:
601
        break;
602
    }
603
}
604

    
605
void slirp_input(const uint8_t *pkt, int pkt_len)
606
{
607
    struct mbuf *m;
608
    int proto;
609

    
610
    if (pkt_len < ETH_HLEN)
611
        return;
612

    
613
    proto = ntohs(*(uint16_t *)(pkt + 12));
614
    switch(proto) {
615
    case ETH_P_ARP:
616
        arp_input(pkt, pkt_len);
617
        break;
618
    case ETH_P_IP:
619
        m = m_get();
620
        if (!m)
621
            return;
622
        /* Note: we add to align the IP header */
623
        m->m_len = pkt_len + 2;
624
        memcpy(m->m_data + 2, pkt, pkt_len);
625

    
626
        m->m_data += 2 + ETH_HLEN;
627
        m->m_len -= 2 + ETH_HLEN;
628

    
629
        ip_input(m);
630
        break;
631
    default:
632
        break;
633
    }
634
}
635

    
636
/* output the IP packet to the ethernet device */
637
void if_encap(const uint8_t *ip_data, int ip_data_len)
638
{
639
    uint8_t buf[1600];
640
    struct ethhdr *eh = (struct ethhdr *)buf;
641

    
642
    if (ip_data_len + ETH_HLEN > sizeof(buf))
643
        return;
644

    
645
    memcpy(eh->h_dest, client_ethaddr, ETH_ALEN);
646
    memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 1);
647
    /* XXX: not correct */
648
    eh->h_source[5] = CTL_ALIAS;
649
    eh->h_proto = htons(ETH_P_IP);
650
    memcpy(buf + sizeof(struct ethhdr), ip_data, ip_data_len);
651
    slirp_output(buf, ip_data_len + ETH_HLEN);
652
}
653

    
654
int slirp_redir(int is_udp, int host_port,
655
                struct in_addr guest_addr, int guest_port)
656
{
657
    if (is_udp) {
658
        if (!udp_listen(htons(host_port), guest_addr.s_addr,
659
                        htons(guest_port), 0))
660
            return -1;
661
    } else {
662
        if (!solisten(htons(host_port), guest_addr.s_addr,
663
                      htons(guest_port), 0))
664
            return -1;
665
    }
666
    return 0;
667
}
668

    
669
int slirp_add_exec(int do_pty, const char *args, int addr_low_byte,
670
                  int guest_port)
671
{
672
    return add_exec(&exec_list, do_pty, (char *)args,
673
                    addr_low_byte, htons(guest_port));
674
}