3

What could cause this?

$ sudo ip route show                                                                                                                                
192.168.100.0/24 dev usb0 scope link                                                                                          
$ sudo ip addr show usb0 
85: usb0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state
UNKNOWN group default qlen 1000
link/ether 16:3d:0a:3f:3b:e6 brd ff:ff:ff:ff:ff:ff                                                                                                                    
inet 192.168.100.86/24 brd 192.168.100.255 scope global usb0                                                                                                             
valid_lft forever preferred_lft forever                                                                                                                            
inet6 fe80::143d:aff:fe3f:3be6/64 scope link                                                                                                                             
valid_lft forever preferred_lft forever                                                                                                                        
$ sudo ip route get 192.168.100.2
RTNETLINK answers: Network is unreachable

This is on my host device, running Android atop a Linux 4.4 kernel. I have plugged in my usb gadget (a Mendel linux device). The usb0 interface appeared; I raised it and ran udhcpc on it. The gadget assigned me 192.168.100.86/24 and advertised itself over mDNS as 192.168.100.2, so I know the link is working. I downed all the other host interfaces to be sure they weren't stealing the route. But if I try to ping it or ssh to it, I get 'Network is unreachable'.

When I do the same steps on a different, non-android host, it works fine. I know that android has some funky iptables rules (e.g. for per-uid data usage tracking) but I didn't think that would affect the routing table (and flushing them all doesn't seem to help). There's also SElinux, but I thought that was just a filesystem thing. What other obscure (to me) linux feature could be blocking me here?

Edit to add, as requested:

$ ip rule
0:      from all lookup local
999:    from all fwmark 0xa/0xffff lookup 2454
10000:  from all fwmark 0xc0000/0xd0000 lookup 99
10500:  from all iif lo oif ccmni1 uidrange 0-0 lookup 1003
13000:  from all fwmark 0x10063/0x1ffff iif lo lookup 97
13000:  from all fwmark 0xd006c/0xdffff iif lo lookup 1003
14000:  from all fwmark 0xc0000/0xc0000 iif lo oif ccmni1 lookup 1003
15000:  from all fwmark 0x0/0x10000 lookup 99
16000:  from all fwmark 0x0/0x10000 lookup 98
17000:  from all fwmark 0x0/0x10000 lookup 97
32000:  from all unreachable
$ ip route show table local
broadcast 127.0.0.0 dev lo proto kernel scope link src 127.0.0.1
local 127.0.0.0/8 dev lo proto kernel scope host src 127.0.0.1
local 127.0.0.1 dev lo proto kernel scope host src 127.0.0.1
broadcast 127.255.255.255 dev lo proto kernel scope link src 127.0.0.1
broadcast 192.168.100.0 dev usb0 proto kernel scope link src 192.168.100.86
local 192.168.100.86 dev usb0 proto kernel scope host src 192.168.100.86
broadcast 192.168.100.255 dev usb0 proto kernel scope link src 192.168.100.86
$ ip route show table 2454
default dev ccmni1 proto static
$ ip route show table 99
$ ip route show table 1003
$ ip route show table 97
$ ip route show table 99
$ ip route show table 98
$
Adam Bliss
  • 131
  • 4
  • 1
    Add the result of `ip rule` in your question. And for every entry except those with preference 0, 32766 and 32767 if they reference a routing table (keyword lookup) add this routing table too (`ip route show table xxx`). – A.B Sep 29 '21 at 22:34

1 Answers1

2

Android uses a lot of routing rules and tables, probably one per application.

As can be seen, without such rule added and probably its corresponding fwmark, a packet will hit routing rule 32000: unreachable.

It's a bit frail to do something manually over this mechanism. In particular routing rule 10500 allows (only) root to use outgoing interface ccmni1, but oif isn't about allowing a packet to be selected to this interface, it's about allowing a packet from a socket bound to this interface (using SO_BINDTODEVICE) to be selected (oif isn't a direct equivalent of iif which is used for routed packets, and iif lo is also a special case for non-routed packets).

Many rules receive a firewall mark probably set by equivalent complex iptables rules to select specific routing rules per application (and its specific UID too). I guess there are specific Android APIs to register such rules when an application is installed.

If you want to allow root to use first the main routing table thus avoiding the unreachable fate, among multiple possible choices:

ip rule add pref 998 uidrange 0-0 lookup main

Or if you don't care that any user so any application can use usb0 simply:

ip rule add pref 998 lookup main

This probably won't integrate well with the Android system which might shuffle rules around when applications are installed or started and one can't tell what's left with iptables/nftables (or even along SELinux, tc etc.) about blocking access. Even binding to a socket might be restricted by additional mechanism (see for example: CONFIG_ANDROID_PARANOID_NETWORK).

A.B
  • 9,037
  • 2
  • 19
  • 37