Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion server/handlers/wireguard/fields/fields_formatted.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ var AllOptionsFormatted = map[NormalizedName]string{
"mtu": "MTU",
"preup": "PreUp",
"postup": "PostUp",
"predown": "Predown",
"predown": "PreDown",
"postdown": "PostDown",
"fwmark": "FwMark",

Expand Down
1 change: 1 addition & 0 deletions server/handlers/wireguard/handlers/code-actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const (
CodeActionGeneratePrivateKey CodeActionName = "generatePrivateKey"
CodeActionGeneratePresharedKey CodeActionName = "generatePresharedKey"
CodeActionCreatePeer CodeActionName = "createPeer"
CodeActionGeneratePostDown CodeActionName = "generatePostDown"
)

type CodeAction interface {
Expand Down
101 changes: 101 additions & 0 deletions server/handlers/wireguard/handlers/code-actions_generate-postdown.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package handlers

import (
"config-lsp/handlers/wireguard"
"config-lsp/utils"
"errors"
"strings"

protocol "github.com/tliron/glsp/protocol_3_16"
)

type CodeActionGeneratePostdownKeyArgs struct {
URI protocol.DocumentUri
}

func CodeActionGeneratePostdownArgsFromArguments(arguments map[string]any) CodeActionGeneratePostdownKeyArgs {
return CodeActionGeneratePostdownKeyArgs{
URI: arguments["URI"].(protocol.DocumentUri),
}
}

func (args CodeActionGeneratePostdownKeyArgs) RunCommand(d *wireguard.WGDocument) (*protocol.ApplyWorkspaceEditParams, error) {
if utils.BlockUntilIndexesNotNil(d.Indexes) == false {
return nil, errors.New("Indexes are not ready yet")
}

lastUpPropertyKey := utils.FindBiggestKey(d.Indexes.UpProperties)
lastUpProperty := d.Indexes.UpProperties[lastUpPropertyKey]

// TODO: Find out if the user specified multiple PreDown or only one (or maybe don't do this at all)

rules := findAllIPTableRules(d)
invertedRules := generateInvertedRules(rules)

if len(invertedRules) == 0 {
return nil, errors.New("No valid iptables rules found to invert")
}

newRulesString := strings.Join(invertedRules, "; ")
newPropertyString := "\nPostDown = " + newRulesString + "\n"

label := "Generate PostDown with inverted rules"
return &protocol.ApplyWorkspaceEditParams{
Label: &label,
Edit: protocol.WorkspaceEdit{
Changes: map[protocol.DocumentUri][]protocol.TextEdit{
args.URI: {
{
Range: protocol.Range{
Start: lastUpProperty.Property.Value.ToLSPRange().End,
End: lastUpProperty.Property.Value.ToLSPRange().End,
},
NewText: newPropertyString,
},
},
},
},
}, nil
}

func findAllIPTableRules(
d *wireguard.WGDocument,
) []string {
upRules := make([]string, 0)

for _, info := range d.Indexes.UpProperties {
if info.Property != nil && info.Property.Value != nil {
rulesRaw := info.Property.Value.Value
rules := strings.Split(rulesRaw, ";")

upRules = append(upRules, rules...)
}
}

return upRules
}

func generateInvertedRules(rules []string) []string {
var postDownRules []string

for _, rule := range rules {
ipTableRule, err := utils.ParseIpTableRule(rule)

if err != nil {
return nil
}

inverted := ipTableRule.InvertAction()

if inverted.Action != utils.IpTableActionDelete {
// We only want to generate actions for common actions
return nil
}

ruleStringRaw := inverted.String()
ruleString := strings.ReplaceAll(strings.TrimSpace(ruleStringRaw), " ", " ")
postDownRules = append(postDownRules, ruleString)
}

return postDownRules
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
protocol "github.com/tliron/glsp/protocol_3_16"
)

func GetAddPeerLikeThis(
func GetAddPeerLikeThisCodeActions(
d *wireguard.WGDocument,
params *protocol.CodeActionParams,
) []protocol.CodeAction {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package handlers

import (
"config-lsp/handlers/wireguard"
"config-lsp/handlers/wireguard/fields"
"config-lsp/parsers/ini"
"config-lsp/utils"

protocol "github.com/tliron/glsp/protocol_3_16"
)

func GetGeneratePostDownCodeActions(
d *wireguard.WGDocument,
params *protocol.CodeActionParams,
) []protocol.CodeAction {
postDownPropertyNames := map[fields.NormalizedName]struct{}{
fields.CreateNormalizedName("PreUp"): {},
fields.CreateNormalizedName("PostUp"): {},
}

line := params.Range.Start.Line

section := d.Config.FindSectionByLine(line)

if section == nil {
return nil
}

rawProperty, found := section.Properties.Get(line)

if !found {
return nil
}

property := rawProperty.(*ini.Property)

propertyName := fields.CreateNormalizedName(property.Key.Name)
if (utils.KeyExists(postDownPropertyNames, propertyName)) && (property.Value != nil) {
// Only propose this action if no PostDown is already present
_, postDownProperty := section.FindFirstPropertyByName("PostDown")

if postDownProperty == nil {
commandID := "wireguard." + CodeActionGeneratePostDown

command := protocol.Command{
Title: "Generate PostDown with inverted rules",
Command: string(commandID),
Arguments: []any{
CodeActionGeneratePostdownKeyArgs{
URI: params.TextDocument.URI,
},
},
}

return []protocol.CodeAction{
{
Title: "Generate PostDown with inverted rules",
Command: &command,
},
}
}
}

return nil
}
5 changes: 4 additions & 1 deletion server/handlers/wireguard/indexes/indexes.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ type WGIndexes struct {
// map of: section name -> *ini.Section
SectionsByName map[string][]*ini.Section

// map of: line number -> *WGIndexPropertyInfo
// map of: line number -> WGIndexPropertyInfo
UnknownProperties map[uint32]WGIndexPropertyInfo

// map of: line number -> WGIndexPropertyInfo (PreUp / PostUp properties)
UpProperties map[uint32]WGIndexPropertyInfo
}
21 changes: 21 additions & 0 deletions server/handlers/wireguard/indexes/indexes_handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,21 @@ package indexes
import (
"config-lsp/common"
"config-lsp/handlers/wireguard/ast"
"config-lsp/handlers/wireguard/fields"
"config-lsp/parsers/ini"
)

var upPropertyNames = map[fields.NormalizedName]struct{}{
fields.CreateNormalizedName("PreUp"): {},
fields.CreateNormalizedName("PostUp"): {},
}

func CreateIndexes(config *ast.WGConfig) (*WGIndexes, []common.LSPError) {
errs := make([]common.LSPError, 0)
indexes := &WGIndexes{
SectionsByName: make(map[string][]*ini.Section),
UnknownProperties: make(map[uint32]WGIndexPropertyInfo),
UpProperties: make(map[uint32]WGIndexPropertyInfo),
}

// Use the WGSections from the config
Expand All @@ -21,6 +28,20 @@ func CreateIndexes(config *ast.WGConfig) (*WGIndexes, []common.LSPError) {
indexes.SectionsByName[sectionName],
section,
)

it := section.Properties.Iterator()
for it.Next() {
lineNumber := it.Key().(uint32)
property := it.Value().(*ini.Property)
normalizedName := fields.CreateNormalizedName(property.Key.Name)

if _, found := upPropertyNames[normalizedName]; found {
indexes.UpProperties[lineNumber] = WGIndexPropertyInfo{
Section: section,
Property: property,
}
}
}
}

return indexes, errs
Expand Down
43 changes: 43 additions & 0 deletions server/handlers/wireguard/indexes/indexes_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package indexes

import (
"config-lsp/handlers/wireguard/ast"
"testing"
)

func TestIndexesUpProperties(t *testing.T) {
content := `
[Interface]
PrivateKey = abc
PreUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT
`

config := ast.NewWGConfig()
errs := config.Parse(content)

if len(errs) > 0 {
t.Fatalf("Failed to parse config: %v", errs)
}

indexes, errs := CreateIndexes(config)

if len(errs) > 0 {
t.Fatalf("Unexpected errors while creating indexes: %v", errs)
}

if len(indexes.UpProperties) != 1 {
t.Errorf("Expected 1 UpProperty, got %d", len(indexes.UpProperties))
}

if indexes.UpProperties[3].Section.Header.Name != "Interface" {
t.Errorf("Expected UpProperty section name 'Interface', got '%s'", indexes.UpProperties[0].Section.Header.Name)
}

if indexes.UpProperties[3].Property.Key.Name != "PreUp" {
t.Errorf("Expected UpProperty key name 'PreUp', got '%s'", indexes.UpProperties[0].Property.Key.Name)
}

if indexes.UpProperties[3].Property.Value.Value != "iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT" {
t.Errorf("Expected UpProperty value; %v", indexes.UpProperties[0].Property.Value.Value)
}
}
3 changes: 2 additions & 1 deletion server/handlers/wireguard/lsp/text-document-code-action.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ func TextDocumentCodeAction(context *glsp.Context, params *protocol.CodeActionPa

actions = append(actions, handlers.GetKeyGenerationCodeActions(d, params)...)
actions = append(actions, handlers.GetKeepaliveCodeActions(d, params)...)
actions = append(actions, handlers.GetAddPeerLikeThis(d, params)...)
actions = append(actions, handlers.GetAddPeerLikeThisCodeActions(d, params)...)
actions = append(actions, handlers.GetPropertyKeywordTypoFixes(d, params)...)
actions = append(actions, handlers.GetGeneratePostDownCodeActions(d, params)...)

if len(actions) > 0 {
return actions, nil
Expand Down
5 changes: 5 additions & 0 deletions server/handlers/wireguard/lsp/workspace-execute-command.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ func WorkspaceExecuteCommand(context *glsp.Context, params *protocol.ExecuteComm

d := wireguard.DocumentParserMap[args.URI]

return args.RunCommand(d)
case string(handlers.CodeActionGeneratePostDown):
args := handlers.CodeActionGeneratePostdownArgsFromArguments(params.Arguments[0].(map[string]any))

d := wireguard.DocumentParserMap[args.URI]
return args.RunCommand(d)
}

Expand Down
5 changes: 5 additions & 0 deletions server/nvim-lsp-debug.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
vim.lsp.start {
name = "config-lsp",
cmd = { "./result/bin/config-lsp" },
root_dir = vim.fn.getcwd(),
};
2 changes: 1 addition & 1 deletion server/parsers/ini/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func (c *Config) Clear() {
var commentPattern = regexp.MustCompile(`^\s*([;#])`)
var emptyPattern = regexp.MustCompile(`^\s*$`)
var headerPattern = regexp.MustCompile(`^\s*\[(\w+)?]?`)
var linePattern = regexp.MustCompile(`^\s*(?P<key>.+?)\s*(?P<separator>=)\s*(?P<value>\S.*?)?\s*(?:[;#].*)?\s*$`)
var linePattern = regexp.MustCompile(`^\s*(?P<key>.+?)\s*(?P<separator>=)\s*(?P<value>\S.*?)?\s*(?: [;#].*)?\s*$`)

// Parse parses an INI string and returns any errors encountered
func (c *Config) Parse(input string) []common.LSPError {
Expand Down
19 changes: 13 additions & 6 deletions server/parsers/ini/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ func TestParserWorks(t *testing.T) {
[Interface]
PrivateKey = 1234567890 # Some comment
Address = 10.0.0.1
PostUp = iptables -I FORWARD -i wg0 -j ACCEPT; iptables -I INPUT -i wg0 -j ACCEPT



Expand All @@ -30,12 +31,12 @@ PublicKey = 1234567890
t.Fatalf("Parse: Expected no errors, but got %v", errors)
}

if !(utils.KeyExists(config.CommentLines, 0) && utils.KeyExists(config.CommentLines, 12)) {
t.Errorf("Parse: Expected comments to be present on lines 0 and 12")
if !(utils.KeyExists(config.CommentLines, 0) && utils.KeyExists(config.CommentLines, 13)) {
t.Errorf("Parse: Expected comments to be present on lines 0 and 13")
}

if !(config.Sections[0].Start.Line == 3 && config.Sections[0].End.Line == 8) {
t.Errorf("Parse: Expected section 0 to be present on lines 3 and 6, but it is: %v", config.Sections[0].End)
if !(config.Sections[0].Start.Line == 3 && config.Sections[0].End.Line == 9) {
t.Errorf("Parse: Expected section 0 to be present on lines 3 and 9, but it is: %v", config.Sections[0].End)
}

if !(config.Sections[0].Start.Character == 0 && config.Sections[0].End.Character == 0) {
Expand All @@ -58,9 +59,15 @@ PublicKey = 1234567890
t.Errorf("Parse: Expected property line 5 to be correct")
}

rawTenthProperty, _ := config.Sections[1].Properties.Get(uint32(10))
rawTenthProperty, _ := config.Sections[1].Properties.Get(uint32(11))
tenthProperty := rawTenthProperty.(*Property)
if !(tenthProperty.Key.Name == "PublicKey" && tenthProperty.Value.Value == "1234567890") {
t.Errorf("Parse: Expected property line 10 to be correct")
t.Errorf("Parse: Expected property line 11 to be correct")
}

rawPostUpProperty, _ := config.Sections[0].Properties.Get(uint32(6))
postUpProperty := rawPostUpProperty.(*Property)
if !(postUpProperty.Key.Name == "PostUp" && postUpProperty.Value.Value == "iptables -I FORWARD -i wg0 -j ACCEPT; iptables -I INPUT -i wg0 -j ACCEPT") {
t.Errorf("Parse: Expected PostUp property to be correct; %v; %v", postUpProperty, postUpProperty.Value.Value)
}
}
Loading