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 <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <netdb.h>
#include <string.h>


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 <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <netdb.h>
#include <string.h>
#include <errno.h>
#include <syslog.h>
#include <stdarg.h>

#include <poll.h>


void doit()
{
        printf("child forked end ended\n");
}

main(int argc, char **argv)
{
        struct sockaddr_in6 from;
        struct addrinfo req, *ans, *ans2;
        int    code, 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].revents = 0;
                fds[1].fd = sockFd2;    /* will not be poll'ed if -1 */
                fds[1].events = POLLIN | POLLPRI;
                fds[1].revents = 0;

                polled = poll(fds, 2, INFTIM);
                printf("poll fds ready: (IPv6) %d (IPv4) %d\n", fds[0].revents, 
fds[1].revents);
                
                /* this is rather dirty, because both fds could be ready and 
this would always prefer the 2nd fd */

                if( fds[0].revents )
                        readyFd = fds[0].fd;
                if( fds[1].revents )
                        readyFd = fds[1].fd;

                newsockFd = accept(readyFd, (struct sockaddr *)&from, &len);
                if (newsockFd < 0) {
                        perror("accept");
                        exit(-1);
                } 
                
                if (fork() == 0) {
                        close(readyFd);
                        (void) doit(newsockFd, &from);
                        exit(0);
                } 
                close(newsockFd);
        }

         /* Free answers after use */
         
        freeaddrinfo(ans);
        exit(0);
}
-- 
Matthias Apitz
e <g...@unixarea.de> - w http://www.unixarea.de/
UNIX since V7 on PDP-11, UNIX on mainframe since ESER 1055 (IBM /370)
UNIX on x86 since SVR4.2 UnixWare 2.1.2, FreeBSD since 2.2.5
_______________________________________________
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"

Reply via email to