~ubuntu-branches/ubuntu/hardy/klibc/hardy-updates

« back to all changes in this revision

Viewing changes to usr/kinit/ipconfig/main.c

  • Committer: Bazaar Package Importer
  • Author(s): Jeff Bailey
  • Date: 2006-01-04 20:24:52 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20060104202452-ec4v3n829rymukuv
Tags: 1.1.15-0ubuntu1
* New upstream version.

* Patch to fix compilation on parisc64 kernels.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * ipconfig/main.c
 
3
 */
 
4
#include <errno.h>
 
5
#include <poll.h>
 
6
#include <limits.h>
 
7
#include <stdio.h>
 
8
#include <string.h>
 
9
#include <stdlib.h>
 
10
#include <time.h>
 
11
#include <arpa/inet.h>
 
12
#include <sys/types.h>
 
13
#include <sys/time.h>
 
14
#include <dirent.h>
 
15
#include <fcntl.h>
 
16
#include <unistd.h>     /* for getopts */
 
17
 
 
18
#include <net/if_arp.h>
 
19
 
 
20
#include "ipconfig.h"
 
21
#include "netdev.h"
 
22
#include "bootp_packet.h"
 
23
#include "bootp_proto.h"
 
24
#include "dhcp_proto.h"
 
25
#include "packet.h"
 
26
 
 
27
static const char sysfs_class_net[] = "/sys/class/net";
 
28
static const char *progname;
 
29
static char do_not_config;
 
30
static unsigned int default_caps = CAP_DHCP | CAP_BOOTP | CAP_RARP;
 
31
static int loop_timeout = -1;
 
32
static int configured;
 
33
 
 
34
struct state {
 
35
        int             state;
 
36
        int             restart_state;
 
37
        time_t          expire;
 
38
        int             retry_period;
 
39
 
 
40
        struct netdev   *dev;
 
41
        struct state    *next;
 
42
};
 
43
 
 
44
static inline const char *my_inet_ntoa(__u32 addr)
 
45
{
 
46
        struct in_addr a;
 
47
 
 
48
        a.s_addr = addr;
 
49
 
 
50
        return inet_ntoa(a);
 
51
}
 
52
 
 
53
static void print_device_config(struct netdev *dev)
 
54
{
 
55
        printf("IP-Config: %s complete (from %s):\n", dev->name,
 
56
                my_inet_ntoa(dev->serverid ? dev->serverid : dev->ip_server));
 
57
        printf(" address: %-16s ", my_inet_ntoa(dev->ip_addr));
 
58
        printf("broadcast: %-16s ", my_inet_ntoa(dev->ip_broadcast));
 
59
        printf("netmask: %-16s\n", my_inet_ntoa(dev->ip_netmask));
 
60
        printf(" gateway: %-16s ", my_inet_ntoa(dev->ip_gateway));
 
61
        printf("dns0     : %-16s ", my_inet_ntoa(dev->ip_nameserver[0]));
 
62
        printf("dns1   : %-16s\n", my_inet_ntoa(dev->ip_nameserver[1]));
 
63
        if (dev->hostname[0])
 
64
                printf(" host   : %-64s\n", dev->hostname);
 
65
        if (dev->dnsdomainname[0])
 
66
                printf(" domain : %-64s\n", dev->dnsdomainname);
 
67
        if (dev->nisdomainname[0])
 
68
                printf(" nisdomain: %-64s\n", dev->nisdomainname);
 
69
        printf(" rootserver: %s ", my_inet_ntoa(dev->ip_server));
 
70
        printf("rootpath: %s\n", dev->bootpath);
 
71
}
 
72
 
 
73
static void configure_device(struct netdev *dev)
 
74
{
 
75
        if (do_not_config)
 
76
                return;
 
77
 
 
78
        if (netdev_setmtu(dev))
 
79
                printf("IP-Config: failed to set MTU on %s to %u\n",
 
80
                       dev->name, dev->mtu);
 
81
 
 
82
        if (netdev_setaddress(dev))
 
83
                printf("IP-Config: failed to set addresses on %s\n", dev->name);
 
84
        if (netdev_setdefaultroute(dev))
 
85
                printf("IP-Config: failed to set default route on %s\n", dev->name);
 
86
}
 
