124 lines
2.5 KiB
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, r.RegistryTopLevel+":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")
|
|
}
|