whois42d/whois/query.go

124 lines
2.5 KiB
Go

package whois
import (
"bufio"
"flag"
"fmt"
"net"
"os"
"path"
"strings"
)
type pathpair struct {
objtype string
obj string
}
func (r *Registry) handleObject(conn *net.TCPConn, object Object, flags *Flags) bool {
found := false
paths := r.findObjectPaths(object)
for _, p := range paths {
r.printObject(conn, p.objtype, p.obj)
found = true
}
return found
}
func (r *Registry) HandleQuery(conn *net.TCPConn) {
fmt.Fprint(conn, "% "+r.Header+"\n\n")
query := parseQuery(conn)
if query == nil {
return
}
flags := query.Flags
if flags.ServerInfo != "" {
r.printServerInfo(conn, strings.TrimSpace(flags.ServerInfo))
return
}
found := false
for _, obj := range query.Objects {
if r.handleObject(conn, obj, flags) {
found = true
}
}
if !found {
fmt.Fprint(conn, "% 404\n")
}
fmt.Fprint(conn, "\n")
}
func parseQuery(conn *net.TCPConn) *Query {
r := bufio.NewReader(conn)
req, e := r.ReadString('\n')
if e != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", e)
return nil
}
flags, flagSet, err := parseFlags(req)
if err != nil {
flagSet.SetOutput(conn)
if err != flag.ErrHelp {
fmt.Fprintf(conn, "%s", err)
}
flagSet.PrintDefaults()
return nil
}
query := Query{}
query.Flags = flags
query.Objects = make([]Object, len(flags.Args))
for i, arg := range flags.Args {
query.Objects[i] = parseObject(strings.TrimSpace(arg))
}
fmt.Fprintf(os.Stdout, "[%s] %s\n", conn.RemoteAddr(), req)
return &query
}
func (r *Registry) printServerInfo(conn *net.TCPConn, what string) {
switch what {
case "version":
fmt.Fprintf(conn, "%% whois42d v%d\n", VERSION)
case "sources":
fmt.Fprintf(conn, "DN42:3:N:0-0\n")
case "types":
for _, t := range r.whoisTypes {
fmt.Fprintf(conn, "%s\n", t.Name)
}
default:
fmt.Fprintf(conn, "%% unknown option %s\n", what)
}
}
func (r *Registry) printNet(conn *net.TCPConn, name string, ip net.IP) bool {
routePath := path.Join(r.DataPath, name)
cidrs, err := readCidrs(routePath)
if err != nil {
fmt.Printf("Error reading cidr from '%s'\n", routePath)
}
found := false
for _, c := range cidrs {
if c.Contains(ip) {
obj := strings.Replace(c.String(), "/", "_", -1)
r.printObject(conn, name, obj)
found = true
}
}
return found
}
func (r *Registry) printObject(conn *net.TCPConn, objType string, obj string) {
content, path, err := r.retrieveObject(objType, obj)
if err != nil {
fmt.Fprintf(os.Stderr, "Error: %s\n", err)
return
}
fmt.Fprintf(conn, "%% Information related to '%s':\n", path)
conn.Write(content)
fmt.Fprint(conn, "\n")
}