How to get current public IP address using UCI?

I have tried uci get network.wan.ipaddr, but it says "uci: Entry not found".

OpenWrt 18.06.3
BusyBox 1.28.4

UCI is for configuration not runtime status. uci get will only read what is stored in a config file.

Thus the answer is that you don't use UCI. You might look at the scripts in the ddns-scripts package for ways to do it. Ultimately it likely comes down to an ip addr show or for a more OpenWrt specific implementation, some sort of ubus call on network.interface.wan.

2 Likes

For IPv4

ip -4 addr show ${link_name} | sed -Ene 's/^.*inet ([0-9.]+)\/.*$/\1/p'
ifstatus wan |  jsonfilter -e '@["ipv4-address"][0].address'

ifstatus wan is the same as ubus call network.interface.wan status

2 Likes

https://openwrt.org/docs/guide-user/base-system/uci#get_wan_ip_address

This is obsolete. /var/state/network doesn't contain IP.

3 Likes

This should work, but it's too complex to get an IP, isn't it? ubus is a bit easier.

  • It is the officially recommended method.
  • This API should be more stable than ubus.
  • It can give you both IPv4/IPv6 addresses.
  • It doesn't depend on the WAN/WAN6 interface names.

That's funny. Look into /lib/functions/network.sh and you'll see where it gets IPs from :wink:

network_get_ipaddr() {
	__network_ifstatus "$1" "$2" "['ipv4-address'][0].address";
}
__network_ifstatus() {
	local __tmp

	[ -z "$__NETWORK_CACHE" ] && {
		__tmp="$(ubus call network.interface dump 2>&1)"
		case "$?" in
			4) : ;;
			0) export __NETWORK_CACHE="$__tmp" ;;
			*) echo "$__tmp" >&2 ;;
		esac
	}

	__tmp="$(jsonfilter ${4:+-F "$4"} ${5:+-l "$5"} -s "${__NETWORK_CACHE:-{}}" -e "$1=@.interface${2:+[@.interface='$2']}$3")"

	[ -z "$__tmp" ] && \
		unset "$1" && \
		return 1

	eval "$__tmp"
}

etc.

1 Like

That's true :wink: But this is too simple a case to argue on API levels.

1 Like

Thanks. To be honest, I had seen that source before posting this, but since I'm not familiar with shell script, I could not understand the code (looked like just a bunch of variable declarations), and the "uci get" seemed more understandable, so I had tried to use that.

Anyways, I am not interested in IP6 (my ISP doesn't support it anyway), I removed the IP6 three lines and ran the code. It worked but it seems that I cannot refresh the value. I was trying to print the IP before and after the MAC address change (my ISP assigns a new IP for that), but running the same three lines of code again gave me the same old IP, not the new IP. Can I get the current one, again?

It should be fine when invoked in a script:

source /lib/functions/network.sh
network_find_wan NET_IF
network_get_ipaddr NET_ADDR "${NET_IF}"
echo "${NET_ADDR}"

If not, then post your script here.

#!/bin/sh

source /lib/functions/network.sh
network_find_wan NET_IF
network_get_ipaddr NET_ADDR "${NET_IF}"
echo "IP before = ${NET_ADDR}"

NEWMAC=$(dd if=/dev/urandom bs=1024 count=1 2>/dev/null | md5sum | sed -e 's/^\(
uci set network.wan.macaddr=${NEWMAC}
uci commit network
/etc/init.d/network restart

network_find_wan NET_IF
network_get_ipaddr NET_ADDR "${NET_IF}"
echo "IP after = ${NET_ADDR}"

It prints the same IP address.

@jow, requesting the developer's opinion.

Just my two cents: OpenWrt has DDNS support, and scripts that obtain he public address; perhaps it would be a good idea to see how it was done on those scripts.

2 Likes

How about just
curl https://api.ipify.org/ ?

run network_flush_cache to refresh the cache before trying to get the WAN IP again.

1 Like

/sbin/ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'

Just parse it. Seems to be accurate and fast.