feat: initial commit
This commit is contained in:
52
internal/openwrt/uci/parser.go
Normal file
52
internal/openwrt/uci/parser.go
Normal file
@ -0,0 +1,52 @@
|
||||
package uci
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/alecthomas/participle/v2"
|
||||
"github.com/alecthomas/participle/v2/lexer"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
var (
|
||||
uciLexer = lexer.MustSimple([]lexer.SimpleRule{
|
||||
{Name: `Ident`, Pattern: `[a-zA-Z][a-zA-Z\d_\-]*`},
|
||||
{Name: `String`, Pattern: `'([^'])*'`},
|
||||
{Name: "whitespace", Pattern: `\s+`},
|
||||
})
|
||||
parser = participle.MustBuild[UCI](
|
||||
participle.Lexer(uciLexer),
|
||||
participle.Unquote("String"),
|
||||
)
|
||||
)
|
||||
|
||||
type Parser struct{}
|
||||
|
||||
func ParseFile(filename string) (*UCI, error) {
|
||||
file, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err := file.Close(); err != nil {
|
||||
panic(errors.WithStack(err))
|
||||
}
|
||||
}()
|
||||
|
||||
uci, err := parser.Parse(filename, file, participle.Trace(os.Stdout))
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
return uci, nil
|
||||
}
|
||||
|
||||
func Parse(data []byte) (*UCI, error) {
|
||||
uci, err := parser.ParseBytes("", data)
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
return uci, nil
|
||||
}
|
36
internal/openwrt/uci/parser_test.go
Normal file
36
internal/openwrt/uci/parser_test.go
Normal file
@ -0,0 +1,36 @@
|
||||
package uci
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/andreyvit/diff"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func TestParser(t *testing.T) {
|
||||
data, err := ioutil.ReadFile("./testdata/openwrt_22.03.2_linksys_wrt1900ac-v2_default.conf")
|
||||
if err != nil {
|
||||
t.Fatal(errors.WithStack(err))
|
||||
}
|
||||
|
||||
uci, err := Parse(data)
|
||||
if err != nil {
|
||||
t.Fatal(errors.WithStack(err))
|
||||
}
|
||||
|
||||
exported := uci.Export()
|
||||
|
||||
if e, g := string(data), exported; e != g {
|
||||
t.Errorf("uci.Export(): %s", diff.LineDiff(e, g))
|
||||
}
|
||||
|
||||
err = ioutil.WriteFile(
|
||||
"./testdata/exported/openwrt_22.03.2_linksys_wrt1900ac-v2_default.conf",
|
||||
[]byte(exported), os.ModePerm,
|
||||
)
|
||||
if err != nil {
|
||||
t.Error(errors.WithStack(err))
|
||||
}
|
||||
}
|
2
internal/openwrt/uci/testdata/exported/.gitignore
vendored
Normal file
2
internal/openwrt/uci/testdata/exported/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
*
|
||||
!.gitignore
|
441
internal/openwrt/uci/testdata/openwrt_22.03.2_linksys_wrt1900ac-v2_default.conf
vendored
Normal file
441
internal/openwrt/uci/testdata/openwrt_22.03.2_linksys_wrt1900ac-v2_default.conf
vendored
Normal file
@ -0,0 +1,441 @@
|
||||
package dhcp
|
||||
|
||||
config dnsmasq
|
||||
option domainneeded '1'
|
||||
option boguspriv '1'
|
||||
option filterwin2k '0'
|
||||
option localise_queries '1'
|
||||
option rebind_protection '1'
|
||||
option rebind_localhost '1'
|
||||
option local '/lan/'
|
||||
option domain 'lan'
|
||||
option expandhosts '1'
|
||||
option nonegcache '0'
|
||||
option authoritative '1'
|
||||
option readethers '1'
|
||||
option leasefile '/tmp/dhcp.leases'
|
||||
option resolvfile '/tmp/resolv.conf.d/resolv.conf.auto'
|
||||
option nonwildcard '1'
|
||||
option localservice '1'
|
||||
option ednspacket_max '1232'
|
||||
|
||||
config dhcp 'lan'
|
||||
option interface 'lan'
|
||||
option start '100'
|
||||
option limit '150'
|
||||
option leasetime '12h'
|
||||
option dhcpv4 'server'
|
||||
option dhcpv6 'server'
|
||||
option ra 'server'
|
||||
option ra_slaac '1'
|
||||
list ra_flags 'managed-config'
|
||||
list ra_flags 'other-config'
|
||||
|
||||
config dhcp 'wan'
|
||||
option interface 'wan'
|
||||
option ignore '1'
|
||||
|
||||
config odhcpd 'odhcpd'
|
||||
option maindhcp '0'
|
||||
option leasefile '/tmp/hosts/odhcpd'
|
||||
option leasetrigger '/usr/sbin/odhcpd-update'
|
||||
option loglevel '4'
|
||||
|
||||
package dropbear
|
||||
|
||||
config dropbear
|
||||
option PasswordAuth 'on'
|
||||
option RootPasswordAuth 'on'
|
||||
option Port '22'
|
||||
|
||||
package firewall
|
||||
|
||||
config defaults
|
||||
option syn_flood '1'
|
||||
option input 'ACCEPT'
|
||||
option output 'ACCEPT'
|
||||
option forward 'REJECT'
|
||||
|
||||
config zone
|
||||
option name 'lan'
|
||||
list network 'lan'
|
||||
option input 'ACCEPT'
|
||||
option output 'ACCEPT'
|
||||
option forward 'ACCEPT'
|
||||
|
||||
config zone
|
||||
option name 'wan'
|
||||
list network 'wan'
|
||||
list network 'wan6'
|
||||
option input 'REJECT'
|
||||
option output 'ACCEPT'
|
||||
option forward 'REJECT'
|
||||
option masq '1'
|
||||
option mtu_fix '1'
|
||||
|
||||
config forwarding
|
||||
option src 'lan'
|
||||
option dest 'wan'
|
||||
|
||||
config rule
|
||||
option name 'Allow-DHCP-Renew'
|
||||
option src 'wan'
|
||||
option proto 'udp'
|
||||
option dest_port '68'
|
||||
option target 'ACCEPT'
|
||||
option family 'ipv4'
|
||||
|
||||
config rule
|
||||
option name 'Allow-Ping'
|
||||
option src 'wan'
|
||||
option proto 'icmp'
|
||||
option icmp_type 'echo-request'
|
||||
option family 'ipv4'
|
||||
option target 'ACCEPT'
|
||||
|
||||
config rule
|
||||
option name 'Allow-IGMP'
|
||||
option src 'wan'
|
||||
option proto 'igmp'
|
||||
option family 'ipv4'
|
||||
option target 'ACCEPT'
|
||||
|
||||
config rule
|
||||
option name 'Allow-DHCPv6'
|
||||
option src 'wan'
|
||||
option proto 'udp'
|
||||
option dest_port '546'
|
||||
option family 'ipv6'
|
||||
option target 'ACCEPT'
|
||||
|
||||
config rule
|
||||
option name 'Allow-MLD'
|
||||
option src 'wan'
|
||||
option proto 'icmp'
|
||||
option src_ip 'fe80::/10'
|
||||
list icmp_type '130/0'
|
||||
list icmp_type '131/0'
|
||||
list icmp_type '132/0'
|
||||
list icmp_type '143/0'
|
||||
option family 'ipv6'
|
||||
option target 'ACCEPT'
|
||||
|
||||
config rule
|
||||
option name 'Allow-ICMPv6-Input'
|
||||
option src 'wan'
|
||||
option proto 'icmp'
|
||||
list icmp_type 'echo-request'
|
||||
list icmp_type 'echo-reply'
|
||||
list icmp_type 'destination-unreachable'
|
||||
list icmp_type 'packet-too-big'
|
||||
list icmp_type 'time-exceeded'
|
||||
list icmp_type 'bad-header'
|
||||
list icmp_type 'unknown-header-type'
|
||||
list icmp_type 'router-solicitation'
|
||||
list icmp_type 'neighbour-solicitation'
|
||||
list icmp_type 'router-advertisement'
|
||||
list icmp_type 'neighbour-advertisement'
|
||||
option limit '1000/sec'
|
||||
option family 'ipv6'
|
||||
option target 'ACCEPT'
|
||||
|
||||
config rule
|
||||
option name 'Allow-ICMPv6-Forward'
|
||||
option src 'wan'
|
||||
option dest '*'
|
||||
option proto 'icmp'
|
||||
list icmp_type 'echo-request'
|
||||
list icmp_type 'echo-reply'
|
||||
list icmp_type 'destination-unreachable'
|
||||
list icmp_type 'packet-too-big'
|
||||
list icmp_type 'time-exceeded'
|
||||
list icmp_type 'bad-header'
|
||||
list icmp_type 'unknown-header-type'
|
||||
option limit '1000/sec'
|
||||
option family 'ipv6'
|
||||
option target 'ACCEPT'
|
||||
|
||||
config rule
|
||||
option name 'Allow-IPSec-ESP'
|
||||
option src 'wan'
|
||||
option dest 'lan'
|
||||
option proto 'esp'
|
||||
option target 'ACCEPT'
|
||||
|
||||
config rule
|
||||
option name 'Allow-ISAKMP'
|
||||
option src 'wan'
|
||||
option dest 'lan'
|
||||
option dest_port '500'
|
||||
option proto 'udp'
|
||||
option target 'ACCEPT'
|
||||
|
||||
package luci
|
||||
|
||||
config core 'main'
|
||||
option lang 'auto'
|
||||
option mediaurlbase '/luci-static/bootstrap'
|
||||
option resourcebase '/luci-static/resources'
|
||||
option ubuspath '/ubus/'
|
||||
|
||||
config extern 'flash_keep'
|
||||
option uci '/etc/config/'
|
||||
option dropbear '/etc/dropbear/'
|
||||
option openvpn '/etc/openvpn/'
|
||||
option passwd '/etc/passwd'
|
||||
option opkg '/etc/opkg.conf'
|
||||
option firewall '/etc/firewall.user'
|
||||
option uploads '/lib/uci/upload/'
|
||||
|
||||
config internal 'languages'
|
||||
|
||||
config internal 'sauth'
|
||||
option sessionpath '/tmp/luci-sessions'
|
||||
option sessiontime '3600'
|
||||
|
||||
config internal 'ccache'
|
||||
option enable '1'
|
||||
|
||||
config internal 'themes'
|
||||
option Bootstrap '/luci-static/bootstrap'
|
||||
option BootstrapDark '/luci-static/bootstrap-dark'
|
||||
option BootstrapLight '/luci-static/bootstrap-light'
|
||||
|
||||
config internal 'apply'
|
||||
option rollback '90'
|
||||
option holdoff '4'
|
||||
option timeout '5'
|
||||
option display '1.5'
|
||||
|
||||
config internal 'diag'
|
||||
option dns 'openwrt.org'
|
||||
option ping 'openwrt.org'
|
||||
option route 'openwrt.org'
|
||||
|
||||
package network
|
||||
|
||||
config interface 'loopback'
|
||||
option device 'lo'
|
||||
option proto 'static'
|
||||
option ipaddr '127.0.0.1'
|
||||
option netmask '255.0.0.0'
|
||||
|
||||
config globals 'globals'
|
||||
option ula_prefix 'fd04:9171:adaa::/48'
|
||||
|
||||
config device
|
||||
option name 'br-lan'
|
||||
option type 'bridge'
|
||||
list ports 'lan1'
|
||||
list ports 'lan2'
|
||||
list ports 'lan3'
|
||||
list ports 'lan4'
|
||||
|
||||
config interface 'lan'
|
||||
option device 'br-lan'
|
||||
option proto 'static'
|
||||
option ipaddr '192.168.1.1'
|
||||
option netmask '255.255.255.0'
|
||||
option ip6assign '60'
|
||||
|
||||
config device
|
||||
option name 'wan'
|
||||
option macaddr '32:23:03:cd:b6:6c'
|
||||
|
||||
config interface 'wan'
|
||||
option device 'wan'
|
||||
option proto 'dhcp'
|
||||
|
||||
config interface 'wan6'
|
||||
option device 'wan'
|
||||
option proto 'dhcpv6'
|
||||
|
||||
package rpcd
|
||||
|
||||
config rpcd
|
||||
option socket '/var/run/ubus/ubus.sock'
|
||||
option timeout '30'
|
||||
|
||||
config login
|
||||
option username 'root'
|
||||
option password '$p$root'
|
||||
list read '*'
|
||||
list write '*'
|
||||
|
||||
package system
|
||||
|
||||
config system
|
||||
option hostname 'OpenWrt'
|
||||
option timezone 'UTC'
|
||||
option ttylogin '0'
|
||||
option log_size '64'
|
||||
option urandom_seed '0'
|
||||
option compat_version '1.1'
|
||||
|
||||
config timeserver 'ntp'
|
||||
option enabled '1'
|
||||
option enable_server '0'
|
||||
list server '0.openwrt.pool.ntp.org'
|
||||
list server '1.openwrt.pool.ntp.org'
|
||||
list server '2.openwrt.pool.ntp.org'
|
||||
list server '3.openwrt.pool.ntp.org'
|
||||
|
||||
config led 'led_wan'
|
||||
option name 'WAN'
|
||||
option sysfs 'pca963x:cobra:white:wan'
|
||||
option trigger 'netdev'
|
||||
option mode 'link tx rx'
|
||||
option dev 'wan'
|
||||
|
||||
config led 'led_usb1'
|
||||
option name 'USB 1'
|
||||
option sysfs 'pca963x:cobra:white:usb2'
|
||||
option trigger 'usbport'
|
||||
list port 'usb1-port1'
|
||||
|
||||
config led 'led_usb2'
|
||||
option name 'USB 2'
|
||||
option sysfs 'pca963x:cobra:white:usb3_1'
|
||||
option trigger 'usbport'
|
||||
list port 'usb2-port1'
|
||||
list port 'usb3-port1'
|
||||
|
||||
config led 'led_usb2_ss'
|
||||
option name 'USB 2 SS'
|
||||
option sysfs 'pca963x:cobra:white:usb3_2'
|
||||
option trigger 'usbport'
|
||||
list port 'usb3-port1'
|
||||
|
||||
package ubootenv
|
||||
|
||||
config ubootenv
|
||||
option dev '/dev/mtd1'
|
||||
option offset '0x0'
|
||||
option envsize '0x20000'
|
||||
option secsize '0x40000'
|
||||
|
||||
package ucitrack
|
||||
|
||||
config network
|
||||
option init 'network'
|
||||
list affects 'dhcp'
|
||||
|
||||
config wireless
|
||||
list affects 'network'
|
||||
|
||||
config firewall
|
||||
option init 'firewall'
|
||||
list affects 'luci-splash'
|
||||
list affects 'qos'
|
||||
list affects 'miniupnpd'
|
||||
|
||||
config olsr
|
||||
option init 'olsrd'
|
||||
|
||||
config dhcp
|
||||
option init 'dnsmasq'
|
||||
list affects 'odhcpd'
|
||||
|
||||
config odhcpd
|
||||
option init 'odhcpd'
|
||||
|
||||
config dropbear
|
||||
option init 'dropbear'
|
||||
|
||||
config httpd
|
||||
option init 'httpd'
|
||||
|
||||
config fstab
|
||||
option exec '/sbin/block mount'
|
||||
|
||||
config qos
|
||||
option init 'qos'
|
||||
|
||||
config system
|
||||
option init 'led'
|
||||
option exec '/etc/init.d/log reload'
|
||||
list affects 'luci_statistics'
|
||||
list affects 'dhcp'
|
||||
|
||||
config luci_splash
|
||||
option init 'luci_splash'
|
||||
|
||||
config upnpd
|
||||
option init 'miniupnpd'
|
||||
|
||||
config ntpclient
|
||||
option init 'ntpclient'
|
||||
|
||||
config samba
|
||||
option init 'samba'
|
||||
|
||||
config tinyproxy
|
||||
option init 'tinyproxy'
|
||||
|
||||
package uhttpd
|
||||
|
||||
config uhttpd 'main'
|
||||
list listen_http '0.0.0.0:80'
|
||||
list listen_http '[::]:80'
|
||||
list listen_https '0.0.0.0:443'
|
||||
list listen_https '[::]:443'
|
||||
option redirect_https '0'
|
||||
option home '/www'
|
||||
option rfc1918_filter '1'
|
||||
option max_requests '3'
|
||||
option max_connections '100'
|
||||
option cert '/etc/uhttpd.crt'
|
||||
option key '/etc/uhttpd.key'
|
||||
option cgi_prefix '/cgi-bin'
|
||||
list lua_prefix '/cgi-bin/luci=/usr/lib/lua/luci/sgi/uhttpd.lua'
|
||||
option script_timeout '60'
|
||||
option network_timeout '30'
|
||||
option http_keepalive '20'
|
||||
option tcp_keepalive '1'
|
||||
option ubus_prefix '/ubus'
|
||||
|
||||
config cert 'defaults'
|
||||
option days '730'
|
||||
option key_type 'ec'
|
||||
option bits '2048'
|
||||
option ec_curve 'P-256'
|
||||
option country 'ZZ'
|
||||
option state 'Somewhere'
|
||||
option location 'Unknown'
|
||||
option commonname 'OpenWrt'
|
||||
|
||||
package wireless
|
||||
|
||||
config wifi-device 'radio0'
|
||||
option type 'mac80211'
|
||||
option path 'soc/soc:pcie/pci0000:00/0000:00:01.0/0000:01:00.0'
|
||||
option channel '36'
|
||||
option band '5g'
|
||||
option htmode 'VHT80'
|
||||
option disabled '1'
|
||||
option country 'FR'
|
||||
|
||||
config wifi-iface 'default_radio0'
|
||||
option device 'radio0'
|
||||
option network 'lan'
|
||||
option mode 'ap'
|
||||
option ssid 'OpenWrt'
|
||||
option encryption 'none'
|
||||
option macaddr '30:23:03:cd:b6:6e'
|
||||
|
||||
config wifi-device 'radio1'
|
||||
option type 'mac80211'
|
||||
option path 'soc/soc:pcie/pci0000:00/0000:00:02.0/0000:02:00.0'
|
||||
option channel '1'
|
||||
option band '2g'
|
||||
option htmode 'HT20'
|
||||
option disabled '1'
|
||||
option country 'FR'
|
||||
|
||||
config wifi-iface 'default_radio1'
|
||||
option device 'radio1'
|
||||
option network 'lan'
|
||||
option mode 'ap'
|
||||
option ssid 'OpenWrt'
|
||||
option encryption 'none'
|
||||
option macaddr '30:23:03:cd:b6:6d'
|
75
internal/openwrt/uci/uci.go
Normal file
75
internal/openwrt/uci/uci.go
Normal file
@ -0,0 +1,75 @@
|
||||
package uci
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
type UCI struct {
|
||||
Packages []*Package `parser:"@@*" json:"packages"`
|
||||
}
|
||||
|
||||
type Package struct {
|
||||
Name string `parser:"'package' @Ident" json:"name"`
|
||||
Configs []*Config `parser:"@@*" json:"configs"`
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Name string `parser:"'config' @Ident" json:"name"`
|
||||
Section *string `parser:"@String?" json:"section,omitempty"`
|
||||
Options []Option `parser:"@@*" json:"options"`
|
||||
}
|
||||
|
||||
type Option struct {
|
||||
Type string `parser:"@( 'list' | 'option' )" json:"type"`
|
||||
Name string `parser:"@Ident" json:"name"`
|
||||
Value string `parser:"@String" json:"value"`
|
||||
}
|
||||
|
||||
func (u *UCI) Export() string {
|
||||
var sb strings.Builder
|
||||
|
||||
for pkgIdx, pkg := range u.Packages {
|
||||
if pkgIdx > 0 {
|
||||
sb.WriteString("\n")
|
||||
}
|
||||
|
||||
sb.WriteString("package ")
|
||||
sb.WriteString(pkg.Name)
|
||||
sb.WriteString("\n")
|
||||
|
||||
for _, cfg := range pkg.Configs {
|
||||
sb.WriteString("\n")
|
||||
|
||||
sb.WriteString("config ")
|
||||
sb.WriteString(cfg.Name)
|
||||
|
||||
if cfg.Section != nil {
|
||||
sb.WriteString(" '")
|
||||
sb.WriteString(*cfg.Section)
|
||||
sb.WriteString("'")
|
||||
}
|
||||
|
||||
for _, opt := range cfg.Options {
|
||||
sb.WriteString("\n")
|
||||
|
||||
sb.WriteString("\t")
|
||||
sb.WriteString(opt.Type)
|
||||
sb.WriteString(" ")
|
||||
sb.WriteString(opt.Name)
|
||||
sb.WriteString(" '")
|
||||
sb.WriteString(opt.Value)
|
||||
sb.WriteString("'")
|
||||
}
|
||||
|
||||
sb.WriteString("\n")
|
||||
}
|
||||
}
|
||||
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
func NewUCI() *UCI {
|
||||
return &UCI{
|
||||
Packages: make([]*Package, 0),
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user