diff --git a/packages/networking/hyprspace/cli/up.go b/packages/networking/hyprspace/cli/up.go index 1064121..ca02159 100644 --- a/packages/networking/hyprspace/cli/up.go +++ b/packages/networking/hyprspace/cli/up.go @@ -151,7 +151,7 @@ func UpRun(r *cmd.Root, c *cmd.Sub) { go eventLogger(ctx, host) // RPC server - go hsrpc.RpcServer(ctx, multiaddr.StringCast(fmt.Sprintf("/unix/run/hyprspace-rpc.%s.sock", cfg.Interface.Name)), host, *cfg) + go hsrpc.RpcServer(ctx, multiaddr.StringCast(fmt.Sprintf("/unix/run/hyprspace-rpc.%s.sock", cfg.Interface.Name)), host, *cfg, *tunDev) // Magic DNS server go hsdns.MagicDnsServer(ctx, *cfg) diff --git a/packages/networking/hyprspace/config/config.go b/packages/networking/hyprspace/config/config.go index d72d0c8..b615d51 100644 --- a/packages/networking/hyprspace/config/config.go +++ b/packages/networking/hyprspace/config/config.go @@ -49,12 +49,12 @@ type PeerLookup struct { } type RouteTableEntry struct { - network net.IPNet - Target Peer + Net net.IPNet + Target Peer } func (rte RouteTableEntry) Network() net.IPNet { - return rte.network + return rte.Net } // Read initializes a config from a file. @@ -101,8 +101,8 @@ func Read(path string) (*Config, error) { } result.PeerLookup.ByRoute.Insert(&RouteTableEntry{ - network: r.Network, - Target: p, + Net: r.Network, + Target: p, }) fmt.Printf("[+] Route %s via /p2p/%s\n", r.Network.String(), p.ID) diff --git a/packages/networking/hyprspace/project.nix b/packages/networking/hyprspace/project.nix index e63df42..5da34ca 100644 --- a/packages/networking/hyprspace/project.nix +++ b/packages/networking/hyprspace/project.nix @@ -10,7 +10,7 @@ }; packages.hyprspace = with pkgs; buildGo120Module { pname = "hyprspace"; - version = "0.7.0"; + version = "0.7.1"; src = with inputs.nix-filter.lib; let dirs = map inDirectory; diff --git a/packages/networking/hyprspace/rpc/server.go b/packages/networking/hyprspace/rpc/server.go index 3da79f6..f5a6f64 100644 --- a/packages/networking/hyprspace/rpc/server.go +++ b/packages/networking/hyprspace/rpc/server.go @@ -11,6 +11,7 @@ import ( "github.com/hyprspace/hyprspace/config" "github.com/hyprspace/hyprspace/p2p" + "github.com/hyprspace/hyprspace/tun" "github.com/libp2p/go-libp2p/core/host" "github.com/libp2p/go-libp2p/core/network" "github.com/libp2p/go-libp2p/core/peer" @@ -21,6 +22,7 @@ import ( type HyprspaceRPC struct { host host.Host config config.Config + tunDev tun.TUN } func (hsr *HyprspaceRPC) Status(args *Args, reply *StatusReply) error { @@ -99,6 +101,58 @@ func (hsr *HyprspaceRPC) Route(args *RouteArgs, reply *RouteReply) error { *reply = RouteReply{ Routes: routeInfos, } + case Add: + if len(args.Args) != 2 { + return errors.New("expected exactly 2 arguments") + } + _, network, err := net.ParseCIDR(args.Args[0]) + if err != nil { + return err + } + peerId, err := peer.Decode(args.Args[1]) + if err != nil { + return err + } + var target config.Peer + var found bool + for _, p := range hsr.config.Peers { + if p.ID == peerId { + target = p + found = true + break + } + } + if !found { + return errors.New("no such peer") + } + err = hsr.tunDev.Apply(tun.Route(*network)) + if err != nil { + return err + } + + hsr.config.PeerLookup.ByRoute.Insert(&config.RouteTableEntry{ + Net: *network, + Target: target, + }) + case Del: + if len(args.Args) != 1 { + return errors.New("expected exactly 1 argument") + } + _, network, err := net.ParseCIDR(args.Args[0]) + if err != nil { + return err + } + + err = hsr.tunDev.Apply(tun.RemoveRoute(*network)) + if err != nil { + return err + } + + _, err = hsr.config.PeerLookup.ByRoute.Remove(*network) + if err != nil { + _ = hsr.tunDev.Apply(tun.Route(*network)) + return err + } default: return errors.New("no such action") } @@ -114,8 +168,8 @@ func (hsr *HyprspaceRPC) Peers(args *Args, reply *PeersReply) error { return nil } -func RpcServer(ctx context.Context, ma multiaddr.Multiaddr, host host.Host, config config.Config) { - hsr := HyprspaceRPC{host, config} +func RpcServer(ctx context.Context, ma multiaddr.Multiaddr, host host.Host, config config.Config, tunDev tun.TUN) { + hsr := HyprspaceRPC{host, config, tunDev} rpc.Register(&hsr) addr, err := ma.ValueForProtocol(multiaddr.P_UNIX) diff --git a/packages/networking/hyprspace/rpc/types.go b/packages/networking/hyprspace/rpc/types.go index d663821..001aa82 100644 --- a/packages/networking/hyprspace/rpc/types.go +++ b/packages/networking/hyprspace/rpc/types.go @@ -26,6 +26,8 @@ type RouteAction string const ( Show RouteAction = "show" + Add = "add" + Del = "del" ) type RouteInfo struct { diff --git a/packages/networking/hyprspace/tun/options.go b/packages/networking/hyprspace/tun/options.go index 59f6417..e815d49 100644 --- a/packages/networking/hyprspace/tun/options.go +++ b/packages/networking/hyprspace/tun/options.go @@ -35,3 +35,10 @@ func Route(dest net.IPNet) Option { return tun.addRoute(dest) } } + +// RemoveRoute removes an entry from the system route table +func RemoveRoute(dest net.IPNet) Option { + return func(tun *TUN) error { + return tun.delRoute(dest) + } +} diff --git a/packages/networking/hyprspace/tun/tun_linux.go b/packages/networking/hyprspace/tun/tun_linux.go index 8a91493..8c9f2fb 100644 --- a/packages/networking/hyprspace/tun/tun_linux.go +++ b/packages/networking/hyprspace/tun/tun_linux.go @@ -77,6 +77,18 @@ func (t *TUN) addRoute(network net.IPNet) error { }) } +func (t *TUN) delRoute(network net.IPNet) error { + link, err := netlink.LinkByName(t.Iface.Name()) + if err != nil { + return err + } + return netlink.RouteDel(&netlink.Route{ + LinkIndex: link.Attrs().Index, + Dst: &network, + Priority: 3000, + }) +} + // Up brings up an interface to allow it to start accepting connections. func (t *TUN) Up() error { link, err := netlink.LinkByName(t.Iface.Name())