-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathrouter.go
110 lines (92 loc) · 2.63 KB
/
router.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
package main
import (
"encoding/binary"
"log"
"net"
"strconv"
)
func router(in chan<- []byte, out chan []byte, virtualIP net.IP, ifaceName string) {
parseCommand("sysctl net.ipv4.icmp_echo_ignore_broadcasts=0")
broadcaster := NewBroadcaster(ifaceName)
routingTable := NewRoutingTable(virtualIP, ifaceName, broadcaster)
multicastIP := net.IPv6linklocalallnodes // ff02::1
multicastAddr := &net.UDPAddr{multicastIP, PORT_MULTICAST, ""}
// listen multicast
listenMulti, err := net.ListenMulticastUDP("udp6", nil, multicastAddr)
if err != nil {
log.Fatal(err)
}
listenMulti.SetReadBuffer(MAXDATAGRAMSIZE)
go func() {
buffer := make([]byte, MAXDATAGRAMSIZE)
for {
length, src, err := listenMulti.ReadFromUDP(buffer)
if err != nil {
log.Fatal("ReadFromUDP failed:", err)
}
src.Port = PORT_UNICAST
if buffer[0] == 0 && length == 50 {
vIP := net.IP(buffer[2:18])
senderIP := net.IP(buffer[18:34])
if vIP.Equal(virtualIP) || senderIP.Equal(virtualIP) {
continue
}
sequence := binary.LittleEndian.Uint16(buffer[34:50])
//log.Printf("%s can join %s with %d hops (sequence %d)", src.IP.String(), vIP.String(), buffer[1], sequence)
routingTable.SetRule(buffer[1]+1, src, vIP, sequence)
}
}
}()
// handle outgoing packets
go func() {
for {
outPacket := <-out
nextHop := routingTable.NextHop(IPDst(outPacket))
if nextHop != nil {
if *debug_showPackets {
log.Printf("%s -> %s", IPSrc(outPacket).String(), IPDst(outPacket).String())
}
socket, err := net.DialUDP("udp6", nil, nextHop)
if err != nil {
log.Print(err)
continue
}
socket.SetWriteBuffer(MAXDATAGRAMSIZE)
socket.Write(outPacket)
socket.Close()
} else if *debug_showPackets {
log.Printf("%s -> %s (dropped)", IPSrc(outPacket).String(), IPDst(outPacket).String())
}
}
}()
unicastAddr, err := net.ResolveUDPAddr("udp6", ":"+strconv.Itoa(PORT_UNICAST))
if err != nil {
log.Fatal(err)
}
// listen unicast
listenUni, err := net.ListenUDP("udp6", unicastAddr)
if err != nil {
log.Fatal(err)
}
listenUni.SetReadBuffer(MAXDATAGRAMSIZE)
buffer := make([]byte, MAXDATAGRAMSIZE)
for {
length, _, err := listenUni.ReadFromUDP(buffer)
if err != nil {
log.Fatal("ReadFromUDP failed:", err)
}
packet := make([]byte, length)
copy(packet, buffer[:length])
packet[7]--
if *debug_showPackets {
log.Printf("%s <- %s", IPDst(packet).String(), IPSrc(packet).String())
}
if IPDst(packet).Equal(virtualIP) {
in <- packet
} else if packet[7] > 0 {
out <- packet
} //else {
// TODO : send ICMP "Time Exceeded", "hop limit exceeded in transit"
//}
}
}