Temporary IPv6 addresses were introduced for privacy reasons in RFC 3041 and updated in RFC 4941. A good overview is given by Privacy and IPv6 Addresses . Another discussion at Understanding security flaws in IPv6 addressing schemes is also relevant.
The function getifaddrs()
will list all
IP addresses on the interfaces of the host it is run on.
The man page gives a program
#define _GNU_SOURCE /* To get defns of NI_MAXSERV and NI_MAXHOST */
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netdb.h>
#include <ifaddrs.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <linux/if_link.h>
int main(int argc, char *argv[])
{
struct ifaddrs *ifaddr, *ifa;
int family, s, n;
char host[NI_MAXHOST];
if (getifaddrs(&ifaddr) == -1) {
perror("getifaddrs");
exit(EXIT_FAILURE);
}
/* Walk through linked list, maintaining head pointer so we
can free list later */
for (ifa = ifaddr, n = 0; ifa != NULL; ifa = ifa->ifa_next, n++) {
if (ifa->ifa_addr == NULL)
continue;
family = ifa->ifa_addr->sa_family;
/* Display interface name and family (including symbolic
form of the latter for the common families) */
printf("%-8s %s (%d)\n",
ifa->ifa_name,
(family == AF_PACKET) ? "AF_PACKET" :
(family == AF_INET) ? "AF_INET" :
(family == AF_INET6) ? "AF_INET6" : "???",
family);
/* For an AF_INET* interface address, display the address */
if (family == AF_INET || family == AF_INET6) {
s = getnameinfo(ifa->ifa_addr,
(family == AF_INET) ? sizeof(struct sockaddr_in) :
sizeof(struct sockaddr_in6),
host, NI_MAXHOST,
NULL, 0, NI_NUMERICHOST);
if (s != 0) {
printf("getnameinfo() failed: %s\n", gai_strerror(s));
exit(EXIT_FAILURE);
}
printf("\t\taddress: <%s>\n", host);
} else if (family == AF_PACKET && ifa->ifa_data != NULL) {
struct rtnl_link_stats *stats = ifa->ifa_data;
printf("\t\ttx_packets = %10u; rx_packets = %10u\n"
"\t\ttx_bytes = %10u; rx_bytes = %10u\n",
stats->tx_packets, stats->rx_packets,
stats->tx_bytes, stats->rx_bytes);
}
}
freeifaddrs(ifaddr);
exit(EXIT_SUCCESS);
}
On one of my hosts, running it gives
lo AF_PACKET (17)
tx_packets = 34146; rx_packets = 34146
tx_bytes = 4521698; rx_bytes = 4521698
enp3s0 AF_PACKET (17)
tx_packets = 0; rx_packets = 0
tx_bytes = 0; rx_bytes = 0
wlp2s0 AF_PACKET (17)
tx_packets = 2521087; rx_packets = 4530609
tx_bytes = 577960812; rx_bytes = 1254696604
lo AF_INET (2)
address: <127.0.0.1>
wlp2s0 AF_INET (2)
address: <10.0.237.126>
lo AF_INET6 (10)
address: <::1>
wlp2s0 AF_INET6 (10)
address: <2400:3740:200:d900:1d55:c3c7:4d47:4d02>
wlp2s0 AF_INET6 (10)
address: <2400:3740:200:d900:90c8:cd68:244:2bac>
wlp2s0 AF_INET6 (10)
address: <2400:3740:200:d900:6070:9918:bafd:51a5>
wlp2s0 AF_INET6 (10)
address: <2400:3740:200:d900:3c58:d451:fae2:5a81>
wlp2s0 AF_INET6 (10)
address: <2400:3740:200:d900:387a:a68c:7a40:6503>
wlp2s0 AF_INET6 (10)
address: <fe80::f7c3:950c:6f91:90e6%wlp2s0>
An API is discussed in RFC 5014 IPv6 Socket API for Source Address Selection and implemented in Linux.
There are many web sites which will tell you the IP address you have connected
from. Many of them are quite verbose.
Dennis
points to checkip.dyndns.com
as giving one-line
answers, with a simple script to extract an IPv4 address
at
Simplest way to check for dynamic IP change
:
wget -q -O - checkip.dyndns.com | grep -Po "[\d\.]+"
Code from https://gist.github.com/jirihnidek/388271b57003c043d322
An alternative 'global' method is described in
IPv6 privacy extensions on Linux
using entries in /proc/sys/net/ipv6/conf/eth0/use_tempaddr
.