Re: IPv6 && getaddrinfo(3C)
El día Thursday, July 12, 2012 a las 09:01:50PM -0500, Robert Bonomi escribió: > > > req.ai_flags = AI_ADDRCONFIG|AI_NUMERICHOST; > > > req.ai_family = AF_INET6;/* Same as AF_INET6. */ > > Isn't the setting of 'req.ai_family', above, going to guarantee that > something that "looks like" an IPv4 address will not be considered valid? > > After all, what *POSSIBLE* _IPv6_info_ is there about an IPv4 address? > > Per the manpage example, try PF_UNSPEC. With PF_UNSPEC it works fine now, thanks for the hint; I'm attaching the code for the client and as well one for a server creating LISTEN on IPv6 and IPv4 at the same time and handling the connections on both ports; HIH matthias /* IPv6 client code using getaddrinfo */ #include #include #include #include #include #include #include main(int argc, char **argv) { struct addrinfo req, *ans; int code, s, n; char buf[1024]; memset(&req, 0, sizeof(req)); req.ai_flags = 0; /* may be restricted to AI_ADDRCONFIG|AI_NUMERICHOST|... */ /* req.ai_family = AF_INET6;/* validates only AF_INET6 */ /* req.ai_family = AF_INET; /* validates only AF_INET, i.e. IPv4 */ req.ai_family = PF_UNSPEC; /* validates IPv4 and IPv6. */ req.ai_socktype = SOCK_STREAM; /* Use protocol TCP */ req.ai_protocol = IPPROTO_TCP; /* 0: any, IPPROTO_UDP: UDP */ printf("host: %s\n", argv[1]); if ((code = getaddrinfo(argv[1], "ssh", &req, &ans)) != 0) { fprintf(stderr, "ssh: getaddrinfo failed code %d: %s\n", code, gai_strerror(code)); exit(1); } /* 'ans' must contain at least one addrinfo, use the first */ s = socket(ans->ai_family, ans->ai_socktype, ans->ai_protocol); if (s < 0) { perror("ssh: socket"); exit(3); } /* Connect does the bind for us */ if (connect(s, ans->ai_addr, ans->ai_addrlen) < 0) { perror("ssh: connect"); exit(5); } /* just for test: read in SSH' good morning message */ n = read(s, buf, 1024); printf ("read: %s", buf); /* Free answers after use */ freeaddrinfo(ans); exit(0); } /* IPv6 server code using getaddrinfo */ #include #include #include #include #include #include #include #include #include #include #include void doit() { printf("child forked end ended\n"); } main(int argc, char **argv) { struct sockaddr_in6 from; struct addrinfo req, *ans, *ans2; intcode, sockFd1, sockFd2, len; /* Set ai_flags to AI_PASSIVE to indicate that return addres s is suitable for bind() */ memset(&req, 0, sizeof(req)); req.ai_flags = AI_PASSIVE; req.ai_family = PF_UNSPEC; /* IPv6+IPv4: PF_UNSPEC, IPv4: PF_INET */ req.ai_socktype = SOCK_STREAM; req.ai_protocol = IPPROTO_TCP; #define SLNP "3025" if ((code = getaddrinfo(NULL, SLNP, &req, &ans)) != 0) { fprintf(stderr, "SLNP (%s): getaddrinfo failed code %d: %s\n", SLNP, code, gai_strerror(code)); exit(1); } /* 'ans' must contain at least one addrinfo and we use the first. */ /* it seems(!) that 1st one is the IPv6 when we use PF_UNSPEC */ if( (sockFd1 = socket(ans->ai_family, ans->ai_socktype, ans->ai_protocol)) < 0) { perror("socket"); exit(-1); } if (bind(sockFd1, ans->ai_addr, ans->ai_addrlen) < 0) { perror("bind"); close(sockFd1); exit(-1); } /* create the 1st LISTEN */ printf("1st (IPv6) LISTEN...\n"); listen(sockFd1, 5); /* if there is a 2nd addrinfo provided by getaddrinfo(3C) and we will create 2nd socket... */ ans2 = NULL; if( ans->ai_next != NULL ) ans2 = ans->ai_next; sockFd2 = -1; /* set to -1 to be used as this in poll, see below */ if( ans2 != NULL ) { if( (sockFd2 = socket(ans2->ai_family, ans2->ai_socktype, ans2->ai_protocol)) < 0) { perror("socket"); exit(-1); } if (bind(sockFd2, ans2->ai_addr, ans2->ai_addrlen) < 0) { perror("bind"); close(sockFd2); exit(-1); } printf("2nd (IPv4) LISTEN...\n"); listen(sockFd2, 5); } for (;;) { int newsockFd, len = sizeof(from), readyFd, polled; struct pollfd fds[2]; /* we poll both fds for events and accept the one which is ready */ fds[0].fd = sockFd1; fds[0].events = POLLIN | POLLPRI; fds[0].revent
Re: IPv6 && getaddrinfo(3C)
> From: Doug Hardie > Date: Thu, 12 Jul 2012 14:21:38 -0700 > Subject: Re: IPv6 && getaddrinfo(3C) > > On 12 July 2012, at 07:24, Matthias Apitz wrote: > > > Hello, > > > > I'm playing around with IPv6 code on a FreeBSD 9 system and can't get > > getaddrinfo(3C) to do what it should do as stated in its man page: > > accept an IPv6 and IPv4 IP addr, it only works with the IPv6 form: > > > > $ ./a.out ::1 > > host: ::1 read: SSH-2.0-OpenSSH_5.6p1 FreeBSD-2010 > > $ ./a.out 127.0.0.1 > > host: 127.0.0.1 ssh: getaddrinfo failed code 8: hostname nor servname > > provided, or not known > > $ telnet 127.0.0.1 22 > > Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. > > SSH-2.0-OpenSSH_5.6p1 FreeBSD-2010 > > > > the used C-code is attached below; what I'm doing wrong in the code? > > > > Thanks > > > > matthias > > > > /* IPv6 client code using getaddrinfo */ > > > > #include > > #include > > #include > > #include > > #include > > #include > > #include > > > > > > main(argc, argv)/* client side */ > > intargc; char *argv[]; > > { > > > > struct addrinforeq, *ans; int code, s, n; char buf[1024]; > > > > memset(&req, 0, sizeof(req)); > > req.ai_flags = AI_ADDRCONFIG|AI_NUMERICHOST; > > req.ai_family = AF_INET6; /* Same as AF_INET6. */ Isn't the setting of 'req.ai_family', above, going to guarantee that something that "looks like" an IPv4 address will not be considered valid? After all, what *POSSIBLE* _IPv6_info_ is there about an IPv4 address? Per the manpage example, try PF_UNSPEC. ___ freebsd-questions@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/freebsd-questions To unsubscribe, send any mail to "freebsd-questions-unsubscr...@freebsd.org"
Re: IPv6 && getaddrinfo(3C)
On 12 July 2012, at 07:24, Matthias Apitz wrote: > > Hello, > > I'm playing around with IPv6 code on a FreeBSD 9 system and can't get > getaddrinfo(3C) to do what it should do as stated in its man page: > accept an IPv6 and IPv4 IP addr, it only works with the IPv6 form: > > $ ./a.out ::1 > host: ::1 > read: SSH-2.0-OpenSSH_5.6p1 FreeBSD-2010 > $ ./a.out 127.0.0.1 > host: 127.0.0.1 > ssh: getaddrinfo failed code 8: hostname nor servname provided, or not known > $ telnet 127.0.0.1 22 > Trying 127.0.0.1... > Connected to localhost. > Escape character is '^]'. > SSH-2.0-OpenSSH_5.6p1 FreeBSD-2010 > > the used C-code is attached below; what I'm doing wrong in the code? > > Thanks > > matthias > > /* IPv6 client code using getaddrinfo */ > > #include > #include > #include > #include > #include > #include > #include > > > main(argc, argv) /* client side */ > int argc; > char *argv[]; > { > > struct addrinfo req, *ans; > int code, s, n; > char buf[1024]; > > memset(&req, 0, sizeof(req)); > req.ai_flags = AI_ADDRCONFIG|AI_NUMERICHOST; > req.ai_family = AF_INET6; /* Same as AF_INET6. */ > req.ai_socktype = SOCK_STREAM; > > /* */ > /* Use default protocol (in this case tcp) */ > /* */ > > req.ai_protocol = 0; > > printf("host: %s\n", argv[1]); > if ((code = getaddrinfo(argv[1], "ssh", &req, &ans)) != 0) { > fprintf(stderr, "ssh: getaddrinfo failed code %d: %s\n", code, > gai_strerror(code)); > exit(1); > } > > > /* */ > /* ans must contain at least one addrinfo, use */ > /* the first. */ > /* */ > > s = socket(ans->ai_family, ans->ai_socktype, ans->ai_protocol); > if (s < 0) { > perror("ssh: socket"); > exit(3); > } > > /* Connect does the bind for us */ > > if (connect(s, ans->ai_addr, ans->ai_addrlen) < 0) { > perror("ssh: connect"); > exit(5); > } > > n = read(s, buf, 1024); > printf ("read: %s", buf); > > /* */ > /* Free answers after use */ > /* */ > freeaddrinfo(ans); > > exit(0); > } > > I won't claim to be an expert on this, but I have used getaddrinfo successfully in servers. The only thing I see that might be an issue is the use of zero for ai_protocol. The comment in the man page implies that value is for servers and not clients. I suspect you have to set the specific protocol you want. You haven't included AI_PASSIVE so I suspect its expecting you to use the address to contact a server. ___ freebsd-questions@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/freebsd-questions To unsubscribe, send any mail to "freebsd-questions-unsubscr...@freebsd.org"