87
 
 
88
static void dump_device_config(struct netdev *dev)
 
89
{
 
90
        char fn[40];
 
91
        FILE *f;
 
92
 
 
93
        snprintf(fn, sizeof(fn), "/tmp/net-%s.conf", dev->name);
 
94
        f = fopen(fn, "w");
 
95
        if (f) {
 
96
                fprintf(f, "DEVICE=%s\n", dev->name);
 
97
                fprintf(f, "IPV4ADDR=%s\n", my_inet_ntoa(dev->ip_addr));
 
98
                fprintf(f, "IPV4BROADCAST=%s\n", my_inet_ntoa(dev->ip_broadcast));
 
99
                fprintf(f, "IPV4NETMASK=%s\n", my_inet_ntoa(dev->ip_netmask));
 
100
                fprintf(f, "IPV4GATEWAY=%s\n", my_inet_ntoa(dev->ip_gateway));
 
101
                fprintf(f, "IPV4DNS0=%s\n", my_inet_ntoa(dev->ip_nameserver[0]));
 
102
                fprintf(f, "IPV4DNS1=%s\n", my_inet_ntoa(dev->ip_nameserver[1]));
 
103
                fprintf(f, "HOSTNAME=%s\n", dev->hostname);
 
104
                fprintf(f, "DNSDOMAIN=%s\n", dev->dnsdomainname);
 
105
                fprintf(f, "NISDOMAIN=%s\n", dev->nisdomainname);
 
106
                fprintf(f, "ROOTSERVER=%s\n", my_inet_ntoa(dev->ip_server));
 
107
                fprintf(f, "ROOTPATH=%s\n", dev->bootpath);
 
108
                fclose(f);
 
109
        }
 
110
}
 
111
 
 
112
static __u32 inet_class_netmask(__u32 ip)
 
113
{
 
114
        ip = ntohl(ip);
 
115
        if (IN_CLASSA(ip))
 
116
                return htonl(IN_CLASSA_NET);
 
117
        if (IN_CLASSB(ip))
 
118
                return htonl(IN_CLASSB_NET);
 
119
        if (IN_CLASSC(ip))
 
120
                return htonl(IN_CLASSC_NET);
 
121
        return INADDR_ANY;
 
122
}
 
123
 
 
124
static void postprocess_device(struct netdev *dev)
 
125
{
 
126
        if (dev->ip_netmask == INADDR_ANY) {
 
127
                dev->ip_netmask = inet_class_netmask(dev->ip_addr);
 
128
                printf("IP-Config: %s guessed netmask %s\n",
 
129
                        dev->name, my_inet_ntoa(dev->ip_netmask));
 
130
        }
 
131
        if (dev->ip_broadcast == INADDR_ANY) {
 
132
                dev->ip_broadcast = (dev->ip_addr & dev->ip_netmask) | ~dev->ip_netmask;
 
133
                printf("IP-Config: %s guessed broadcast address %s\n",
 
134
                        dev->name, my_inet_ntoa(dev->ip_broadcast));
 
135
        }
 
136
        if (dev->ip_nameserver[0] == INADDR_ANY) {
 
137
                dev->ip_nameserver[0] = dev->ip_server;
 
138
                printf("IP-Config: %s guessed nameserver address %s\n",
 
139
                        dev->name, my_inet_ntoa(dev->ip_nameserver[0]));
 
140
        }
 
141
}
 
142
 
 
143
static void complete_device(struct netdev *dev)
 
144
{
 
145
        postprocess_device(dev);
 
146
        configure_device(dev);
 
147
        dump_device_config(dev);
 
148
        print_device_config(dev);
 
149
 
 
150
        ++configured;
 
151
 
 
152
        dev->next = ifaces;
 
153
        ifaces = dev;
 
154
}
 
155
 
 
156
static int process_receive_event(struct state *s, time_t now)
 
