mirror of
https://github.com/oneclickvirt/backtrace.git
synced 2025-06-07 20:14:46 +08:00
Compare commits
2 Commits
7a644b403e
...
5b416aa419
Author | SHA1 | Date | |
---|---|---|---|
![]() |
5b416aa419 | ||
![]() |
b93b8fbb4a |
30
bk/asn.go
30
bk/asn.go
@ -14,19 +14,30 @@ type Result struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ips = []string{
|
ipv4s = []string{
|
||||||
// "219.141.136.12", "202.106.50.1",
|
// "219.141.136.12", "202.106.50.1",
|
||||||
"219.141.140.10", "202.106.195.68", "221.179.155.161",
|
"219.141.140.10", "202.106.195.68", "221.179.155.161",
|
||||||
"202.96.209.133", "210.22.97.1", "211.136.112.200",
|
"202.96.209.133", "210.22.97.1", "211.136.112.200",
|
||||||
"58.60.188.222", "210.21.196.6", "120.196.165.24",
|
"58.60.188.222", "210.21.196.6", "120.196.165.24",
|
||||||
"61.139.2.69", "119.6.6.6", "211.137.96.205",
|
"61.139.2.69", "119.6.6.6", "211.137.96.205",
|
||||||
}
|
}
|
||||||
names = []string{
|
ipv6s = []string{
|
||||||
|
"2408:80f0:4100:2005::10", // 北京电信 IPv6
|
||||||
|
"2408:8000:1010:1::6", // 北京联通 IPv6
|
||||||
|
"2409:8000:1003:5::5", // 北京移动 IPv6
|
||||||
|
"2408:8026:1:1::6", // 上海联通 IPv6
|
||||||
|
"2409:8089:1020:50::6", // 上海移动 IPv6
|
||||||
|
}
|
||||||
|
ipv4Names = []string{
|
||||||
"北京电信", "北京联通", "北京移动",
|
"北京电信", "北京联通", "北京移动",
|
||||||
"上海电信", "上海联通", "上海移动",
|
"上海电信", "上海联通", "上海移动",
|
||||||
"广州电信", "广州联通", "广州移动",
|
"广州电信", "广州联通", "广州移动",
|
||||||
"成都电信", "成都联通", "成都移动",
|
"成都电信", "成都联通", "成都移动",
|
||||||
}
|
}
|
||||||
|
ipv6Names = []string{
|
||||||
|
"北京电信v6", "北京联通v6", "北京移动v6",
|
||||||
|
"上海联通v6", "上海移动v6",
|
||||||
|
}
|
||||||
m = map[string]string{
|
m = map[string]string{
|
||||||
// [] 前的字符串个数,中文占2个字符串
|
// [] 前的字符串个数,中文占2个字符串
|
||||||
"AS23764": "电信CTGNET [精品线路]",
|
"AS23764": "电信CTGNET [精品线路]",
|
||||||
@ -56,9 +67,9 @@ func removeDuplicates(elements []string) []string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func trace(ch chan Result, i int) {
|
func trace(ch chan Result, i int) {
|
||||||
hops, err := Trace(net.ParseIP(ips[i]))
|
hops, err := Trace(net.ParseIP(ipv4s[i]))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s := fmt.Sprintf("%v %-15s %v", names[i], ips[i], err)
|
s := fmt.Sprintf("%v %-15s %v", ipv4Names[i], ipv4s[i], err)
|
||||||
ch <- Result{i, s}
|
ch <- Result{i, s}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -75,7 +86,7 @@ func trace(ch chan Result, i int) {
|
|||||||
if asns != nil && len(asns) > 0 {
|
if asns != nil && len(asns) > 0 {
|
||||||
var tempText string
|
var tempText string
|
||||||
asns = removeDuplicates(asns)
|
asns = removeDuplicates(asns)
|
||||||
tempText += fmt.Sprintf("%v ", names[i])
|
tempText += fmt.Sprintf("%v ", ipv4Names[i])
|
||||||
hasAS4134 := false
|
hasAS4134 := false
|
||||||
hasAS4809 := false
|
hasAS4809 := false
|
||||||
for _, asn := range asns {
|
for _, asn := range asns {
|
||||||
@ -94,7 +105,7 @@ func trace(ch chan Result, i int) {
|
|||||||
// 仅包含 AS4809 属于 CN2GIA
|
// 仅包含 AS4809 属于 CN2GIA
|
||||||
asns = append([]string{"AS4809a"}, asns...)
|
asns = append([]string{"AS4809a"}, asns...)
|
||||||
}
|
}
|
||||||
tempText += fmt.Sprintf("%-15s ", ips[i])
|
tempText += fmt.Sprintf("%-15s ", ipv4s[i])
|
||||||
for _, asn := range asns {
|
for _, asn := range asns {
|
||||||
asnDescription := m[asn]
|
asnDescription := m[asn]
|
||||||
switch asn {
|
switch asn {
|
||||||
@ -128,17 +139,20 @@ func trace(ch chan Result, i int) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if tempText == (fmt.Sprintf("%v ", names[i]) + fmt.Sprintf("%-15s ", ips[i])) {
|
if tempText == (fmt.Sprintf("%v ", ipv4Names[i]) + fmt.Sprintf("%-15s ", ipv4s[i])) {
|
||||||
tempText += fmt.Sprintf("%v", Red("检测不到已知线路的ASN"))
|
tempText += fmt.Sprintf("%v", Red("检测不到已知线路的ASN"))
|
||||||
}
|
}
|
||||||
ch <- Result{i, tempText}
|
ch <- Result{i, tempText}
|
||||||
} else {
|
} else {
|
||||||
s := fmt.Sprintf("%v %-15s %v", names[i], ips[i], Red("检测不到回程路由节点的IP地址"))
|
s := fmt.Sprintf("%v %-15s %v", ipv4Names[i], ipv4s[i], Red("检测不到回程路由节点的IP地址"))
|
||||||
ch <- Result{i, s}
|
ch <- Result{i, s}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ipAsn(ip string) string {
|
func ipAsn(ip string) string {
|
||||||
|
if strings.Contains(ip, ":") {
|
||||||
|
return ipv6Asn(ip)
|
||||||
|
}
|
||||||
switch {
|
switch {
|
||||||
case strings.HasPrefix(ip, "59.43"):
|
case strings.HasPrefix(ip, "59.43"):
|
||||||
return "AS4809"
|
return "AS4809"
|
||||||
|
@ -6,24 +6,30 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func BackTrace() {
|
func BackTrace() {
|
||||||
var (
|
// 获取IP地址数量
|
||||||
s [12]string // 对应 ips 目标地址数量
|
ipCount := len(ipv4s)
|
||||||
c = make(chan Result)
|
var (
|
||||||
t = time.After(time.Second * 10)
|
s = make([]string, ipCount) // 动态分配切片大小
|
||||||
)
|
c = make(chan Result)
|
||||||
for i := range ips {
|
t = time.After(time.Second * 10)
|
||||||
go trace(c, i)
|
)
|
||||||
}
|
for i := range ipv4s {
|
||||||
|
go trace(c, i)
|
||||||
|
}
|
||||||
|
|
||||||
loop:
|
loop:
|
||||||
for range s {
|
for range s {
|
||||||
select {
|
select {
|
||||||
case o := <-c:
|
case o := <-c:
|
||||||
s[o.i] = o.s
|
s[o.i] = o.s
|
||||||
case <-t:
|
case <-t:
|
||||||
break loop
|
break loop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, r := range s {
|
|
||||||
fmt.Println(r)
|
for _, r := range s {
|
||||||
}
|
if r != "" {
|
||||||
|
fmt.Println(r)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
40
bk/ipv6_asn.go
Normal file
40
bk/ipv6_asn.go
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
package backtrace
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 识别IPv6地址的ASN
|
||||||
|
func ipv6Asn(ip string) string {
|
||||||
|
switch {
|
||||||
|
// 电信CN2GIA
|
||||||
|
case strings.HasPrefix(ip, "2408:80"):
|
||||||
|
return "AS4809a"
|
||||||
|
// 电信CN2GT
|
||||||
|
case strings.HasPrefix(ip, "2408:8000"):
|
||||||
|
return "AS4809b"
|
||||||
|
// 电信163
|
||||||
|
case strings.HasPrefix(ip, "240e:") || strings.HasPrefix(ip, "2408:8"):
|
||||||
|
return "AS4134"
|
||||||
|
// 联通9929
|
||||||
|
case strings.HasPrefix(ip, "2408:8026:"):
|
||||||
|
return "AS9929"
|
||||||
|
// 联通4837
|
||||||
|
case strings.HasPrefix(ip, "2408:8000:"):
|
||||||
|
return "AS4837"
|
||||||
|
// 移动CMIN2
|
||||||
|
case strings.HasPrefix(ip, "2409:8880:"):
|
||||||
|
return "AS58807"
|
||||||
|
// 移动CMI
|
||||||
|
case strings.HasPrefix(ip, "2409:8000:") || strings.HasPrefix(ip, "2409:"):
|
||||||
|
return "AS9808"
|
||||||
|
// 移动CMI
|
||||||
|
case strings.HasPrefix(ip, "2407:") || strings.HasPrefix(ip, "2401:"):
|
||||||
|
return "AS58453"
|
||||||
|
// 电信CTGNET
|
||||||
|
case strings.HasPrefix(ip, "2402:0:") || strings.HasPrefix(ip, "2400:8:"):
|
||||||
|
return "AS23764"
|
||||||
|
default:
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
@ -17,11 +17,11 @@ import (
|
|||||||
|
|
||||||
// DefaultConfig is the default configuration for Tracer.
|
// DefaultConfig is the default configuration for Tracer.
|
||||||
var DefaultConfig = Config{
|
var DefaultConfig = Config{
|
||||||
Delay: 50 * time.Millisecond,
|
Delay: 50 * time.Millisecond,
|
||||||
Timeout: 500 * time.Millisecond,
|
Timeout: 500 * time.Millisecond,
|
||||||
MaxHops: 15,
|
MaxHops: 15,
|
||||||
Count: 1,
|
Count: 1,
|
||||||
Networks: []string{"ip4:icmp", "ip4:ip"},
|
Networks: []string{"ip4:icmp", "ip4:ip", "ip6:ipv6-icmp", "ip6:ip"},
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultTracer is a tracer with DefaultConfig.
|
// DefaultTracer is a tracer with DefaultConfig.
|
||||||
@ -126,17 +126,6 @@ func (t *Tracer) init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 初始化IPv6 ICMP连接
|
|
||||||
c, err := net.ListenPacket("ip6:ipv6-icmp", "")
|
|
||||||
if err == nil {
|
|
||||||
p := ipv6.NewPacketConn(c)
|
|
||||||
if err := p.SetControlMessage(ipv6.FlagHopLimit|ipv6.FlagSrc|ipv6.FlagDst|ipv6.FlagInterface, true); err == nil {
|
|
||||||
t.ipv6conn = p
|
|
||||||
go t.serveIPv6(p)
|
|
||||||
} else {
|
|
||||||
c.Close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close closes listening socket.
|
// Close closes listening socket.
|
||||||
@ -167,55 +156,73 @@ func (t *Tracer) serve(conn *net.IPConn) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *Tracer) serveData(from net.IP, b []byte) error {
|
func (t *Tracer) serveData(from net.IP, b []byte) error {
|
||||||
if from.To4() == nil {
|
if from.To4() == nil {
|
||||||
// TODO: implement ProtocolIPv6ICMP
|
// IPv6 处理
|
||||||
return errUnsupportedProtocol
|
msg, err := icmp.ParseMessage(ProtocolIPv6ICMP, b)
|
||||||
}
|
if err != nil {
|
||||||
now := time.Now()
|
return err
|
||||||
msg, err := icmp.ParseMessage(ProtocolICMP, b)
|
}
|
||||||
if err != nil {
|
if msg.Type == ipv6.ICMPTypeEchoReply {
|
||||||
return err
|
echo := msg.Body.(*icmp.Echo)
|
||||||
}
|
return t.serveReply(from, &packet{from, uint16(echo.ID), 1, time.Now()})
|
||||||
if msg.Type == ipv4.ICMPTypeEchoReply {
|
}
|
||||||
echo := msg.Body.(*icmp.Echo)
|
b = getReplyData(msg)
|
||||||
return t.serveReply(from, &packet{from, uint16(echo.ID), 1, now})
|
if len(b) < ipv6.HeaderLen {
|
||||||
}
|
return errMessageTooShort
|
||||||
b = getReplyData(msg)
|
}
|
||||||
if len(b) < ipv4.HeaderLen {
|
switch b[0] >> 4 {
|
||||||
return errMessageTooShort
|
case ipv6.Version:
|
||||||
}
|
ip, err := ipv6.ParseHeader(b)
|
||||||
switch b[0] >> 4 {
|
if err != nil {
|
||||||
case ipv4.Version:
|
return err
|
||||||
ip, err := ipv4.ParseHeader(b)
|
}
|
||||||
if err != nil {
|
return t.serveReply(ip.Dst, &packet{from, uint16(ip.FlowLabel), ip.HopLimit, time.Now()})
|
||||||
return err
|
default:
|
||||||
}
|
return errUnsupportedProtocol
|
||||||
return t.serveReply(ip.Dst, &packet{from, uint16(ip.ID), ip.TTL, now})
|
}
|
||||||
case ipv6.Version:
|
} else {
|
||||||
ip, err := ipv6.ParseHeader(b)
|
// 原有的IPv4处理逻辑
|
||||||
if err != nil {
|
msg, err := icmp.ParseMessage(ProtocolICMP, b)
|
||||||
return err
|
if err != nil {
|
||||||
}
|
return err
|
||||||
return t.serveReply(ip.Dst, &packet{from, uint16(ip.FlowLabel), ip.HopLimit, now})
|
}
|
||||||
default:
|
if msg.Type == ipv4.ICMPTypeEchoReply {
|
||||||
return errUnsupportedProtocol
|
echo := msg.Body.(*icmp.Echo)
|
||||||
}
|
return t.serveReply(from, &packet{from, uint16(echo.ID), 1, time.Now()})
|
||||||
|
}
|
||||||
|
b = getReplyData(msg)
|
||||||
|
if len(b) < ipv4.HeaderLen {
|
||||||
|
return errMessageTooShort
|
||||||
|
}
|
||||||
|
switch b[0] >> 4 {
|
||||||
|
case ipv4.Version:
|
||||||
|
ip, err := ipv4.ParseHeader(b)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return t.serveReply(ip.Dst, &packet{from, uint16(ip.ID), ip.TTL, time.Now()})
|
||||||
|
default:
|
||||||
|
return errUnsupportedProtocol
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Tracer) sendRequest(dst net.IP, ttl int) (*packet, error) {
|
func (t *Tracer) sendRequest(dst net.IP, ttl int) (*packet, error) {
|
||||||
if dst.To4() == nil {
|
id := uint16(atomic.AddUint32(&t.seq, 1))
|
||||||
// IPv6
|
var b []byte
|
||||||
return t.sendRequestV6(dst, ttl)
|
if dst.To4() == nil {
|
||||||
}
|
// IPv6
|
||||||
// Ipv4
|
b = newPacketV6(id, dst, ttl)
|
||||||
id := uint16(atomic.AddUint32(&t.seq, 1))
|
} else {
|
||||||
b := newPacketV4(id, dst, ttl)
|
// IPv4
|
||||||
req := &packet{dst, id, ttl, time.Now()}
|
b = newPacketV4(id, dst, ttl)
|
||||||
_, err := t.conn.WriteToIP(b, &net.IPAddr{IP: dst})
|
}
|
||||||
if err != nil {
|
req := &packet{dst, id, ttl, time.Now()}
|
||||||
return nil, err
|
_, err := t.conn.WriteToIP(b, &net.IPAddr{IP: dst})
|
||||||
}
|
if err != nil {
|
||||||
return req, nil
|
return nil, err
|
||||||
|
}
|
||||||
|
return req, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Tracer) addSession(s *Session) {
|
func (t *Tracer) addSession(s *Session) {
|
||||||
|
131
bk/trace_ipv6.go
131
bk/trace_ipv6.go
@ -1,125 +1,36 @@
|
|||||||
package backtrace
|
package backtrace
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/binary"
|
||||||
"net"
|
"net"
|
||||||
"sync/atomic"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"golang.org/x/net/icmp"
|
"golang.org/x/net/icmp"
|
||||||
"golang.org/x/net/ipv6"
|
"golang.org/x/net/ipv6"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newPacketV6(id uint16, dst net.IP, ttl int) ([]byte, error) {
|
func newPacketV6(id uint16, dst net.IP, ttl int) []byte {
|
||||||
// 创建ICMPv6 Echo请求消息
|
// 创建ICMP消息(回显请求)
|
||||||
msg := icmp.Message{
|
msg := icmp.Message{
|
||||||
Type: ipv6.ICMPTypeEchoRequest,
|
Type: ipv6.ICMPTypeEchoRequest,
|
||||||
Code: 0,
|
|
||||||
Body: &icmp.Echo{
|
Body: &icmp.Echo{
|
||||||
ID: int(id),
|
ID: int(id),
|
||||||
Seq: int(id),
|
Seq: int(id),
|
||||||
Data: []byte("TRACEROUTE"),
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
// 序列化ICMP消息
|
||||||
// 直接序列化ICMPv6消息
|
icmpData, _ := msg.Marshal(nil)
|
||||||
// 第一个参数是协议号,对于ICMPv6应该是58
|
// 手动创建原始IPv6数据包头部
|
||||||
return msg.Marshal(nil)
|
ipHeaderBytes := make([]byte, ipv6.HeaderLen)
|
||||||
}
|
// 设置版本和流量类别(第一个字节)
|
||||||
|
ipHeaderBytes[0] = (ipv6.Version << 4)
|
||||||
func (t *Tracer) sendRequestV6(dst net.IP, ttl int) (*packet, error) {
|
// 设置下一个头部(协议)
|
||||||
id := uint16(atomic.AddUint32(&t.seq, 1))
|
ipHeaderBytes[6] = ProtocolIPv6ICMP
|
||||||
// 创建ICMPv6消息
|
// 设置跳数限制
|
||||||
msg := icmp.Message{
|
ipHeaderBytes[7] = byte(ttl)
|
||||||
Type: ipv6.ICMPTypeEchoRequest,
|
// 设置有效载荷长度(2字节字段)
|
||||||
Code: 0,
|
binary.BigEndian.PutUint16(ipHeaderBytes[4:6], uint16(len(icmpData)))
|
||||||
Body: &icmp.Echo{
|
// 设置目标地址(最后16个字节)
|
||||||
ID: int(id),
|
copy(ipHeaderBytes[24:40], dst.To16())
|
||||||
Seq: int(id),
|
// 合并头部和ICMP数据
|
||||||
Data: []byte("TRACEROUTE"),
|
return append(ipHeaderBytes, icmpData...)
|
||||||
},
|
|
||||||
}
|
|
||||||
// 序列化ICMPv6消息
|
|
||||||
b, err := msg.Marshal(nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// 获取底层连接
|
|
||||||
ipv6Conn, err := t.getIPv6Conn()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// 设置IPv6数据包的跳数限制(TTL)
|
|
||||||
if err := ipv6Conn.SetHopLimit(ttl); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// 发送数据包
|
|
||||||
if _, err := ipv6Conn.WriteTo(b, nil, &net.IPAddr{IP: dst}); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// 创建一个数据包记录,用于后续匹配回复
|
|
||||||
req := &packet{dst, id, ttl, time.Now()}
|
|
||||||
return req, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// getIPv6Conn 获取IPv6的PacketConn接口
|
|
||||||
func (t *Tracer) getIPv6Conn() (*ipv6.PacketConn, error) {
|
|
||||||
if t.ipv6conn != nil {
|
|
||||||
return t.ipv6conn, nil
|
|
||||||
}
|
|
||||||
// 创建一个UDP连接
|
|
||||||
c, err := net.ListenPacket("udp6", "::")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// 将其包装为IPv6 PacketConn
|
|
||||||
p := ipv6.NewPacketConn(c)
|
|
||||||
// 设置控制消息
|
|
||||||
if err := p.SetControlMessage(ipv6.FlagHopLimit|ipv6.FlagSrc|ipv6.FlagDst|ipv6.FlagInterface, true); err != nil {
|
|
||||||
c.Close()
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
t.ipv6conn = p
|
|
||||||
return p, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Tracer) serveIPv6(conn *ipv6.PacketConn) error {
|
|
||||||
defer conn.Close()
|
|
||||||
buf := make([]byte, 1500)
|
|
||||||
for {
|
|
||||||
n, cm, src, err := conn.ReadFrom(buf)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// 从控制消息中获取跳数限制
|
|
||||||
hopLimit := 0
|
|
||||||
if cm != nil {
|
|
||||||
hopLimit = cm.HopLimit
|
|
||||||
}
|
|
||||||
// 解析ICMP消息
|
|
||||||
msg, err := icmp.ParseMessage(ProtocolIPv6ICMP, buf[:n])
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// 根据消息类型处理
|
|
||||||
switch msg.Type {
|
|
||||||
case ipv6.ICMPTypeEchoReply:
|
|
||||||
echo := msg.Body.(*icmp.Echo)
|
|
||||||
t.serveReply(src.(*net.IPAddr).IP, &packet{src.(*net.IPAddr).IP, uint16(echo.ID), hopLimit, time.Now()})
|
|
||||||
case ipv6.ICMPTypeTimeExceeded:
|
|
||||||
// 处理超时消息,获取原始数据包
|
|
||||||
data := msg.Body.(*icmp.TimeExceeded).Data
|
|
||||||
// 尝试提取嵌入的原始Echo请求
|
|
||||||
if len(data) < 8 { // 至少需要IPv6头部前8个字节
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// 跳过IPv6头部和ICMPv6头部,简化处理,实际可能需要更复杂的解析
|
|
||||||
innerMsg, err := icmp.ParseMessage(ProtocolIPv6ICMP, data[48:])
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if echo, ok := innerMsg.Body.(*icmp.Echo); ok {
|
|
||||||
t.serveReply(src.(*net.IPAddr).IP, &packet{src.(*net.IPAddr).IP, uint16(echo.ID), hopLimit, time.Now()})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user