Sssssuppp
Sssssuppp

Reputation: 711

getaddrinfo: Address family for nodename not supported in MacOS

I keep getting this error getaddrinfo failed: Undefined error: 0. I am trying to compile my code on MacOS using the command gcc mac-client-2.c -o client. The program is compiling successfully, but when I run the executable, the error above shows up. I searched google and SO, the closest thing I could find to the problem was this link Undefined reference to getaddrinfo But, this link talks about the issue for windows, not for MacOS.

I am pasting my code as it is below. Could anyone please help.

EDIT: Got a more descriptive error saying getaddrinfo: Address family for nodename not supported

// Client side implementation of UDP client-server model
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/udp.h> //Provides declarations for udp header
#include <netinet/ip.h>  //Provides declarations for ip header
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <netdb.h>
#include <errno.h>

#define PORT 12345
#define MAXLINE 1024

//standard checksum function
unsigned short csum(unsigned short *ptr, int nbytes)
{
  register long sum;
  unsigned short oddbyte;
  register short answer;

  sum = 0;
  while (nbytes > 1)
  {
    sum += *ptr++;
    nbytes -= 2;
  }
  if (nbytes == 1)
  {
    oddbyte = 0;
    *((u_char *)&oddbyte) = *(u_char *)ptr;
    sum += oddbyte;
  }

  sum = (sum >> 16) + (sum & 0xffff);
  sum = sum + (sum >> 16);
  answer = (short)~sum;

  return (answer);
}

// struct ip
// {
//   unsigned char ihl;
//   unsigned char version;
//   unsigned char tos;
//   unsigned short int tot_len;
//   unsigned short int id;
//   unsigned short int frag_off;
//   unsigned char ttl;
//   unsigned char protocol;
//   unsigned short int check;
//   unsigned int saddr;
//   unsigned int daddr;
// };

//required for udp
struct pseudo_header
{
  u_int32_t source_address;
  u_int32_t dest_address;
  u_int8_t placeholder;
  u_int8_t protocol;
  u_int16_t udp_length;
};

