What's new

YazFi Wrong IPs or Inactive Clients shown on YazFi WebUI

  • SNBForums Code of Conduct

    SNBForums is a community for everyone, no matter what their level of experience.

    Please be tolerant and patient of others, especially newcomers. We are all here to share and learn!

    The rules are simple: Be patient, be nice, be helpful or be gone!

Martinski

Very Senior Member
YazFi 4.4.2 version, one 2.4 GHz + one 5GHz Guest network. RT-AC86U running AsusWRT-Merlin 386.5_0 F/W.

I have found 2 problems in the YazFi WebGUI tab where connected clients' information is displayed. The 1st problem is that sometimes the wrong IP address for a Guest client is shown. The 2nd problem is that sometimes a client device is shown as being "connected" to a Guest network, but the device is in fact no longer connected to the network at all.

Here is a screenshot of the YazFi WebGUI showing the 2 problems in one entry. An "Unknown" device is shown as connected to the 5GHz Guest network. However, the IP address is incorrect (it's from the Main WLAN IP range, *not* from the Guest WLAN IP range). In addition, this device is actually not connected at all to the network at this time, so the entry should not even be there.

RT-AC86U_YazFi_GUI_ERROR.jpg


For a little more context, here is a screenshot of related information obtained via CLI while the GUI problem was happening.

RT-AC86U_CLI_INFO.jpg


In the above screenshot, note the following:

1) The output from wl -i wl1.1 assoclist command shows 2 devices "associated" with the 5GHz Guest network.

2) The arp -an | grep -i "xx:xx:xx:E0:DB:25" command returns no output.

3) The output from cat /var/lib/misc/dnsmasq.leases | grep -i "xx:xx:xx:E0:DB:25" command shows an IP address from the Main WLAN, not from the Guest WLAN.

