no message

This commit is contained in:
Jeremy Tellier - ROG
2020-10-09 23:12:15 +01:00
18 changed files with 159 additions and 90 deletions
+3 -4
View File
@@ -84,15 +84,14 @@ namespace ZitiDesktopEdge
ConfigItems.Visibility = Visibility.Collapsed;
LogLevelItems.Visibility = Visibility.Collapsed;
if (menuState=="About") {
if (menuState == "About") {
MenuTitle.Content = "About";
AboutItemsArea.Visibility = Visibility.Visible;
AboutItems.Visibility = Visibility.Visible;
BackArrow.Visibility = Visibility.Visible;
// Service Version - Lose the snapshot
string version = File.ReadAllText(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "OpenZiti", "Service", "Version.txt"));
if (version.IndexOf("-") > 0) version = version.Split('-')[0];
ZitiDesktopEdge.ServiceClient.TunnelStatus s = (ZitiDesktopEdge.ServiceClient.TunnelStatus)Application.Current.Properties["CurrentTunnelStatus"];
string version = $"{s.ServiceVersion.Version}@{s.ServiceVersion.Revision}";
// Interface Version
VersionInfo.Content = "App: " + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString()+" Service: "+ version;
+1
View File
@@ -245,6 +245,7 @@ namespace ZitiDesktopEdge {
private void ServiceClient_OnTunnelStatusEvent(object sender, TunnelStatusEvent e) {
if (e == null) return; //just skip it for now...
Debug.WriteLine($"==== TunnelStatusEvent: ");
Application.Current.Properties.Add("CurrentTunnelStatus", e.Status);
e.Status.Dump(Console.Out);
this.Dispatcher.Invoke(() => {
if(e.ApiVersion != Client.EXPECTED_API_VERSION) {
@@ -165,6 +165,18 @@ namespace ZitiDesktopEdge.ServiceClient
public string DNS { get; set; }
}
class ServiceVersion
{
public string Version { get; set; }
public string Revision { get; set; }
public string BuildDate { get; set; }
public override string ToString()
{
return $"Version: {Version}, Revision: {Revision}, BuildDate: {BuildDate}";
}
}
class ZitiTunnelStatus : SvcResponse
{
public TunnelStatus Status { get; set; }
@@ -182,8 +194,11 @@ namespace ZitiDesktopEdge.ServiceClient
public string LogLevel { get; set; }
public ServiceVersion ServiceVersion { get; set; }
public void Dump(System.IO.TextWriter writer)
{
<<<<<<< HEAD
try {
writer.WriteLine($"Tunnel Active: {Active}");
writer.WriteLine($" LogLevel : {LogLevel}");
@@ -198,6 +213,22 @@ namespace ZitiDesktopEdge.ServiceClient
writer.WriteLine($" Name: {s.Name} HostName: {s.InterceptHost} Port: {s.InterceptPort}");
}
writer.WriteLine("=============================================");
=======
writer.WriteLine($"Tunnel Active: {Active}");
writer.WriteLine($" ServiceVersion : {ServiceVersion}");
writer.WriteLine($" LogLevel : {LogLevel}");
writer.WriteLine($" EvaluatedLogLevel: {EvaluateLogLevel()}");
foreach (Identity id in Identities)
{
writer.WriteLine($" FingerPrint: {id.FingerPrint}");
writer.WriteLine($" Name : {id.Name}");
writer.WriteLine($" Active : {id.Active}");
writer.WriteLine($" Status : {id.Status}");
writer.WriteLine($" Services:");
foreach (Service s in id?.Services)
{
writer.WriteLine($" Name: {s.Name} HostName: {s.InterceptHost} Port: {s.InterceptPort}");
>>>>>>> b73d8c5563fcb51ed0c170b6da19f6e3d29d0e55
}
} catch (Exception e) {
+1
View File
@@ -6,6 +6,7 @@ For UI changes or installer changes see [release-notes.md]()
* What's New
* Continually improved logging
* changed ip from 169.254.0.0/16 to 100.64.0.0/10
* [#120](https://github.com/openziti/desktop-edge-win/issues/120) - Allow UI/client to get and set log level dynamically via ipc
* Bug fixes
+12
View File
@@ -1,6 +1,18 @@
These release notes will try to cover the changes made for the installer. For changes made
to the Windows service see [release-notes-service.md]()
# Release 1.2.6
* What's New
* 'About' updated to reflect actual service version
* Added ability to set the log level of the service dynamically through Advanced Setttings
*
* Bug fixes
* [#102](https://github.com/openziti/desktop-edge-win/pull/102) - DNS requests with "connection-specific local domain" would not resolve
# Release 1.0.4
* What's New
+1 -1
View File
@@ -34,7 +34,7 @@ echo changing to service folder: %SVC_ROOT_DIR%
cd %SVC_ROOT_DIR%
SET REPO_URL=https://github.com/openziti/ziti-tunneler-sdk-c.git
SET ZITI_TUNNEL_REPO_BRANCH=v0.6.8
SET ZITI_TUNNEL_REPO_BRANCH=v0.6.9
SET TUNNELER_SDK_DIR=%SVC_ROOT_DIR%deps\ziti-tunneler-sdk-c\
SET CGO_CFLAGS=-DNOGDI -I %TUNNELER_SDK_DIR%install\include
SET CGO_LDFLAGS=-L %TUNNELER_SDK_DIR%install\lib
+15 -12
View File
@@ -28,10 +28,10 @@ import (
)
var domains []string // get any connection-specific local domains
var reqch = make(chan dnsreq, 64)
var proxiedRequests = make(chan *proxiedReq, 64)
var respChan = make(chan []byte, 64)
const MaxDnsRequests = 64
var reqch = make(chan dnsreq, MaxDnsRequests)
var proxiedRequests = make(chan *proxiedReq, MaxDnsRequests)
var respChan = make(chan []byte, MaxDnsRequests)
func processDNSquery(packet []byte, p *net.UDPAddr, s *net.UDPConn, ipVer int) {
q := &dns.Msg{}
@@ -155,10 +155,10 @@ func runListener(ip net.IP, port int, reqch chan dnsreq) {
if err != nil {
if err == io.EOF || err == os.ErrClosed || strings.HasSuffix(err.Error(), "use of closed network connection") {
log.Warnf("DNS listener closing.")
server.Close()
_ = server.Close()
break
} else {
server.Close()
_ = server.Close()
panic(err)
}
}
@@ -230,14 +230,14 @@ func runDNSproxy(dnsServers []string) {
}
for _, proxy := range dnsUpstreams {
go func() {
go func(p *net.UDPConn) {
resp := make([]byte, 1024) //make a buffer which is reused
for {
n, err := proxy.Read(resp)
n, err := p.Read(resp)
if err != nil {
// something is wrong with the DNS connection panic and let DNS recovery kick in
if err == io.EOF || err == os.ErrClosed || strings.HasSuffix(err.Error(), "use of closed network connection") {
log.Errorf("error receiving from ip: %v. error %v", proxy.RemoteAddr(), err)
log.Errorf("error receiving from ip: %v. error %v", p.RemoteAddr(), err)
return
} else {
log.Warnf("odd error: %v", err)
@@ -246,7 +246,7 @@ func runDNSproxy(dnsServers []string) {
respChan <- resp[:n]
}
}
}()
}(proxy)
}
reqs := make(map[uint32]*proxiedReq)
@@ -261,7 +261,7 @@ func runDNSproxy(dnsServers []string) {
if _, err := proxy.Write(b); err != nil {
//TODO: if this happens -does this mean the next dns server is not available?
proxy.Close() //first thing - close the proxy connection
_ = proxy.Close() //first thing - close the proxy connection
// when this hits - it never seems to recover. throw a panic which will get recovered
// via the defer specified above and try to recreate the connections. this is a heavy
@@ -284,7 +284,10 @@ func runDNSproxy(dnsServers []string) {
if found {
delete(reqs, id)
log.Tracef("proxy resolved request for %v id:%d", reply.Question[0].Name, reply.Id)
req.s.WriteMsgUDP(rep, nil, req.peer)
n, oobn, err := req.s.WriteMsgUDP(rep, nil, req.peer)
if err != nil {
log.Errorf("an error has occurred while trying to write a udp message. n:%d, oobn:%d, err:%v", n, oobn, err)
}
} else {
// keep this log but leave commented out. When two listeners are enabled (ipv4/v6) this msg will
// just mean some other request was processed successfully and removed the entry from the map
+3 -4
View File
@@ -21,6 +21,8 @@ import "C"
import (
"encoding/binary"
"fmt"
"github.com/openziti/desktop-edge-win/service/ziti-tunnel/constants"
"net"
"strings"
"sync"
@@ -35,9 +37,6 @@ type DnsManager interface {
GetService(ip net.IP, port uint16) (*CZitiCtx, string, error)
}
const defaultCidr = "169.254.0.0"
const defaultMaskBits = 16
var initOnce = sync.Once{}
var DNS = &dnsImpl{}
@@ -80,7 +79,7 @@ func normalizeDnsName(dnsName string) string {
// assigned to a hostname an error will also be returned indicating why.
func (dns *dnsImpl) RegisterService(svcId string, dnsNameToReg string, port uint16, ctx *CZitiCtx, svcName string) (net.IP, error) {
log.Infof("adding DNS entry for service name %s@%s:%d", svcName, dnsNameToReg, port)
DnsInit(defaultCidr, defaultMaskBits)
DnsInit(constants.Ipv4ip, constants.Ipv4DefaultMask)
dnsName := normalizeDnsName(dnsNameToReg)
key := fmt.Sprint(dnsName, ':', port)
+7
View File
@@ -0,0 +1,7 @@
package constants
const(
Ipv4ip = "100.64.0.0"
Ipv4MaxMask = 10
Ipv4DefaultMask = 24
)
+14 -7
View File
@@ -83,13 +83,20 @@ func (id *Identity) Path() string {
}
type TunnelStatus struct {
Active bool
Duration int64
Identities []*Identity
IpInfo *TunIpInfo `json:"IpInfo,omitempty"`
LogLevel string
TunIpv4 string
TunIpv4Mask int
Active bool
Duration int64
Identities []*Identity
IpInfo *TunIpInfo `json:"IpInfo,omitempty"`
LogLevel string
ServiceVersion ServiceVersion
TunIpv4 string
TunIpv4Mask int
}
type ServiceVersion struct {
Version string
Revision string
BuildDate string
}
type ZitiTunnelStatus struct {
+14 -8
View File
@@ -20,20 +20,26 @@ package main
import (
"fmt"
"github.com/openziti/desktop-edge-win/service/ziti-tunnel/dto"
"github.com/openziti/desktop-edge-win/service/ziti-tunnel/util/logging"
"golang.org/x/sys/windows/svc/debug"
"golang.org/x/sys/windows/svc/eventlog"
"os"
"strings"
"github.com/openziti/desktop-edge-win/service/ziti-tunnel/globals"
"golang.org/x/sys/windows/svc"
"github.com/openziti/desktop-edge-win/service/ziti-tunnel/service"
"golang.org/x/sys/windows/svc"
)
var log = globals.Logger()
var log = logging.Logger()
func main() {
globals.InitLogger("info")
service.Version = dto.ServiceVersion{
Version: Version,
Revision: Revision,
BuildDate: BuildDate,
}
logging.InitLogger("info")
//if len(os.Args) < 2 {
// // if no args supplied - expect to run as service
@@ -51,9 +57,9 @@ func main() {
var err error
if hasArgs {
globals.Elog = debug.New(service.SvcName)
logging.Elog = debug.New(service.SvcName)
} else {
globals.Elog, err = eventlog.Open(service.SvcName)
logging.Elog, err = eventlog.Open(service.SvcName)
if err != nil {
return
}
@@ -68,9 +74,9 @@ func main() {
usage("no command specified")
}
defer globals.Elog.Close()
defer logging.Elog.Close()
elog := globals.Elog
elog := logging.Elog
cmd := strings.ToLower(os.Args[1])
switch cmd {
+25 -21
View File
@@ -23,14 +23,16 @@ import (
"encoding/json"
"fmt"
"github.com/Microsoft/go-winio"
"github.com/openziti/desktop-edge-win/service/ziti-tunnel/constants"
"github.com/openziti/desktop-edge-win/service/ziti-tunnel/util/idutil"
"github.com/openziti/desktop-edge-win/service/ziti-tunnel/util/logging"
"github.com/openziti/foundation/identity/identity"
idcfg "github.com/openziti/sdk-golang/ziti/config"
"github.com/openziti/sdk-golang/ziti/enroll"
"github.com/openziti/desktop-edge-win/service/cziti"
"github.com/openziti/desktop-edge-win/service/ziti-tunnel/config"
"github.com/openziti/desktop-edge-win/service/ziti-tunnel/dto"
"github.com/openziti/desktop-edge-win/service/ziti-tunnel/globals"
"github.com/openziti/desktop-edge-win/service/ziti-tunnel/idutil"
"github.com/sirupsen/logrus"
"golang.org/x/sys/windows/svc"
"golang.zx2c4.com/wireguard/tun"
"io"
@@ -63,11 +65,11 @@ func SubMain(ops chan string, changes chan<- svc.Status) error {
rts.LoadConfig()
l := rts.state.LogLevel
_, czitiLevel := globals.ParseLevel(l)
_, czitiLevel := logging.ParseLevel(l)
globals.InitLogger(l)
logging.InitLogger(l )
_ = globals.Elog.Info(InformationEvent, SvcName+" starting. log file located at "+config.LogFile())
_ = logging.Elog.Info(InformationEvent, SvcName+" starting. log file located at "+config.LogFile())
// create a channel for notifying any connections that they are to be interrupted
interrupt = make(chan struct{}, 8)
@@ -100,7 +102,7 @@ func SubMain(ops chan string, changes chan<- svc.Status) error {
// notify the service is running
changes <- svc.Status{State: svc.Running, Accepts: cmdsAccepted}
_ = globals.Elog.Info(InformationEvent, SvcName+" status set to running")
_ = logging.Elog.Info(InformationEvent, SvcName+" status set to running")
log.Info(SvcName + " status set to running. starting cancel loop")
waitForStopRequest(ops)
@@ -245,12 +247,12 @@ func initialize(ipv4 string, ipv4mask int) error {
func setTunInfo(s *dto.TunnelStatus, ipv4 string, ipv4mask int) {
if strings.TrimSpace(ipv4) == "" {
log.Infof("ip not provided using default: %v", ipv4)
ipv4 = Ipv4ip
ipv4 = constants.Ipv4ip
rts.UpdateIpv4(ipv4)
}
if ipv4mask < 8 || ipv4mask > 24 {
log.Warnf("provided mask is invalid: %d. using default value: %d", ipv4mask, Ipv4mask)
ipv4mask = Ipv4mask
if ipv4mask < 8 || ipv4mask > constants.Ipv4MaxMask {
log.Warnf("provided mask is invalid: %d. using default value: %d", ipv4mask, constants.Ipv4DefaultMask)
ipv4mask = constants.Ipv4DefaultMask
rts.UpdateIpv4Mask(ipv4mask)
}
_, ipnet, err := net.ParseCIDR(fmt.Sprintf("%s/%d", ipv4, ipv4mask))
@@ -295,7 +297,7 @@ func accept(p net.Listener, serveFunction func(net.Conn), debug string) {
c, err := p.Accept()
if err != nil {
if err != winio.ErrPipeListenerClosed {
log.Errorf("unexpected error while accepting a connection. exiting loop. %v", err)
log.Errorf("%v unexpected error while accepting a connection. exiting loop. %v", debug, err)
}
return
}
@@ -332,7 +334,7 @@ func serveIpc(conn net.Conn) {
select {
case <-interrupt:
log.Info("request to interrupt read loop received")
conn.Close()
_ = conn.Close()
log.Info("read loop interrupted")
case <-done:
log.Debug("loop finished normally")
@@ -430,8 +432,10 @@ func serveIpc(conn net.Conn) {
}
func setLogLevel(out *json.Encoder, level string) {
goLevel, cLevel := globals.ParseLevel(level)
globals.SetLogLevel(goLevel, cLevel)
goLevel, cLevel := logging.ParseLevel(level)
logrus.Infof("Setting logger levels to %s", goLevel)
logrus.SetLevel(goLevel)
cziti.SetLogLevel(cLevel)
rts.state.LogLevel = goLevel.String()
respond(out, dto.Response{Message: "log level set", Code: SUCCESS, Error: "", Payload: nil})
}
@@ -600,7 +604,7 @@ func toggleIdentity(out *json.Encoder, fingerprint string, onOff bool) {
if onOff {
connectIdentity(id)
} else {
disconnectIdentity(id)
_ = disconnectIdentity(id)
}
respond(out, dto.Response{Message: "identity toggled", Code: SUCCESS, Error: "", Payload: idutil.Clean(*id)})
@@ -846,7 +850,7 @@ func acceptServices() {
switch c.Operation {
case cziti.ADDED:
//add the service to the identity
svc := dto.Service{
s := dto.Service{
Name: c.Service.Name,
InterceptHost: c.Service.InterceptHost,
InterceptPort: c.Service.InterceptPort,
@@ -854,22 +858,22 @@ func acceptServices() {
AssignedIP: c.Service.AssignedIP,
OwnsIntercept: c.Service.OwnsIntercept,
}
id.Services = append(id.Services, &svc)
id.Services = append(id.Services, &s)
events.broadcast <- dto.ServiceEvent{
ActionEvent: SERVICE_ADDED,
Fingerprint: id.FingerPrint,
Service: svc,
Service: s,
}
log.Debug("dispatched added service change event")
case cziti.REMOVED:
for idx, svc := range id.Services {
if svc.Name == c.Service.Name {
for idx, s := range id.Services {
if s.Name == c.Service.Name {
id.Services = append(id.Services[:idx], id.Services[idx+1:]...)
events.broadcast <- dto.ServiceEvent{
ActionEvent: SERVICE_REMOVED,
Fingerprint: id.FingerPrint,
Service: *svc,
Service: *s,
}
log.Debug(" dispatched remove service change event")
}
+4 -6
View File
@@ -18,13 +18,13 @@
package service
import (
"github.com/openziti/desktop-edge-win/service/ziti-tunnel/dto"
"github.com/openziti/desktop-edge-win/service/ziti-tunnel/util/logging"
"golang.org/x/sys/windows/svc"
"sync"
"time"
"github.com/openziti/desktop-edge-win/service/ziti-tunnel/dto"
"github.com/openziti/desktop-edge-win/service/ziti-tunnel/globals"
)
var Version dto.ServiceVersion
var pipeBase = `\\.\pipe\NetFoundry\tunneler\`
var activeIds = make(map[string]*dto.Identity)
@@ -39,7 +39,7 @@ var eventsConnections int
var Debug bool
var TunStarted time.Time
var log = globals.Logger()
var log = logging.Logger()
var events = newTopic()
@@ -87,8 +87,6 @@ const (
NF_GROUP_NAME = "NetFoundry Tunneler Users"
TunName = "ZitiTUN"
Ipv4ip = "169.254.1.1"
Ipv4mask = 24
Ipv4dns = "127.0.0.1" // use lo -- don't pass DNS queries through tunneler SDK
// IPv6 CIDR fe80:6e66:7a69:7469::/64
+12 -13
View File
@@ -21,12 +21,11 @@ package service
import (
"fmt"
"github.com/openziti/desktop-edge-win/service/ziti-tunnel/util/logging"
"golang.org/x/sys/windows/svc"
"golang.org/x/sys/windows/svc/debug"
"github.com/openziti/desktop-edge-win/service/ziti-tunnel/globals"
)
type zitiService struct{}
func (m *zitiService) Execute(args []string, r <-chan svc.ChangeRequest, changes chan<- svc.Status) (ssec bool, errno uint32) {
@@ -52,26 +51,26 @@ loop:
switch c.Cmd {
case svc.Interrogate:
changes <- c.CurrentStatus
_ = globals.Elog.Info(InterrogateEvent, "interrogate request received")
_ = logging.Elog.Info(InterrogateEvent, "interrogate request received")
changes <- c.CurrentStatus
case svc.Stop:
_ = globals.Elog.Info(StopEvent, "issuing stop")
_ = logging.Elog.Info(StopEvent, "issuing stop")
control <- "stop"
_ = globals.Elog.Info(StopEvent, "stop issued")
_ = logging.Elog.Info(StopEvent, "stop issued")
break loop
case svc.Shutdown:
_ = globals.Elog.Info(ShutdownEvent, "issuing shutdown")
_ = logging.Elog.Info(ShutdownEvent, "issuing shutdown")
control <- "stop"
_ = globals.Elog.Info(ShutdownEvent, "shutdown issued")
_ = logging.Elog.Info(ShutdownEvent, "shutdown issued")
break loop
case svc.Pause:
changes <- svc.Status{State: svc.Paused, Accepts: cmdsAccepted}
_ = globals.Elog.Info(PauseEvent, "request to pause service received. todo - unimplemented")
_ = logging.Elog.Info(PauseEvent, "request to pause service received. todo - unimplemented")
case svc.Continue:
changes <- svc.Status{State: svc.Running, Accepts: cmdsAccepted}
_ = globals.Elog.Info(ContinueEvent, "request to continue service received. todo - unimplemented")
_ = logging.Elog.Info(ContinueEvent, "request to continue service received. todo - unimplemented")
default:
_ = globals.Elog.Error(1, fmt.Sprintf("unexpected control request #%d", c))
_ = logging.Elog.Error(1, fmt.Sprintf("unexpected control request #%d", c))
}
}
}
@@ -86,7 +85,7 @@ loop:
}
func RunService(isDebug bool) {
_ = globals.Elog.Info(InformationEvent, fmt.Sprintf("starting %s service", SvcStartName))
_ = logging.Elog.Info(InformationEvent, fmt.Sprintf("starting %s service", SvcStartName))
run := svc.Run
if isDebug {
log.Info("debug specified. using debug.run")
@@ -95,8 +94,8 @@ func RunService(isDebug bool) {
err := run(SvcStartName, &zitiService{})
if err != nil {
_ = globals.Elog.Error(ErrorEvent, fmt.Sprintf("%s service failed: %v", SvcStartName, err))
_ = logging.Elog.Error(ErrorEvent, fmt.Sprintf("%s service failed: %v", SvcStartName, err))
return
}
_ = globals.Elog.Info(StopEvent, fmt.Sprintf("%s service stopped", SvcStartName))
_ = logging.Elog.Info(StopEvent, fmt.Sprintf("%s service stopped", SvcStartName))
}
+14 -12
View File
@@ -23,8 +23,9 @@ import (
"fmt"
"github.com/openziti/desktop-edge-win/service/cziti"
"github.com/openziti/desktop-edge-win/service/ziti-tunnel/config"
"github.com/openziti/desktop-edge-win/service/ziti-tunnel/constants"
"github.com/openziti/desktop-edge-win/service/ziti-tunnel/dto"
"github.com/openziti/desktop-edge-win/service/ziti-tunnel/idutil"
"github.com/openziti/desktop-edge-win/service/ziti-tunnel/util/idutil"
"golang.org/x/sys/windows/registry"
"golang.zx2c4.com/wireguard/tun"
"golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
@@ -100,13 +101,14 @@ func (t *RuntimeState) ToStatus() dto.TunnelStatus {
}
clean := dto.TunnelStatus{
Active: t.state.Active,
Duration: uptime,
Identities: make([]*dto.Identity, idCount),
IpInfo: t.state.IpInfo,
LogLevel: t.state.LogLevel,
TunIpv4: t.state.TunIpv4,
TunIpv4Mask: t.state.TunIpv4Mask,
Active: t.state.Active,
Duration: uptime,
Identities: make([]*dto.Identity, idCount),
IpInfo: t.state.IpInfo,
LogLevel: t.state.LogLevel,
ServiceVersion: Version,
TunIpv4: t.state.TunIpv4,
TunIpv4Mask: t.state.TunIpv4Mask,
}
for i, id := range t.state.Identities {
@@ -146,11 +148,11 @@ func (t *RuntimeState) CreateTun(ipv4 string, ipv4mask int) error {
if strings.TrimSpace(ipv4) == "" {
log.Infof("ip not provided using default: %v", ipv4)
ipv4 = Ipv4ip
ipv4 = constants.Ipv4ip
}
if ipv4mask < 8 || ipv4mask > 24 {
log.Warnf("provided mask is invalid: %d. using default value: %d", ipv4mask, Ipv4mask)
ipv4mask = Ipv4mask
if ipv4mask < 8 || ipv4mask > constants.Ipv4MaxMask {
log.Warnf("provided mask is invalid: %d. using default value: %d", ipv4mask, constants.Ipv4DefaultMask)
ipv4mask = constants.Ipv4DefaultMask
rts.UpdateIpv4Mask(ipv4mask)
}
ip, ipnet, err := net.ParseCIDR(fmt.Sprintf("%s/%d", ipv4, ipv4mask))
@@ -1,4 +1,4 @@
package ipchanges
package util
import (
"github.com/michaelquigley/pfxlog"
@@ -15,7 +15,7 @@
*
*/
package globals
package logging
import (
rotatelogs "github.com/lestrrat-go/file-rotatelogs"