Magellan Linux

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 532 - (show annotations) (download)
Sat Sep 1 22:45:15 2007 UTC (16 years, 8 months ago) by niro
File MIME type: text/plain
File size: 17182 byte(s)
-import if magellan mkinitrd; it is a fork of redhats mkinitrd-5.0.8 with all magellan patches and features; deprecates magellan-src/mkinitrd

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