An open community 
of Macintosh users,
for Macintosh users.

FineTunedMac Dashboard widget now available! Download Here

Topic Options
#31958 - 12/01/14 01:01 PM identifying current LAN ip address from terminal
Virtual1 Offline


Registered: 08/04/09
Loc: Iowa
Code:
MAC:~ virtual1 $ ifconfig
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384
	options=3<RXCSUM,TXCSUM>
	inet6 ::1 prefixlen 128 
	inet 127.0.0.1 netmask 0xff000000 
	inet6 fe80::1%lo0 prefixlen 64 scopeid 0x1 
	nd6 options=1<PERFORMNUD>
gif0: flags=8010<POINTOPOINT,MULTICAST> mtu 1280
stf0: flags=0<> mtu 1280
en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
	ether 78:31:c1:d4:d8:16 
	inet6 fe80::7a31:c1ff:fed4:d816%en0 prefixlen 64 scopeid 0x4 
	inet 10.15.0.208 netmask 0xffff0000 broadcast 10.15.255.255
	nd6 options=1<PERFORMNUD>
	media: autoselect
	status: active
en1: flags=8963<UP,BROADCAST,SMART,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1500
	options=60<TSO4,TSO6>
	ether 72:00:02:e6:f9:80 
	media: autoselect <full-duplex>
	status: inactive
en2: flags=8963<UP,BROADCAST,SMART,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1500
	options=60<TSO4,TSO6>
	ether 72:00:02:e6:f9:81 
	media: autoselect <full-duplex>
	status: inactive
bridge0: flags=8822<BROADCAST,SMART,SIMPLEX,MULTICAST> mtu 1500
	options=63<RXCSUM,TXCSUM,TSO4,TSO6>
	ether 7a:31:c1:4d:9b:00 
	Configuration:
		id 0:0:0:0:0:0 priority 0 hellotime 0 fwddelay 0
		maxage 0 holdcnt 0 proto stp maxaddr 100 timeout 1200
		root id 0:0:0:0:0:0 priority 0 ifcost 0 port 0
		ipfilter disabled flags 0x2
	member: en1 flags=3<LEARNING,DISCOVER>
	        ifmaxaddr 0 port 5 priority 0 path cost 0
	member: en2 flags=3<LEARNING,DISCOVER>
	        ifmaxaddr 0 port 6 priority 0 path cost 0
	media: <unknown type>
	status: inactive
p2p0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 2304
	ether 0a:31:c1:d4:d8:16 
	media: autoselect
	status: inactive
utun0: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1380
	inet6 fe80::e1a1:3f66:87bd:db95%utun0 prefixlen 64 scopeid 0xa 
	inet6 fd58:e0cd:efe3:3d3c:e1a1:3f66:87bd:db95 prefixlen 64 
	nd6 options=1<PERFORMNUD>
en4: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
	options=10b<RXCSUM,TXCSUM,VLAN_HWTAGGING,AV>
	ether a8:20:66:28:87:0b 
	inet6 fe80::aa20:66ff:fe28:870b%en4 prefixlen 64 scopeid 0x7 
	inet 10.3.24.143 netmask 0xffff0000 broadcast 10.3.255.255
	nd6 options=1<PERFORMNUD>
	media: autoselect (1000baseT <full-duplex>)
	status: active


ok that's pretty useful, but let me narrow it down

Code:
en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
	ether 78:31:c1:d4:d8:16 
	inet6 fe80::7a31:c1ff:fed4:d816%en0 prefixlen 64 scopeid 0x4 
	inet 10.15.0.208 netmask 0xffff0000 broadcast 10.15.255.255
	nd6 options=1<PERFORMNUD>
	media: autoselect
	status: active

en4: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
	options=10b<RXCSUM,TXCSUM,VLAN_HWTAGGING,AV>
	ether a8:20:66:28:87:0b 
	inet6 fe80::aa20:66ff:fe28:870b%en4 prefixlen 64 scopeid 0x7 
	inet 10.3.24.143 netmask 0xffff0000 broadcast 10.3.255.255
	nd6 options=1<PERFORMNUD>
	media: autoselect (1000baseT <full-duplex>)
	status: active


Close. Now... one is my airport, and one is my ethernet. Which one is my primary (listed at the top in the Network prefs) - i.e. where my traffic is going out on?

In this specific case, en4 is actually my primary, I'm using a TB/Enet adapter on the retina. en0 is the wifi, which is placed below ethernet in my list.

So how do I tell my script to figure out which one is primary? (en4 in this case) Note that wifi is turned on, which is why status is "active". Wifi will sometimes be active when ethernet is the primary, so "active" isn't sufficient to identify primary. I cannot rely on any consistency with the adapter name ("enXXX") I need to know which is primary.

Any suggestions? I'm not limited to ifconfig and I can explore, I just need to know what to query. systemsetup doesn't have it... tongue
_________________________
I work for the Department of Redundancy Department

Top
#31972 - 12/02/14 11:17 AM Re: identifying current LAN ip address from terminal [Re: Virtual1]
ganbustein Offline


Registered: 08/04/09
Your "primary" interface is the one with the default gateway on it.

You can get the default gateway with

netstat -r | grep default

Conceptually, there could be a different default gateway for IPv4 and IPv6. They could be on different networks. On my machine there is only one, for IPv4. You can restrict the output from netstat to a specific family using the -f flag.

Once you have an IP address for the default gateway, examine the inet/inet6 entries in the output from ifconfig to find the one whose IP address matches that of the default gateway, modulo the netmask/prefixlen.

