-
Notifications
You must be signed in to change notification settings - Fork 0
/
sendrecv.go
139 lines (105 loc) · 2.72 KB
/
sendrecv.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
133
134
135
136
137
138
139
package vizion
import (
"fmt"
"log"
"net"
"os"
"os/signal"
"syscall"
"github.com/AnataarXVI/vizion/packet"
)
type RawSocket struct {
protocol uint16
fd int
ifi *net.Interface
addr *syscall.SockaddrLinklayer
}
func htons(i uint16) uint16 {
return (i<<8)&0xff00 | i>>8
}
// Create and return a Raw socket
func NewSocket(iface string) *RawSocket {
protocol := htons(syscall.ETH_P_ALL)
// Open raw socket
fd, err := syscall.Socket(syscall.AF_PACKET, syscall.SOCK_RAW, int(protocol))
if err != nil {
fmt.Printf("error opening raw socket: %s", err)
return &RawSocket{}
}
// Retrieve network interface index
ifi, err := net.InterfaceByName(iface)
if err != nil {
fmt.Printf("error getting interface index: %s", err)
return &RawSocket{}
}
addr := syscall.SockaddrLinklayer{
Protocol: protocol,
Ifindex: ifi.Index,
}
err = syscall.Bind(fd, &addr)
if err != nil {
fmt.Printf("error failed to bind socket: %s", err)
return &RawSocket{}
}
return &RawSocket{protocol: protocol, fd: fd, ifi: ifi, addr: &addr}
}
// Send sends the packet to a raw socket.
func Send(pkt packet.Packet, iface string) error {
// Build package in bytes
packetBytes, err := pkt.Build()
if err != nil {
return fmt.Errorf("error building packet: %s", err)
}
// Create the socket
s := NewSocket(iface)
defer syscall.Close(s.fd)
// Send bytes to network interface
err = syscall.Sendto(s.fd, packetBytes, 0, s.addr)
if err != nil {
return fmt.Errorf("error sending packet: %s", err)
}
fmt.Println("Packet sent successfully.")
return nil
}
/*
Sniff will capture traffic on an interface.
The iface parameter corresponding to the interface name.
The prn parameter handle a function called when a packet is received. The function need to handle a packet.Packet struct to get the packet.
*/
func Sniff(iface string, prn func(pkt packet.Packet)) []*packet.Packet {
var pkt_list []*packet.Packet
s := NewSocket(iface)
defer syscall.Close(s.fd)
// Initiate sigs chan to handle Ctrl+C
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, os.Interrupt)
// Initiate data chan to handle data stream
data := make(chan packet.Packet)
// Convert data into Packet and send it in the data chan
go func() {
for {
buffer := make([]byte, 1460)
n, error := syscall.Read(s.fd, buffer)
if error != nil {
log.Fatal(error)
}
new_pkt := packet.Packet{Raw: buffer[:n]}
new_pkt.Dissect()
// If prn is not nil. It will call the func give in parameters
if prn != nil {
prn(new_pkt)
}
data <- new_pkt
}
}()
for {
select {
// If Interrupt
case <-sigs:
return pkt_list
// Dissect each packet and save it into a list
case pkt := <-data:
pkt_list = append(pkt_list, &pkt)
}
}
}