// Driver code
int main()
{
  int errno;
  int sockfd, raw_sock;
  char buffer[MAXLINE];
  int port;
  char *hello = "Client Hello";
  char *done = "Client Done";
  char source_ip[32];
  struct sockaddr_in servaddr;
  struct sockaddr_in local_address;
  int addr_size = sizeof(local_address);

  if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
  {
    perror("socket creation failed");
    exit(EXIT_FAILURE);
  }

  if ((raw_sock = socket(AF_INET, SOCK_RAW, IPPROTO_UDP)) < 0) //PF_PACKET -- 0 can be replaced with IPPROTO_UDP (gives same outcome)
  {
    perror("Raw Socket creation failed");
    exit(EXIT_FAILURE);
  }

  setuid(getuid());

  //********** Part with getaddrinfo//*********
  int stat;
  struct addrinfo hints;
  struct addrinfo *info, *ptr;
  struct sockaddr_in *client_address;
  char clientIPstr[16];

  hints.ai_family = AF_INET;
  hints.ai_socktype = SOCK_DGRAM;
  hints.ai_flags = AI_PASSIVE; //put NULL in getaddrinfo
  //AI_PASSIVE allows to assign address of local host
  //No hardcoding needed

  if ((stat = getaddrinfo(NULL, "0", &hints, &info) != 0))
  {
    perror("getaddrinfo failed");
    exit(EXIT_FAILURE);
  }

  for (ptr = info; ptr != NULL; ptr = ptr->ai_next)
  {
    if (ptr->ai_family == AF_INET)
    {
      client_address = (struct sockaddr_in *)ptr->ai_addr;
      inet_ntop(AF_INET, &(client_address->sin_addr), clientIPstr, sizeof(clientIPstr));
      printf("%s\n", clientIPstr);

      int x = bind(sockfd, ptr->ai_addr, ptr->ai_addrlen);
      //int y = bind(raw_sock, ptr->ai_addr, ptr->ai_addrlen);
      //printf("Bind Status: %d, %d\n", x, y);
      break;
    }
  }

  ///************///************////*****************

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

  // Filling server information
  servaddr.sin_family = AF_INET;                           //IPv4
  servaddr.sin_port = htons(PORT);                         //8080
  inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr); 
                                                           
  int len, n;
  //send hello
  sendto(sockfd, (const char *)hello, strlen(hello),
         0, (const struct sockaddr *)&servaddr,
         sizeof(servaddr));

  //fetch the port number and store in local address -- dont forget to convert using ntohs
  getsockname(sockfd, (struct sockaddr *)&local_address, &addr_size);
  port = ntohs(local_address.sin_port);
  printf("My Port: %u\n", port);

  //receive hello
  bzero(buffer, MAXLINE);
  recvfrom(sockfd, buffer, sizeof(buffer),
           0, (struct sockaddr *)&servaddr,
           &len);
  printf("%s\n", buffer);

  /* ---------------------Packet spoofing code starts here----------------------- */
  printf("Creating spoofed packet\n");
  char spoof_packet[4096];
  char *data, *pseudogram;
  int one = 1;
  const int *val = &one;

  memset(spoof_packet, 0, 4096);
  //strcpy(clientIPstr, "127.0.0.1");
  struct ip *iph = (struct ip *)spoof_packet;
  struct udphdr *udph = (struct udphdr *)(spoof_packet + sizeof(struct ip));
  struct pseudo_header psh;
  struct sockaddr_in my_sockaddress;
  my_sockaddress.sin_addr.s_addr = inet_addr(clientIPstr); //just set this to htonl(INADDR_ANY); instead of 127.0.0.1

  //struct sockaddr_in sin;

  data = spoof_packet + sizeof(struct ip) + sizeof(struct udphdr);
  strcpy(data, "SPOOFED CLIENT DONE");
  strcpy(source_ip, clientIPstr);

  //IP Header
  iph->ip_hl = 5;
  iph->ip_v = 4;
  iph->ip_tos = 0;
  iph->ip_len = sizeof(struct ip) + sizeof(struct udphdr) + strlen(data);
  iph->ip_id = htonl(54321); //Id of this packet
  iph->ip_off = 0;
  iph->ip_ttl = 255;
  iph->ip_p = IPPROTO_UDP;
  iph->ip_sum = 0;                                                 //Set to 0 before calculating checksum
  iph->ip_src = my_sockaddress.sin_addr;                           //Spoof the source ip address
  iph->ip_dst = servaddr.sin_addr;                                 //value should be of type in_addr
  iph->ip_sum = csum((unsigned short *)spoof_packet, iph->ip_len); //ip checksum

  //UDP header
  udph->uh_sport = local_address.sin_port;
  udph->uh_dport = htons(PORT);
  udph->uh_ulen = htons(8 + strlen(data)); //header size
  udph->uh_sum = 0;                        //leave checksum 0 now, filled later by pseudo header

  /* Stackoverflow - The IPv4 layer generates an IP header when sending a packet unless the IP_HDRINCL socket 
option is enabled on the socket. When it is enabled, the packet must contain an IP header. 
For receiving the IP header is always included in the packet.*/
  if (setsockopt(raw_sock, IPPROTO_IP, IP_HDRINCL, val, sizeof(one)) < 0)
  {
    perror("setsockopt() error");
    exit(-1);
  }
  //UDP checksum using the pseudo header
  psh.source_address = inet_addr(source_ip);
  psh.dest_address = servaddr.sin_addr.s_addr;
  psh.placeholder = 0;
  psh.protocol = IPPROTO_UDP;
  psh.udp_length = htons(sizeof(struct udphdr) + strlen(data));

  int psize = sizeof(struct pseudo_header) + sizeof(struct udphdr) + strlen(data);
  pseudogram = malloc(psize);

  memcpy(pseudogram, (char *)&psh, sizeof(struct pseudo_header));
  memcpy(pseudogram + sizeof(struct pseudo_header), udph, sizeof(struct udphdr) + strlen(data));

  udph->uh_sum = csum((unsigned short *)pseudogram, psize);
  printf("%s\n", spoof_packet);
  printf("Sending spoofed packet.......");
  int k;

  //send spoofed Done
  k = sendto(raw_sock, spoof_packet, iph->ip_len,
             0, (const struct sockaddr *)&servaddr,
             sizeof(servaddr));
  if (k == -1)
  {
    printf("Error sending: %i\n", errno);
  }
  printf("%d\n", k);
  fflush(stdout);
  /*---------------------------------END------------------------------------------*/

  //send Done
  // sendto(sockfd, (const char *)done, strlen(done),
  //        0, (const struct sockaddr *)&servaddr,
  //        sizeof(servaddr));

  //receive done
  bzero(buffer, MAXLINE);
  recvfrom(sockfd, buffer, sizeof(buffer),
           0, (struct sockaddr *)&servaddr,
           &len);
  printf("%s\n", buffer);

  //close(sockfd);
  return 0;
}

/* get ip and port number:
  char myIP[16];
  struct sockaddr_in local_address;

  getsockname(sockfd, (struct sockaddr *)&local_address, &addr_size); //get socket info
  inet_ntop(AF_INET, &local_address.sin_addr, myIP, sizeof(myIP)); // get IP info
  int myPort = ntohs(local_address.sin_port); //get port info
  printf("Local ip address: %s\n", myIP);
  printf("Local port : %u\n", myPort);
  */

Upvotes: 0

Views: 1104

Answers (2)

Sssssuppp
Sssssuppp

Reputation: 711

So, I forgot to post back here. I had figured out the solution. Its basically the same as the above post. Just added the line memset(&hints,0,sizeof(hints)) and everything worked perfectly.

Upvotes: 0

R.. GitHub STOP HELPING ICE
R.. GitHub STOP HELPING ICE

Reputation: 215287

Your struct addrinfo hints; is uninitialized, and has junk in the members you did not explicitly write to. Change it to struct addrinfo hints = { 0 }; or put all the hints in designated initializers rather than assignments after creation of an uninitialized object.

Upvotes: 2

Related Questions