Please tell me something I can't understand. There is a function getaddrinfo() and there is a flag AI_NUMERICHOST. MSDN says that in getaddrinfo() with this flag, you need to send the numeric value of the IP address, and not the domain name. But why?
I already have an IP address, why should I ask DNS for an IP address?
getaddrinfo() outputs sockaddr_... structs (sockaddr_in or sockaddr_in6) for the requested host/service. It is not just about IP addresses, it is also about other things, like socket types, service ports, etc, depending on your input and hint values.
So, if you already have an IP address in a string format, you can have getaddrinfo() parse that string for you (specifying AI_NUMERICHOST to avoid DNS) into a binary format in the output sockaddr_..., as well as fill in other sockaddr_... fields at the same time.
Related
Having a strange issue while trying to convert an ipv4 list file to ipv6:
ipv6calc -q --action conv6to4 --in ipv4 1.1.23.1 --out ipv6
2002:101:1701::
Trying to validate that result is correct, I used some online converters and it seems that 1.1.23.1 is 2002:0:0:0:0:0:101:1701 (or else 2002::101:1701).
So the last "::" should be removed & 2002 should have extra ":".
I really don't want to use sed/awk commands in order to manipulate this result, so the questions are:
is there alternative cmd/linux SW?
is this somehow fixed inside ipv6 calc, am I doing something wrong?
Thanks
This is the correct 6to4 address. A 6to4 subnet is on the format 2002:IP4_HI:IP4_LO::/48. IP4_HI is the top 16 bits of the IPv4 address, while IP4_LO is the low 16 bits of the address.
For example, the IPv4 address 1.2.3.4 gives you the 6to4 subnet 2002:0102:0304::/48.
See 6to4 address block allocation for more details.
A different question is whether this is actually the address you want? There are other ways to map IPv4 addresses to IPv6 addresses. For example, there are IPv4-mapped IPv6 addresses, which are typically written as ::ffff:1.2.3.4.
The address format you need depends on what you are going to use it for.
when i'm filling out a SOCKADDR_IN struct for the connect function, i tend to fill it out with the exact ip address, but let's say i wanted to set up a dynamic domain name online to represent an occasionally changing ip address? I'm not quite sure how i would fill out the struct, given a domain name. What i do now is this:
#define DEFAULT_PORT 12345
SOCKADDR_IN serverInfo;
serverInfo.sin_port=htons(DEFAULT_PORT);
serverInfo.sin_family=AF_INET;
serverInfo.sin_addr.s_addr= inet_addr("127.0.0.1"); // actual ip normally here
but how do you resolve domain names to get the ip of the server for this struct?
You want to use the gethostbyname function
http://msdn.microsoft.com/en-us/library/windows/desktop/ms738524%28v=vs.85%29.aspx
I want to add a persistent IPv6 address using just API calls or with Registry edits. I have currently implemented a code which uses CreateUnicastIpAddressEntry API to add the IPv6 address successfully, but the IP address is destroyed when the adapter is reset or machine rebooted (as mentioned in MSDN docs).
With IPv4, it was easy to do. Just use AddIPAddress API combined with registry entries to get the desired result.
I have tried to find any entry in the Windows Registry which is being used to save the IPv6 address without any success. The MSDN docs suggests to use netsh.exe to do the task, but then I am quite sure netsh.exe is doing some API call or Registry entry to achieve this task (which is not documented by Microsoft anywhere).
How can this be achieved?
Well, after some reverse engineering of netsh.exe and detailed analysis I think there is sufficient info to create a persistent ipv6 address.
The ipv6 address (UNICAST) is stored in following registry key:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nsi\{eb004a01-9b1a-11d4-9123-0050047759bc}\10
For every ipv6 address to be added, create a REG_BINARY value such that the name of the value contains NET_LUID concatenated with the ipv6 address in full. Like for example, if the ipv6 address is 2001::1, the name of the value will be 000000090000060020010000000000000000000000000001, where the first 16 characters is the NET_LUID of the network adapter and the rest the ipv6 address in full.
This registry value data is made of a 48 byte long structure given below:
typedef struct _UNKNOWN {
ULONG ValidLifetime;
ULONG PreferredLifetime;
NL_PREFIX_ORIGIN PrefixOrigin;
NL_SUFFIX_ORIGIN SuffixOrigin;
UINT8 OnLinkPrefixLength;
BOOLEAN SkipAsSource;
UCHAR Unknown[28];
} UNKNOWN;
The last 28 bytes of this structure is unknown and must be initialized to 0xFF.
Refer to MIB_UNICASTIPADDRESS_ROW structure info in msdn for more info on the UNKNOWN structure members.
While doing this, I also figured out that ipv6 ANYCAST addresses are stored similarly in registry key:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nsi\{eb004a01-9b1a-11d4-9123-0050047759bc}\8`\
Is 74DC::02BA a valid IPv6 address?
I am trying to break it down, but the various shortcuts are confusing me.
Valid address, yes. See this question. Also, this validator breaks it down nicely.
Correct address, probably not. See RFC 4291, section 2.4, where this address is defined as a Global Unicast address. (the first bits are 0111 0100, which falls under "everything else" in the table) Then see the IPv6 address assignments. You'll notice this address range has not been assigned for use.
Normally you wouldn't see an address written like this, since it contains extra information. (the leading 0 in the second group of digits) So you would probably see it written like 74dc::2ba. (The IETF makes recommendations about how to print IPv6 addresses in RFC 5952.)
If you want to know the rules for IPv6 address shortening, they are specified in RFC 4291, section 2.2.
Here's what I believe to be the best online IPv6 validator (and not just because I wrote it). It will show you the various address forms and show you how the different representations relate to each other (try hovering over each address group).
The "::" means there's all 0s in between the colons. The address expands to 74dc:0000:0000:0000:0000:0000:0000:02ba
IPv6 Address Validator
I am already aware of many ways of getting your internal IP (ifconfig, ip addr, /etc/hosts, etc), but I am trying to write a bash script that will always return the internal IP. The problem is, many one-liners (/sbin/ifconfig|grep inet|head -1|sed 's/\:/ /'|awk '{print $3}') can return multiple IPs, and I need to distinguish the internal one manually.
I suspect that to the computer, there is no difference between and an external IP and an internal IP, and thus no 100%, guaranteed way to get the right IP.
The end result is that this script will return the internal IP, no matter if its a 192 address or a 204 address, etc.
Thanks in advance.
"hostname -i" should hopefully give you the same result
As others have mentioned, a machine is not really guaranteed, or even likely, to have a single IP address. I'm not sure exactly what you mean by "internal IP"; sometimes this can mean "IP address on the local network", i.e. the interface which connects to a NAT-enabled firewall.
I'm thinking that the best way to do this is to connect to a host on the network you want and use the address from which that connection originates. This will be the interface which the machine normally uses to connect to that network. The user Unkwntech had the same idea on this thread. The code below is just taken from that answer.
I don't know if this really qualifies as a "bash" solution, since it's just an inline Python script, but anyway this will get you the local ip address used to reach google.com. So this will give you the IP address of whichever interface the machine uses to reach Internet hosts.
$ python -c 'import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("google.com", 80))
print s.getsockname()[0]'
A more bash-y solution might use tracepath or some similar utility.
Systems can have multiple private IPs too though. You would have to limit your searching on IPs to private IPs. 10.0.0.0/8, 172.16.0.0/12, and 192.168.0.0/16.
Within the RFC 1918 private address spaces, a machine could conceivably have every address in the 10/8 range, the 172.16/12 range, and the 192.168/16 range, for a total of 17891328 IP addresses, and all of them would be legal "internal" IPs.
Oh yes, don't forget IPv6 :) 2^64 possible addresses per network for a single machine, which might participate in multiple networks.
This isn't exactly academic, either: it is quite common for VMWare, VirtualBox, QEMU, etc. host systems to have multiple RFC 1918 addresses assigned; one for the 'usual use', and one that is used specifically to communicate with guest operating systems. Or routers / firewalls, they might have a dozen internal IPs specifically to subnet a network for access control reasons.