If I were doing it, I'd use Perl for the script, to get easy access to both pattern matching and bit manipulation in one package.

Oh, what the heck...
Code:
#!/usr/bin/env perl

use strict;
use warnings;

sub scan_ip {
	if ($_[0] =~ /^\s*(\d+)\.(\d+)\.(\d+)\.(\d+)\s*$/) {
		return (($1 & 255) << 24) | (($2 & 255) << 16) | (($3 & 255) << 8) | ($4 & 255); }
	else {
		return 0; }
	}

sub fmt_ip {
	my $ip = shift;
	return sprintf("%d.%d.%d.%d", 
	  ($ip >> 24) & 255, ($ip >> 16) & 255, ($ip >> 8) & 255, $ip & 255);
	}

my $gw = 0;
my $ip = 0;

open *NS, "/usr/sbin/netstat -rf inet|" or die;
while (<NS>) {
	if (m/^default\s+([\d\.]+)/) {
		$gw = scan_ip($1);
		last; }}
close *NS;

die "couldn't find default gateway" if $gw == 0;

# printf "Default gateway is %s\n", fmt_ip($gw);

open *IF, "/sbin/ifconfig|" or die;
while (<IF>) {
	next unless m/^\s+inet\s+([\d\.]+)\s+netmask\s+0x([0-9a-fA-F]{8})\s/;
	my $this_nm = hex($2);
	my $this_ip = scan_ip($1);
	if (($this_ip & $this_nm) == ($gw & $this_nm)) {
		$ip = $this_ip;
		last; }}
close *IF;

die "couldn't find primary IP address" if $ip == 0;

printf "Primary IP address is %s\n", fmt_ip($ip);

That's only for IPv4. IPv6 is left as an exercise for the student.

Top
#31989 - 12/03/14 06:41 AM Re: identifying current LAN ip address from terminal [Re: ganbustein]
Virtual1 Offline


Registered: 08/04/09
Loc: Iowa
for whatever reason, netstat -r takes a very long time to run. it dumps a good deal of information, then burps out one more line every 10-15 seconds or so.
_________________________
I work for the Department of Redundancy Department

Top
#31999 - 12/03/14 01:27 PM Re: identifying current LAN ip address from terminal [Re: Virtual1]
ganbustein Offline


Registered: 08/04/09
Originally Posted By: Virtual1
for whatever reason, netstat -r takes a very long time to run. it dumps a good deal of information, then burps out one more line every 10-15 seconds or so.

Really? Sounds like you're adding extra flags, like maybe the -w flag to produce more data at intervals. Or you added flags that ask for additional information. Or you left out the -r, which makes it produce just the additional information, unasked. Check to see if you've made it into an alias/function by entering

type netstat

If so, you can call the bare unaliased command by either invoking it as command netstat or better yet using it's full path. (You should be in the habit of using full paths in scripts anyway. A script that relies on $PATH is fragile, and scripts that run as root or invoke root processes should never be fragile. Besides, the purpose of $PATH is to save keystrokes in an interactive shell. Saving keystrokes is not a high priority when composing a script.)

On my machine:
Code:
$ type netstat
netstat is hashed (/usr/sbin/netstat)
$ time /usr/sbin/netstat -rf inet
Routing tables

Internet:
Destination        Gateway            Flags        Refs      Use   Netif Expire
default            192.168.0.1        UGSc           19        0     en0
127                localhost          UCS             0        0     lo0
localhost          localhost          UH              3     2789     lo0
169.254            link#4             UCS             0        0     en0
192.168.0          link#4             UCS             4        0     en0
192.168.0.1/32     link#4             UCS             1        0     en0
192.168.0.1        0:1b:63:f2:27:19   UHLWIir        25   275890     en0    359
192.168.0.15/32    link#4             UCS             1        0     en0
192.168.0.15       c8:2a:14:3c:44:54  UHLWI           0        1     lo0
192.168.0.132      0:26:ab:2b:4b:d3   UHLWI           0        0     en0   1200
192.168.0.133      d0:4f:7e:57:6:5    UHLWIi          2        6     en0   1184
192.168.0.134      70:3e:ac:cc:a7:f1  UHLWIi        252     1686     en0    360
192.168.0.255      ff:ff:ff:ff:ff:ff  UHLWbI          0       54     en0

real	0m0.026s
user	0m0.002s
sys	0m0.005s


Actually, looking at that output I now notice the Netif column, which spares you the trouble of searching for the right interface.
Code:
/usr/sbin/netstat -rf inet | 
  while read NS_dest NS_gate NS_flags NS_refs NS_use NS_if NS_exp; do
    if [[ "$NS_dest" = default ]]; then 
        /sbin/ifconfig $NS_if inet | 
          while read IF_if IF_ip IF_rest; do
              if [[ "$IF_if" = inet ]]; then echo $IF_ip; fi
          done
          break
    fi
  done


Top
#32001 - 12/03/14 03:03 PM Re: identifying current LAN ip address from terminal [Re: ganbustein]
ganbustein Offline


Registered: 08/04/09
Shorter version:
Code:
ifconfig $(netstat -rf inet | awk '{if ($1 == "default") print $6}') inet | awk '{if ($1 == "inet") print $2}'


or $PATH-independently:
Code:
/sbin/ifconfig $(/usr/sbin/netstat -rf inet | /usr/bin/awk '{if ($1 == "default") print $6}') inet | /usr/bin/awk '{if ($1 == "inet") print $2}'


Top

Moderator:  alternaut, dianne, MacManiac