-1

I am trying to create a client/server program(both programs lies on different machine and not on localhost) in C but the protocol used is IPv6 only. when i run the client,it pauses for sometime at the connect() and then fails.Why connect() is failing?

Server Code:

#include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<stdlib.h>
#include<unistd.h>
#include<netdb.h>
int main()
{
 int sockfd,connfd,rv;
 struct addrinfo hints,*servinfo,*p;
 struct sockaddr_in6 client_addr;

 memset(&hints,0,sizeof hints);

 hints.ai_family=AF_INET6;
 hints.ai_socktype=SOCK_STREAM;
 hints.ai_flags=AI_PASSIVE;


 if((rv=getaddrinfo(NULL,"8888",&hints,&servinfo))!=0)
 {      printf("\n Error 1 \n"); return 0; }


for(p=servinfo;p!=NULL;p=p->ai_next)
{

 if((sockfd=socket(servinfo->ai_family,servinfo->ai_socktype,0))==-1)
 {      perror("socket"); continue;}

 if(bind(sockfd,servinfo->ai_addr,servinfo->ai_addrlen)==-1)
 {      close(sockfd); perror("bind"); continue;}

  break;
}
 if(p==NULL)
{
 fprintf(stderr,"failed to bind");
 return 0;
}

  listen(sockfd,8);

  printf("\n\n Waiting for connection....\n");

  socklen_t size=sizeof(client_addr);

  if((connfd=accept(sockfd,(struct sockaddr *)&client_addr,&size))<0)
  {     printf("\n Error 4 \n"); return 0; }
  else
  {
       char ch[50];
       inet_ntop(AF_INET6,&(client_addr.sin6_addr),ch,50);
       printf("\n Connected to %s \n",ch);
  }

  close(sockfd);
  close(connfd);

  return 0;
}

Client Code:

#include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<stdlib.h>
#include<unistd.h>
#include<netdb.h>
int main()
{
 int i,s;

 struct addrinfo hints,*res,*p;

 memset(&hints,0,sizeof (hints));

 hints.ai_family=AF_INET6;
 hints.ai_socktype=SOCK_STREAM;

 i=getaddrinfo("fe80::20c:29ff:fe60:7593%eth0","8888",&hints,&res);//because the system in which server code is has IPv6 address fe80::20c:29ff:fe60:7593

 if(i!=0)
  { printf("\n Fail 1 \n"); return 0;}

 for(p=res;p!=NULL;p=p->ai_next)
 { 
   if((s=socket(res->ai_family,res->ai_socktype,0))==-1)
    {perror("socket"); continue;}

   if(connect(s,p->ai_addr,p->ai_addrlen)==-1)
    { close(s); perror("connect"); continue;}

   break;
 }

 if(p==NULL)
 {
  fprintf(stderr,"failed to connect\n");
   return 0;
  }

 close(s);
 return 0;
}
Shikhar Deep
  • 253
  • 2
  • 8
  • 19
  • 1
    Why indeed? Why are you asking us when you already know what perror() printed? NB you must call it immediately, before any other system call such as close(). – user207421 Jun 05 '14 at 18:45
  • thanks actually it was not printing the error,but as you told i call perror() immediately.error received:connection time out – Shikhar Deep Jun 06 '14 at 10:28
  • Actually it *was* printing an error, but the wrong one. You should have included all that information in your question. Without that, it's unanswerable. – user207421 Jun 06 '14 at 22:30

2 Answers2

2

firstly, can you ping that link-local address?
secondly, you are filling res structure and then iterating over it, but inside your for loop you always use res structure for socket() call, not p, which is your iterator.
it should look like this:

for(p=res;p!=NULL;p=p->ai_next)
 { 
   if((s=socket(p->ai_family,p->ai_socktype,p->ai_protocol))==-1)
    {perror("socket"); continue;}

   if(connect(s,p->ai_addr,p->ai_addrlen)==-1)
    { close(s); perror("connect"); continue;}

   break;
 }

you might have noticed that last argument of socket() call is not 0, but p->ai_protocol. since you want to handle only ipv6 connections and you specified in hints structure that you're interested in it, it is safer to pass it than 0.

there's a good practice to know what was wrong with calling getaddrinfo :

if(i!=0){                                                                  
    fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(i));                
    return 1;                                                            
}

from man getaddrinfo:

The gai_strerror() function translates these error codes to a human readable string, suitable for error reporting.

I was getting following error:

getaddrinfo: Name or service not known

I checked that i was not able to ping address that i was passing to getaddrinfo (i was passing wrong interface).

all in all, i managed to got your code working. i can connect from virtual machine to localhost. i have also specified what protocol are we interested in inside hints structure:

hints.ai_protocol = IPPROTO_TCP;
macfij
  • 3,093
  • 1
  • 19
  • 24
  • I made the necessary changes inside the loop in both client and server and included hints.ai_protocol = IPPROTO_TCP; on both side...but still i am getting connection time out...I am able to ping the system(in which server lies) by its IPv4 address but not with IPv6 one.it says destination unreachable,address unreachable with IPv6 one..why?? – Shikhar Deep Jun 06 '14 at 10:31
  • please paste on pastebin.com results of "ip a" commands on both machines, send me a link and tell me what ping6 command you are executing. maybe i can help :) – macfij Jun 06 '14 at 10:47
0

I fixed it.Actually the router was not supporting IPv6.that's why i was unable to ping the server system via ping6 from my system. Thanks anyways macfji :-)

Shikhar Deep
  • 253
  • 2
  • 8
  • 19
  • because as he mentioned inside the loop i was calling res and not p..check his post – Shikhar Deep Jun 09 '14 at 05:18
  • You can't use link-local addresses unless it's on the same machine, you have to find a different interface on the server to connect to. `ifconfig` or `ip address show` and look for an ipv6 address that doesn't start with fe80. Router is fine – Tyler Curtis Jowers Aug 18 '19 at 02:57