- case 'h':
- help(stdout);
- exit(0);
- case 'v':
- version(stdout);
- exit(0);
- case 'u':
- usage(stdout);
- exit(0);
- case 'l':
- parseaddr(optarg, 0, &pt);
- cw.me.sin_port = pt;
- break;
- case 'p':
- parseaddr(optarg, &cw.peer, 0);
- break;
- case 'b':
- parseaddr(optarg, &bindaddr.sin_addr, 0);
- break;
- case 'c':
- parseaddr(optarg, &connaddr.sin_addr, &pt);
- connaddr.sin_port = pt;
- break;
- default:
- f |= f_bogus;
- break;
+ case 'h': help(stdout); exit(0);
+ case 'v': version(stdout); exit(0);
+ case 'u': usage(stdout); exit(0);
+ case '4': af = AF_INET; break;
+ case '6': af = AF_INET6; break;
+ case 'l': bindsvc = optarg; break;
+ case 'p': DA_PUSH(&peerhosts, optarg); break;
+ case 'b': DA_PUSH(&bindhosts, optarg); break;
+ case 'c': connhost = optarg; break;
+ default: f |= f_bogus; break;
+ }
+ }
+ if (optind + 2 != argc || (f&f_bogus)) { usage(stderr); exit(1); }
+
+ if (DA_LEN(&bindhosts) && !bindsvc && !connhost)
+ die(1, "bind addr only makes sense when listening or connecting");
+ if (DA_LEN(&peerhosts) && !bindsvc)
+ die(1, "peer addr only makes sense when listening");
+ if (bindsvc && connhost)
+ die(1, "can't listen and connect");
+
+ aihint.ai_family = af;
+ DA_CREATE(&cw.me); DA_CREATE(&cw.peer);
+
+ n = DA_LEN(&bindhosts);
+ if (n || bindsvc) {
+ aihint.ai_socktype = SOCK_STREAM;
+ aihint.ai_protocol = IPPROTO_TCP;
+ aihint.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;
+ if (!n) {
+ parseaddr(&aihint, 0, bindsvc, 0, &ailist);
+ pushaddrs(&cw.me, ailist);
+ freeaddrinfo(ailist);
+ } else if (!bindsvc) {
+ if (n != 1) die(1, "can only bind to one address as client");
+ parseaddr(&aihint, DA(&bindhosts)[0], 0, 0, &ailist);
+ for (ai = ailist; ai && !knownafp(ai->ai_family); ai = ai->ai_next);
+ if (!ai)
+ die(1, "no usable addresses returned for `%s'", DA(&bindhosts)[0]);
+ initaddr(&bindaddr, ai->ai_family);
+ copyaddr(&bindaddr, ai->ai_addr, caf_addr);
+ aihint.ai_family = ai->ai_family;
+ freeaddrinfo(ailist);
+ } else for (i = 0; i < n; i++) {
+ parseaddr(&aihint, DA(&bindhosts)[i], bindsvc, 0, &ailist);
+ pushaddrs(&cw.me, ailist);
+ freeaddrinfo(ailist);
+ }
+ if (bindsvc) {
+ cw.f |= cwf_port;
+ n = DA_LEN(&cw.me);
+ cw.sfv = xmalloc(n*sizeof(*cw.sfv));