package main import ( "errors" "fmt" "net" ) var subCmdVPNPublicAddressGet = subCmd{ name: "get", descr: "Display the currently configured public address", do: doWithOutput(func(ctx subCmdCtx) (any, error) { ctx, err := ctx.withParsedFlags(nil) if err != nil { return nil, fmt.Errorf("parsing flags: %w", err) } daemonRPC, err := ctx.newDaemonRPC() if err != nil { return nil, fmt.Errorf("creating daemon RPC client: %w", err) } defer daemonRPC.Close() config, err := daemonRPC.GetConfig(ctx) if err != nil { return nil, fmt.Errorf("getting network config: %w", err) } if config.VPN.PublicAddr == "" { return nil, errors.New("No public address configured") } return config.VPN.PublicAddr, nil }), } var subCmdVPNPublicAddressSet = subCmd{ name: "set", descr: "Set the public address of the host, or overwrite the already configured one", do: func(ctx subCmdCtx) error { publicAddr := ctx.flags.String( "public-addr", "", "Public address (host:port) that this host is publicly available on", ) ctx, err := ctx.withParsedFlags(nil) if err != nil { return fmt.Errorf("parsing flags: %w", err) } if *publicAddr == "" { return errors.New("--public-addr is required") } else if _, _, err := net.SplitHostPort(*publicAddr); err != nil { return fmt.Errorf("invalid --public-addr: %w", err) } daemonRPC, err := ctx.newDaemonRPC() if err != nil { return fmt.Errorf("creating daemon RPC client: %w", err) } defer daemonRPC.Close() config, err := daemonRPC.GetConfig(ctx) if err != nil { return fmt.Errorf("getting network config: %w", err) } config.VPN.PublicAddr = *publicAddr return daemonRPC.SetConfig(ctx, config) }, } var subCmdVPNPublicAddressUnset = subCmd{ name: "unset", descr: "Unset the public address", do: func(ctx subCmdCtx) error { ctx, err := ctx.withParsedFlags(nil) if err != nil { return fmt.Errorf("parsing flags: %w", err) } daemonRPC, err := ctx.newDaemonRPC() if err != nil { return fmt.Errorf("creating daemon RPC client: %w", err) } defer daemonRPC.Close() config, err := daemonRPC.GetConfig(ctx) if err != nil { return fmt.Errorf("getting network config: %w", err) } config.VPN.PublicAddr = "" return daemonRPC.SetConfig(ctx, config) }, } var subCmdVPNPublicAddress = subCmd{ name: "public-address", descr: "Configure the public address of this host, allowing other hosts to use it in order to find and communicate directly with each other", do: func(ctx subCmdCtx) error { return ctx.doSubCmd( subCmdVPNPublicAddressGet, subCmdVPNPublicAddressSet, subCmdVPNPublicAddressUnset, ) }, }