Re: IPv6 && getaddrinfo(3C)

2012-07-13 Thread Matthias Apitz
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)

2012-07-12 Thread Robert Bonomi


> 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)

2012-07-12 Thread Doug Hardie

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"