4) The output from cat /proc/net/arp | grep -i "xx:xx:xx:E0:DB:25" command shows that the device is no longer found in the network (flag says it's an "incomplete" entry), and that it was previously associated with the br0 interface (i.e. Main LAN).

My curiosity then led me to review the YazFi script, and I found the section of code where the problems occur. The root cause is essentially similar to the one causing the GUI problem I reported for the "Wireless Log" tab from "System Log" (see details here in this thread, particularly post #20). As recommended in that previous thread, the key is getting the ARP cache entries for each client's MAC address, and when found, one must check if the 2nd flag (3rd column from the left) indicates an "incomplete" entry. If so, the client device should be ignored.

Here are my proposed code changes to implement the fix in the YazFi script.

FROM current code [Lines #2702]
Bash:
ARPDUMP="$(arp -an)"

TO fixed code:
Bash:
ARP_CACHE="/proc/net/arp"
NOT_LANIP="grep -v "$(nvram get lan_ipaddr | cut -d'.' -f1-3)""


FROM current code [Lines #2715 to #2722]
Bash:
...
GUEST_MACADDR="$(echo "$GUEST_MAC" | awk '{print $2}')"
GUEST_ARPINFO="$(echo "$ARPDUMP" | grep "$IFACE" | grep -i "$GUEST_MACADDR" | grep -v "$(nvram get lan_ipaddr | cut -d'.' -f1-3)")"
GUEST_IPADDR="$(echo "$GUEST_ARPINFO" | awk '{print $2}' | sed 's/(//g;s/)//g')"
GUEST_HOST=""
                  
if [ -z "$GUEST_IPADDR" ]; then
    GUEST_IPADDR=$(grep -i "$GUEST_MACADDR" /var/lib/misc/dnsmasq.leases | awk '{print $3}')
fi
...

TO fixed code:
Bash:
...
GUEST_MACADDR="$(echo "$GUEST_MAC" | awk '{print $2}')"

GUEST_ARPCOUNT="$(cat $ARP_CACHE | grep -ic "$GUEST_MACADDR")"
if [ $GUEST_ARPCOUNT -lt 2 ] ; then
    GUEST_ARPENTRY="$(cat $ARP_CACHE | grep -i "$GUEST_MACADDR")"
    GUEST_ARPINFO="$(echo "$GUEST_ARPENTRY" | grep "$IFACE" | eval "$NOT_LANIP")"
else
    GUEST_ARPENTRY="$(cat $ARP_CACHE | grep -i "$GUEST_MACADDR" | grep "$IFACE")"
    GUEST_ARPINFO="$(echo "$GUEST_ARPENTRY" | eval "$NOT_LANIP")"
fi

GUEST_IPADDR="$(echo "$GUEST_ARPINFO" | awk '{print $1}')"
GUEST_ARPFLAG="$(echo "$GUEST_ARPENTRY" | awk '{print $3}')"

# Skip guest client when ARP entry is marked as "incomplete" #
if [ "$GUEST_ARPFLAG" = "0x0" ] ; then continue ; fi

GUEST_HOST=""

if [ -z "$GUEST_IPADDR" ]; then
    GUEST_IPADDR=$(grep -i "$GUEST_MACADDR" /var/lib/misc/dnsmasq.leases | eval "$NOT_LANIP" | awk '{print $3}')
fi
...

I have already made & tested the above changes in the YazFi script that's installed on my own router & my relative's router (same model), and everything has been working fine for the last 36 hours or so. The "Unknown" device is gone, and we have not seen any clients with the wrong IP address anymore.

@Jack Yaz, ignoring any differences in coding style, what do you think about the code modifications I have proposed above?
 
YazFi 4.4.2 version, one 2.4 GHz + one 5GHz Guest network. RT-AC86U running AsusWRT-Merlin 386.5_0 F/W.

I have found 2 problems in the YazFi WebGUI tab where connected clients' information is displayed. The 1st problem is that sometimes the wrong IP address for a Guest client is shown. The 2nd problem is that sometimes a client device is shown as being "connected" to a Guest network, but the device is in fact no longer connected to the network at all.

Here is a screenshot of the YazFi WebGUI showing the 2 problems in one entry. An "Unknown" device is shown as connected to the 5GHz Guest network. However, the IP address is incorrect (it's from the Main WLAN IP range, *not* from the Guest WLAN IP range). In addition, this device is actually not connected at all to the network at this time, so the entry should not even be there.

View attachment 40290

For a little more context, here is a screenshot of related information obtained via CLI while the GUI problem was happening.

View attachment 40291

In the above screenshot, note the following:

1) The output from wl -i wl1.1 assoclist command shows 2 devices "associated" with the 5GHz Guest network.

2) The arp -an | grep -i "xx:xx:xx:E0:DB:25" command returns no output.

3) The output from cat /var/lib/misc/dnsmasq.leases | grep -i "xx:xx:xx:E0:DB:25" command shows an IP address from the Main WLAN, not from the Guest WLAN.

4) The output from cat /proc/net/arp | grep -i "xx:xx:xx:E0:DB:25" command shows that the device is no longer found in the network (flag says it's an "incomplete" entry), and that it was previously associated with the br0 interface (i.e. Main LAN).

My curiosity then led me to review the YazFi script, and I found the section of code where the problems occur. The root cause is essentially similar to the one causing the GUI problem I reported for the "Wireless Log" tab from "System Log" (see details here in this thread, particularly post #20). As recommended in that previous thread, the key is getting the ARP cache entries for each client's MAC address, and when found, one must check if the 2nd flag (3rd column from the left) indicates an "incomplete" entry. If so, the client device should be ignored.

Here are my proposed code changes to implement the fix in the YazFi script.

FROM current code [Lines #2702]
Bash:
ARPDUMP="$(arp -an)"

TO fixed code:
Bash:
ARP_CACHE="/proc/net/arp"
NOT_LANIP="grep -v "$(nvram get lan_ipaddr | cut -d'.' -f1-3)""


FROM current code [Lines #2715 to #2722]
Bash:
...
GUEST_MACADDR="$(echo "$GUEST_MAC" | awk '{print $2}')"
GUEST_ARPINFO="$(echo "$ARPDUMP" | grep "$IFACE" | grep -i "$GUEST_MACADDR" | grep -v "$(nvram get lan_ipaddr | cut -d'.' -f1-3)")"
GUEST_IPADDR="$(echo "$GUEST_ARPINFO" | awk '{print $2}' | sed 's/(//g;s/)//g')"
GUEST_HOST=""
                  
if [ -z "$GUEST_IPADDR" ]; then
    GUEST_IPADDR=$(grep -i "$GUEST_MACADDR" /var/lib/misc/dnsmasq.leases | awk '{print $3}')
fi
...

TO fixed code:
Bash:
...
GUEST_MACADDR="$(echo "$GUEST_MAC" | awk '{print $2}')"

GUEST_ARPCOUNT="$(cat $ARP_CACHE | grep -ic "$GUEST_MACADDR")"
if [ $GUEST_ARPCOUNT -lt 2 ] ; then
    GUEST_ARPENTRY="$(cat $ARP_CACHE | grep -i "$GUEST_MACADDR")"
    GUEST_ARPINFO="$(echo "$GUEST_ARPENTRY" | grep "$IFACE" | eval "$NOT_LANIP")"
else
    GUEST_ARPENTRY="$(cat $ARP_CACHE | grep -i "$GUEST_MACADDR" | grep "$IFACE")"
    GUEST_ARPINFO="$(echo "$GUEST_ARPENTRY" | eval "$NOT_LANIP")"
fi

GUEST_IPADDR="$(echo "$GUEST_ARPINFO" | awk '{print $1}')"
GUEST_ARPFLAG="$(echo "$GUEST_ARPENTRY" | awk '{print $3}')"

# Skip guest client when ARP entry is marked as "incomplete" #
if [ "$GUEST_ARPFLAG" = "0x0" ] ; then continue ; fi

GUEST_HOST=""

if [ -z "$GUEST_IPADDR" ]; then
    GUEST_IPADDR=$(grep -i "$GUEST_MACADDR" /var/lib/misc/dnsmasq.leases | eval "$NOT_LANIP" | awk '{print $3}')
fi
...

I have already made & tested the above changes in the YazFi script that's installed on my own router & my relative's router (same model), and everything has been working fine for the last 36 hours or so. The "Unknown" device is gone, and we have not seen any clients with the wrong IP address anymore.

@Jack Yaz, ignoring any differences in coding style, what do you think about the code modifications I have proposed above?
My first question, is arp an entware package? Or is it available on merlin fresh out of the box?
If so you may want to stay consistent with

arp which would be

/proc/net/arp -an

Instead of just

arp -an
 
YazFi 4.4.2 version, one 2.4 GHz + one 5GHz Guest network. RT-AC86U running AsusWRT-Merlin 386.5_0 F/W.

I have found 2 problems in the YazFi WebGUI tab where connected clients' information is displayed. The 1st problem is that sometimes the wrong IP address for a Guest client is shown. The 2nd problem is that sometimes a client device is shown as being "connected" to a Guest network, but the device is in fact no longer connected to the network at all.

Here is a screenshot of the YazFi WebGUI showing the 2 problems in one entry. An "Unknown" device is shown as connected to the 5GHz Guest network. However, the IP address is incorrect (it's from the Main WLAN IP range, *not* from the Guest WLAN IP range). In addition, this device is actually not connected at all to the network at this time, so the entry should not even be there.

View attachment 40290

For a little more context, here is a screenshot of related information obtained via CLI while the GUI problem was happening.

View attachment 40291

In the above screenshot, note the following:

1) The output from wl -i wl1.1 assoclist command shows 2 devices "associated" with the 5GHz Guest network.

2) The arp -an | grep -i "xx:xx:xx:E0:DB:25" command returns no output.

3) The output from cat /var/lib/misc/dnsmasq.leases | grep -i "xx:xx:xx:E0:DB:25" command shows an IP address from the Main WLAN, not from the Guest WLAN.

4) The output from cat /proc/net/arp | grep -i "xx:xx:xx:E0:DB:25" command shows that the device is no longer found in the network (flag says it's an "incomplete" entry), and that it was previously associated with the br0 interface (i.e. Main LAN).

My curiosity then led me to review the YazFi script, and I found the section of code where the problems occur. The root cause is essentially similar to the one causing the GUI problem I reported for the "Wireless Log" tab from "System Log" (see details here in this thread, particularly post #20). As recommended in that previous thread, the key is getting the ARP cache entries for each client's MAC address, and when found, one must check if the 2nd flag (3rd column from the left) indicates an "incomplete" entry. If so, the client device should be ignored.

Here are my proposed code changes to implement the fix in the YazFi script.

FROM current code [Lines #2702]
Bash:
ARPDUMP="$(arp -an)"

TO fixed code:
Bash:
ARP_CACHE="/proc/net/arp"
NOT_LANIP="grep -v "$(nvram get lan_ipaddr | cut -d'.' -f1-3)""


FROM current code [Lines #2715 to #2722]
Bash:
...
GUEST_MACADDR="$(echo "$GUEST_MAC" | awk '{print $2}')"
GUEST_ARPINFO="$(echo "$ARPDUMP" | grep "$IFACE" | grep -i "$GUEST_MACADDR" | grep -v "$(nvram get lan_ipaddr | cut -d'.' -f1-3)")"
GUEST_IPADDR="$(echo "$GUEST_ARPINFO" | awk '{print $2}' | sed 's/(//g;s/)//g')"
GUEST_HOST=""
                 
if [ -z "$GUEST_IPADDR" ]; then
    GUEST_IPADDR=$(grep -i "$GUEST_MACADDR" /var/lib/misc/dnsmasq.leases | awk '{print $3}')
fi
...

TO fixed code:
Bash:
...
GUEST_MACADDR="$(echo "$GUEST_MAC" | awk '{print $2}')"

GUEST_ARPCOUNT="$(cat $ARP_CACHE | grep -ic "$GUEST_MACADDR")"
if [ $GUEST_ARPCOUNT -lt 2 ] ; then
    GUEST_ARPENTRY="$(cat $ARP_CACHE | grep -i "$GUEST_MACADDR")"
    GUEST_ARPINFO="$(echo "$GUEST_ARPENTRY" | grep "$IFACE" | eval "$NOT_LANIP")"
else
    GUEST_ARPENTRY="$(cat $ARP_CACHE | grep -i "$GUEST_MACADDR" | grep "$IFACE")"
    GUEST_ARPINFO="$(echo "$GUEST_ARPENTRY" | eval "$NOT_LANIP")"
fi

GUEST_IPADDR="$(echo "$GUEST_ARPINFO" | awk '{print $1}')"
GUEST_ARPFLAG="$(echo "$GUEST_ARPENTRY" | awk '{print $3}')"

# Skip guest client when ARP entry is marked as "incomplete" #
if [ "$GUEST_ARPFLAG" = "0x0" ] ; then continue ; fi

GUEST_HOST=""

if [ -z "$GUEST_IPADDR" ]; then
    GUEST_IPADDR=$(grep -i "$GUEST_MACADDR" /var/lib/misc/dnsmasq.leases | eval "$NOT_LANIP" | awk '{print $3}')
fi
...

I have already made & tested the above changes in the YazFi script that's installed on my own router & my relative's router (same model), and everything has been working fine for the last 36 hours or so. The "Unknown" device is gone, and we have not seen any clients with the wrong IP address anymore.

@Jack Yaz, ignoring any differences in coding style, what do you think about the code modifications I have proposed above?
I see one flaw.
 
When you choose to do the command like this as a variable. It gets called at the time the variable is called.

ARPDUMP="$(arp -an)"

The problem is, you may have several lines of code that follow after this command. And by then a new address could have already joined.

And you wouldn't know until the next interval because you called the command too soon when you told it to expand as a variable. So technically there would be a delay from the time a client joins to the time your code passes to the next interval check.

Jack accounted for this when he chose to do

"/proc/net/arp" without the $() in the variable.
 
My first question, is arp an entware package? Or is it available on merlin fresh out of the box?
If so you may want to stay consistent with

arp which would be

/proc/net/arp -an

Instead of just

arp -an
The arp command (Address Resolution Protocol) is absolutely an essential component of any IPv4 network router and, as such, it's must be part of the F/W. In ASUS routers is built-in with busybox (see /sbin/arp ).

/proc/net/arp is NOT a command, it's the IPv4 network ARP cache.
 
The arp command (Address Resolution Protocol) is absolutely an essential component of any IPv4 network router and, as such, it's must be part of the F/W. In ASUS routers is built-in with busybox (see /sbin/arp ).

/proc/net/arp is NOT a command, it's the IPv4 network ARP cache.
Okay well whatever the case you wouldn't want to expand arp dump as a variable like that. Instead do

ARPDUMP="/sbin/arp -an"

Call it like this

$ARPDUMP with your pipes following after.
 
When you choose to do the command like this as a variable. It gets called at the time the variable is called.

ARPDUMP="$(arp -an)"

The problem is, you may have several lines of code that follow after this command. And by then a new address could have already joined.

And you wouldn't know until the next interval because you called the command too soon when you told it to expand as a variable. So technically there would be a delay from the time a client joins to the time your code passes to the next interval check.

Jack accounted for this when he chose to do

"/proc/net/arp" without the $() in the variable.
Looks like you're getting all confused.

The "FROM current code" sections are the current original code from Jack Yaz.
The "TO fixed code" sections are my proposed code changes.
 
Okay so that clear up abit
Just a bit ?? ;)

OK, to be clearer. This is Jack Yaz's ORIGINAL code:

Bash:
...
    ARPDUMP="$(arp -an)"
    
    for IFACE in $IFACELIST; do
        if [ "$(eval echo '$'"$(Get_Iface_Var "$IFACE")_ENABLED")" = "true" ] && Validate_Exists_IFACE "$IFACE" silent && Validate_Enabled_IFACE "$IFACE" silent; then
            [ -z "$1" ] && printf "%75s\\n\\n" "" | tr " " "-"
            [ -z "$1" ] && printf "${BOLD}INTERFACE: %-5s${CLEARFORMAT}\\n" "$IFACE"
            [ -z "$1" ] && printf "${BOLD}SSID: %-20s${CLEARFORMAT}\\n\\n" "$(nvram get "${IFACE}_ssid")"
            
            IFACE_MACS="$(wl -i "$IFACE" assoclist)"
            if [ "$IFACE_MACS" != "" ]; then
                [ -z "$1" ] && printf "${BOLD}%-30s%-20s%-20s%-15s%-15s%-10s%-5s${CLEARFORMAT}\\n" "HOSTNAME" "IP" "MAC" "CONNECTED" "RX/TX" "RSSI" "PHY"
                IFS=$'\n'
                for GUEST_MAC in $IFACE_MACS; do
                    GUEST_MACADDR="$(echo "$GUEST_MAC" | awk '{print $2}')"
                    GUEST_ARPINFO="$(echo "$ARPDUMP" | grep "$IFACE" | grep -i "$GUEST_MACADDR" | grep -v "$(nvram get lan_ipaddr | cut -d'.' -f1-3)")"
                    GUEST_IPADDR="$(echo "$GUEST_ARPINFO" | awk '{print $2}' | sed 's/(//g;s/)//g')"
                    GUEST_HOST=""
                    
                    if [ -z "$GUEST_IPADDR" ]; then
                        GUEST_IPADDR=$(grep -i "$GUEST_MACADDR" /var/lib/misc/dnsmasq.leases | awk '{print $3}')
                    fi
...


And this is the NEW modified code with my proposed changes:

Bash:
...
    ARP_CACHE="/proc/net/arp"
    NOT_LANIP="grep -v "$(nvram get lan_ipaddr | cut -d'.' -f1-3)""
    
    for IFACE in $IFACELIST; do
        if [ "$(eval echo '$'"$(Get_Iface_Var "$IFACE")_ENABLED")" = "true" ] && Validate_Exists_IFACE "$IFACE" silent && Validate_Enabled_IFACE "$IFACE" silent; then
            [ -z "$1" ] && printf "%75s\\n\\n" "" | tr " " "-"
            [ -z "$1" ] && printf "${BOLD}INTERFACE: %-5s${CLEARFORMAT}\\n" "$IFACE"
            [ -z "$1" ] && printf "${BOLD}SSID: %-20s${CLEARFORMAT}\\n\\n" "$(nvram get "${IFACE}_ssid")"
            
            IFACE_MACS="$(wl -i "$IFACE" assoclist)"
            if [ "$IFACE_MACS" != "" ]; then
                [ -z "$1" ] && printf "${BOLD}%-30s%-20s%-20s%-15s%-15s%-10s%-5s${CLEARFORMAT}\\n" "HOSTNAME" "IP" "MAC" "CONNECTED" "RX/TX" "RSSI" "PHY"
                IFS=$'\n'
                for GUEST_MAC in $IFACE_MACS; do
                    GUEST_MACADDR="$(echo "$GUEST_MAC" | awk '{print $2}')"

                    GUEST_ARPCOUNT="$(cat $ARP_CACHE | grep -ic "$GUEST_MACADDR")"
                    if [ $GUEST_ARPCOUNT -lt 2 ] ; then
                        GUEST_ARPENTRY="$(cat $ARP_CACHE | grep -i "$GUEST_MACADDR")"
                        GUEST_ARPINFO="$(echo "$GUEST_ARPENTRY" | grep "$IFACE" | eval "$NOT_LANIP")"
                    else
                        GUEST_ARPENTRY="$(cat $ARP_CACHE | grep -i "$GUEST_MACADDR" | grep "$IFACE")"
                        GUEST_ARPINFO="$(echo "$GUEST_ARPENTRY" | eval "$NOT_LANIP")"
                    fi

                    GUEST_IPADDR="$(echo "$GUEST_ARPINFO" | awk '{print $1}')"
                    GUEST_ARPFLAG="$(echo "$GUEST_ARPENTRY" | awk '{print $3}')"

                    # Skip guest client when ARP entry is marked as "incomplete" #
                    if [ "$GUEST_ARPFLAG" = "0x0" ] ; then continue ; fi

                    GUEST_HOST=""

                    if [ -z "$GUEST_IPADDR" ]; then
                        GUEST_IPADDR=$(grep -i "$GUEST_MACADDR" /var/lib/misc/dnsmasq.leases | eval "$NOT_LANIP" | awk '{print $3}')
                    fi
...

Is that better?
 
When you choose to do the command like this as a variable. It gets called at the time the variable is called.

ARPDUMP="$(arp -an)"
that's the point, we're parsing arp at the particular time the command gets called. since it repeats every 3s its somewhat irrelevant if a device lands mid parsing, so i disagree with the point you're making here
 
Just a bit ?? ;)

OK, to be clearer. This is Jack Yaz's ORIGINAL code:

Bash:
...
    ARPDUMP="$(arp -an)"
   
    for IFACE in $IFACELIST; do
        if [ "$(eval echo '$'"$(Get_Iface_Var "$IFACE")_ENABLED")" = "true" ] && Validate_Exists_IFACE "$IFACE" silent && Validate_Enabled_IFACE "$IFACE" silent; then
            [ -z "$1" ] && printf "%75s\\n\\n" "" | tr " " "-"
            [ -z "$1" ] && printf "${BOLD}INTERFACE: %-5s${CLEARFORMAT}\\n" "$IFACE"
            [ -z "$1" ] && printf "${BOLD}SSID: %-20s${CLEARFORMAT}\\n\\n" "$(nvram get "${IFACE}_ssid")"
           
            IFACE_MACS="$(wl -i "$IFACE" assoclist)"
            if [ "$IFACE_MACS" != "" ]; then
                [ -z "$1" ] && printf "${BOLD}%-30s%-20s%-20s%-15s%-15s%-10s%-5s${CLEARFORMAT}\\n" "HOSTNAME" "IP" "MAC" "CONNECTED" "RX/TX" "RSSI" "PHY"
                IFS=$'\n'
                for GUEST_MAC in $IFACE_MACS; do
                    GUEST_MACADDR="$(echo "$GUEST_MAC" | awk '{print $2}')"
                    GUEST_ARPINFO="$(echo "$ARPDUMP" | grep "$IFACE" | grep -i "$GUEST_MACADDR" | grep -v "$(nvram get lan_ipaddr | cut -d'.' -f1-3)")"
                    GUEST_IPADDR="$(echo "$GUEST_ARPINFO" | awk '{print $2}' | sed 's/(//g;s/)//g')"
                    GUEST_HOST=""
                   
                    if [ -z "$GUEST_IPADDR" ]; then
                        GUEST_IPADDR=$(grep -i "$GUEST_MACADDR" /var/lib/misc/dnsmasq.leases | awk '{print $3}')
                    fi
...


And this is the NEW modified code with my proposed changes:

Bash:
...
    ARP_CACHE="/proc/net/arp"
    NOT_LANIP="grep -v "$(nvram get lan_ipaddr | cut -d'.' -f1-3)""
   
    for IFACE in $IFACELIST; do
        if [ "$(eval echo '$'"$(Get_Iface_Var "$IFACE")_ENABLED")" = "true" ] && Validate_Exists_IFACE "$IFACE" silent && Validate_Enabled_IFACE "$IFACE" silent; then
            [ -z "$1" ] && printf "%75s\\n\\n" "" | tr " " "-"
            [ -z "$1" ] && printf "${BOLD}INTERFACE: %-5s${CLEARFORMAT}\\n" "$IFACE"
            [ -z "$1" ] && printf "${BOLD}SSID: %-20s${CLEARFORMAT}\\n\\n" "$(nvram get "${IFACE}_ssid")"
           
            IFACE_MACS="$(wl -i "$IFACE" assoclist)"
            if [ "$IFACE_MACS" != "" ]; then
                [ -z "$1" ] && printf "${BOLD}%-30s%-20s%-20s%-15s%-15s%-10s%-5s${CLEARFORMAT}\\n" "HOSTNAME" "IP" "MAC" "CONNECTED" "RX/TX" "RSSI" "PHY"
                IFS=$'\n'
                for GUEST_MAC in $IFACE_MACS; do
                    GUEST_MACADDR="$(echo "$GUEST_MAC" | awk '{print $2}')"

                    GUEST_ARPCOUNT="$(cat $ARP_CACHE | grep -ic "$GUEST_MACADDR")"
                    if [ $GUEST_ARPCOUNT -lt 2 ] ; then
                        GUEST_ARPENTRY="$(cat $ARP_CACHE | grep -i "$GUEST_MACADDR")"
                        GUEST_ARPINFO="$(echo "$GUEST_ARPENTRY" | grep "$IFACE" | eval "$NOT_LANIP")"
                    else
                        GUEST_ARPENTRY="$(cat $ARP_CACHE | grep -i "$GUEST_MACADDR" | grep "$IFACE")"
                        GUEST_ARPINFO="$(echo "$GUEST_ARPENTRY" | eval "$NOT_LANIP")"
                    fi

                    GUEST_IPADDR="$(echo "$GUEST_ARPINFO" | awk '{print $1}')"
                    GUEST_ARPFLAG="$(echo "$GUEST_ARPENTRY" | awk '{print $3}')"

                    # Skip guest client when ARP entry is marked as "incomplete" #
                    if [ "$GUEST_ARPFLAG" = "0x0" ] ; then continue ; fi

                    GUEST_HOST=""

                    if [ -z "$GUEST_IPADDR" ]; then
                        GUEST_IPADDR=$(grep -i "$GUEST_MACADDR" /var/lib/misc/dnsmasq.leases | eval "$NOT_LANIP" | awk '{print $3}')
                    fi
...

Is that better?
other than my point about use of arp -an vs. arp cache above, this looks good to me. are you able to put a PR against YazFi's develop branch please?
 
that's the point, we're parsing arp at the particular time the command gets called. since it repeats every 3s its somewhat irrelevant if a device lands mid parsing, so i disagree with the point you're making here
There would still be a delay on disconnects as well. Devices that have disconnected may still be listed as connected after 3 seconds. It doesn't really matter to me persay, but in terms of being the most accurate as possible per 3 second interval. You would think since it is only an every 3 second parse you would atleast want that the moment the parse happens and the command be as fresh as possible.

For example, if there are three lines of code before the already expanded variable is used, then the list has already changed.
 
Looks like you're getting all confused.

The "FROM current code" sections are the current original code from Jack Yaz.
The "TO fixed code" sections are my proposed code changes.
Yep I definitely got it mixed up orginally. Hard to tell from my cellphone on the job, but once I got home, I did some test with your additions. It seems superb. Awesome job! I hope @RMerlin takes a look at the previous post you tagged him in. (if he hasn't already.)..
 
Just a bit ?? ;)

OK, to be clearer. This is Jack Yaz's ORIGINAL code:

Bash:
...
    ARPDUMP="$(arp -an)"

    for IFACE in $IFACELIST; do
        if [ "$(eval echo '$'"$(Get_Iface_Var "$IFACE")_ENABLED")" = "true" ] && Validate_Exists_IFACE "$IFACE" silent && Validate_Enabled_IFACE "$IFACE" silent; then
            [ -z "$1" ] && printf "%75s\\n\\n" "" | tr " " "-"
            [ -z "$1" ] && printf "${BOLD}INTERFACE: %-5s${CLEARFORMAT}\\n" "$IFACE"
            [ -z "$1" ] && printf "${BOLD}SSID: %-20s${CLEARFORMAT}\\n\\n" "$(nvram get "${IFACE}_ssid")"
       
            IFACE_MACS="$(wl -i "$IFACE" assoclist)"
            if [ "$IFACE_MACS" != "" ]; then
                [ -z "$1" ] && printf "${BOLD}%-30s%-20s%-20s%-15s%-15s%-10s%-5s${CLEARFORMAT}\\n" "HOSTNAME" "IP" "MAC" "CONNECTED" "RX/TX" "RSSI" "PHY"
                IFS=$'\n'
                for GUEST_MAC in $IFACE_MACS; do
                    GUEST_MACADDR="$(echo "$GUEST_MAC" | awk '{print $2}')"
                    GUEST_ARPINFO="$(echo "$ARPDUMP" | grep "$IFACE" | grep -i "$GUEST_MACADDR" | grep -v "$(nvram get lan_ipaddr | cut -d'.' -f1-3)")"
                    GUEST_IPADDR="$(echo "$GUEST_ARPINFO" | awk '{print $2}' | sed 's/(//g;s/)//g')"
                    GUEST_HOST=""
               
                    if [ -z "$GUEST_IPADDR" ]; then
                        GUEST_IPADDR=$(grep -i "$GUEST_MACADDR" /var/lib/misc/dnsmasq.leases | awk '{print $3}')
                    fi
...


And this is the NEW modified code with my proposed changes:

Bash:
...
    ARP_CACHE="/proc/net/arp"
    NOT_LANIP="grep -v "$(nvram get lan_ipaddr | cut -d'.' -f1-3)""

    for IFACE in $IFACELIST; do
        if [ "$(eval echo '$'"$(Get_Iface_Var "$IFACE")_ENABLED")" = "true" ] && Validate_Exists_IFACE "$IFACE" silent && Validate_Enabled_IFACE "$IFACE" silent; then
            [ -z "$1" ] && printf "%75s\\n\\n" "" | tr " " "-"
            [ -z "$1" ] && printf "${BOLD}INTERFACE: %-5s${CLEARFORMAT}\\n" "$IFACE"
            [ -z "$1" ] && printf "${BOLD}SSID: %-20s${CLEARFORMAT}\\n\\n" "$(nvram get "${IFACE}_ssid")"
       
            IFACE_MACS="$(wl -i "$IFACE" assoclist)"
            if [ "$IFACE_MACS" != "" ]; then
                [ -z "$1" ] && printf "${BOLD}%-30s%-20s%-20s%-15s%-15s%-10s%-5s${CLEARFORMAT}\\n" "HOSTNAME" "IP" "MAC" "CONNECTED" "RX/TX" "RSSI" "PHY"
                IFS=$'\n'
                for GUEST_MAC in $IFACE_MACS; do
                    GUEST_MACADDR="$(echo "$GUEST_MAC" | awk '{print $2}')"

                    GUEST_ARPCOUNT="$(cat $ARP_CACHE | grep -ic "$GUEST_MACADDR")"
                    if [ $GUEST_ARPCOUNT -lt 2 ] ; then
                        GUEST_ARPENTRY="$(cat $ARP_CACHE | grep -i "$GUEST_MACADDR")"
                        GUEST_ARPINFO="$(echo "$GUEST_ARPENTRY" | grep "$IFACE" | eval "$NOT_LANIP")"
                    else
                        GUEST_ARPENTRY="$(cat $ARP_CACHE | grep -i "$GUEST_MACADDR" | grep "$IFACE")"
                        GUEST_ARPINFO="$(echo "$GUEST_ARPENTRY" | eval "$NOT_LANIP")"
                    fi

                    GUEST_IPADDR="$(echo "$GUEST_ARPINFO" | awk '{print $1}')"
                    GUEST_ARPFLAG="$(echo "$GUEST_ARPENTRY" | awk '{print $3}')"

                    # Skip guest client when ARP entry is marked as "incomplete" #
                    if [ "$GUEST_ARPFLAG" = "0x0" ] ; then continue ; fi

                    GUEST_HOST=""

                    if [ -z "$GUEST_IPADDR" ]; then
                        GUEST_IPADDR=$(grep -i "$GUEST_MACADDR" /var/lib/misc/dnsmasq.leases | eval "$NOT_LANIP" | awk '{print $3}')
                    fi
...

Is that better?
Have you placed any timers in there to measure the difference in time it takes to run yours versus Jacks? I ask because I see cat being used alot.

Edit:

After running additional test, it seems to be pretty on par with each other. no real noticeable differences.
 
Last edited:
@Jack Yaz,

Apologies for my belated response. At work, we got extremely busy this past week as my s/w dev. team was looking into some issues found during our latest development sprint. We'll be putting in some extra hours during this weekend as well so my spare time is limited (and likely will be for the next few days at least).

other than my point about use of arp -an vs. arp cache above, this looks good to me.
If I understood you correctly, the following code should satisfy your requirement.

NEW modified code:
Bash:
ARP_CACHE="$(cat /proc/net/arp)"
NOT_LANIP="grep -v "$(nvram get lan_ipaddr | cut -d'.' -f1-3)""
    
for IFACE in $IFACELIST; do
    if [ "$(eval echo '$'"$(Get_Iface_Var "$IFACE")_ENABLED")" = "true" ] && Validate_Exists_IFACE "$IFACE" silent && Validate_Enabled_IFACE "$IFACE" silent; then
        [ -z "$1" ] && printf "%75s\\n\\n" "" | tr " " "-"
        [ -z "$1" ] && printf "${BOLD}INTERFACE: %-5s${CLEARFORMAT}\\n" "$IFACE"
        [ -z "$1" ] && printf "${BOLD}SSID: %-20s${CLEARFORMAT}\\n\\n" "$(nvram get "${IFACE}_ssid")"
            
        IFACE_MACS="$(wl -i "$IFACE" assoclist)"
        if [ "$IFACE_MACS" != "" ]; then
            [ -z "$1" ] && printf "${BOLD}%-30s%-20s%-20s%-15s%-15s%-10s%-5s${CLEARFORMAT}\\n" "HOSTNAME" "IP" "MAC" "CONNECTED" "RX/TX" "RSSI" "PHY"
            IFS=$'\n'
            for GUEST_MAC in $IFACE_MACS; do
                GUEST_MACADDR="$(echo "$GUEST_MAC" | awk '{print $2}')"

                GUEST_ARPCOUNT="$(echo "$ARP_CACHE" | grep -ic "$GUEST_MACADDR")"
                if [ $GUEST_ARPCOUNT -lt 2 ] ; then
                    GUEST_ARPENTRY="$(echo "$ARP_CACHE" | grep -i "$GUEST_MACADDR")"
                    GUEST_ARPINFO="$(echo "$GUEST_ARPENTRY" | grep "$IFACE" | eval "$NOT_LANIP")"
                else
                    GUEST_ARPENTRY="$(echo "$ARP_CACHE" | grep -i "$GUEST_MACADDR" | grep "$IFACE")"
                    GUEST_ARPINFO="$(echo "$GUEST_ARPENTRY" | eval "$NOT_LANIP")"
                fi

                GUEST_IPADDR="$(echo "$GUEST_ARPINFO" | awk '{print $1}')"
                GUEST_ARPFLAG="$(echo "$GUEST_ARPENTRY" | awk '{print $3}')"

                # Skip guest client when ARP entry is marked as "incomplete" #
                if [ "$GUEST_ARPFLAG" = "0x0" ] ; then continue ; fi

                GUEST_HOST=""

                if [ -z "$GUEST_IPADDR" ]; then
                    GUEST_IPADDR=$(grep -i "$GUEST_MACADDR" /var/lib/misc/dnsmasq.leases | eval "$NOT_LANIP" | awk '{print $3}')
                fi

Is this what you meant? Either way is fine with me. It's your project so you get to decide what's best for your "baby" ;)
 
are you able to put a PR against YazFi's develop branch please?
Currently, I don't have a GitHub account. During my entire professional career so far, I have never had the need to have one because I've worked only with private companies that have proprietary products/projects so all source code repositories are kept in-house, in company-owned servers, using other source code version control management tools. I have in the past integrated some open source libraries (e.g. OpenSSL, Boost C++ libraries, Expat library, etc.) into our projects, but that's as close as I've gotten to open source code. I suppose I could open a GitHub account if you really need a PR to merge any code changes. It's likely that I'll continue to be very busy in the next few days/weeks as s/w development ramps up with approaching deadlines, but one of these weekends I could take some time to open an account if really necessary.

How soon do you need to have the PR in place?
 
There would still be a delay on disconnects as well. Devices that have disconnected may still be listed as connected after 3 seconds. It doesn't really matter to me persay, but in terms of being the most accurate as possible per 3 second interval. You would think since it is only an every 3 second parse you would atleast want that the moment the parse happens and the command be as fresh as possible.

For example, if there are three lines of code before the already expanded variable is used, then the list has already changed.
In general, I understand your points & concerns; however, you also have to take into consideration the platform & the environment in which the code is running as well as the nature of the component that is presenting the data.

We're not talking about a piece of code that's feeding data to a HUD on a modern commercial airliner or a military tactical fighter aircraft, where the response time requirements & execution time constraints are measured in milliseconds, not full seconds. If the appropriate sensors data is not collected, processed, and presented accurately onto the HUD in real-time, consequences can be catastrophic in a "life or death" scenario.

The particular piece of code that we're talking about here is feeding data to a WebUI tab on a consumer-grade router to show currently connected clients. This is done every 5 seconds when the "Table will refresh every 5s" checkbox is in fact checked. The responsiveness and execution of this particular code are not tied to a time-critical component, so while the data presented in the GUI should be as accurate as possible at any given time, there's no penalty or catastrophic consequences if the data is temporarily "inaccurate" until the next 5-second refresh cycle when newly-acquired data is processed, parsed, and fed to the GUI.

Just my 2 cents.
 
In general, I understand your points & concerns; however, you also have to take into consideration the platform & the environment in which the code is running as well as the nature of the component that is presenting the data.

We're not talking about a piece of code that's feeding data to a HUD on a modern commercial airliner or a military tactical fighter aircraft, where the response time requirements & execution time constraints are measured in milliseconds, not full seconds. If the appropriate sensors data is not collected, processed, and presented accurately onto the HUD in real-time, consequences can be catastrophic in a "life or death" scenario.

The particular piece of code that we're talking about here is feeding data to a WebUI tab on a consumer-grade router to show currently connected clients. This is done every 5 seconds when the "Table will refresh every 5s" checkbox is in fact checked. The responsiveness and execution of this particular code are not tied to a time-critical component, so while the data presented in the GUI should be as accurate as possible at any given time, there's no penalty or catastrophic consequences if the data is temporarily "inaccurate" until the next 5-second refresh cycle when newly-acquired data is processed, parsed, and fed to the GUI.

Just my 2 cents.
The same should be said about seeing addresses that aren't even connected. I understand your disposition, but granted your 2 cent you should also take into consideration all devices and not just the ghost devices.
 
What is the point of a five second interval if the clients in question are from several lines of code ago. So the instance you are observing the information may already be inaccurate. That is putting it plainly , the moment that variable gets used the information is already a lie unless the device is still connected. is my 2 cents.
 
Last edited:
What is the point of a five second interval if the clients in question are from several lines of code ago. So the instance you are observing the information may already be inaccurate. That is putting it plainly , the moment that variable gets used the information is already a lie unless the device is still connected. is my 2 cents.
IIRC, the ARP cache itself has its own timer for refreshing its own data so, technically, even the ARP cache may not be "fully accurate" at the instant we collect the information because its data is not refreshed in real-time as clients join & leave the network. Again, this is a reasonable compromise in the system design because we're not talking about a time-sensitive component behind a time-critical system that must be accurate to the millisecond.

At any rate, we'll just have to agree to disagree.
 
Similar threads

Latest threads

Sign Up For SNBForums Daily Digest

Get an update of what's new every day delivered to your mailbox. Sign up here!
Top