157
{
 
158
        int handled = 1;
 
159
 
 
160
        switch (s->state) {
 
161
        case DEVST_BOOTP:
 
162
                s->restart_state = DEVST_BOOTP;
 
163
                switch (bootp_recv_reply(s->dev)) {
 
164
                case -1:
 
165
                        s->state = DEVST_ERROR;
 
166
                        break;
 
167
                case 1:
 
168
                        s->state = DEVST_COMPLETE;
 
169
                        DEBUG(("\n   bootp reply\n"));
 
170
                        break;
 
171
                }
 
172
                break;
 
173
 
 
174
        case DEVST_DHCPDISC:
 
175
                s->restart_state = DEVST_DHCPDISC;
 
176
                switch (dhcp_recv_offer(s->dev)) {
 
177
                case -1:
 
178
                        s->state = DEVST_ERROR;
 
179
                        break;
 
180
                case 1: /* Offer received */
 
181
                        s->state = DEVST_DHCPREQ;
 
182
                        dhcp_send_request(s->dev);
 
183
                        break;
 
184
                }
 
185
                break;
 
186
 
 
187
        case DEVST_DHCPREQ:
 
188
                s->restart_state = DEVST_DHCPDISC;
 
189
                switch (dhcp_recv_ack(s->dev)) {
 
190
                case -1: /* error */
 
191
                        s->state = DEVST_ERROR;
 
192
                        break;
 
193
                case 1: /* ACK received */
 
194
                        s->state = DEVST_COMPLETE;
 
195
                        break;
 
196
                case 2: /* NAK received */
 
197
                        s->state = DEVST_DHCPDISC;
 
198
                        break;
 
199
                }
 
200
                break;
 
201
        }
 
202
 
 
203
        switch (s->state) {
 
204
        case DEVST_COMPLETE:
 
205
                complete_device(s->dev);
 
206
                break;
 
207
 
 
208
        case DEVST_ERROR:
 
209
                /* error occurred, try again in 10 seconds */
 
210
                s->expire = now + 10;
 
211
        default:
 
212
                DEBUG(("\n"));
 
213
                handled = 0;
 
214
                break;
 
215
        }
 
216
 
 
217
        return handled;
 
218
}
 
219
 
 
220
static void process_timeout_event(struct state *s, time_t now)
 
221
{
 
222
        int ret = 0;
 
223
 
 
224
        /*
 
225
         * Is the link up?  If not, try again in 1 second.
 
226
         */
 
227
        if (!netdev_running(s->dev)) {
 
228
                s->expire = now + 1;
 
229
                s->state = s->restart_state;
 
230
                return;
 
231
        }
 
232
 
 
233
        /*
 
234
         * If we had an error, restore a sane state to
 
235
         * restart from.
 
236
         */
 
237
        if (s->state == DEVST_ERROR)
 
238
                s->state = s->restart_state;
 
239
 
 
240
        /*
 
241
         * Now send a packet depending on our state.
 
242
         */
 
243
        switch (s->state) {
 
244
        case DEVST_BOOTP:
 
245
                ret = bootp_send_request(s->dev);
 
246
                s->restart_state = DEVST_BOOTP;
 
247
                break;
 
248
 
 
249
        case DEVST_DHCPDISC:
 
250
                ret = dhcp_send_discover(s->dev);
 
251
                s->restart_state = DEVST_DHCPDISC;
 
252
                break;
 
253
 
 
254
        case DEVST_DHCPREQ:
 
255
                ret = dhcp_send_request(s->dev);
 
256
                s->restart_state = DEVST_DHCPDISC;
 
257
                break;
 
258
        }
 
259
 
 
260
        if (ret == -1) {
 
261
                s->state = DEVST_ERROR;
 
262
                s->expire = now + 10;
 
263
        } else {
 
264
                s->expire = now + s->retry_period;
 
265
 
 
266
                s->retry_period *= 2;
 
267
                if (s->retry_period > 60)
 
268
                        s->retry_period = 60;
 
269
        }
 
270
}
 
271
 
 
272
static struct state *slist;
 
273
struct netdev *ifaces;
 
274
 
 
275
static int do_pkt_recv(int pkt_fd, time_t now)
 
276
{
 
277
        int ifindex, ret;
 
278
        struct state *s;
 
279
 
 
280
        ret = packet_peek(&ifindex);
 
281
        if (ret < 0)
 
282
                goto bail;
 
283
 
 
284
        for (s = slist; s; s = s->next) {
 
285
                if (s->dev->ifindex == ifindex) {
 
286
                        ret |= process_receive_event(s, now);
 
287
                        break;
 
288
                }
 
289
        }
 
290
 
 
291
 bail:
 
292
        return ret;
 
293
}
 
