forked from ctulek/stun
-
Notifications
You must be signed in to change notification settings - Fork 0
/
xor_mapped_address.go
115 lines (104 loc) · 2.1 KB
/
xor_mapped_address.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
package stun
import (
"errors"
"fmt"
"net"
)
type XORMappedAddress struct {
Family byte
Port uint16
IP net.IP
}
func (x *XORMappedAddress) Type() uint16 {
return ATTR_TYPE_XOR_MAPPED_ADDRESS
}
func (x *XORMappedAddress) Length() uint16 {
if x.Family == 0x01 {
return 8
} else {
return 20
}
}
func (x *XORMappedAddress) Pack(b []byte) error {
b = b[4:]
if x.Family == 0x01 {
if len(b) < 8 {
return errors.New("Buffer too short for IPv4")
}
b[1] = 0x01 // Family
putUint16(b[2:4], xorPort(x.Port))
i := copy(b[4:8], xorIP(x.IP.To4()))
if i != 4 {
return errors.New("Copy failed")
}
return nil
} else if x.Family == 0x02 {
if len(b) < 20 {
return errors.New("Buffer too short for IPv6")
}
b[1] = 0x02 // Family
putUint16(b[2:4], xorPort(x.Port))
i := copy(b[4:20], xorIP(x.IP))
if i != 16 {
return errors.New("Copy failed")
}
return nil
}
return errors.New("Undefined Family")
}
func xorPort(p uint16) uint16 {
var cookie [4]byte
putUint32(cookie[:], RFC5389_COOKIE)
var bytes [2]byte
putUint16(bytes[:], p)
for i := 0; i < len(bytes); i++ {
bytes[i] = bytes[i] ^ cookie[i]
}
p = toUint16(bytes[:])
return p
}
func xorIP(ip []byte) net.IP {
var cookie [4]byte
putUint32(cookie[:], RFC5389_COOKIE)
for i := 0; i < len(ip); i++ {
ip[i] = ip[i] ^ cookie[i%4]
}
return ip
}
func (x *XORMappedAddress) UnPack(b []byte) error {
b = b[4:]
if len(b) < 8 {
return errors.New("Buffer too short")
}
x.Family = b[1]
if x.Family == 0x02 && len(b) < 20 {
return errors.New("Buffer is too short for IPv6")
}
x.Port = toUint16(b[2:4])
x.Port = xorPort(x.Port)
if x.Family == 0x01 {
x.IP = make(net.IP, 4)
i := copy(x.IP, b[4:8])
if i != 4 {
return errors.New("Copy failed")
}
x.IP = xorIP(x.IP)
} else {
x.IP = make(net.IP, 16)
i := copy(x.IP, b[4:20])
if i != 16 {
return errors.New("Copy failed")
}
}
return nil
}
func (x *XORMappedAddress) String() string {
var family string
switch x.Family {
case 1:
family = "IPv4"
case 2:
family = "IPv6"
}
return fmt.Sprintf("XOR Mapped Address: %s %s:%d", family, x.IP, x.Port)
}