netifd: Fix restore of original device settings
[project/netifd.git] / system-linux.c
index 83827d5..4662bf8 100644 (file)
@@ -1033,6 +1033,8 @@ system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned
 int system_if_up(struct device *dev)
 {
        system_if_get_settings(dev, &dev->orig_settings);
+       /* Only keep orig settings based on what needs to be set */
+       dev->orig_settings.flags &= dev->settings.flags;
        system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
        return system_if_flags(dev->ifname, IFF_UP, 0);
 }
@@ -1040,7 +1042,6 @@ int system_if_up(struct device *dev)
 int system_if_down(struct device *dev)
 {
        int ret = system_if_flags(dev->ifname, 0, IFF_UP);
-       dev->orig_settings.flags &= dev->settings.flags;
        system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
        return ret;
 }
@@ -1412,11 +1413,16 @@ static int system_rt(struct device *dev, struct device_route *route, int cmd)
                                rtm.rtm_table = RT_TABLE_LOCAL;
                }
 
-               if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT)
+               if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT) {
                        rtm.rtm_scope = RT_SCOPE_HOST;
-               else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
-                       rtm.rtm_type == RTN_ANYCAST)
+               else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
+                               rtm.rtm_type == RTN_ANYCAST) {
                        rtm.rtm_scope = RT_SCOPE_LINK;
+               } else if (rtm.rtm_type == RTN_BLACKHOLE || rtm.rtm_type == RTN_UNREACHABLE ||
+                               rtm.rtm_type == RTN_PROHIBIT || rtm.rtm_type == RTN_FAILED_POLICY) {
+                       rtm.rtm_scope = RT_SCOPE_UNIVERSE;
+                       dev = NULL;
+               }
        }
 
        msg = nlmsg_alloc_simple(cmd, flags);
@@ -1428,8 +1434,12 @@ static int system_rt(struct device *dev, struct device_route *route, int cmd)
        if (route->mask)
                nla_put(msg, RTA_DST, alen, &route->addr);
 
-       if (route->sourcemask)
-               nla_put(msg, RTA_SRC, alen, &route->source);
+       if (route->sourcemask) {
+               if (rtm.rtm_family == AF_INET)
+                       nla_put(msg, RTA_PREFSRC, alen, &route->source);
+               else
+                       nla_put(msg, RTA_SRC, alen, &route->source);
+       }
 
        if (route->metric > 0)
                nla_put_u32(msg, RTA_PRIORITY, route->metric);