Magellan Linux

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

Parent Directory Parent Directory | Revision Log Revision Log


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