-
Notifications
You must be signed in to change notification settings - Fork 0
/
xor_decode.go
132 lines (112 loc) · 3.71 KB
/
xor_decode.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package gostun
import (
"encoding/binary"
"errors"
"fmt"
"net"
"strconv"
)
type Addr struct {
Port int // port number
IP net.IP // IP address
}
/*
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|x x x x x x x x| Family | X-Port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| X-Address (Variable)
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Format of XOR-MAPPED-ADDRESS Attribute
*/
// 0x01:IPv4
// 0x02:IPv6
const (
IPv4 uint16 = 0x01
IPv6 uint16 = 0x02
)
type XORMappedAddr Addr
func (addr XORMappedAddr) String() string {
return fmt.Sprintf("IP: %s\nPort:%s", addr.IP.String(), strconv.Itoa(addr.Port))
}
func (attr Attributes) GetAttrFiledValue(attrtype AttributeType) ([]byte, error) {
for _, a := range attr {
if a.Type == attrtype {
return a.Value, nil
}
}
return nil, errors.New("Attribute is not matched")
}
func (m *Message) GetRapped(attrtype AttributeType) ([]byte, error) {
val, err := m.Attributes.GetAttrFiledValue(attrtype)
if err != nil {
return nil, err
}
return val, nil
}
func (addr *XORMappedAddr) DecodexorAddr(m *Message, attrtype AttributeType) error {
val, err := m.GetRapped(attrtype)
if err != nil {
return err
}
var (
family uint16
ipl int
)
family = binary.BigEndian.Uint16(val[0:2])
//check family address
if family == IPv4 {
ipl = net.IPv4len
} else if family == IPv6 {
ipl = net.IPv6len
} else {
err := fmt.Sprintf("family decode err: family = %d\n", family)
return errors.New(err)
}
addr.IP = addr.IP[:cap(addr.IP)]
for len(addr.IP) < ipl {
addr.IP = append(addr.IP, 0)
}
addr.IP = addr.IP[:ipl]
/*
X-Port is computed by taking the mapped port in host byte order,
XOR'ing it with the most significant 16 bits of the magic cookie, and
then the converting the result to network byte order.
*/
/*
If the IPaddress family is IPv4, X-Address is computed by taking the mapped IP
address in host byte order, XOR'ing it with the magic cookie, and
converting the result to network byte order. If the IP address
family is IPv6, X-Address is computed by taking the mapped IP address
in host byte order, XOR'ing it with the concatenation of the magic
cookie and the 96-bit transaction ID, and converting the result to
network byte order(BigEndian).
IPアドレスファミリーがIPv4であるなら、X-アドレスは、マップされたIPアドレスをホ
ストバイトオーダーで取得して、マジッククッキーでそれをXORして、そして
その結果をネットワークバイトオーダーに変換することで計算される
IPアドレスファミリーがIPv6であるなら、X-アドレスは、マップされたIPアドレ
スをホストバイトオーダーで取得して、マジッククッキーと96ビットのトラ
ンザクションIDとを連結したものでそれをXORして、そしてその結果をネット
ワークバイトオーダーに変換することで計算される
*/
buf := make([]byte, ipl)
binary.BigEndian.PutUint32(buf[:4], magicCookie)
copy(buf[4:], m.TransactionID[:])
addr.XorAddr(val[2:], buf)
return nil
}
// xor addr
func (addr *XORMappedAddr) XorAddr(value, buf []byte) {
//port
mscookie := magicCookie >> 16
addr.Port = int(binary.BigEndian.Uint16(value[0:2])) ^ mscookie
// address
value = value[2:]
for i := 0; i < len(value); i++ {
addr.IP[i] = value[i] ^ buf[i]
}
}
func (addr *XORMappedAddr) GetXORMapped(m *Message) error {
return addr.DecodexorAddr(m, XOR_MAPPED_ADDRESS)
}