Add support for IPv6

This commit is contained in:
Kai Huuhko 2016-03-05 08:20:56 +02:00
parent 4702710f7c
commit 18e7be6bf8
1 changed files with 197 additions and 15 deletions

View File

@ -56,10 +56,10 @@ except:
dbus_ml = DBusEcoreMainLoop()
bus = dbus.SystemBus(mainloop=dbus_ml)
log = logging.getLogger("econnman")
log = logging.getLogger("econnman-bin")
log_handler = logging.StreamHandler()
log_formatter = logging.Formatter(
"%(relativeCreated)d %(levelname)s %(name)s: %(message)s"
"%(created)d %(name)s [%(levelname)s]:: %(message)s (@lineno %(lineno)d)"
)
log_handler.setFormatter(log_formatter)
log.addHandler(log_handler)
@ -347,6 +347,20 @@ class ObjectView(object):
sc.callback_changed_add(callback)
return sc, items
def add_label_and_segment_control(self, box, options, callback, label):
lb = self.add_label(box, label)
sc = SegmentControl(box)
sc.size_hint_weight = EXPAND_HORIZ
sc.size_hint_align = FILL_BOTH
items = {}
for o in options:
items[o] = sc.item_add(None, o)
sc.show()
box.pack_end(sc)
sc.callback_changed_add(callback)
return lb, sc, items
def add_frame_and_box(self, box, label):
fr = Frame(box)
fr.size_hint_weight = EXPAND_HORIZ
@ -925,6 +939,28 @@ class ServiceView(ObjectView):
"""
bus_interface = "net.connman.Service"
ipv4_fields = (#("Method", "ipv4_method"),
("Address", "ipv4_address"),
("Netmask", "ipv4_netmask"),
("Gateway", "ipv4_gateway"),
)
ipv6_fields = (#("Method", "ipv6_method"),
("Address", "ipv6_address"),
("Prefix Length", "ipv6_prefix_length"),
("Gateway", "ipv6_gateway"),
#("Privacy", "ipv6_privacy"),
)
proxy_fields = (("Method", "proxy_method"),
("URL", "proxy_url"),
("Servers", "proxy_servers"),
("Excludes", "proxy_excludes"),
)
vpn_fields = ( # named Provider in spec
("Host", "vpn_host"),
("Domain", "vpn_domain"),
("Name", "vpn_name"),
("Type", "vpn_type"),
)
eth_fields = (("Method", "eth_method"),
("Interface", "eth_iface"),
("Address", "eth_addr"),
@ -932,15 +968,6 @@ class ServiceView(ObjectView):
("Speed", "eth_speed"),
("Duplex", "eth_duplex"),
)
vpn_fields = (("Host", "vpn_host"),
("Domain", "vpn_domain"),
("Name", "vpn_name"),
("Type", "vpn_type"),
)
ipv4_fields = (("Address", "ipv4_address"),
("Netmask", "ipv4_netmask"),
("Gateway", "ipv4_gateway"),
)
top_widgets = (
"connect",
@ -959,6 +986,7 @@ class ServiceView(ObjectView):
"domains_label",
"domains_entry",
"ipv4_frame",
"ipv6_frame",
"proxy_frame",
"ethernet_frame",
"vpn_frame",
@ -1033,10 +1061,22 @@ class ServiceView(ObjectView):
en.callback_unfocused_add(self._on_ipv4_property_unfocused)
setattr(self, attr, en)
# section: IPv6: similar to ipv4? refactor ipv4?
if properties.get("IPv6"):
# section: IPv6
self.ipv6_properties = {"IPv6": {}, "IPv6.Configuration": {}}
fr, bx = self.add_frame_and_box(self.box, "IPv6")
lb = self.add_label(bx, "TODO")
self.ipv6_frame = fr
self.ipv6_box = bx
options = ("Automatic", "Manual", "Off")
self.ipv6_method, self.ipv6_method_items = self.add_segment_control(
bx, options, self._on_ipv6_method)
for name, attr in self.ipv6_fields:
lb, en = self.add_label_and_entry(bx, name)
en.callback_activated_add(self._on_ipv6_property_changed)
en.callback_unfocused_add(self._on_ipv6_property_unfocused)
setattr(self, attr, en)
options = ("Disabled", "Enabled", "Prefered")
self.ipv6_privacy_lb, self.ipv6_privacy, self.ipv6_privacy_items = self.add_label_and_segment_control(
bx, options, self._on_ipv6_privacy, "Privacy")
# section: Proxy: custom contents for direct, auto and manual
# - direct: nothing
@ -1186,6 +1226,11 @@ class ServiceView(ObjectView):
self.ipv4_address.disabled = value
self.ipv4_netmask.disabled = value
self.ipv4_gateway.disabled = value
self.ipv6_method.disabled = value
self.ipv6_address.disabled = value
self.ipv6_prefix_length.disabled = value
self.ipv6_gateway.disabled = value
self.ipv6_privacy.disabled = value
self.proxy_method.disabled = value
elif name == "Favorite":
value = bool(value)
@ -1250,6 +1295,47 @@ class ServiceView(ObjectView):
self.ipv4_method_items["Off"].selected = True
elif method:
log.error("Unknown method: %s", method)
elif name in ("IPv6", "IPv6.Configuration"):
self.ipv6_properties[name] = value
used = self.ipv6_properties["IPv6"]
conf = self.ipv6_properties["IPv6.Configuration"]
def get_val(name):
v = used.get(name) or conf.get(name)
if not v:
return ""
return str(v)
self.ipv6_address.text = get_val("Address")
self.ipv6_prefix_length.text = get_val("PrefixLength")
self.ipv6_gateway.text = get_val("Gateway")
method = str(conf.get("Method", ""))
editable = (method == "manual") and (not self.immutable)
self.ipv6_address.editable = editable
self.ipv6_prefix_length.editable = editable
self.ipv6_gateway.editable = editable
# privacy has only meaning if Method is set to "auto"
editable = (method == "auto") and (not self.immutable)
self.ipv6_privacy.disabled = not editable
if method in ("auto", "fixed", "6to4"):
self.ipv6_method_items["Automatic"].selected = True
elif method == "manual":
self.ipv6_method_items["Manual"].selected = True
elif method == "off":
self.ipv6_method_items["Off"].selected = True
elif method:
log.error("Unknown method: %s", method)
privacy = str(conf.get("Privacy", ""))
if privacy == "disabled":
self.ipv6_privacy_items["Disabled"].selected = True
elif privacy == "enabled":
self.ipv6_privacy_items["Enabled"].selected = True
elif privacy == "prefered":
self.ipv6_privacy_items["Prefered"].selected = True
elif privacy:
log.error("Unknown privacy: %s", privacy)
elif name in ("Proxy", "Proxy.Configuration"):
self.proxy_properties[name] = value
@ -1437,6 +1523,102 @@ class ServiceView(ObjectView):
self.ipv4_netmask.text = get_val("Netmask")
self.ipv4_gateway.text = get_val("Gateway")
def _ipv6_apply(self):
value = self.ipv6_method.item_selected.text
if value == "Automatic":
method = "auto"
elif value == "Manual":
method = "manual"
elif value == "Off":
method = "off"
def make_variant(s):
return dbus.String(s, variant_level=1)
new = {"Method": make_variant(method)}
if method == "manual":
if self.ipv6_address.text:
new["Address"] = make_variant(self.ipv6_address.text)
if self.ipv6_prefix_length.text:
new["PrefixLength"] = make_variant(self.ipv6_prefix_length.text)
if self.ipv6_gateway.text:
new["Gateway"] = make_variant(self.ipv6_gateway.text)
value = self.ipv6_privacy.item_selected.text
if value:
new["Privacy"] = make_variant(value)
if len(new) == 1: # no properties yet
return
conf = self.ipv6_properties["IPv6.Configuration"]
changed = []
for k, v in new.items():
if conf.get(k) != v:
changed.append(k)
log.debug("Changed IPv6: %s", ", ".join(changed))
if not changed:
return
def on_reply():
log.info("Set IPv6=%s", new)
def on_error(exc):
log.error("Failed to set IPv6.Configuration=%s: %s", new, exc)
popup_error(self.obj, "Failed to Apply IPv6",
exc.get_dbus_message())
self.bus_obj.SetProperty(
"IPv6.Configuration", new,
reply_handler=on_reply, error_handler=on_error
)
def _on_ipv6_method(self, obj, item):
if item.text == "Automatic":
method = "auto"
elif item.text == "Manual":
method = "manual"
elif item.text == "Off":
method = "off"
conf = self.ipv6_properties["IPv6.Configuration"]
editable = (method == "manual") and (not self.immutable)
self.ipv6_address.editable = editable
self.ipv6_prefix_length.editable = editable
self.ipv6_gateway.editable = editable
# privacy has only meaning if Method is set to "auto"
editable = (method == "auto") and (not self.immutable)
self.ipv6_privacy.disabled = not editable
if method == conf["Method"]:
return
self._ipv6_apply()
def _on_ipv6_privacy(self, obj, item):
if item.text == "Disabled":
privacy = "disabled"
elif item.text == "Enabled":
privacy = "enabled"
elif item.text == "Prefered":
privacy = "prefered"
conf = self.ipv6_properties["IPv6.Configuration"]
if privacy == conf["Privacy"]:
return
self._ipv6_apply()
def _on_ipv6_property_changed(self, obj):
self._ipv6_apply()
def _on_ipv6_property_unfocused(self, obj):
used = self.ipv6_properties["IPv6"]
conf = self.ipv6_properties["IPv6.Configuration"]
def get_val(name):
v = used.get(name) or conf.get(name)
if not v:
return ""
return str(v)
self.ipv6_address.text = get_val("Address")
self.ipv6_prefix_length.text = get_val("PrefixLength")
self.ipv6_gateway.text = get_val("Gateway")
#self.ipv6_privacy.text = get_val("Privacy")
def _on_proxy_method(self, obj, item):
if item.text == "Direct":
method = "direct"