294
 
 
295
static int loop(void)
 
296
{
 
297
#define NR_FDS  1
 
298
        struct pollfd fds[NR_FDS];
 
299
        struct state *s;
 
300
        int pkt_fd;
 
301
        int nr = 0;
 
302
        struct timeval now, prev;
 
303
        time_t start;
 
304
 
 
305
        pkt_fd = packet_open();
 
306
        if (pkt_fd == -1) {
 
307
                perror("packet_open");
 
308
                return -1;
 
309
        }
 
310
 
 
311
        fds[0].fd = pkt_fd;
 
312
        fds[0].events = POLLRDNORM;
 
313
 
 
314
        gettimeofday(&now, NULL);
 
315
        start = now.tv_sec;
 
316
        while (1) {
 
317
                int timeout = 60;
 
318
                int pending = 0;
 
319
                int timeout_ms;
 
320
                int x;
 
321
 
 
322
                for (s = slist; s; s = s->next) {
 
323
                        if (s->state == DEVST_COMPLETE)
 
324
                                continue;
 
325
 
 
326
                        pending++;
 
327
 
 
328
                        if (s->expire - now.tv_sec <= 0)
 
329
                                process_timeout_event(s, now.tv_sec);
 
330
 
 
331
                        if (timeout > s->expire - now.tv_sec)
 
332
                                timeout = s->expire - now.tv_sec;
 
333
                }
 
334
 
 
335
                if (pending == 0)
 
336
                        break;
 
337
 
 
338
                timeout_ms = timeout * 1000;
 
339
 
 
340
                for (x = 0; x < 2; x++) {
 
341
                        int delta_ms;
 
342
 
 
343
                        if (timeout_ms <= 0)
 
344
                                timeout_ms = 100;
 
345
 
 
346
                        nr = poll(fds, NR_FDS, timeout_ms);
 
347
                        prev = now;
 
348
                        gettimeofday(&now, NULL);
 
349
 
 
350
                        if ((fds[0].revents & POLLRDNORM)) {
 
351
                                nr = do_pkt_recv(pkt_fd, now.tv_sec);
 
352
                                if (nr == 1)
 
353
                                        break;
 
354
                                else if (nr == 0)
 
355
                                        packet_discard();
 
356
                        }
 
357
 
 
358
                        if (loop_timeout >= 0 &&
 
359
                            now.tv_sec - start >= loop_timeout) {
 
360
                                printf("IP-Config: no response after %d "
 
361
                                       "secs - giving up\n", loop_timeout);
 
362
                                goto bail;
 
363
                        }
 
364
 
 
365
                        delta_ms = (now.tv_sec - prev.tv_sec) * 1000;
 
366
                        delta_ms += (now.tv_usec - prev.tv_usec) / 1000;
 
367
 
 
368
                        DEBUG(("Delta: %d ms\n", delta_ms));
 
369
 
 
370
                        timeout_ms -= delta_ms;
 
371
                }
 
372
        }
 
373
 bail:
 
374
        packet_close();
 
375
 
 
376
        return 0;
 
377
}
 
378
 
 
379
static int add_one_dev(struct netdev *dev)
 
380
{
 
381
        struct state *state;
 
382
 
 
383
        state = malloc(sizeof(struct state));
 
384
        if (!state)
 
385
                return -1;
 
386
 
 
387
        state->dev = dev;
 
388
        state->expire = time(NULL);
 
389
        state->retry_period = 1;
 
390
 
 
391
        /*
 
392
         * Select the state that we start from.
 
393
         */
 
394
        if (dev->caps & CAP_DHCP && dev->ip_addr == INADDR_ANY) {
 
395
                state->restart_state = state->state = DEVST_DHCPDISC;
 
396
        } else if (dev->caps & CAP_DHCP) {
 
397
                state->restart_state = state->state = DEVST_DHCPREQ;
 
398
        } else if (dev->caps & CAP_BOOTP) {
 
399
                state->restart_state = state->state = DEVST_BOOTP;
 
400
        }
 
401
 
 
402
        state->next = slist;
 
403
        slist = state;
 
404
 
 
405
        return 0;
 
406
}
 
