/*
Copyright (c) Edgeless Systems GmbH

SPDX-License-Identifier: AGPL-3.0-only
*/

package iproute

import (
	"context"
	"errors"
	"fmt"
	"os/exec"
	"strings"
)

// AddToLocalRoutingTable adds the IP to the local routing table.
func AddToLocalRoutingTable(ctx context.Context, ip string) error {
	return manipulateLocalRoutingTable(ctx, "add", ip)
}

// RemoveFromLocalRoutingTable removes the IPfrom the local routing table.
func RemoveFromLocalRoutingTable(ctx context.Context, ip string) error {
	return manipulateLocalRoutingTable(ctx, "del", ip)
}

func manipulateLocalRoutingTable(ctx context.Context, action string, ip string) error {
	// https://github.com/GoogleCloudPlatform/guest-agent/blob/792fce795218633bcbde505fb3457a0b24f26d37/google_guest_agent/addresses.go#L179
	if !strings.Contains(ip, "/") {
		ip = ip + "/32"
	}

	args := []string{"route", action, "to", "local", ip, "scope", "host", "dev", "ens3", "proto", "66"}
	_, err := exec.CommandContext(ctx, "ip", args...).Output()
	if err == nil {
		return nil
	}
	var exitErr *exec.ExitError
	if !errors.As(err, &exitErr) {
		return fmt.Errorf("ip route %s: %w", action, err)
	}
	if exitErr.ExitCode() == 2 {
		// "RTNETLINK answers: File exists" or "RTNETLINK answers: No such process"
		//
		// Ignore, expected in case of adding an existing route or deleting a route
		// that does not exist.
		return nil
	}
	return fmt.Errorf("ip route %s (code %v) with: %s", action, exitErr.ExitCode(), exitErr.Stderr)
}
