+function protocol.netmask(self)
+ local addrs = self:_ubus("ipv4-address")
+ return addrs and #addrs > 0 and
+ ipc.IPv4("0.0.0.0/%d" % addrs[1].mask):mask():string()
+end
+
+function protocol.gwaddr(self)
+ local _, route
+ for _, route in ipairs(self:_ubus("route") or { }) do
+ if route.target == "0.0.0.0" and route.mask == 0 then
+ return route.nexthop
+ end
+ end
+end
+
+function protocol.dnsaddrs(self)
+ local dns = { }
+ local _, addr
+ for _, addr in ipairs(self:_ubus("dns-server") or { }) do
+ if not addr:match(":") then
+ dns[#dns+1] = addr
+ end
+ end
+ return dns
+end
+
+function protocol.ip6addr(self)
+ local addrs = self:_ubus("ipv6-address")
+ return addrs and #addrs > 0
+ and "%s/%d" %{ addrs[1].address, addrs[1].mask }
+end
+
+function protocol.gw6addr(self)
+ local _, route
+ for _, route in ipairs(self:_ubus("route") or { }) do
+ if route.target == "::" and route.mask == 0 then
+ return ipc.IPv6(route.nexthop):string()
+ end
+ end
+end
+
+function protocol.dns6addrs(self)
+ local dns = { }
+ local _, addr
+ for _, addr in ipairs(self:_ubus("dns-server") or { }) do
+ if addr:match(":") then
+ dns[#dns+1] = addr
+ end
+ end
+ return dns
+end
+
+function protocol.is_bridge(self)
+ return (not self:is_virtual() and self:type() == "bridge")
+end
+
+function protocol.opkg_package(self)
+ return nil
+end
+
+function protocol.is_installed(self)
+ return true
+end
+
+function protocol.is_virtual(self)
+ return false
+end
+
+function protocol.is_floating(self)
+ return false
+end
+
+function protocol.is_empty(self)
+ if self:is_floating() then