Magellan Linux

Annotation of /trunk/mkinitrd-magellan/klibc/usr/kinit/ipconfig/main.c

Parent Directory Parent Directory | Revision Log Revision Log


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