407
 
 
408
static void parse_addr(__u32 *addr, const char *ip)
 
409
{
 
410
        struct in_addr in;
 
411
        if (inet_aton(ip, &in) == 0) {
 
412
                fprintf(stderr, "%s: can't parse IP address '%s'\n",
 
413
                        progname, ip);
 
414
                exit(1);
 
415
        }
 
416
        *addr = in.s_addr;
 
417
}
 
418
 
 
419
static unsigned int parse_proto(const char *ip)
 
420
{
 
421
        unsigned int caps = 0;
 
422
 
 
423
        if (*ip == '\0' || strcmp(ip, "on") == 0 || strcmp(ip, "any") == 0)
 
424
                caps = CAP_BOOTP | CAP_DHCP | CAP_RARP;
 
425
        else if (strcmp(ip, "both") == 0)
 
426
                caps = CAP_BOOTP | CAP_RARP;
 
427
        else if (strcmp(ip, "dhcp") == 0)
 
428
                caps = CAP_BOOTP | CAP_DHCP;
 
429
        else if (strcmp(ip, "bootp") == 0)
 
430
                caps = CAP_BOOTP;
 
431
        else if (strcmp(ip, "rarp") == 0)
 
432
                caps = CAP_RARP;
 
433
        else if (strcmp(ip, "none") == 0 || strcmp(ip, "static") == 0 || strcmp(ip, "off") == 0)
 
434
                goto bail;
 
435
        else {
 
436
                fprintf(stderr, "%s: invalid protocol '%s'\n",
 
437
                        progname, ip);
 
438
                exit(1);
 
439
        }
 
440
 bail:
 
441
        return caps;
 
442
}
 
443
 
 
444
static int add_all_devices(struct netdev *template);
 
445
 
 
446
static int parse_device(struct netdev *dev, const char *ip)
 
447
{
 
448
        char *cp;
 
449
        int i, opt;
 
450
 
 
451
        if (strncmp(ip, "ip=", 3) == 0) {
 
452
                ip += 3;
 
453
        }
 
454
        else if (strncmp(ip, "nfsaddrs=", 9) == 0) {
 
455
                ip += 9;
 
456
        }
 
457
 
 
458
        if (strchr(ip, ':') == NULL) {
 
459
                dev->name = ip;
 
460
                goto done;
 
461
        }
 
462
 
 
463
        for (i = opt = 0; ip && *ip; ip = cp, opt++) {
 
464
                if ((cp = strchr(ip, ':'))) {
 
465
                        *cp++ = '\0';
 
466
                }
 
467
                if (opt > 6) {
 
468
                        fprintf(stderr, "%s: too many options for %s\n",
 
469
                                progname, dev->name);
 
470
                        exit(1);
 
471
                }
 
472
 
 
473
                if (*ip == '\0')
 
474
                        continue;
 
475
                DEBUG(("IP-Config: opt #%d: '%s'\n", opt, ip));
 
476
                switch (opt) {
 
477
                case 0:
 
478
                        parse_addr(&dev->ip_addr, ip);
 
479
                        dev->caps = 0;
 
480
                        break;
 
481
                case 1:
 
482
                        parse_addr(&dev->ip_server, ip);
 
483
                        break;
 
484
                case 2:
 
485
                        parse_addr(&dev->ip_gateway, ip);
 
486
                        break;
 
487
                case 3:
 
488
                        parse_addr(&dev->ip_netmask, ip);
 
489
                        break;
 
490
                case 4:
 
491
                        strncpy(dev->hostname, ip, SYS_NMLN - 1);
 
492
                        dev->hostname[SYS_NMLN - 1] = '\0';
 
493
                        break;
 
494
                case 5:
 
495
                        dev->name = ip;
 
496
                        break;
 
497
                case 6:
 
498
                        dev->caps = parse_proto(ip);
 
499
                        break;
 
500
                }
 
501
        }
 
502
 done:
 
503
        if (dev->name == NULL ||
 
504
            dev->name[0] == '\0' ||
 
505
            strcmp(dev->name, "all") == 0) {
 
506
                add_all_devices(dev);
 
507
                return 0;
 
508
        }
 
509
        return 1;
 
510
}
 
