Partage
  • Partager sur Facebook
  • Partager sur Twitter

[Serveur IPV6] bind: invalid argument (EINVAL)

programmation socket

    30 mai 2013 à 12:43:39

    Bonjour,

    Je vien demander de l'aide dans ce forum car je suis en train de programmer un serveur qui fonctionne avec IPV6.
    Après avoir trouvé de nombreux exemple, j'ai créé le mien qui est tout simple et qui pourtant ne fonctionne pas.

    Le problème vien de l'appel à l'appel système bind(). il me retourne l'erreur "invalid argument", qui correspond par ailleur au code errno EINVAL.

    voicie mon code qui est non fonctionnel, il est compilé sous linux avec gcc:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <sys/socket.h>
    #include <netdb.h>
    #include <arpa/inet.h>
    #include <errno.h>
     
     
    #define PORT	4000
    //#define	IP_LO			"::1"
    //#define	IP_SERV 		"fe80::2c0:caff:fe32:3de5"
     
     
    int main()
    {
    	char ip[50];
    	char HostName[100];
     
    	struct sockaddr_in6 from;
    	struct sockaddr_in6 server;
    	struct addrinfo hints, *res;
    	struct sockaddr_in6 *extract;
     
    	int sockS=0, sockC=0;
    	int ecode=0;
    	socklen_t len =  sizeof(server);
    	void *addr = NULL;
     
     
    	memset( &ip, 0, sizeof(ip) );
    	memset( &hints, 0, sizeof hints );
    	memset( &HostName, 0, sizeof(HostName) ); 
    	memset( &from, 0, sizeof(struct sockaddr_in6) );
    	memset( &server, 0, sizeof(struct sockaddr_in6) );	
     
    			// récupére l'IP de la machine
    	if(gethostname( HostName, sizeof(HostName) ) == -1)
    	{
    		perror("gethostname");
    		exit(1);
    	}
     
    	hints.ai_socktype = SOCK_STREAM;
    	hints.ai_family = PF_INET6;
     
            if((ecode = getaddrinfo(HostName, NULL, &hints, &res)) != 0) 
    	{
    		fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(ecode));
    		exit(1);
            }
     
    	extract = (struct sockaddr_in6 *)res->ai_addr; 
    	addr = &(extract->sin6_addr);
     
    	inet_ntop(PF_INET6, addr, ip, sizeof(ip));
     
     
    			/*	remplie la structure du server	*/
    	server.sin6_family = PF_INET6;
    	server.sin6_port = htons(PORT);
    	server.sin6_flowinfo = 0;
     
    	if( (ecode = inet_pton(PF_INET6, ip, &(server.sin6_addr))) == 1 )
    	{
    		puts(" :: IP OK ::");
    	}
    	else
    	{
    		puts(" :: Invalid Adresse or Adresse family ::");	
    	}
     
    /* debugage: affiche bien l'adresse IPV6 de ma machine */
    inet_ntop(PF_INET6, &(server.sin6_addr), ip, INET6_ADDRSTRLEN);
    printf("::<%s>::\n", ip);
     
     
    			/*	construit le serveur	*/
    	if((sockS = socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP)) == -1) 
    	{
    		perror("socket");
    		exit(1);
    	}
     
    	if(bind(sockS,  (struct sockaddr*)&server, sizeof(server)) != 0)
    	{		
    		perror("bind");
    		exit(1);
    	}
     
    	if( listen(sockS, 4) == -1)
    	{
    		perror("listen");
    		exit(1);
    	}
     
    	if( (sockC = accept(sockS, (struct sockaddr *)&from, &len)) == -1)
    	{
    		perror("accept");
    		exit(1);
    	}
    	else	puts("connection OK");
     
     
    	return 0;
    }


    Je n'ai pas trouvé de réponse sur d'autre forum, voilà pourquoi je me tourne vers vous.

    Je pense que j'ai fais une grossière erreur pourtant je trouve rien qui cloche au niveau du code. Je précise par ailleur que ce serveur marche très bien lorsque je tente de lié à l'interface local que j'ai mis en haut "#define IP_LO "::1"".


    Merci d'avance de votre aide. =-)

    • Partager sur Facebook
    • Partager sur Twitter
      30 mai 2013 à 14:40:47

      Salut,
      Est-ce que tu es sous Unixoïdes (GNU/Linux, *BSD, Solaris ou Mac OS) ? Si oui, tu peux afficher les lignes contenant ton nom d'hôte au sein du fichier /etc/hosts (à l'aide de la commande cat /etc/hosts | grep <hostname> par exemple) ?
      Sinon, il me semble que ton passage par getaddrinfo n'est pas nécessaire, tu peux utiliser l'adresse « joker » "::" pour recevoir les paquets à destination de ta machine.
      EDIT: je pense que le problème se situe à la ligne 57 : tu dois utiliser la constante INET6_ADDRSTRLEN et non sizeof(ip) comme dernier argument de inet_ntop.

      -
      Edité par Taurre 30 mai 2013 à 15:21:33

      • Partager sur Facebook
      • Partager sur Twitter
        30 mai 2013 à 15:45:25

        Bonjour Taurre, je te remercie de ton aide.
        
        Mon problème est résolue et effectivement je suis sous un Unixoïdes (archlinux).
        
        En faite le code si-dessus est parfaitement fonctionnel à condition d'avoir son système 
        bien configurer. J'ai obtenue la réponse sur un autre forum, le problème était que j'avais uniquement
        une adresse IPv6 liée au lien physique et aucune IPv6 associée à mon interface.
        Pour le résoudre il fallait ajouter une IPv6 à mon interface. (En faite à la ligne 57 cela marche très bien, j'ai juste crée un tableau
        bien plus grand que ce qu'il faut c'est tout =-) ) Mercie encore pour le dérangement.
        ps: désolé d'avoir écrit dans une balise de code mais ma réponse ne passait
        pas entièrement (mystérieux).

        -
        Edité par rasta69 30 mai 2013 à 15:51:58

        • Partager sur Facebook
        • Partager sur Twitter

        [Serveur IPV6] bind: invalid argument (EINVAL)

        × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
        × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
        • Editeur
        • Markdown