|
|
@@ -50,20 +50,31 @@ func replaceSet(name, family string, addresses []string) error {
|
|
|
}
|
|
|
}
|
|
|
digest := sha256.Sum256([]byte(family + "\n" + strings.Join(clean, "\n")))
|
|
|
- if setDigests[name] == digest {
|
|
|
- out, err := exec.Command("ipset", "list", name, "-terse").Output()
|
|
|
- if err == nil && strings.Contains(string(out), "Number of entries: "+strconv.Itoa(len(clean))+"\n") {
|
|
|
- return nil
|
|
|
- }
|
|
|
+ header, inspectErr := exec.Command("ipset", "list", name, "-terse").CombinedOutput()
|
|
|
+ exists := inspectErr == nil
|
|
|
+ if inspectErr != nil && !strings.Contains(string(header), "does not exist") {
|
|
|
+ return fmt.Errorf("cannot inspect ipset %s: %s: %w", name, header, inspectErr)
|
|
|
+ }
|
|
|
+ if exists && (!strings.Contains(string(header), "Type: hash:net\n") || !strings.Contains(string(header), "family "+family+" ")) {
|
|
|
+ return fmt.Errorf("set %s has an incompatible type/family; existing data was preserved", name)
|
|
|
+ }
|
|
|
+ if exists && setDigests[name] == digest && strings.Contains(string(header), "Number of entries: "+strconv.Itoa(len(clean))+"\n") {
|
|
|
+ return nil
|
|
|
}
|
|
|
+
|
|
|
h := sha256.Sum256([]byte(name))
|
|
|
temp := fmt.Sprintf("dt_tmp_%x", h[:8])
|
|
|
+ // A previous version may have left a temporary set with different limits.
|
|
|
+ _ = exec.Command("ipset", "destroy", temp).Run()
|
|
|
var restore strings.Builder
|
|
|
- fmt.Fprintf(&restore, "create %s hash:net family %s maxelem 1048576 -exist\nflush %s\n", temp, family, temp)
|
|
|
+ fmt.Fprintf(&restore, "create %s hash:net family %s maxelem 1048576\n", temp, family)
|
|
|
for _, address := range clean {
|
|
|
fmt.Fprintf(&restore, "add %s %s -exist\n", temp, address)
|
|
|
}
|
|
|
- fmt.Fprintf(&restore, "create %s hash:net family %s maxelem 1048576 -exist\nswap %s %s\ndestroy %s\n", name, family, temp, name, temp)
|
|
|
+ if !exists {
|
|
|
+ fmt.Fprintf(&restore, "create %s hash:net family %s maxelem 1048576\n", name, family)
|
|
|
+ }
|
|
|
+ fmt.Fprintf(&restore, "swap %s %s\ndestroy %s\n", temp, name, temp)
|
|
|
cmd := exec.Command("ipset", "restore")
|
|
|
cmd.Stdin = strings.NewReader(restore.String())
|
|
|
if out, err := cmd.CombinedOutput(); err != nil {
|