511
 
 
512
static void bringup_device(struct netdev *dev)
 
513
{
 
514
        if (netdev_up(dev) == 0) {
 
515
                if (dev->caps) {
 
516
                        add_one_dev(dev);
 
517
                } else {
 
518
                        complete_device(dev);
 
519
                }
 
520
        }
 
521
}
 
522
 
 
523
static void bringup_one_dev(struct netdev *template, struct netdev *dev)
 
524
{
 
525
                if (template->ip_addr != INADDR_NONE)
 
526
                        dev->ip_addr = template->ip_addr;
 
527
                if (template->ip_server != INADDR_NONE)
 
528
                        dev->ip_server = template->ip_server;
 
529
                if (template->ip_gateway != INADDR_NONE)
 
530
                        dev->ip_gateway = template->ip_gateway;
 
531
                if (template->ip_netmask != INADDR_NONE)
 
532
                        dev->ip_netmask = template->ip_netmask;
 
533
                if (template->ip_nameserver[0] != INADDR_NONE)
 
534
                        dev->ip_nameserver[0] = template->ip_nameserver[0];
 
535
                if (template->ip_nameserver[1] != INADDR_NONE)
 
536
                        dev->ip_nameserver[1] = template->ip_nameserver[1];
 
537
                if (template->hostname[0] != '\0')
 
538
                        strcpy(dev->hostname, template->hostname);
 
539
                dev->caps &= template->caps;
 
540
 
 
541
                bringup_device(dev);
 
542
}
 
543
 
 
544
static struct netdev *add_device(const char *info)
 
545
{
 
546
        struct netdev *dev;
 
547
        int i;
 
548
 
 
549
        dev = malloc(sizeof(struct netdev));
 
550
        if (dev == NULL) {
 
551
                fprintf(stderr, "%s: out of memory\n", progname);
 
552
                exit(1);
 
553
        }
 
554
 
 
555
        memset(dev, 0, sizeof(struct netdev));
 
556
        dev->caps = default_caps;
 
557
 
 
558
        if (parse_device(dev, info) == 0)
 
559
                goto bail;
 
560
 
 
561
        if (netdev_init_if(dev) == -1)
 
562
                goto bail;
 
563
 
 
564
        if (bootp_init_if(dev) == -1)
 
565
                goto bail;
 
566
 
 
567
        printf("IP-Config: %s hardware address", dev->name);
 
568
        for (i = 0; i < dev->hwlen; i++)
 
569
                printf("%c%02x", i == 0 ? ' ' : ':', dev->hwaddr[i]);
 
570
        printf(" mtu %d%s%s\n", dev->mtu,
 
571
                dev->caps & CAP_DHCP  ? " DHCP"  :
 
572
                dev->caps & CAP_BOOTP ? " BOOTP" : "",
 
573
               dev->caps & CAP_RARP  ? " RARP"  : "");
 
574
        return dev;
 
575
 bail:
 
576
        free(dev);
 
577
        return NULL;
 
578
}
 
579
 
 
580
static int add_all_devices(struct netdev *template)
 
581
{
 
582
        DIR *d;
 
583
        struct dirent *de;
 
584
        struct netdev *dev;
 
585
        char t[PATH_MAX], p[255];
 
586
        int i, fd;
 
587
        unsigned long flags;
 
588
 
 
589
        d = opendir(sysfs_class_net);
 
590
        if (!d)
 
591
                return 0;
 
592
 
 
593
        while((de = readdir(d)) != NULL ) {
 
594
                /* This excludes devices beginning with dots or "dummy", as well as . or .. */
 
595
                if ( de->d_name[0] == '.' || !strcmp(de->d_name, "..") )
 
596
                        continue;
 
597
                i = snprintf(t, PATH_MAX-1, "%s/%s/flags", sysfs_class_net, de->d_name);
 
598
                if (i < 0 || i >= PATH_MAX-1)
 
599
                        continue;
 
600
                t[i] = '\0';
 
601
                fd = open(t, O_RDONLY);
 
602
                if (fd < 0) {
 
603
                        perror(t);
 
604
                        continue;
 
605
                }
 
606
                i = read(fd, &p, sizeof(p) - 1);
 
607
                close(fd);
 
608
                if (i < 0) {
 
609
                        perror(t);
 
610
                        continue;
 
611
                }
 
612
                p[i] = '\0';
 
613
                flags = strtoul(p, NULL, 0);
 
614
                /* Heuristic for if this is a reasonable boot interface.
 
615
                   This is the same
 
616
                   logic the in-kernel ipconfig uses... */
 
617
                if ( !(flags & IFF_LOOPBACK) &&
 
618
                     (flags & (IFF_BROADCAST|IFF_POINTOPOINT)) )
 
619
                {
 
620
                        if ( !(dev = add_device(de->d_name)) )
 
621
                                continue;
 
622
                        bringup_one_dev(template, dev);
 
623
                }
 
624
        }
 
625
        closedir(d);
 
626
        return 1;
 
627
}
 
