Skip to content
Snippets Groups Projects
Commit d82d0d15 authored by Volker Schukai's avatar Volker Schukai :alien:
Browse files

first version of the code

parent aa8834e3
No related branches found
No related tags found
No related merge requests found
package traceroute
import (
"errors"
"github.com/jackpal/gateway"
"net"
)
func getOutboundIP(mode int) (*address, error) {
ip, err := gateway.DiscoverInterface()
if err != nil {
return nil, err
}
a := newAddress(ip)
switch mode {
case addressV4:
if isV4(ip) {
return &a, nil
}
case addressV6:
if !isV4(ip) {
return &a, nil
}
case unknown:
default:
return nil, errors.New("the mode parameter must be either 4 or 6")
}
interfaces, err := net.Interfaces()
if err != nil {
return nil, err
}
for _, i := range interfaces {
addrs, err := i.Addrs()
if err != nil {
continue
}
var ipv6, ipv4 net.IP
var found bool
for _, a := range addrs {
if a.Network() != "ip+net" {
continue
}
b, _, err := net.ParseCIDR(a.String())
if err != nil {
continue
}
if !b.IsGlobalUnicast() {
continue
}
if isV4(b) {
ipv4 = b
} else {
ipv6 = b
}
if b.String() == ip.String() {
found = true
}
}
if !found {
continue
}
if mode <= addressV4 {
if ipv4 == nil {
return nil, errors.New("no suitable interface was found")
}
a:= newAddress(ipv4)
return &a, nil
}
if ipv6 == nil {
return nil, errors.New("no suitable interface was found")
}
a:= newAddress(ipv6)
return &a, nil
}
return nil, errors.New("no suitable interface was found")
}
package traceroute
import (
"testing"
)
func TestGetOutboundIPV6(t *testing.T) {
ip, err := getOutboundIP(addressV6)
if err != nil {
t.Errorf("this call should not return an error " + err.Error())
}
if !ip.isV6() {
t.Errorf("this call should not return an error " + err.Error())
}
}
func TestGetOutboundIPV4(t *testing.T) {
ip, err := getOutboundIP(addressV4)
if err != nil {
t.Errorf("this call should not return an error " + err.Error())
}
if !ip.isV4() {
t.Errorf("this call should not return an error " + err.Error())
}
}
func BenchmarkGetOutboundIP(b *testing.B) {
for n := 0; n < b.N; n++ {
getOutboundIP(addressV6)
}
}
package traceroute
import (
"github.com/creasty/defaults"
"golang.org/x/net/icmp"
"golang.org/x/net/ipv4"
"time"
)
// Session is Transaction Struct
type Session struct {
Destination *address
Source *address
CallBack func(result Result)
Timeout time.Duration `default:"2"` // in seconds
MaxHops int `default:"30"`
nextHop int
isFinale bool
ipV4Sock *ipv4.PacketConn
icmpEcho icmp.Message
readBuffer []byte
}
// NewSession creates a new Session
func NewSession(destination string) (*Session, error) {
s := Session{}
if err := defaults.Set(&s); err != nil {
return nil, err
}
dest, err := resolve(destination)
if err != nil {
return nil, err
}
s.Destination = dest
var mode int
if dest.isV6() {
mode = addressV6
} else {
mode = addressV4
}
s.Timeout = s.Timeout*time.Second
//* time.Second
src, err := getOutboundIP(mode)
s.Source = src
return &s, nil
}
package traceroute
import (
"fmt"
"testing"
)
func TestNewSession(t *testing.T) {
testCases := []struct {
destination string
shouldSessionError bool
}{
{
"www.schukai.com",
false,
},
}
for _, tc := range testCases {
t.Run(fmt.Sprintf(""), func(t *testing.T) {
session, err := NewSession(tc.destination)
if err != nil {
if tc.shouldSessionError {
return
}
t.Errorf("%s shout not error %s", tc.destination, err.Error())
return
}
if session.Timeout==0 {
t.Errorf("timeout should be greater than 0")
}
_, err = session.TraceRoute()
if err!=nil {
t.Errorf("%s shout not error %s", tc.destination, err.Error())
return
}
})
}
}
mode: count
gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:26.39,36.16 4 0
gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:41.2,41.45 1 0
gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:46.2,55.68 4 0
gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:60.2,60.78 1 0
gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:65.2,67.20 2 0
gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:71.2,71.16 1 0
gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:76.2,78.16 2 0
gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:83.2,86.50 3 0
gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:91.2,91.47 1 0
gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:96.2,98.10 2 0
gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:36.16,39.3 2 0
gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:41.45,44.3 2 0
gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:55.68,58.3 2 0
gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:60.78,63.3 2 0
gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:67.20,69.3 1 0
gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:71.16,74.3 2 0
gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:78.16,81.3 2 0
gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:86.50,89.3 2 0
gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:91.47,94.3 2 0
gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:101.52,105.16 2 2
gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:109.2,114.118 4 0
gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:118.2,126.33 4 0
gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:133.2,133.22 1 0
gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:105.16,107.3 1 2
gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:114.118,116.3 1 0
gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:126.33,128.17 2 0
gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:128.17,129.9 1 0
gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:142.50,144.26 1 2
gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:159.2,159.74 1 0
gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:144.26,146.17 2 2
gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:149.3,149.22 1 0
gitlab.schukai.com/oss/libraries/go/network/traceroute/traceroute.go:146.17,148.4 1 2
gitlab.schukai.com/oss/libraries/go/network/traceroute/dns.go:8.52,11.16 2 5
gitlab.schukai.com/oss/libraries/go/network/traceroute/dns.go:15.2,16.25 2 4
gitlab.schukai.com/oss/libraries/go/network/traceroute/dns.go:24.2,24.17 1 3
gitlab.schukai.com/oss/libraries/go/network/traceroute/dns.go:28.2,28.73 1 0
gitlab.schukai.com/oss/libraries/go/network/traceroute/dns.go:11.16,13.3 1 1
gitlab.schukai.com/oss/libraries/go/network/traceroute/dns.go:16.25,17.29 1 4
gitlab.schukai.com/oss/libraries/go/network/traceroute/dns.go:17.29,19.4 1 1
gitlab.schukai.com/oss/libraries/go/network/traceroute/dns.go:19.9,19.36 1 3
gitlab.schukai.com/oss/libraries/go/network/traceroute/dns.go:19.36,21.4 1 3
gitlab.schukai.com/oss/libraries/go/network/traceroute/dns.go:24.17,26.3 1 3
gitlab.schukai.com/oss/libraries/go/network/traceroute/dns.go:33.49,36.21 2 8
gitlab.schukai.com/oss/libraries/go/network/traceroute/dns.go:40.2,40.22 1 6
gitlab.schukai.com/oss/libraries/go/network/traceroute/dns.go:44.2,44.29 1 5
gitlab.schukai.com/oss/libraries/go/network/traceroute/dns.go:36.21,38.3 1 2
gitlab.schukai.com/oss/libraries/go/network/traceroute/dns.go:40.22,42.3 1 1
gitlab.schukai.com/oss/libraries/go/network/traceroute/ip.go:11.27,13.14 2 15
gitlab.schukai.com/oss/libraries/go/network/traceroute/ip.go:16.2,16.14 1 4
gitlab.schukai.com/oss/libraries/go/network/traceroute/ip.go:13.14,15.3 1 11
gitlab.schukai.com/oss/libraries/go/network/traceroute/ip.go:24.30,26.2 1 13
gitlab.schukai.com/oss/libraries/go/network/traceroute/ip.go:27.30,29.2 1 13
gitlab.schukai.com/oss/libraries/go/network/traceroute/ip.go:31.34,33.2 1 5
gitlab.schukai.com/oss/libraries/go/network/traceroute/ip.go:35.34,37.2 1 5
gitlab.schukai.com/oss/libraries/go/network/traceroute/ip.go:39.36,45.2 2 0
gitlab.schukai.com/oss/libraries/go/network/traceroute/ip.go:47.36,49.15 1 10
gitlab.schukai.com/oss/libraries/go/network/traceroute/ip.go:57.2,57.14 1 9
gitlab.schukai.com/oss/libraries/go/network/traceroute/ip.go:64.2,67.3 1 3
gitlab.schukai.com/oss/libraries/go/network/traceroute/ip.go:49.15,55.3 1 1
gitlab.schukai.com/oss/libraries/go/network/traceroute/ip.go:57.14,62.3 1 6
gitlab.schukai.com/oss/libraries/go/network/traceroute/main.go:3.14,5.2 0 0
gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:9.48,11.16 2 4
gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:15.2,17.14 2 4
gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:31.2,33.16 2 1
gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:37.2,37.31 1 1
gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:95.2,95.59 1 0
gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:11.16,13.3 1 0
gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:18.17,19.15 1 3
gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:22.17,23.16 1 1
gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:26.15,26.15 0 0
gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:27.10,28.69 1 0
gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:19.15,21.4 1 3
gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:23.16,25.4 1 0
gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:33.16,35.3 1 0
gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:37.31,40.17 2 2
gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:44.3,47.27 3 2
gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:73.3,73.13 1 2
gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:77.3,77.24 1 1
gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:86.3,86.18 1 1
gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:90.3,91.17 2 1
gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:40.17,41.12 1 0
gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:47.27,48.31 1 5
gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:52.4,53.18 2 5
gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:57.4,57.28 1 5
gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:61.4,61.15 1 2
gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:67.4,67.33 1 2
gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:48.31,49.13 1 0
gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:53.18,54.13 1 0
gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:57.28,58.13 1 3
gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:61.15,63.5 1 1
gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:63.10,65.5 1 1
gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:67.33,69.5 1 1
gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:73.13,74.12 1 1
gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:77.24,78.19 1 0
gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:82.4,83.18 2 0
gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:78.19,80.5 1 0
gitlab.schukai.com/oss/libraries/go/network/traceroute/outbound.go:86.18,88.4 1 0
gitlab.schukai.com/oss/libraries/go/network/traceroute/session.go:27.55,31.41 2 2
gitlab.schukai.com/oss/libraries/go/network/traceroute/session.go:35.2,36.16 2 2
gitlab.schukai.com/oss/libraries/go/network/traceroute/session.go:39.2,42.17 3 2
gitlab.schukai.com/oss/libraries/go/network/traceroute/session.go:49.2,55.16 4 2
gitlab.schukai.com/oss/libraries/go/network/traceroute/session.go:31.41,33.3 1 0
gitlab.schukai.com/oss/libraries/go/network/traceroute/session.go:36.16,38.3 1 0
gitlab.schukai.com/oss/libraries/go/network/traceroute/session.go:42.17,44.3 1 0
gitlab.schukai.com/oss/libraries/go/network/traceroute/session.go:44.8,46.3 1 2
package traceroute
import (
"errors"
"fmt"
"golang.org/x/net/icmp"
"golang.org/x/net/ipv4"
"math/rand"
"net"
"time"
)
type Result struct {
Hop int
Station string
Latency time.Duration
Err error
}
// Results is a collection of hops
type Results struct {
Hops []Result
}
func (s *Session) doHop(i int) Result {
s.icmpEcho.Body.(*icmp.Echo).Seq = i
r := Result{
Hop: i,
Station: "*",
}
writeBuffer, err := s.icmpEcho.Marshal(nil)
if err != nil {
r.Err = err
return r
}
if err := s.ipV4Sock.SetTTL(i); err != nil {
r.Err = fmt.Errorf("socket: %w", err)
return r
}
timeNow := time.Now()
dst := s.Destination
a := net.IPAddr{
IP: dst.ip,
Zone: "",
}
if _, err := s.ipV4Sock.WriteTo(writeBuffer, nil, &a); err != nil {
r.Err = err
return r
}
if err := s.ipV4Sock.SetReadDeadline(time.Now().Add(s.Timeout)); err != nil {
r.Err = err
return r
}
readBytes, _, hopNode, err := s.ipV4Sock.ReadFrom(s.readBuffer)
if hopNode != nil {
r.Station = hopNode.String()
}
if err != nil {
r.Err = err
return r
}
icmpAnswer, err := icmp.ParseMessage(1, s.readBuffer[:readBytes])
if err != nil {
r.Err = err
return r
}
latency := time.Since(timeNow)
r.Latency = latency
if icmpAnswer.Type == ipv4.ICMPTypeTimeExceeded {
s.nextHop++
return r
}
if icmpAnswer.Type == ipv4.ICMPTypeEchoReply {
s.isFinale = true
return r
}
r.Err = fmt.Errorf("unknown icmp answer: %d", icmpAnswer.Type.Protocol())
return r
}
func (s *Session) TraceRouteV4() (*Results, error) {
sock, err := net.ListenPacket("ip4:icmp", s.Source.ip.String())
if err != nil {
return nil, err
}
defer sock.Close()
s.ipV4Sock = ipv4.NewPacketConn(sock)
defer s.ipV4Sock.Close()
if err := s.ipV4Sock.SetControlMessage(ipv4.FlagTTL|ipv4.FlagDst|ipv4.FlagInterface|ipv4.FlagSrc, true); err != nil {
return nil, err
}
s.icmpEcho = icmp.Message{
Type: ipv4.ICMPTypeEcho, Code: 0, Body: &icmp.Echo{ID: rand.Int(), Data: []byte("")},
}
s.readBuffer = make([]byte, 1500)
results := Results{}
for i := 1; i < s.MaxHops; i++ {
r:=s.doHop(i)
results.Hops = append(results.Hops, r)
if s.CallBack!=nil {
s.CallBack(r)
}
if s.isFinale {
break
}
}
return &results, nil
}
// currently not implemented
//func (s *Session) traceRouteV6() error {
// return nil
//}
// TraceRoute measures the steps to the target host
func (s *Session) TraceRoute() (*Results, error) {
if s.Destination.isV4() {
results, err := s.TraceRouteV4()
if err != nil {
return nil, err
}
return results, nil
}
// currently not implemented
//if s.Destination.isV6() {
// if err := s.traceRouteV6(); err != nil {
// return nil, err
// }
//}
return nil, errors.New("could not traceroute " + s.Destination.String())
}
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="Go" enabled="true" />
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
\ No newline at end of file
package traceroute
import (
"fmt"
"testing"
)
func TestTraceroute(t *testing.T) {
testCases := []struct {
destination string
shouldSessionError bool
}{
{
"www.schukai.com",
false,
},
}
for _, tc := range testCases {
t.Run(fmt.Sprintf(""), func(t *testing.T) {
session, err := NewSession(tc.destination)
if err != nil {
t.Errorf("%s shout not error %s", tc.destination, err.Error())
}
_,err = session.TraceRoute()
if err != nil {
t.Errorf("%s shout not error %s", tc.destination, err.Error())
}
})
}
}
func benchmarkTraceroute(address string, b *testing.B) {
for n := 0; n < b.N; n++ {
resolve(address)
}
}
func BenchmarkTraceroute1(b *testing.B) { benchmarkTraceroute("www.google.com", b) }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment