added support for string type
[govpp.git] / vendor / github.com / google / gopacket / examples / synscan / main.go
1 // Copyright 2012 Google, Inc. All rights reserved.
2 //
3 // Use of this source code is governed by a BSD-style license
4 // that can be found in the LICENSE file in the root of the source
5 // tree.
6
7 // synscan implements a TCP syn scanner on top of pcap.
8 // It's more complicated than arpscan, since it has to handle sending packets
9 // outside the local network, requiring some routing and ARP work.
10 //
11 // Since this is just an example program, it aims for simplicity over
12 // performance.  It doesn't handle sending packets very quickly, it scans IPs
13 // serially instead of in parallel, and uses gopacket.Packet instead of
14 // gopacket.DecodingLayerParser for packet processing.  We also make use of very
15 // simple timeout logic with time.Since.
16 //
17 // Making it blazingly fast is left as an exercise to the reader.
18 package main
19
20 import (
21         "errors"
22         "flag"
23         "log"
24         "net"
25         "time"
26
27         "github.com/google/gopacket"
28         "github.com/google/gopacket/examples/util"
29         "github.com/google/gopacket/layers"
30         "github.com/google/gopacket/pcap"
31         "github.com/google/gopacket/routing"
32 )
33
34 // scanner handles scanning a single IP address.
35 type scanner struct {
36         // iface is the interface to send packets on.
37         iface *net.Interface
38         // destination, gateway (if applicable), and source IP addresses to use.
39         dst, gw, src net.IP
40
41         handle *pcap.Handle
42
43         // opts and buf allow us to easily serialize packets in the send()
44         // method.
45         opts gopacket.SerializeOptions
46         buf  gopacket.SerializeBuffer
47 }
48
49 // newScanner creates a new scanner for a given destination IP address, using
50 // router to determine how to route packets to that IP.
51 func newScanner(ip net.IP, router routing.Router) (*scanner, error) {
52         s := &scanner{
53                 dst: ip,
54                 opts: gopacket.SerializeOptions{
55                         FixLengths:       true,
56                         ComputeChecksums: true,
57                 },
58                 buf: gopacket.NewSerializeBuffer(),
59         }
60         // Figure out the route to the IP.
61         iface, gw, src, err := router.Route(ip)
62         if err != nil {
63                 return nil, err
64         }
65         log.Printf("scanning ip %v with interface %v, gateway %v, src %v", ip, iface.Name, gw, src)
66         s.gw, s.src, s.iface = gw, src, iface
67
68         // Open the handle for reading/writing.
69         // Note we could very easily add some BPF filtering here to greatly
70         // decrease the number of packets we have to look at when getting back
71         // scan results.
72         handle, err := pcap.OpenLive(iface.Name, 65536, true, pcap.BlockForever)
73         if err != nil {
74                 return nil, err
75         }
76         s.handle = handle
77         return s, nil
78 }
79
80 // close cleans up the handle.
81 func (s *scanner) close() {
82         s.handle.Close()
83 }
84
85 // getHwAddr is a hacky but effective way to get the destination hardware
86 // address for our packets.  It does an ARP request for our gateway (if there is
87 // one) or destination IP (if no gateway is necessary), then waits for an ARP
88 // reply.  This is pretty slow right now, since it blocks on the ARP
89 // request/reply.
90 func (s *scanner) getHwAddr() (net.HardwareAddr, error) {
91         start := time.Now()
92         arpDst := s.dst
93         if s.gw != nil {
94                 arpDst = s.gw
95         }
96         // Prepare the layers to send for an ARP request.
97         eth := layers.Ethernet{
98                 SrcMAC:       s.iface.HardwareAddr,
99                 DstMAC:       net.HardwareAddr{0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
100                 EthernetType: layers.EthernetTypeARP,
101         }
102         arp := layers.ARP{
103                 AddrType:          layers.LinkTypeEthernet,
104                 Protocol:          layers.EthernetTypeIPv4,
105                 HwAddressSize:     6,
106                 ProtAddressSize:   4,
107                 Operation:         layers.ARPRequest,
108                 SourceHwAddress:   []byte(s.iface.HardwareAddr),
109                 SourceProtAddress: []byte(s.src),
110                 DstHwAddress:      []byte{0, 0, 0, 0, 0, 0},
111                 DstProtAddress:    []byte(arpDst),
112         }
113         // Send a single ARP request packet (we never retry a send, since this
114         // is just an example ;)
115         if err := s.send(&eth, &arp); err != nil {
116                 return nil, err
117         }
118         // Wait 3 seconds for an ARP reply.
119         for {
120                 if time.Since(start) > time.Second*3 {
121                         return nil, errors.New("timeout getting ARP reply")
122                 }
123                 data, _, err := s.handle.ReadPacketData()
124                 if err == pcap.NextErrorTimeoutExpired {
125                         continue
126                 } else if err != nil {
127                         return nil, err
128                 }
129                 packet := gopacket.NewPacket(data, layers.LayerTypeEthernet, gopacket.NoCopy)
130                 if arpLayer := packet.Layer(layers.LayerTypeARP); arpLayer != nil {
131                         arp := arpLayer.(*layers.ARP)
132                         if net.IP(arp.SourceProtAddress).Equal(net.IP(arpDst)) {
133                                 return net.HardwareAddr(arp.SourceHwAddress), nil
134                         }
135                 }
136         }
137 }
138
139 // scan scans the dst IP address of this scanner.
140 func (s *scanner) scan() error {
141         // First off, get the MAC address we should be sending packets to.
142         hwaddr, err := s.getHwAddr()
143         if err != nil {
144                 return err
145         }
146         // Construct all the network layers we need.
147         eth := layers.Ethernet{
148                 SrcMAC:       s.iface.HardwareAddr,
149                 DstMAC:       hwaddr,
150                 EthernetType: layers.EthernetTypeIPv4,
151         }
152         ip4 := layers.IPv4{
153                 SrcIP:    s.src,
154                 DstIP:    s.dst,
155                 Version:  4,
156                 TTL:      64,
157                 Protocol: layers.IPProtocolTCP,
158         }
159         tcp := layers.TCP{
160                 SrcPort: 54321,
161                 DstPort: 0, // will be incremented during the scan
162                 SYN:     true,
163         }
164         tcp.SetNetworkLayerForChecksum(&ip4)
165
166         // Create the flow we expect returning packets to have, so we can check
167         // against it and discard useless packets.
168         ipFlow := gopacket.NewFlow(layers.EndpointIPv4, s.dst, s.src)
169         start := time.Now()
170         for {
171                 // Send one packet per loop iteration until we've sent packets
172                 // to all of ports [1, 65535].
173                 if tcp.DstPort < 65535 {
174                         start = time.Now()
175                         tcp.DstPort++
176                         if err := s.send(&eth, &ip4, &tcp); err != nil {
177                                 log.Printf("error sending to port %v: %v", tcp.DstPort, err)
178                         }
179                 }
180                 // Time out 5 seconds after the last packet we sent.
181                 if time.Since(start) > time.Second*5 {
182                         log.Printf("timed out for %v, assuming we've seen all we can", s.dst)
183                         return nil
184                 }
185
186                 // Read in the next packet.
187                 data, _, err := s.handle.ReadPacketData()
188                 if err == pcap.NextErrorTimeoutExpired {
189                         continue
190                 } else if err != nil {
191                         log.Printf("error reading packet: %v", err)
192                         continue
193                 }
194
195                 // Parse the packet.  We'd use DecodingLayerParser here if we
196                 // wanted to be really fast.
197                 packet := gopacket.NewPacket(data, layers.LayerTypeEthernet, gopacket.NoCopy)
198
199                 // Find the packets we care about, and print out logging
200                 // information about them.  All others are ignored.
201                 if net := packet.NetworkLayer(); net == nil {
202                         // log.Printf("packet has no network layer")
203                 } else if net.NetworkFlow() != ipFlow {
204                         // log.Printf("packet does not match our ip src/dst")
205                 } else if tcpLayer := packet.Layer(layers.LayerTypeTCP); tcpLayer == nil {
206                         // log.Printf("packet has not tcp layer")
207                 } else if tcp, ok := tcpLayer.(*layers.TCP); !ok {
208                         // We panic here because this is guaranteed to never
209                         // happen.
210                         panic("tcp layer is not tcp layer :-/")
211                 } else if tcp.DstPort != 54321 {
212                         // log.Printf("dst port %v does not match", tcp.DstPort)
213                 } else if tcp.RST {
214                         log.Printf("  port %v closed", tcp.SrcPort)
215                 } else if tcp.SYN && tcp.ACK {
216                         log.Printf("  port %v open", tcp.SrcPort)
217                 } else {
218                         // log.Printf("ignoring useless packet")
219                 }
220         }
221 }
222
223 // send sends the given layers as a single packet on the network.
224 func (s *scanner) send(l ...gopacket.SerializableLayer) error {
225         if err := gopacket.SerializeLayers(s.buf, s.opts, l...); err != nil {
226                 return err
227         }
228         return s.handle.WritePacketData(s.buf.Bytes())
229 }
230
231 func main() {
232         defer util.Run()()
233         router, err := routing.New()
234         if err != nil {
235                 log.Fatal("routing error:", err)
236         }
237         for _, arg := range flag.Args() {
238                 var ip net.IP
239                 if ip = net.ParseIP(arg); ip == nil {
240                         log.Printf("non-ip target: %q", arg)
241                         continue
242                 } else if ip = ip.To4(); ip == nil {
243                         log.Printf("non-ipv4 target: %q", arg)
244                         continue
245                 }
246                 // Note:  newScanner creates and closes a pcap Handle once for
247                 // every scan target.  We could do much better, were this not an
248                 // example ;)
249                 s, err := newScanner(ip, router)
250                 if err != nil {
251                         log.Printf("unable to create scanner for %v: %v", ip, err)
252                         continue
253                 }
254                 if err := s.scan(); err != nil {
255                         log.Printf("unable to scan %v: %v", ip, err)
256                 }
257                 s.close()
258         }
259 }