I'm attempting to refactor old perl code to support some new IPV6-only hosts.
In testing the basic 'connect.pl' script, it fails with
Unsupported IP address format:
#/usr/lib/vmware-vcli/apps/general/connect.pl --url https://fe80::b6b5:2fff:fe5a:c5d8:443/sdk --username root --password pw
Unsupported IP address format
I also wrote a little test script to exercise Util::connect, and it fails in the same way.
Caveats:
I'm using VMware-vSphere-Perl-SDK-5.1.0-780721.
In my scenario, the ESXi hosts run IPV6 only, and the guests will run IPV4 only.
You have two issues here.
IPv6 literal addresses in a URL need to be in brackets.
Your link-local address is missing an interface identifier.
Specify the link-local address in brackets with the correct interface identifier. For example:
https://[fe80::b6b5:2fff:fe5a:c5d8%eth0]:443/sdk
The correct answer here is that, for unknown reasons, the API checks for link-local "fe80" addresses, and errors if it sees them.
connect.pl (which is sample code provided by VMware) works just fine with a global-scoped IPV6 address.
Related
I wrote a script that goes through all local IPs in the '0' network (192.168.0.*).
I use a loop with socket.gethostbyaddr(ip_modified_by_the_loop_each_time).
The loop returns me 3 devices their hostnames.
Now, I found that it does not find 4 devices (at least).
It does wind my Windows Laptop, not my Android Phone. It does find
one MacBook, not the iMac, not the other MacBook. It also does not
find any phone.
I know that all the devices are online and have an IPv4 address.
I can ping them very well, it responds just fine. But when I use socket.gethostbyaddr(ip_modified_by_the_loop_each_time) it throws an error.
I used a try:/except: statement to get around the error, but it still can not find my phone by IP and get the hostname, but I know it is there.
I am using python 3.3
Why is that happening, how to fix that?
Thank you.
gethostbyaddr tries to find out the hostname for a given IP address by using either locally stored information (i.e. /etc/hosts) or doing a reverse DNS lookup. The result does not depend on the host being online or not, they only depend on the availability of these information.
And these information can also not be trusted. For example the DNS operator of a domain could add the following records:
test.example.com A public.ip.of.test
public.ip.of.test PTR localhost.
In this case a lookup (gethostbyname) of test.example.com would return the IP address of this host while a reverse lookup (gethostbyaddr) would claim that the hostname is localhost. And if the PTR record would be missing gethostbyaddr would fail, even if the host is online.
See also wikipedia: reverse dns lookup.
Assuming the following is defined in .../hosts:
127.0.0.1 localhost
What, if any, are the actual differences between using 127.0.0.1 and localhost as the server name, especially when hitting processes running locally that are listening for connections?
Well, the most likely difference is that you still have to do an actual lookup of localhost somewhere.
If you use 127.0.0.1, then (intelligent) software will just turn that directly into an IP address and use it. Some implementations of gethostbyname will detect the dotted format (and presumably the equivalent IPv6 format) and not do a lookup at all.
Otherwise, the name has to be resolved. And there's no guarantee that your hosts file will actually be used for that resolution (first, or at all) so localhost may become a totally different IP address.
By that I mean that, on some systems, a local hosts file can be bypassed. The host.conf file controls this on Linux (and many other Unices).
Wikipedia sums this up well:
On modern computer systems, localhost as a hostname translates to an IPv4 address in the 127.0.0.0/8 (loopback) net block, usually 127.0.0.1, or ::1 in IPv6.
The only difference is that it would be looking up in the DNS for the system what localhost resolves to. This lookup is really, really quick. For instance, to get to stackoverflow.com you typed in that to the address bar (or used a bookmarklet that pointed here). Either way, you got here through a hostname. localhost provides a similar functionality.
some applications will treat "localhost" specially. the mysql client will treat localhost as a request to connect to the local unix domain socket instead of using tcp to connect to the server on 127.0.0.1. This may be faster, and may be in a different authentication zone.
I don't know of other apps that treat localhost differently than 127.0.0.1, but there probably are some.
Well, by IP is faster.
Basically, when you call by server name, it is converted to original IP.
But it would be difficult to memorize an IP, for this reason the domain name was created.
Personally I use http://localhost instead of http://127.0.0.1 or http://username.
There is nothing different. One is easier to remember than the other. Generally, you define a name to associate with an IP address. You don't have to specify localhost for 127.0.0.1, you could specify any name you want.
I'm trying to portably (Windows & Linux) find all of the IP addresses of the local machine. The method I am using is to first call gethostname(), and then pass the result of that to gethostbyname(), which returns an array of ip addresses.
The problem is that on linux, the only address I get back is 127.0.0.1. This works on Windows, and I've seen a few people state that this will not work on Linux if your network was configured by DHCP (don't know if that's a true statement).
Is this not the correct way to do this on Linux?
It is not the correct way on unix/linux. The correct way involves ioctls to pull the necessary information.
struct ifreq ifc_buffer[MAX_NUM_IFREQ];
ioctl(s, SIOCGIFCONF, &ifc) # Interface list
num_ifreq = ifc.ifc_len / sizeof(struct ifreq);
for(cnt=0;cnt<num_ifreq;cnt++)
struct ifreq *ifr = &ifc.ifc_req[cnt]
ioctl(s, SIOCGIFADDR, ifr); # get ip address
There are also more modern methods involving:
if_nameindex()
Doing a SO search for if_nameindex and SIOCGIFCONF will yield a number of questions similar to this one.
This happens because on most distributions you have this in /etc/hosts:
127.0.0.1 localhost.localdomain localhost aiur
gethostbyname simply resolves the hostname (aiure in this example) to an address. If it finds it in /etc/hosts it's more than happy to give you that.
Back to the question. Unfortunately I don't believe you can get all the addresses of your machine in a portable way. You can do it in a Unix-portable way, like ifconfig does. Open a socket s and do an ioctl(..., SIOCGIFCONF, ...).
By the way, gethostbyname is obsolete if you believe kernel.org and deprecated if you believe MSDN.
Check this error and please help me.
2009-07-24 15:58:34.209 LBS[2636] Host 'staging.common.virtualearth.net' not found using 'gethostbyname()' - perhaps the hostname is wrong or networking is not set up on your machine
2009-07-24 15:58:34.209 LBS[2636] Attempt to lookup host entry for bad IP address (staging.common.virtualearth.net)
NOTE: you should run 'diskperf -y' to enable the disk statistics
I am running the objC codes for hitting a webservice on GNU for Windows.
Why is this error?
The first line says it can't find the IP address off the DNS servers.
The second is some kind of fallback with an incredibly cryptic error. Looks like it's trying reverse DNS using hostname as the IP address (hence bad IP address) or ARP resolution using hostname as IP address.
Basically fix the DNS to that host and both will be solved.
Is there a clean and OS independent way to determine the local machine's IP addresses from Perl?
So far I have found the following solutions:
parse the output of ifconfig and ipconfig (hard, different windows versions have different ipconfig outputs)
establish a network connection to a well-known IP and examine the socket's local IP address (won't work if I can't establish a connection and will determine only one IP address)
Any better suggestion?
Net::Address::IP::Local looks promising.
use Net::Address::IP::Local;
# Get the local system's IP address that is "en route" to "the internet":
my $address = Net::Address::IP::Local->public;
You also have some other options, including your solution to "establish a network connection to a well-known IP and examine the socket's local IP address".
In that case (establishing network connection) however, that article points out that:
there is no such thing as a host's IP address.
Network interfaces have IP addresses, not hosts, and a single network interface can have many (virtual) IP addresses. The operating system's routing subsystem decides which network interface and IP address to use to connect to a remote machine.
If your machine only has one external network interface, and this interface only has one IP address then this IP address is commonly called the machine's address, but that is inaccurate.
For example, if the machine is connected to a VPN via a virtual interface it will use this interface's IP address to connect to another machine on the VPN, not the external IP address
Amongst the other solutions: Sys::Hostname - works if it comes up with a resolvable hostname.
use Sys::Hostname;
use Socket;
my $addr = inet_ntoa((gethostbyname(hostname))[4]);
print "$addr\n";
In my case, I need a solution without any non-core dependencies. I came up with this after studying the code in Net::Address::IP::Local:
#!/usr/bin/env perl
use strict;
use warnings;
use IO::Socket::INET;
my $local_ip_address = get_local_ip_address();
print "$local_ip_address\n";
# This idea was stolen from Net::Address::IP::Local::connected_to()
sub get_local_ip_address {
my $socket = IO::Socket::INET->new(
Proto => 'udp',
PeerAddr => '198.41.0.4', # a.root-servers.net
PeerPort => '53', # DNS
);
# A side-effect of making a socket connection is that our IP address
# is available from the 'sockhost' method
my $local_ip_address = $socket->sockhost;
return $local_ip_address;
}
get_local_ip_address() should return the same string as Net::Address::IP::Local->public_ipv4.
If desired, you can change the PeerAddr attribute (in the arguments to the constructor for IO::Socket::INET) to a local DNS server.
To retrieve the IP address of all interfaces, use IO::Interface::Simple:
perl -MIO::Interface::Simple '-Esay $_->address for grep { $_->is_running && defined $_->address } IO::Interface::Simple->interfaces'
If you are not interested in 127.0.0.1 (loopback) you can filter on $_->is_loopback.
Perldoc has an answer to this question in its FAQ ("perlfaq9") - using different modules (which are parts of the Standard Library) or even a built-in function.
I've had good success with IO::Interface on Linux and Solaris, and I think it even worked on AIX but I can't recall for sure. Poking around on search.cpan.org, rt.cpan.org and ActiveState's various sites, it looks like IO::Interface may be experiencing build problems on Windows. I guess the only way to know if it's available is to search for io-interface in PPM.
use WMI?
Example of extracting IP addresses (in Powershell, but it's pretty clear what's happening)
Example of accessing WMI from Perl (not the same WMI functions, but again the process is reasonably clear)
EDIT: after a search on Google codesearch for Networkadapterconfiguration and language "perl":
Example looks like pretty much what you need
EDIT2: In fact the OCS code seems to contain code for most platforms to do this, so while there may be no one set of code that does this, you may be able to re-use their ideas. It's GPL'd, though.
For example, here's the Solaris code. Other bits cover BSD, Linux, MacOS...
getting a network interface's IP address in Perl without additional modules usage and 'ifconfig' output parsing
Net::Address::IP::Local works fine, but since the original poster asks for all the local addresses, I think this one is better:
http://www.perlmonks.org/?node_id=166951
It worked fine for me with ActivePerl for Windows XP.
for windows I use
foreach (split(/\r?\n/,`netstat -r`))
{
next unless /^\s+0.0.0.0/;
#S = split(/\s+/);
# $S[3] = Default Gateway
# $S[4] = Main IP
}
The first line starting 0.0.0.0 is the default gateway. There maybe multiple gateways.
Lines starting 255.255.255.255 are also useful. netstat -r and route print are the same.
Can be adapted for OSX, Linux not so helpful.
I have used a combination of these Linux commands so no dependancy on any perl module.
hostname -i
hostname -I
ls /sys/class/net
ip -f inet addr show eth0| grep -Po 'inet \K[\d.]+'