mirror of
https://github.com/bettercap/bettercap
synced 2025-08-19 13:09:49 -07:00
misc: small fix or general refactoring i did not bother commenting
This commit is contained in:
parent
b0a197b377
commit
17ba1be16c
12 changed files with 239 additions and 498 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -15,4 +15,5 @@ stage/
|
||||||
/snap
|
/snap
|
||||||
.idea
|
.idea
|
||||||
/cover.out
|
/cover.out
|
||||||
/can-data
|
/can-data
|
||||||
|
/test*.yml
|
|
@ -1,26 +0,0 @@
|
||||||
- name: TEST_NAME
|
|
||||||
service: _ipps._tcp
|
|
||||||
domain: local.
|
|
||||||
port: 6631
|
|
||||||
records:
|
|
||||||
- txtvers=1
|
|
||||||
- ty=EPSON XP-630 Series
|
|
||||||
- usb_MFG=EPSON
|
|
||||||
- usb_MDL=XP-630 Series
|
|
||||||
- product=(EPSON XP-630 Series)
|
|
||||||
- pdl=application/octet-stream,image/pwg-raster,image/urf,image/jpeg
|
|
||||||
- rp=ipp/print
|
|
||||||
- qtotal=1
|
|
||||||
- Color=T
|
|
||||||
- Duplex=T
|
|
||||||
- Scan=T
|
|
||||||
- Fax=F
|
|
||||||
- kind=document,envelope,label,photo
|
|
||||||
- PaperMax=legal-A4
|
|
||||||
- URF=CP1,MT1-3-5-8-10-11-12,PQ4-5,OB9,OFU0,RS360,SRGB24,W8,DM3,IS1-7,V1.4
|
|
||||||
- mopria-certified=1.2
|
|
||||||
- priority=30
|
|
||||||
- adminurl=http://EPSON59F5BA.local.:80/PRESENTATION/BONJOUR
|
|
||||||
- note=
|
|
||||||
- UUID=cfe92100-67c4-11d4-a45f-44d24459f5ba
|
|
||||||
- TLS=1.2
|
|
|
@ -1,27 +0,0 @@
|
||||||
- name: TEST_NAME
|
|
||||||
service: _ipps._tcp
|
|
||||||
domain: local.
|
|
||||||
port: 6631
|
|
||||||
responder: 134.122.95.96
|
|
||||||
records:
|
|
||||||
- txtvers=1
|
|
||||||
- ty=EPSON XP-630 Series
|
|
||||||
- usb_MFG=EPSON
|
|
||||||
- usb_MDL=XP-630 Series
|
|
||||||
- product=(EPSON XP-630 Series)
|
|
||||||
- pdl=application/octet-stream,image/pwg-raster,image/urf,image/jpeg
|
|
||||||
- rp=ipp/print
|
|
||||||
- qtotal=1
|
|
||||||
- Color=T
|
|
||||||
- Duplex=T
|
|
||||||
- Scan=T
|
|
||||||
- Fax=F
|
|
||||||
- kind=document,envelope,label,photo
|
|
||||||
- PaperMax=legal-A4
|
|
||||||
- URF=CP1,MT1-3-5-8-10-11-12,PQ4-5,OB9,OFU0,RS360,SRGB24,W8,DM3,IS1-7,V1.4
|
|
||||||
- mopria-certified=1.2
|
|
||||||
- priority=30
|
|
||||||
- adminurl=http://EPSON59F5BA.local.:80/PRESENTATION/BONJOUR
|
|
||||||
- note=
|
|
||||||
- UUID=cfe92100-67c4-11d4-a45f-44d24459f5ba
|
|
||||||
- TLS=1.2
|
|
|
@ -12,10 +12,10 @@ import (
|
||||||
|
|
||||||
type Handler struct {
|
type Handler struct {
|
||||||
TLS bool
|
TLS bool
|
||||||
Handle func(mod *ZeroGod, client net.Conn, srvHost string, srvPort int, srvTLS bool)
|
Handle func(ctx *HandlerContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: add more and possibly autodetect from peeking at the first bytes sent by the client
|
// TODO: possibly autodetect from peeking at the first bytes sent by the client
|
||||||
var TCP_HANDLERS = map[string]Handler{
|
var TCP_HANDLERS = map[string]Handler{
|
||||||
"_ipp": {
|
"_ipp": {
|
||||||
Handle: ippClientHandler,
|
Handle: ippClientHandler,
|
||||||
|
@ -28,27 +28,38 @@ var TCP_HANDLERS = map[string]Handler{
|
||||||
}
|
}
|
||||||
|
|
||||||
type Acceptor struct {
|
type Acceptor struct {
|
||||||
mod *ZeroGod
|
mod *ZeroGod
|
||||||
srvHost string
|
srvHost string
|
||||||
port uint16
|
port uint16
|
||||||
service string
|
service string
|
||||||
tlsConfig *tls.Config
|
tlsConfig *tls.Config
|
||||||
listener net.Listener
|
listener net.Listener
|
||||||
running bool
|
running bool
|
||||||
context context.Context
|
context context.Context
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
handler Handler
|
handler Handler
|
||||||
|
ippAttributes map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAcceptor(mod *ZeroGod, service string, srvHost string, port uint16, tlsConfig *tls.Config) *Acceptor {
|
type HandlerContext struct {
|
||||||
|
mod *ZeroGod
|
||||||
|
client net.Conn
|
||||||
|
srvHost string
|
||||||
|
srvPort int
|
||||||
|
srvTLS bool
|
||||||
|
ippAttributes map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAcceptor(mod *ZeroGod, service string, srvHost string, port uint16, tlsConfig *tls.Config, ippAttributes map[string]string) *Acceptor {
|
||||||
context, ctcCancel := context.WithCancel(context.Background())
|
context, ctcCancel := context.WithCancel(context.Background())
|
||||||
acceptor := Acceptor{
|
acceptor := Acceptor{
|
||||||
mod: mod,
|
mod: mod,
|
||||||
port: port,
|
port: port,
|
||||||
service: service,
|
service: service,
|
||||||
context: context,
|
context: context,
|
||||||
ctxCancel: ctcCancel,
|
ctxCancel: ctcCancel,
|
||||||
srvHost: srvHost,
|
srvHost: srvHost,
|
||||||
|
ippAttributes: ippAttributes,
|
||||||
}
|
}
|
||||||
|
|
||||||
for svcName, svcHandler := range TCP_HANDLERS {
|
for svcName, svcHandler := range TCP_HANDLERS {
|
||||||
|
@ -90,7 +101,14 @@ func (a *Acceptor) Start() (err error) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
a.mod.Info("accepted connection for service %s (port %d): %v", tui.Green(a.service), a.port, conn.RemoteAddr())
|
a.mod.Info("accepted connection for service %s (port %d): %v", tui.Green(a.service), a.port, conn.RemoteAddr())
|
||||||
go a.handler.Handle(a.mod, conn, a.srvHost, int(a.port), a.tlsConfig != nil)
|
go a.handler.Handle(&HandlerContext{
|
||||||
|
mod: a.mod,
|
||||||
|
client: conn,
|
||||||
|
srvHost: a.srvHost,
|
||||||
|
srvPort: int(a.port),
|
||||||
|
srvTLS: a.tlsConfig != nil,
|
||||||
|
ippAttributes: a.ippAttributes,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
a.mod.Debug("tcp listener for port %d (%s) stopped", a.port, tui.Green(a.service))
|
a.mod.Debug("tcp listener for port %d (%s) stopped", a.port, tui.Green(a.service))
|
||||||
|
|
|
@ -5,7 +5,6 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
@ -13,15 +12,13 @@ import (
|
||||||
tls_utils "github.com/bettercap/bettercap/v2/tls"
|
tls_utils "github.com/bettercap/bettercap/v2/tls"
|
||||||
"github.com/bettercap/bettercap/v2/zeroconf"
|
"github.com/bettercap/bettercap/v2/zeroconf"
|
||||||
"github.com/evilsocket/islazy/fs"
|
"github.com/evilsocket/islazy/fs"
|
||||||
"github.com/evilsocket/islazy/tui"
|
|
||||||
yaml "gopkg.in/yaml.v3"
|
yaml "gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Advertiser struct {
|
type Advertiser struct {
|
||||||
Filename string
|
Filename string
|
||||||
|
|
||||||
Services []ServiceData
|
Services []*ServiceData
|
||||||
Servers []*zeroconf.Server
|
|
||||||
Acceptors []*Acceptor
|
Acceptors []*Acceptor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,7 +96,7 @@ func (mod *ZeroGod) startAdvertiser(fileName string) error {
|
||||||
return fmt.Errorf("could not read %s: %v", fileName, err)
|
return fmt.Errorf("could not read %s: %v", fileName, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var services []ServiceData
|
var services []*ServiceData
|
||||||
if err = yaml.Unmarshal(data, &services); err != nil {
|
if err = yaml.Unmarshal(data, &services); err != nil {
|
||||||
return fmt.Errorf("could not deserialize %s: %v", fileName, err)
|
return fmt.Errorf("could not deserialize %s: %v", fileName, err)
|
||||||
}
|
}
|
||||||
|
@ -109,101 +106,47 @@ func (mod *ZeroGod) startAdvertiser(fileName string) error {
|
||||||
advertiser := &Advertiser{
|
advertiser := &Advertiser{
|
||||||
Filename: fileName,
|
Filename: fileName,
|
||||||
Services: services,
|
Services: services,
|
||||||
Servers: make([]*zeroconf.Server, 0),
|
|
||||||
Acceptors: make([]*Acceptor, 0),
|
Acceptors: make([]*Acceptor, 0),
|
||||||
}
|
}
|
||||||
|
|
||||||
svcChan := make(chan setupResult)
|
|
||||||
|
|
||||||
// paralleize initialization
|
// paralleize initialization
|
||||||
for _, svc := range services {
|
svcChan := make(chan error)
|
||||||
go func(svc ServiceData) {
|
for _, svc := range advertiser.Services {
|
||||||
mod.Info("unregistering instance %s ...", tui.Yellow(svc.FullName()))
|
go func(svc *ServiceData) {
|
||||||
|
|
||||||
// deregister the service from the network first
|
// deregister the service from the network first
|
||||||
if err := svc.Unregister(); err != nil {
|
if err := svc.Unregister(mod); err != nil {
|
||||||
svcChan <- setupResult{err: fmt.Errorf("could not unregister service %s: %v", svc.FullName(), err)}
|
svcChan <- fmt.Errorf("could not unregister service %s: %v", svc.FullName(), err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// give some time to the network to adjust
|
// give some time to the network to adjust
|
||||||
time.Sleep(time.Duration(1) * time.Second)
|
time.Sleep(time.Duration(1) * time.Second)
|
||||||
|
|
||||||
var server *zeroconf.Server
|
// register it
|
||||||
|
if err := svc.Register(mod); err != nil {
|
||||||
// now create it again to actually advertise
|
svcChan <- err
|
||||||
if svc.Responder == "" {
|
|
||||||
// use our own IP
|
|
||||||
if server, err = zeroconf.Register(
|
|
||||||
svc.Name,
|
|
||||||
svc.Service,
|
|
||||||
svc.Domain,
|
|
||||||
svc.Port,
|
|
||||||
svc.Records,
|
|
||||||
nil); err != nil {
|
|
||||||
svcChan <- setupResult{err: fmt.Errorf("could not create service %s: %v", svc.FullName(), err)}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
mod.Info("advertising %s with responder=%s port=%d",
|
|
||||||
tui.Yellow(svc.FullName()),
|
|
||||||
tui.Red(svc.Responder),
|
|
||||||
svc.Port)
|
|
||||||
} else {
|
} else {
|
||||||
responderHostName := ""
|
svcChan <- nil
|
||||||
|
|
||||||
// try first to do a reverse DNS of the ip
|
|
||||||
if addr, err := net.LookupAddr(svc.Responder); err == nil && len(addr) > 0 {
|
|
||||||
responderHostName = addr[0]
|
|
||||||
} else {
|
|
||||||
mod.Debug("could not get responder %s reverse dns entry: %v", svc.Responder, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// if we don't have a host, create a .nip.io representation
|
|
||||||
if responderHostName == "" {
|
|
||||||
responderHostName = fmt.Sprintf("%s.nip.io.", strings.ReplaceAll(svc.Responder, ".", "-"))
|
|
||||||
}
|
|
||||||
|
|
||||||
// use external responder
|
|
||||||
if server, err = zeroconf.RegisterExternalResponder(
|
|
||||||
svc.Name,
|
|
||||||
svc.Service,
|
|
||||||
svc.Domain,
|
|
||||||
svc.Port,
|
|
||||||
responderHostName,
|
|
||||||
[]string{svc.Responder},
|
|
||||||
svc.Records,
|
|
||||||
nil); err != nil {
|
|
||||||
svcChan <- setupResult{err: fmt.Errorf("could not create service %s: %v", svc.FullName(), err)}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
mod.Info("advertising %s with responder=%s hostname=%s port=%d",
|
|
||||||
tui.Yellow(svc.FullName()),
|
|
||||||
tui.Red(svc.Responder),
|
|
||||||
tui.Yellow(responderHostName),
|
|
||||||
svc.Port)
|
|
||||||
}
|
|
||||||
|
|
||||||
svcChan <- setupResult{
|
|
||||||
server: server,
|
|
||||||
}
|
}
|
||||||
}(svc)
|
}(svc)
|
||||||
}
|
}
|
||||||
|
|
||||||
for res := range svcChan {
|
got := 0
|
||||||
if res.err != nil {
|
for err := range svcChan {
|
||||||
return res.err
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
advertiser.Servers = append(advertiser.Servers, res.server)
|
got++
|
||||||
if len(advertiser.Servers) == len(advertiser.Services) {
|
if got == len(advertiser.Services) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// now create the tcp acceptors for entries without an explicit responder address
|
// now create the tcp acceptors for entries without an explicit responder address
|
||||||
for _, svc := range advertiser.Services {
|
for _, svc := range advertiser.Services {
|
||||||
|
// if no external responder has been specified
|
||||||
if svc.Responder == "" {
|
if svc.Responder == "" {
|
||||||
acceptor := NewAcceptor(mod, svc.FullName(), hostName, uint16(svc.Port), tlsConfig)
|
acceptor := NewAcceptor(mod, svc.FullName(), hostName, uint16(svc.Port), tlsConfig, svc.IPP)
|
||||||
if err := acceptor.Start(); err != nil {
|
if err := acceptor.Start(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -225,9 +168,8 @@ func (mod *ZeroGod) stopAdvertiser() error {
|
||||||
|
|
||||||
mod.Info("stopping %d services ...", len(mod.advertiser.Services))
|
mod.Info("stopping %d services ...", len(mod.advertiser.Services))
|
||||||
|
|
||||||
for key, server := range mod.advertiser.Servers {
|
for _, service := range mod.advertiser.Services {
|
||||||
mod.Info("stopping %s ...", key)
|
service.Unregister(mod)
|
||||||
server.Shutdown()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mod.Info("all services stopped")
|
mod.Info("all services stopped")
|
||||||
|
|
|
@ -42,7 +42,6 @@ func NewZeroGod(s *session.Session) *ZeroGod {
|
||||||
return mod.Stop()
|
return mod.Stop()
|
||||||
}))
|
}))
|
||||||
|
|
||||||
// TODO: add autocomplete
|
|
||||||
mod.AddHandler(session.NewModuleHandler("zerogod.show", "",
|
mod.AddHandler(session.NewModuleHandler("zerogod.show", "",
|
||||||
"Show discovered services.",
|
"Show discovered services.",
|
||||||
func(args []string) error {
|
func(args []string) error {
|
||||||
|
@ -55,6 +54,7 @@ func NewZeroGod(s *session.Session) *ZeroGod {
|
||||||
return mod.show("", true)
|
return mod.show("", true)
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
// TODO: add autocomplete
|
||||||
mod.AddHandler(session.NewModuleHandler("zerogod.show ADDRESS", "zerogod.show (.+)",
|
mod.AddHandler(session.NewModuleHandler("zerogod.show ADDRESS", "zerogod.show (.+)",
|
||||||
"Show discovered services given an ip address.",
|
"Show discovered services given an ip address.",
|
||||||
func(args []string) error {
|
func(args []string) error {
|
||||||
|
|
|
@ -23,13 +23,11 @@ func (mod *ZeroGod) updateEndpointMeta(address string, endpoint *network.Endpoin
|
||||||
meta[fmt.Sprintf("mdns:%s:name", svcType)] = svc.ServiceName()
|
meta[fmt.Sprintf("mdns:%s:name", svcType)] = svc.ServiceName()
|
||||||
meta[fmt.Sprintf("mdns:%s:hostname", svcType)] = svc.HostName
|
meta[fmt.Sprintf("mdns:%s:hostname", svcType)] = svc.HostName
|
||||||
|
|
||||||
// TODO: include all
|
for i, ip := range svc.AddrIPv4 {
|
||||||
if len(svc.AddrIPv4) > 0 {
|
meta[fmt.Sprintf("mdns:%s:ipv4[%d]", svcType, i)] = ip.String()
|
||||||
meta[fmt.Sprintf("mdns:%s:ipv4", svcType)] = svc.AddrIPv4[0].String()
|
|
||||||
}
|
}
|
||||||
|
for i, ip := range svc.AddrIPv6 {
|
||||||
if len(svc.AddrIPv6) > 0 {
|
meta[fmt.Sprintf("mdns:%s:ipv6[%d]", svcType, i)] = ip.String()
|
||||||
meta[fmt.Sprintf("mdns:%s:ipv6", svcType)] = svc.AddrIPv6[0].String()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
meta[fmt.Sprintf("mdns:%s:port", svcType)] = fmt.Sprintf("%d", svc.Port)
|
meta[fmt.Sprintf("mdns:%s:port", svcType)] = fmt.Sprintf("%d", svc.Port)
|
||||||
|
|
|
@ -2,7 +2,6 @@ package zerogod
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func Dump(by []byte) string {
|
func Dump(by []byte) string {
|
||||||
|
@ -51,19 +50,19 @@ func viewString(b []byte) string {
|
||||||
return string(r)
|
return string(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleGenericTCP(mod *ZeroGod, client net.Conn, srvHost string, srvPort int, srvTLS bool) {
|
func handleGenericTCP(ctx *HandlerContext) {
|
||||||
defer client.Close()
|
defer ctx.client.Close()
|
||||||
|
|
||||||
buf := make([]byte, 1024)
|
buf := make([]byte, 1024)
|
||||||
for {
|
for {
|
||||||
if read, err := client.Read(buf); err != nil {
|
if read, err := ctx.client.Read(buf); err != nil {
|
||||||
mod.Error("error while reading from %v: %v", client.RemoteAddr(), err)
|
ctx.mod.Error("error while reading from %v: %v", ctx.client.RemoteAddr(), err)
|
||||||
break
|
break
|
||||||
} else if read == 0 {
|
} else if read == 0 {
|
||||||
mod.Error("error while reading from %v: no data", client.RemoteAddr())
|
ctx.mod.Error("error while reading from %v: no data", ctx.client.RemoteAddr())
|
||||||
break
|
break
|
||||||
} else {
|
} else {
|
||||||
mod.Info("read %d bytes from %v:\n%s\n", read, client.RemoteAddr(), Dump(buf[0:read]))
|
ctx.mod.Info("read %d bytes from %v:\n%s\n", read, ctx.client.RemoteAddr(), Dump(buf[0:read]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -49,6 +48,15 @@ var IPP_REQUEST_NAMES = map[int16]string{
|
||||||
0x400D: "CUPS-Move-Job",
|
0x400D: "CUPS-Move-Job",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var IPP_USER_ATTRIBUTES = map[string]string{
|
||||||
|
"printer-name": "PRINTER_NAME",
|
||||||
|
"printer-info": "PRINTER_INFO",
|
||||||
|
"printer-make-and-model": "PRINTER_MAKE PRINTER_MODEL",
|
||||||
|
"printer-location": "PRINTER_LOCATION",
|
||||||
|
"printer-privacy-policy-uri": "https://www.bettercap.org/",
|
||||||
|
"ppd-name": "everywhere",
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
ipp.AttributeTagMapping["printer-uri-supported"] = ipp.TagUri
|
ipp.AttributeTagMapping["printer-uri-supported"] = ipp.TagUri
|
||||||
ipp.AttributeTagMapping["uri-authentication-supported"] = ipp.TagKeyword
|
ipp.AttributeTagMapping["uri-authentication-supported"] = ipp.TagKeyword
|
||||||
|
@ -74,56 +82,57 @@ func init() {
|
||||||
ipp.AttributeTagMapping["compression-supported"] = ipp.TagKeyword
|
ipp.AttributeTagMapping["compression-supported"] = ipp.TagKeyword
|
||||||
ipp.AttributeTagMapping["printer-privacy-policy-uri"] = ipp.TagUri
|
ipp.AttributeTagMapping["printer-privacy-policy-uri"] = ipp.TagUri
|
||||||
ipp.AttributeTagMapping["printer-location"] = ipp.TagText
|
ipp.AttributeTagMapping["printer-location"] = ipp.TagText
|
||||||
|
ipp.AttributeTagMapping["ppd-name"] = ipp.TagName
|
||||||
}
|
}
|
||||||
|
|
||||||
func ippClientHandler(mod *ZeroGod, client net.Conn, srvHost string, srvPort int, srvTLS bool) {
|
func ippClientHandler(ctx *HandlerContext) {
|
||||||
defer client.Close()
|
defer ctx.client.Close()
|
||||||
|
|
||||||
buf := make([]byte, 4096)
|
buf := make([]byte, 4096)
|
||||||
|
|
||||||
// read raw request
|
// read raw request
|
||||||
read, err := client.Read(buf)
|
read, err := ctx.client.Read(buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
mod.Error("error while reading from %v: %v", client.RemoteAddr(), err)
|
ctx.mod.Error("error while reading from %v: %v", ctx.client.RemoteAddr(), err)
|
||||||
return
|
return
|
||||||
} else if read == 0 {
|
} else if read == 0 {
|
||||||
mod.Error("error while reading from %v: no data", client.RemoteAddr())
|
ctx.mod.Error("error while reading from %v: no data", ctx.client.RemoteAddr())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
raw_req := buf[0:read]
|
raw_req := buf[0:read]
|
||||||
|
|
||||||
mod.Debug("read %d bytes from %v:\n%s\n", read, client.RemoteAddr(), Dump(raw_req))
|
ctx.mod.Debug("read %d bytes from %v:\n%s\n", read, ctx.client.RemoteAddr(), Dump(raw_req))
|
||||||
|
|
||||||
// parse as http
|
// parse as http
|
||||||
reader := bufio.NewReader(bytes.NewReader(raw_req))
|
reader := bufio.NewReader(bytes.NewReader(raw_req))
|
||||||
http_req, err := http.ReadRequest(reader)
|
http_req, err := http.ReadRequest(reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mod.Error("error while parsing http request from %v: %v", client.RemoteAddr(), err)
|
ctx.mod.Error("error while parsing http request from %v: %v", ctx.client.RemoteAddr(), err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
mod.Info("%v -> %s", client.RemoteAddr(), tui.Green(http_req.UserAgent()))
|
ctx.mod.Info("%v -> %s", ctx.client.RemoteAddr(), tui.Green(http_req.UserAgent()))
|
||||||
|
|
||||||
ipp_body := http_req.Body
|
ipp_body := http_req.Body
|
||||||
|
|
||||||
// check for an Expect 100-continue
|
// check for an Expect 100-continue
|
||||||
if http_req.Header.Get("Expect") == "100-continue" {
|
if http_req.Header.Get("Expect") == "100-continue" {
|
||||||
// inform the client we're ready to read the request body
|
// inform the client we're ready to read the request body
|
||||||
client.Write([]byte("HTTP/1.1 100 Continue\r\n\r\n"))
|
ctx.client.Write([]byte("HTTP/1.1 100 Continue\r\n\r\n"))
|
||||||
// read the body
|
// read the body
|
||||||
read, err := client.Read(buf)
|
read, err := ctx.client.Read(buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
mod.Error("error while reading ipp body from %v: %v", client.RemoteAddr(), err)
|
ctx.mod.Error("error while reading ipp body from %v: %v", ctx.client.RemoteAddr(), err)
|
||||||
return
|
return
|
||||||
} else if read == 0 {
|
} else if read == 0 {
|
||||||
mod.Error("error while reading ipp body from %v: no data", client.RemoteAddr())
|
ctx.mod.Error("error while reading ipp body from %v: no data", ctx.client.RemoteAddr())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,7 +142,7 @@ func ippClientHandler(mod *ZeroGod, client net.Conn, srvHost string, srvPort int
|
||||||
// parse as IPP
|
// parse as IPP
|
||||||
ipp_req, err := ipp.NewRequestDecoder(ipp_body).Decode(nil)
|
ipp_req, err := ipp.NewRequestDecoder(ipp_body).Decode(nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mod.Error("error while parsing ip request from %v: %v", client.RemoteAddr(), err)
|
ctx.mod.Error("error while parsing ip request from %v: %v", ctx.client.RemoteAddr(), err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,24 +151,24 @@ func ippClientHandler(mod *ZeroGod, client net.Conn, srvHost string, srvPort int
|
||||||
ipp_op_name = name
|
ipp_op_name = name
|
||||||
}
|
}
|
||||||
|
|
||||||
mod.Info("%v op=%s attributes=%v", client.RemoteAddr(), tui.Bold(ipp_op_name), ipp_req.OperationAttributes)
|
ctx.mod.Info("%v op=%s attributes=%v", ctx.client.RemoteAddr(), tui.Bold(ipp_op_name), ipp_req.OperationAttributes)
|
||||||
|
|
||||||
switch ipp_req.Operation {
|
switch ipp_req.Operation {
|
||||||
// Get-Printer-Attributes
|
// Get-Printer-Attributes
|
||||||
case 0x000B:
|
case 0x000B:
|
||||||
ippOnGetPrinterAttributes(mod, client, ipp_req, srvHost, srvPort, srvTLS)
|
ippOnGetPrinterAttributes(ctx, ipp_req)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ippOnUnhandledRequest(mod, client, ipp_req, ipp_op_name)
|
ippOnUnhandledRequest(ctx, ipp_req, ipp_op_name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ippSendResponse(mod *ZeroGod, client net.Conn, response *ipp.Response) {
|
func ippSendResponse(ctx *HandlerContext, response *ipp.Response) {
|
||||||
mod.Debug("SENDING %++v", *response)
|
ctx.mod.Debug("SENDING %++v", *response)
|
||||||
|
|
||||||
resp_data, err := response.Encode()
|
resp_data, err := response.Encode()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mod.Error("error while encoding ipp response: %v", err)
|
ctx.mod.Error("error while encoding ipp response: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,29 +181,29 @@ func ippSendResponse(mod *ZeroGod, client net.Conn, response *ipp.Response) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, header := range headers {
|
for _, header := range headers {
|
||||||
if _, err := client.Write(header); err != nil {
|
if _, err := ctx.client.Write(header); err != nil {
|
||||||
mod.Error("error while writing header: %v", err)
|
ctx.mod.Error("error while writing header: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err = client.Write(resp_data); err != nil {
|
if _, err = ctx.client.Write(resp_data); err != nil {
|
||||||
mod.Error("error while writing ipp response data: %v", err)
|
ctx.mod.Error("error while writing ipp response data: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
mod.Debug("sent %d of ipp response to %v", len(resp_data), client.RemoteAddr())
|
ctx.mod.Debug("sent %d of ipp response to %v", len(resp_data), ctx.client.RemoteAddr())
|
||||||
}
|
}
|
||||||
|
|
||||||
func ippOnUnhandledRequest(mod *ZeroGod, client net.Conn, ipp_req *ipp.Request, ipp_op_name string) {
|
func ippOnUnhandledRequest(ctx *HandlerContext, ipp_req *ipp.Request, ipp_op_name string) {
|
||||||
ipp_resp := ipp.NewResponse(ipp.StatusErrorOperationNotSupported, ipp_req.RequestId)
|
ctx.mod.Warning("unhandled request from %v: operation=%s", ctx.client.RemoteAddr(), ipp_op_name)
|
||||||
|
|
||||||
ippSendResponse(mod, client, ipp_resp)
|
ippSendResponse(ctx, ipp.NewResponse(
|
||||||
|
ipp.StatusErrorOperationNotSupported,
|
||||||
mod.Warning("unhandled request from %v: operation=%s", client.RemoteAddr(), ipp_op_name)
|
ipp_req.RequestId))
|
||||||
}
|
}
|
||||||
|
|
||||||
func ippOnGetPrinterAttributes(mod *ZeroGod, client net.Conn, ipp_req *ipp.Request, srvHost string, srvPort int, srvTLS bool) {
|
func ippOnGetPrinterAttributes(ctx *HandlerContext, ipp_req *ipp.Request) {
|
||||||
ipp_resp := ipp.NewResponse(ipp.StatusOk, ipp_req.RequestId)
|
ipp_resp := ipp.NewResponse(ipp.StatusOk, ipp_req.RequestId)
|
||||||
|
|
||||||
// https://tools.ietf.org/html/rfc2911 section 3.1.4.2 Response Operation Attributes
|
// https://tools.ietf.org/html/rfc2911 section 3.1.4.2 Response Operation Attributes
|
||||||
|
@ -211,52 +220,15 @@ func ippOnGetPrinterAttributes(mod *ZeroGod, client net.Conn, ipp_req *ipp.Reque
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// collect user attributes
|
||||||
|
userProps := make(map[string]string)
|
||||||
"""
|
for name, defaultValue := range IPP_USER_ATTRIBUTES {
|
||||||
marker-names (1setOf nameWithoutLanguage) = Black ink,Cyan ink,Magenta ink,Yellow ink
|
if value, found := ctx.ippAttributes[name]; found {
|
||||||
marker-colors (1setOf nameWithoutLanguage) = #000000,#00FFFF,#FF00FF,#FFFF00
|
userProps[name] = value
|
||||||
marker-types (1setOf keyword) = ink-cartridge,ink-cartridge,ink-cartridge,ink-cartridge
|
} else {
|
||||||
marker-low-levels (1setOf integer) = 15,15,15,15
|
userProps[name] = defaultValue
|
||||||
marker-high-levels (1setOf integer) = 100,100,100,100
|
}
|
||||||
marker-levels (1setOf integer) = 57,94,95,95
|
}
|
||||||
"""
|
|
||||||
|
|
||||||
markers = {
|
|
||||||
(
|
|
||||||
SectionEnum.printer,
|
|
||||||
b'marker-names',
|
|
||||||
TagEnum.text_without_language
|
|
||||||
): [b'TestMarker'],
|
|
||||||
(
|
|
||||||
SectionEnum.printer,
|
|
||||||
b'marker-colors',
|
|
||||||
TagEnum.text_without_language
|
|
||||||
): [b'#FF0000'],
|
|
||||||
(
|
|
||||||
SectionEnum.printer,
|
|
||||||
b'marker-types',
|
|
||||||
TagEnum.text_without_language
|
|
||||||
): [b'ink-cartridge'],
|
|
||||||
(
|
|
||||||
SectionEnum.printer,
|
|
||||||
b'marker-low-levels',
|
|
||||||
TagEnum.integer
|
|
||||||
): [Integer(15).bytes()],
|
|
||||||
(
|
|
||||||
SectionEnum.printer,
|
|
||||||
b'marker-high-levels',
|
|
||||||
TagEnum.integer
|
|
||||||
): [Integer(100).bytes()],
|
|
||||||
(
|
|
||||||
SectionEnum.printer,
|
|
||||||
b'marker-levels',
|
|
||||||
TagEnum.integer
|
|
||||||
): [Integer(66).bytes()],
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// TODO: allow customization of these attributes.
|
|
||||||
|
|
||||||
// rfc2911 section 4.4
|
// rfc2911 section 4.4
|
||||||
ipp_resp.PrinterAttributes = []ipp.Attributes{
|
ipp_resp.PrinterAttributes = []ipp.Attributes{
|
||||||
|
@ -264,61 +236,58 @@ func ippOnGetPrinterAttributes(mod *ZeroGod, client net.Conn, ipp_req *ipp.Reque
|
||||||
// custom
|
// custom
|
||||||
"printer-name": []ipp.Attribute{
|
"printer-name": []ipp.Attribute{
|
||||||
{
|
{
|
||||||
Value: "PRINTER_NAME",
|
Value: userProps["printer-name"],
|
||||||
Tag: ipp.TagName,
|
Tag: ipp.TagName,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"printer-info": []ipp.Attribute{
|
"printer-info": []ipp.Attribute{
|
||||||
{
|
{
|
||||||
Value: "PRINTER_INFO",
|
Value: userProps["printer-info"],
|
||||||
Tag: ipp.TagText,
|
Tag: ipp.TagText,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"printer-make-and-model": []ipp.Attribute{
|
"printer-make-and-model": []ipp.Attribute{
|
||||||
{
|
{
|
||||||
Value: "PRINTER_MAKE PRINTER_MODEL",
|
Value: userProps["printer-make-and-model"],
|
||||||
Tag: ipp.TagText,
|
Tag: ipp.TagText,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"printer-location": []ipp.Attribute{
|
"printer-location": []ipp.Attribute{
|
||||||
{
|
{
|
||||||
Value: "PRINTER_LOCATION",
|
Value: userProps["printer-location"],
|
||||||
Tag: ipp.TagText,
|
Tag: ipp.TagText,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"printer-privacy-policy-uri": []ipp.Attribute{
|
"printer-privacy-policy-uri": []ipp.Attribute{
|
||||||
{
|
{
|
||||||
Value: "https://www.google.com/",
|
Value: userProps["printer-privacy-policy-uri"],
|
||||||
Tag: ipp.TagUri,
|
Tag: ipp.TagUri,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// constants
|
"ppd-name": []ipp.Attribute{
|
||||||
/*
|
{
|
||||||
"ppd-name": []ipp.Attribute{
|
Value: userProps["ppd-name"],
|
||||||
{
|
Tag: ipp.TagName,
|
||||||
Value: "everywhere",
|
|
||||||
Tag: ipp.TagName,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
*/
|
},
|
||||||
"printer-uri-supported": []ipp.Attribute{
|
"printer-uri-supported": []ipp.Attribute{
|
||||||
{
|
{
|
||||||
Value: fmt.Sprintf("%s://%s:%d/printer", ops.Ternary(srvTLS, "ipps", "ipp"), srvHost, srvPort),
|
Value: fmt.Sprintf("%s://%s:%d/printer", ops.Ternary(ctx.srvTLS, "ipps", "ipp"), ctx.srvHost, ctx.srvPort),
|
||||||
Tag: ipp.TagUri,
|
Tag: ipp.TagUri,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"uri-security-supported": []ipp.Attribute{
|
||||||
|
{
|
||||||
|
Value: ops.Ternary(ctx.srvTLS, "tls", "none"),
|
||||||
|
Tag: ipp.TagKeyword,
|
||||||
|
},
|
||||||
|
},
|
||||||
"uri-authentication-supported": []ipp.Attribute{
|
"uri-authentication-supported": []ipp.Attribute{
|
||||||
{
|
{
|
||||||
Value: "none",
|
Value: "none",
|
||||||
Tag: ipp.TagKeyword,
|
Tag: ipp.TagKeyword,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"uri-security-supported": []ipp.Attribute{
|
|
||||||
{
|
|
||||||
Value: ops.Ternary(srvTLS, "tls", "none"),
|
|
||||||
Tag: ipp.TagKeyword,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"printer-state": []ipp.Attribute{
|
"printer-state": []ipp.Attribute{
|
||||||
{
|
{
|
||||||
Value: 3, // idle
|
Value: 3, // idle
|
||||||
|
@ -424,5 +393,5 @@ func ippOnGetPrinterAttributes(mod *ZeroGod, client net.Conn, ipp_req *ipp.Reque
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
ippSendResponse(mod, client, ipp_resp)
|
ippSendResponse(ctx, ipp_resp)
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,38 +3,12 @@ package zerogod
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/bettercap/bettercap/v2/zeroconf"
|
"github.com/bettercap/bettercap/v2/zeroconf"
|
||||||
"github.com/evilsocket/islazy/str"
|
"github.com/evilsocket/islazy/str"
|
||||||
yaml "gopkg.in/yaml.v3"
|
yaml "gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ServiceData struct {
|
|
||||||
Name string `yaml:"name"` // Instance name (e.g. "My web page")
|
|
||||||
Service string `yaml:"service"` // Service name (e.g. _http._tcp.)
|
|
||||||
Domain string `yaml:"domain"` // If blank, assumes "local"
|
|
||||||
Port int `yaml:"port"` // Service port
|
|
||||||
Records []string `yaml:"records,omitempty"` // Service DNS text records
|
|
||||||
Responder string `yaml:"responder,omitempty"` // Optional IP to use instead of our tcp acceptor
|
|
||||||
}
|
|
||||||
|
|
||||||
func (svc ServiceData) FullName() string {
|
|
||||||
return fmt.Sprintf("%s.%s.%s",
|
|
||||||
strings.Trim(svc.Name, "."),
|
|
||||||
strings.Trim(svc.Service, "."),
|
|
||||||
strings.Trim(svc.Domain, "."))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (svc ServiceData) Unregister() error {
|
|
||||||
if server, err := zeroconf.Register(svc.Name, svc.Service, svc.Domain, svc.Port, svc.Records, nil); err != nil {
|
|
||||||
return err
|
|
||||||
} else {
|
|
||||||
server.Shutdown()
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func svcEntriesToData(services map[string]*zeroconf.ServiceEntry) []ServiceData {
|
func svcEntriesToData(services map[string]*zeroconf.ServiceEntry) []ServiceData {
|
||||||
data := make([]ServiceData, 0)
|
data := make([]ServiceData, 0)
|
||||||
for _, svc := range services {
|
for _, svc := range services {
|
||||||
|
|
100
modules/zerogod/zerogod_service.go
Normal file
100
modules/zerogod/zerogod_service.go
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
package zerogod
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/bettercap/bettercap/v2/zeroconf"
|
||||||
|
"github.com/evilsocket/islazy/tui"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ServiceData struct {
|
||||||
|
Name string `yaml:"name"` // Instance name (e.g. "My web page")
|
||||||
|
Service string `yaml:"service"` // Service name (e.g. _http._tcp.)
|
||||||
|
Domain string `yaml:"domain"` // If blank, assumes "local"
|
||||||
|
Port int `yaml:"port"` // Service port
|
||||||
|
Records []string `yaml:"records,omitempty"` // Service DNS text records
|
||||||
|
Responder string `yaml:"responder,omitempty"` // Optional IP to use instead of our tcp acceptor
|
||||||
|
IPP map[string]string `yaml:"ipp,omitempty"` // Optional IPP attributes map
|
||||||
|
|
||||||
|
server *zeroconf.Server
|
||||||
|
}
|
||||||
|
|
||||||
|
func (svc ServiceData) FullName() string {
|
||||||
|
return fmt.Sprintf("%s.%s.%s",
|
||||||
|
strings.Trim(svc.Name, "."),
|
||||||
|
strings.Trim(svc.Service, "."),
|
||||||
|
strings.Trim(svc.Domain, "."))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (svc *ServiceData) Register(mod *ZeroGod) (err error) {
|
||||||
|
// now create it again to actually advertise
|
||||||
|
if svc.Responder == "" {
|
||||||
|
// use our own IP
|
||||||
|
if svc.server, err = zeroconf.Register(
|
||||||
|
svc.Name,
|
||||||
|
svc.Service,
|
||||||
|
svc.Domain,
|
||||||
|
svc.Port,
|
||||||
|
svc.Records,
|
||||||
|
nil); err != nil {
|
||||||
|
return fmt.Errorf("could not create service %s: %v", svc.FullName(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
mod.Info("advertising %s with responder=%s port=%d",
|
||||||
|
tui.Yellow(svc.FullName()),
|
||||||
|
tui.Red(svc.Responder),
|
||||||
|
svc.Port)
|
||||||
|
} else {
|
||||||
|
responderHostName := ""
|
||||||
|
// try first to do a reverse DNS of the ip
|
||||||
|
if addr, err := net.LookupAddr(svc.Responder); err == nil && len(addr) > 0 {
|
||||||
|
responderHostName = addr[0]
|
||||||
|
} else {
|
||||||
|
mod.Debug("could not get responder %s reverse dns entry: %v", svc.Responder, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we don't have a host, create a .nip.io representation
|
||||||
|
if responderHostName == "" {
|
||||||
|
responderHostName = fmt.Sprintf("%s.nip.io.", strings.ReplaceAll(svc.Responder, ".", "-"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// use external responder
|
||||||
|
if svc.server, err = zeroconf.RegisterExternalResponder(
|
||||||
|
svc.Name,
|
||||||
|
svc.Service,
|
||||||
|
svc.Domain,
|
||||||
|
svc.Port,
|
||||||
|
responderHostName,
|
||||||
|
[]string{svc.Responder},
|
||||||
|
svc.Records,
|
||||||
|
nil); err != nil {
|
||||||
|
return fmt.Errorf("could not create service %s: %v", svc.FullName(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
mod.Info("advertising %s with responder=%s hostname=%s port=%d",
|
||||||
|
tui.Yellow(svc.FullName()),
|
||||||
|
tui.Red(svc.Responder),
|
||||||
|
tui.Yellow(responderHostName),
|
||||||
|
svc.Port)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (svc *ServiceData) Unregister(mod *ZeroGod) error {
|
||||||
|
mod.Info("unregistering instance %s ...", tui.Yellow(svc.FullName()))
|
||||||
|
|
||||||
|
err := (error)(nil)
|
||||||
|
if svc.server == nil {
|
||||||
|
// if we haven't been registered yet, create the server
|
||||||
|
if svc.server, err = zeroconf.Register(svc.Name, svc.Service, svc.Domain, svc.Port, svc.Records, nil); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
svc.server.Shutdown()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
207
test.yml
207
test.yml
|
@ -1,207 +0,0 @@
|
||||||
EPSON\ XP-630\ Series-59F5BA-04._http._tcp.local.:
|
|
||||||
servicerecord:
|
|
||||||
instance: EPSON\ XP-630\ Series-59F5BA-04
|
|
||||||
service: _http._tcp
|
|
||||||
domain: local.
|
|
||||||
hostname: EPSON59F5BA.local.
|
|
||||||
port: 80
|
|
||||||
text:
|
|
||||||
- ""
|
|
||||||
ttl: 4500
|
|
||||||
addripv4:
|
|
||||||
- 192.168.50.21
|
|
||||||
addripv6:
|
|
||||||
- fe80::46d2:44ff:fe59:f5ba
|
|
||||||
EPSON\ XP-630\ Series-59F5BA-04._ipp._tcp.local.:
|
|
||||||
servicerecord:
|
|
||||||
instance: EPSON\ XP-630\ Series-59F5BA-04
|
|
||||||
service: _ipp._tcp
|
|
||||||
domain: local.
|
|
||||||
hostname: EPSON59F5BA.local.
|
|
||||||
port: 6633
|
|
||||||
text:
|
|
||||||
- txtvers=1
|
|
||||||
- ty=EPSON XP-630 Series
|
|
||||||
- usb_MFG=EPSON
|
|
||||||
- usb_MDL=XP-630 Series
|
|
||||||
- product=(EPSON XP-630 Series)
|
|
||||||
- pdl=application/octet-stream,image/pwg-raster,image/urf,image/jpeg
|
|
||||||
- rp=ipp/print
|
|
||||||
- qtotal=1
|
|
||||||
- Color=T
|
|
||||||
- Duplex=T
|
|
||||||
- Scan=T
|
|
||||||
- Fax=F
|
|
||||||
- kind=document,envelope,label,photo
|
|
||||||
- PaperMax=legal-A4
|
|
||||||
- URF=CP1,MT1-3-5-8-10-11-12,PQ4-5,OB9,OFU0,RS360,SRGB24,W8,DM3,IS1-7,V1.4
|
|
||||||
- mopria-certified=1.2
|
|
||||||
- priority=30
|
|
||||||
- adminurl=http://EPSON59F5BA.local.:80/PRESENTATION/BONJOUR
|
|
||||||
- note=
|
|
||||||
- UUID=cfe92100-67c4-11d4-a45f-44d24459f5ba
|
|
||||||
- TLS=1.2
|
|
||||||
ttl: 4500
|
|
||||||
addripv4:
|
|
||||||
- 192.168.50.21
|
|
||||||
addripv6:
|
|
||||||
- fe80::46d2:44ff:fe59:f5ba
|
|
||||||
EPSON\ XP-630\ Series-59F5BA-04._ipps._tcp.local.:
|
|
||||||
servicerecord:
|
|
||||||
instance: EPSON\ XP-630\ Series-59F5BA-04
|
|
||||||
service: _ipps._tcp
|
|
||||||
domain: local.
|
|
||||||
hostname: EPSON59F5BA.local.
|
|
||||||
port: 6631
|
|
||||||
text:
|
|
||||||
- txtvers=1
|
|
||||||
- ty=EPSON XP-630 Series
|
|
||||||
- usb_MFG=EPSON
|
|
||||||
- usb_MDL=XP-630 Series
|
|
||||||
- product=(EPSON XP-630 Series)
|
|
||||||
- pdl=application/octet-stream,image/pwg-raster,image/urf,image/jpeg
|
|
||||||
- rp=ipp/print
|
|
||||||
- qtotal=1
|
|
||||||
- Color=T
|
|
||||||
- Duplex=T
|
|
||||||
- Scan=T
|
|
||||||
- Fax=F
|
|
||||||
- kind=document,envelope,label,photo
|
|
||||||
- PaperMax=legal-A4
|
|
||||||
- URF=CP1,MT1-3-5-8-10-11-12,PQ4-5,OB9,OFU0,RS360,SRGB24,W8,DM3,IS1-7,V1.4
|
|
||||||
- mopria-certified=1.2
|
|
||||||
- priority=30
|
|
||||||
- adminurl=http://EPSON59F5BA.local.:80/PRESENTATION/BONJOUR
|
|
||||||
- note=
|
|
||||||
- UUID=cfe92100-67c4-11d4-a45f-44d24459f5ba
|
|
||||||
- TLS=1.2
|
|
||||||
ttl: 4500
|
|
||||||
addripv4:
|
|
||||||
- 192.168.50.21
|
|
||||||
addripv6:
|
|
||||||
- fe80::46d2:44ff:fe59:f5ba
|
|
||||||
EPSON\ XP-630\ Series-59F5BA-04._pdl-datastream._tcp.local.:
|
|
||||||
servicerecord:
|
|
||||||
instance: EPSON\ XP-630\ Series-59F5BA-04
|
|
||||||
service: _pdl-datastream._tcp
|
|
||||||
domain: local.
|
|
||||||
hostname: EPSON59F5BA.local.
|
|
||||||
port: 9100
|
|
||||||
text:
|
|
||||||
- txtvers=1
|
|
||||||
- priority=40
|
|
||||||
- ty=EPSON XP-630 Series
|
|
||||||
- usb_MFG=EPSON
|
|
||||||
- usb_MDL=XP-630 Series
|
|
||||||
- product=(EPSON XP-630 Series)
|
|
||||||
- pdl=raw
|
|
||||||
- qtotal=1
|
|
||||||
- adminurl=http://EPSON59F5BA.local.:80/PRESENTATION/BONJOUR
|
|
||||||
- note=
|
|
||||||
ttl: 4500
|
|
||||||
addripv4:
|
|
||||||
- 192.168.50.21
|
|
||||||
addripv6:
|
|
||||||
- fe80::46d2:44ff:fe59:f5ba
|
|
||||||
EPSON\ XP-630\ Series-59F5BA-04._printer._tcp.local.:
|
|
||||||
servicerecord:
|
|
||||||
instance: EPSON\ XP-630\ Series-59F5BA-04
|
|
||||||
service: _printer._tcp
|
|
||||||
domain: local.
|
|
||||||
hostname: EPSON59F5BA.local.
|
|
||||||
port: 1515
|
|
||||||
text:
|
|
||||||
- txtvers=1
|
|
||||||
- priority=50
|
|
||||||
- ty=EPSON XP-630 Series
|
|
||||||
- usb_MFG=EPSON
|
|
||||||
- usb_MDL=XP-630 Series
|
|
||||||
- product=(EPSON XP-630 Series)
|
|
||||||
- pdl=raw
|
|
||||||
- rp=auto
|
|
||||||
- qtotal=1
|
|
||||||
- adminurl=http://EPSON59F5BA.local.:80/PRESENTATION/BONJOUR
|
|
||||||
- note=
|
|
||||||
ttl: 4500
|
|
||||||
addripv4:
|
|
||||||
- 192.168.50.21
|
|
||||||
addripv6:
|
|
||||||
- fe80::46d2:44ff:fe59:f5ba
|
|
||||||
EPSON\ XP-630\ Series-59F5BA-04._privet._tcp.local.:
|
|
||||||
servicerecord:
|
|
||||||
instance: EPSON\ XP-630\ Series-59F5BA-04
|
|
||||||
service: _privet._tcp
|
|
||||||
domain: local.
|
|
||||||
hostname: EPSON59F5BA.local.
|
|
||||||
port: 8081
|
|
||||||
text:
|
|
||||||
- txtvers=1
|
|
||||||
- ty=EPSON XP-630 Series (EPSON59F5BA)
|
|
||||||
- url=https://www.google.com/cloudprint
|
|
||||||
- type=printer
|
|
||||||
- id=0936a89f-33d7-80f5-c1bc-7421d40a78b5
|
|
||||||
- cs=offline
|
|
||||||
ttl: 4500
|
|
||||||
addripv4:
|
|
||||||
- 192.168.50.21
|
|
||||||
addripv6:
|
|
||||||
- fe80::46d2:44ff:fe59:f5ba
|
|
||||||
EPSON\ XP-630\ Series-59F5BA-04._scanner._tcp.local.:
|
|
||||||
servicerecord:
|
|
||||||
instance: EPSON\ XP-630\ Series-59F5BA-04
|
|
||||||
service: _scanner._tcp
|
|
||||||
domain: local.
|
|
||||||
hostname: EPSON59F5BA.local.
|
|
||||||
port: 1865
|
|
||||||
text:
|
|
||||||
- txtvers=1
|
|
||||||
- ty=EPSON XP-630 Series
|
|
||||||
- adminurl=http://EPSON59F5BA.local.:80/PRESENTATION/BONJOUR
|
|
||||||
- mfg=EPSON
|
|
||||||
- mdl=XP-630 Series
|
|
||||||
- UUID=cfe92100-67c4-11d4-a45f-44d24459f5ba
|
|
||||||
- scannerAvailable=0
|
|
||||||
- note=
|
|
||||||
ttl: 4500
|
|
||||||
addripv4:
|
|
||||||
- 192.168.50.21
|
|
||||||
addripv6:
|
|
||||||
- fe80::46d2:44ff:fe59:f5ba
|
|
||||||
EPSON\ XP-630\ Series-59F5BA-04._smb._tcp.local.:
|
|
||||||
servicerecord:
|
|
||||||
instance: EPSON\ XP-630\ Series-59F5BA-04
|
|
||||||
service: _smb._tcp
|
|
||||||
domain: local.
|
|
||||||
hostname: EPSON59F5BA.local.
|
|
||||||
port: 1445
|
|
||||||
text: []
|
|
||||||
ttl: 120
|
|
||||||
addripv4:
|
|
||||||
- 192.168.50.21
|
|
||||||
addripv6:
|
|
||||||
- fe80::46d2:44ff:fe59:f5ba
|
|
||||||
EPSON\ XP-630\ Series-59F5BA-04._uscan._tcp.local.:
|
|
||||||
servicerecord:
|
|
||||||
instance: EPSON\ XP-630\ Series-59F5BA-04
|
|
||||||
service: _uscan._tcp
|
|
||||||
domain: local.
|
|
||||||
hostname: EPSON59F5BA.local.
|
|
||||||
port: 8443
|
|
||||||
text:
|
|
||||||
- txtvers=1
|
|
||||||
- vers=2.5
|
|
||||||
- representation=/PRESENTATION/AIRPRINT/PRINTER_128.PNG
|
|
||||||
- rs=eSCL
|
|
||||||
- ty=EPSON XP-630 Series
|
|
||||||
- pdl=application/pdf,image/jpeg
|
|
||||||
- cs=color,grayscale,binary
|
|
||||||
- is=platen
|
|
||||||
- duplex=F
|
|
||||||
- adminurl=http://EPSON59F5BA.local.:80/PRESENTATION/BONJOUR
|
|
||||||
- UUID=cfe92100-67c4-11d4-a45f-44d24459f5ba
|
|
||||||
- note=
|
|
||||||
ttl: 4500
|
|
||||||
addripv4:
|
|
||||||
- 192.168.50.21
|
|
||||||
addripv6:
|
|
||||||
- fe80::46d2:44ff:fe59:f5ba
|
|
Loading…
Add table
Add a link
Reference in a new issue