0

I have interesting problem with IP address detection in C++. I used inet_pton function and sockaddr_in structure. If string is valid IPv4 or IPv6, function will return AF_INET or AF_INET6. Otherwise zero is returned.

Code below does not work. SIGSEGV in condition with IPv6 detection when input is valid IPv6 address (IPv4 address and invalid address are OK). Same problem is after removal of IPv4 condition.

#include <string>
#include <iostream>
#include <arpa/inet.h>

using namespace std;

int isIP(string);

int main(int argc, char *argv[]){
        string s = "::1";
        int test = isIP(s);
        return 0;
}

int isIP(string addr){
        struct sockaddr_in sa;
        if((inet_pton(AF_INET, addr.c_str(), &(sa.sin_addr))))
                return AF_INET;
        if((inet_pton(AF_INET6, addr.c_str(), &(sa.sin_addr))))
                return AF_INET6;
        return 0;
}

But when is function IsIP changed like codes below, everything is OK.

int isIP(string addr){
        struct sockaddr_in sa;
        cout << addr + "\n";
        if(inet_pton(AF_INET, addr.c_str(), &(sa.sin_addr)))
                return AF_INET;
        if(inet_pton(AF_INET6, addr.c_str(), &(sa.sin_addr)))
                return AF_INET6;
        return 0;
}

or

int isIP(string addr){
        struct sockaddr_in sa, sa2;
        if((inet_pton(AF_INET, addr.c_str(), &(sa.sin_addr))))
                return AF_INET;
        if((inet_pton(AF_INET6, addr.c_str(), &(sa2.sin_addr))))
                return AF_INET6;
        return 0;
}

or

int isIP(string addr){
        struct sockaddr_in sa;
        int r1 = inet_pton(AF_INET, addr.c_str(), &(sa.sin_addr));
        int r2 = inet_pton(AF_INET6, addr.c_str(), &(sa.sin_addr));

        if(r1)
                return AF_INET;
        if(r2)
                return AF_INET6;
        return 0;
}

What is that problem in first implementation of isIP function?

1
  • sockaddr_in6 is bigger than sockaddr_in Commented Nov 8, 2014 at 21:53

2 Answers 2

1

You have to pass pointer to struct in6_addr in case of ipv6 test.

Sign up to request clarification or add additional context in comments.

Comments

0
struct sockaddr_in sa;

This is the structure for IPv4; it does not have enough space for IPv6 addresses, so you are going out of bounds in those cases.

Adding more code to your function just so happens to have made more memory available to the function — either by declaring another variable, or by triggering some arbitrary, implementation-defined constructs about which we cannot rationalise — so that, when you overflow sa, you're overflowing into memory owned by the process and therefore do not trigger an access violation error. However, it's still very wrong.

IPv6 addresses are to be read into a struct in6_addr; one is contained within struct sockaddr_in6 so, e.g.:

bool isIPv6(const string& addr)
{
   struct sockaddr_in6 sa;
   if (inet_pton(AF_INET6, addr.c_str(), &(sa.sin_addr)))
       return true;
   return false;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.