628
 
 
629
static int check_autoconfig(void)
 
630
{
 
631
        int ndev = 0, nauto = 0;
 
632
        struct state *s;
 
633
 
 
634
        for (s = slist; s; s = s->next) {
 
635
                ndev++;
 
636
                if (s->dev->caps)
 
637
                        nauto++;
 
638
        }
 
639
 
 
640
        if (ndev == 0) {
 
641
                if (configured == 0) {
 
642
                        fprintf(stderr, "%s: no devices to configure\n",
 
643
                                progname);
 
644
                        exit(1);
 
645
                }
 
646
        }
 
647
 
 
648
        return nauto;
 
649
}
 
650
 
 
651
int main(int argc, char *argv[])
 
652
        __attribute__ ((weak, alias ("ipconfig_main")));
 
653
 
 
654
int ipconfig_main(int argc, char *argv[])
 
655
{
 
656
        struct netdev *dev;
 
657
        struct timeval now;
 
658
        int c, port;
 
659
 
 
660
        progname = argv[0];
 
661
 
 
662
        gettimeofday(&now, NULL);
 
663
        srand48(now.tv_usec ^ (now.tv_sec << 24));
 
664
 
 
665
        do {
 
666
                c = getopt(argc, argv, "c:d:np:t:");
 
667
                if (c == EOF)
 
668
                        break;
 
669
 
 
670
                switch (c) {
 
671
                case 'c':
 
672
                        default_caps = parse_proto(optarg);
 
673
                        break;
 
674
                case 'p':
 
675
                        port = atoi(optarg);
 
676
                        if (port <= 0 || port > USHRT_MAX) {
 
677
                                fprintf(stderr,
 
678
                                        "%s: invalid port number %d\n",
 
679
                                        progname, port);
 
680
                                exit(1);
 
681
                        }
 
682
                        cfg_local_port = port;
 
683
                        cfg_remote_port = cfg_local_port - 1;
 
684
                        break;
 
685
                case 't':
 
686
                        loop_timeout = atoi(optarg);
 
687
                        if (loop_timeout < 0) {
 
688
                                fprintf(stderr,
 
689
                                        "%s: invalid timeout %d\n",
 
690
                                        progname, loop_timeout);
 
691
                                exit(1);
 
692
                        }
 
693
                        break;
 
694
                case 'n':
 
695
                        do_not_config = 1;
 
696
                        break;
 
697
                case 'd':
 
698
                        dev = add_device(optarg);
 
699
                        if (dev)
 
700
                                bringup_device(dev);
 
701
                        break;
 
702
                case '?':
 
703
                        fprintf(stderr, "%s: invalid option -%c\n",
 
704
                                progname, optopt);
 
705
                        exit(1);
 
706
                }
 
707
        } while (1);
 
708
 
 
709
        for (c = optind; c < argc; c++) {
 
710
                dev = add_device(argv[c]);
 
711
                if (dev)
 
712
                        bringup_device(dev);
 
713
        }
 
714
 
 
715
        if (check_autoconfig()) {
 
716
                if (cfg_local_port != LOCAL_PORT) {
 
717
                        printf("IP-Config: binding source port to %d, "
 
718
                               "dest to %d\n",
 
719
                               cfg_local_port,
 
720
                               cfg_remote_port);
 
721
                }
 
722
                loop();
 
723
        }
 
724
 
 
725
        return 0;
 
726
}