LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Networking (https://www.linuxquestions.org/questions/linux-networking-3/)
-   -   how to get IPv6 address using ioctl() SIOCGIFADDR (https://www.linuxquestions.org/questions/linux-networking-3/how-to-get-ipv6-address-using-ioctl-siocgifaddr-808792/)

ashok449 05-19-2010 04:46 AM

how to get IPv6 address using ioctl() SIOCGIFADDR
 
Hello All,

I have retrieved IPv4 address successfully using
Code:

struct ifreq ifr;
 fd = socket(AF_INET, SOCK_DGRAM, 0);
 ifr.ifr_addr.sa_family = AF_INET;
ioctl(fd, SIOCGIFADDR, &ifr)

for IPv6 address I tried
Code:

struct ifreq ifr;
 fd = socket(AF_INET6, SOCK_DGRAM, 0);
ifr.ifr_addr.sa_family = AF_INET6;
ioctl(fd, SIOCGIFADDR, &ifr)

but ioctl() returning error here, please suggest



Regards,
Ashok

climbingdrummer 06-08-2010 12:05 PM

Any chance you've figured this out? I'm having the same problem. I'm trying to use ioctl to find my ipv6 addresses but I'm only getting back ipv4. I'm using kernel 2.6.18

ashok449 06-09-2010 04:33 AM

Hello,

I tried for some time and not succeeded yet :)

any how here is the code where I've reached regarding this issue.
Code:


#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if.h>
  int main(void)
  {
    int                sfd, i;
  struct in6_ifreq {
        struct in6_addr ifr6_addr;
        uint32_t        ifr6_prefixlen;
        int            ifr6_ifindex;
};
  struct in6_ifreq      ifr;
    struct sockaddr_in6 *sin = (struct sockaddr_in6 *) &ifr.ifr6_addr;

    memset(&ifr, 0, sizeof ifr);

    if (0 > (sfd = socket(AF_INET6, SOCK_DGRAM, 0))) {
      perror("socket()");
      exit(1);
    }

  //  strncpy(ifr.ifr_name, "eth0", IFNAMSIZ -1);
    sin->sin6_family = AF_INET6;

    if (0 == ioctl(sfd, SIOCGIFADDR, &ifr)) {

        //printf("%s: %s\n", ifr.ifr_name, inet_ntoa(sin->sin6_addr));

        }
    else
        printf("ioctl() ---error\n");


char str[INET6_ADDRSTRLEN];
printf("ntop ret= %s\n",inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)sin)->sin6_addr), str, INET6_ADDRSTRLEN));

printf("%s\n", str);


    return 0;
  }

please let me know if there is a break through.


Thanks
Ashok

climbingdrummer 06-09-2010 10:43 AM

I found this site which may be useful to you. I could not get it to print ipv6 addresses though.

http://www.adamrisi.com/?p=84

climbingdrummer 06-09-2010 05:31 PM

If you don't need to use the ioctl call, you can use the method getifaddrs.

Code:

#include <sys/types.h>
#include <sys/socket.h>
#include <ifaddrs.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <string.h>
#include <vector>
#include <string>
#include <iostream>
#include <netinet/in.h>
#include <net/if.h>

using namespace std;
 
std::vector<std::string> listAddresses();
void printAddresses(const std::vector<std::string>& addresses);

int main(int argc, char* argv[], char* envp[])
{
    addresses = listAddresses();
    printAddresses(addresses);
    return 0;
}

void printAddresses(const vector<string>& addresses) {
    for(vector<string>::const_iterator it=addresses.begin(); it!=addresses.end(); ++it) {
        string address = *it;
        cout << address << endl;
    }
}

vector<string> listAddresses()
{
    vector<string> addresses;

    struct ifaddrs *ifa=NULL,*ifEntry=NULL;
    void *addPtr = NULL;
    int rc = 0;
    char addressBuffer[INET6_ADDRSTRLEN];

    rc = getifaddrs(&ifa);
    if (rc==0) {
        for(ifEntry=ifa; ifEntry!=NULL; ifEntry=ifEntry->ifa_next) {
            if(ifEntry->ifa_addr->sa_data == NULL) {
                continue;
            }
            if(ifEntry->ifa_addr->sa_family==AF_INET) {
                addPtr = &((struct sockaddr_in *)ifEntry->ifa_addr)->sin_addr;
            } else if(ifEntry->ifa_addr->sa_family==AF_INET6) {
                addPtr = &((struct sockaddr_in6 *)ifEntry->ifa_addr)->sin6_addr;
            } else {
                //It isn't IPv4 or IPv6
                continue;
            }

            const char *a = inet_ntop(ifEntry->ifa_addr->sa_family,
                          addPtr,
                          addressBuffer,
                          sizeof(addressBuffer));
            if(a != NULL) {
                addresses.push_back(string(a));
            }
        }
    }
    freeifaddrs(ifa);

    return addresses;
}


ashok449 06-11-2010 04:35 AM

Thanks for the Post, Its working.

ssitaram 01-03-2012 11:39 PM

getting if index from IPv6 address
 
use this method instead of ioctl it will work. Hope this helps

/******************************************************************
* FUNCTION: my_get_ipv6_ifindex_from_addr
*
* DESCRIPTION: this function returns ifindex for a given IPV6 address string
*
* PARAMETERS: 'ipv6_addr_str' char string in the format given by inet_ntop()
*
* RETURN VALUE: On Success return value is greater than Zero,
* Zero or Negetive on Error.
*******************************************************************/
int my_get_ipv6_ifindex_from_addr(char *ipv6_addr_str)
{
struct ifaddrs *if_addr, *ifap;
int family, res;
char host_id[NI_MAXHOST], *host_addr;
int ifcount;
int ifindex_matched = -1;

if (getifaddrs(&if_addr) == -1)
{
perror("getif_addrs");
return(ERROR);
}
ifcount = 0;
for (ifap = if_addr; ifap != NULL; ifap = ifap->ifa_next)
{
if (ifap->ifa_addr == NULL)
{
ifcount++;
continue;
}

family = ifap->ifa_addr->sa_family;
if (family == AF_INET6)
{
res = getnameinfo(ifap->ifa_addr, sizeof(struct sockaddr_in6),
host_id, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
if (res != 0)
{ /* failure to get IPv6 address */

continue;
}
host_addr = strtok(host_id, "%");
if ((strncmp(host_id, ipv6_addr_str, INET6_ADDRSTRLEN)) == 0)
{
ifindex_matched = if_nametoindex(ifap->ifa_name);
break;
}
ifcount++;
}
}

return (ifindex_matched);
}


All times are GMT -5. The time now is 02:04 AM.