diff --git a/server.cfg b/server.cfg index 498a6e7..5994b78 100644 --- a/server.cfg +++ b/server.cfg @@ -6,11 +6,19 @@ port 6697 { ssl = true } port 7011 { ssl = true class = "server" + bind_ip = "87.237.63.85" } oper fluffle { - pass = "foobar" + password = "foobar" hostmask = "*camelid@*" link = true } +oper "bb101" { + password = "dongs" + hostmask = "*bb10@*.enta.net" + hostmask = "*bb@*.dongs.com" + renick = true +} + diff --git a/server/config/config.go b/server/config/config.go index 93b0d4a..e78f93f 100644 --- a/server/config/config.go +++ b/server/config/config.go @@ -36,7 +36,7 @@ type keywordMap map[string]func(*Config, interface{}) var configKeywords = configMap{ "port": (*Config).parsePort, -// "oper": (*Config).parseOper, + "oper": (*Config).parseOper, // "link": (*Config).parseLink, // "ban": (*Config).parseBan, // "info": (*Config).parseInfo, @@ -142,6 +142,15 @@ func (conf *Config) expectInt() (int, bool) { return num, true } +func (conf *Config) expectString() (string, bool) { + tok, text := conf.next() + if tok != scanner.String && tok != scanner.Ident { + conf.parseError("Expected string, got '%s'", text) + return "", false + } + return text, true +} + func (conf *Config) expect(str string) bool { _, text := conf.next() if text != str { diff --git a/server/config/oper.go b/server/config/oper.go index 2f009f8..8a41396 100644 --- a/server/config/oper.go +++ b/server/config/oper.go @@ -1,16 +1,106 @@ package config +import ( + "fmt" + "strings" + "scanner" +) + type cOper struct { Username, Password string HostMask []string // Permissions for oper - CanKill, CanBan, CanNick, CanLink bool + CanKill, CanBan, CanRenick, CanLink bool } -var cOperDefaults = &cOper{ - HostMask: []string{"*@*"}, - CanKill: true, CanBan: true, - CanNick: false, CanLink: false, +var operKeywords = keywordMap{ + "password": (*Config).parseOperPassword, + "hostmask": (*Config).parseOperHostMask, + "kill": (*Config).parseOperKill, + "ban": (*Config).parseOperBan, + "renick": (*Config).parseOperRenick, + "link": (*Config).parseOperLink, } +func defaultOper() *cOper { + return &cOper{ + HostMask: []string{}, + CanKill: true, CanBan: true, + CanRenick: false, CanLink: false, + } +} + +func (o *cOper) String() string { + str := []string{fmt.Sprintf("oper \"%s\" {", o.Username)} + str = append(str, fmt.Sprintf("\tpassword = \"%s\"", o.Password)) + if len(o.HostMask) == 0 { + str = append(str, fmt.Sprintf("\thostmask = \"*@*\"")) + } else { + for _, h := range o.HostMask { + str = append(str, fmt.Sprintf("\thostmask = \"%s\"", h)) + } + } + str = append(str, + fmt.Sprintf("\tkill = %t", o.CanKill), + fmt.Sprintf("\tban = %t", o.CanBan), + fmt.Sprintf("\trenick = %t", o.CanRenick), + fmt.Sprintf("\tlink = %t", o.CanLink), + "}", + ) + return strings.Join(str, "\n") +} + +func (conf *Config) parseOper() { + oper := defaultOper() + tok, text := conf.next() + if tok != scanner.String && tok != scanner.Ident { + conf.parseError("Invalid username '%s'", text) + return + } + oper.Username = text + conf.parseKwBlock(oper, "oper", operKeywords) + fmt.Println(oper.String()) +} + +func (conf *Config) parseOperPassword(oi interface{}) { + oper := oi.(*cOper) + if pass, ok := conf.expectString(); ok { + oper.Password = pass + } +} + +func (conf *Config) parseOperHostMask(oi interface{}) { + oper := oi.(*cOper) + if mask, ok := conf.expectString(); ok { + oper.HostMask = append(oper.HostMask, mask) + } +} + +func (conf *Config) parseOperKill(oi interface{}) { + oper := oi.(*cOper) + if kill, ok := conf.expectBool(); ok { + oper.CanKill = kill + } +} + +func (conf *Config) parseOperBan(oi interface{}) { + oper := oi.(*cOper) + if ban, ok := conf.expectBool(); ok { + oper.CanBan = ban + } +} + +func (conf *Config) parseOperRenick(oi interface{}) { + oper := oi.(*cOper) + if renick, ok := conf.expectBool(); ok { + oper.CanRenick = renick + } +} + +func (conf *Config) parseOperLink(oi interface{}) { + oper := oi.(*cOper) + if link, ok := conf.expectBool(); ok { + oper.CanLink = link + } +} diff --git a/server/config/port.go b/server/config/port.go index 0c110c4..a49a4b3 100644 --- a/server/config/port.go +++ b/server/config/port.go @@ -1,6 +1,7 @@ package config import ( + "net" "fmt" "strings" "scanner" @@ -8,40 +9,34 @@ import ( type cPort struct { Port int - BindIP, Family, Class string + BindIP net.IP // bind to a specific IP for listen port + Class string // "server" or "client" // Is port a tls.Listener? Does it support compression (no)? SSL, Zip bool - - // address == ":" - address string } var portKeywords = keywordMap{ -// "bind_ip": (*Config).parsePortBindIP, -// "family": (*Config).parsePortFamily, + "bind_ip": (*Config).parsePortBindIP, "class": (*Config).parsePortClass, "ssl": (*Config).parsePortSSL, -// "zip": (*Config).parsePortZip, -} - -var cPortDefaults = cPort{ - BindIP: "", Family: "tcp", Class: "client", - SSL: false, Zip: false, + "zip": (*Config).parsePortZip, } func defaultPort() *cPort { - p := cPortDefaults - return &p + return &cPort{ + BindIP: nil, Class: "client", + SSL: false, Zip: false, + } } func (p *cPort) String() string { str := []string{fmt.Sprintf("port %d {", p.Port)} - if p.BindIP != "" { - str = append(str, "\tbind_ip = " + p.BindIP) + if p.BindIP != nil { + str = append(str, + fmt.Sprintf("\tbind_ip = \"%s\"", p.BindIP.String())) } str = append(str, - fmt.Sprintf("\tfamily = \"%s\"",p.Family), fmt.Sprintf("\tclass = \"%s\"", p.Class), fmt.Sprintf("\tssl = %t", p.SSL), fmt.Sprintf("\tzip = %t", p.Zip), @@ -66,6 +61,16 @@ func (conf *Config) parsePort() { fmt.Println(port.String()) } +func (conf *Config) parsePortBindIP(pi interface{}) { + port := pi.(*cPort) + _, text := conf.next() + if ip := net.ParseIP(text); ip != nil { + port.BindIP = ip + } else { + conf.parseError("'%s' is not a valid IP address", text) + } +} + func (conf *Config) parsePortClass(pi interface{}) { port := pi.(*cPort) tok, text := conf.next() @@ -84,3 +89,9 @@ func (conf *Config) parsePortSSL(pi interface{}) { } } +func (conf *Config) parsePortZip(pi interface{}) { + port := pi.(*cPort) + if zip, ok := conf.expectBool(); ok { + port.Zip = zip + } +}