backing up
[vsorcdistro/.git] / ryu / build / lib.linux-armv7l-2.7 / ryu / app / simple_switch_snort.py
1 # Copyright (C) 2013 Nippon Telegraph and Telephone Corporation.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #    http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12 # implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15
16 from __future__ import print_function
17
18 import array
19
20 from ryu.base import app_manager
21 from ryu.controller import ofp_event
22 from ryu.controller.handler import CONFIG_DISPATCHER, MAIN_DISPATCHER
23 from ryu.controller.handler import set_ev_cls
24 from ryu.ofproto import ofproto_v1_3
25 from ryu.lib.packet import packet
26 from ryu.lib.packet import ethernet
27 from ryu.lib.packet import ipv4
28 from ryu.lib.packet import icmp
29 from ryu.lib import snortlib
30
31
32 class SimpleSwitchSnort(app_manager.RyuApp):
33     OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]
34     _CONTEXTS = {'snortlib': snortlib.SnortLib}
35
36     def __init__(self, *args, **kwargs):
37         super(SimpleSwitchSnort, self).__init__(*args, **kwargs)
38         self.snort = kwargs['snortlib']
39         self.snort_port = 3
40         self.mac_to_port = {}
41
42         socket_config = {'unixsock': True}
43
44         self.snort.set_config(socket_config)
45         self.snort.start_socket_server()
46
47     def packet_print(self, pkt):
48         pkt = packet.Packet(array.array('B', pkt))
49
50         eth = pkt.get_protocol(ethernet.ethernet)
51         _ipv4 = pkt.get_protocol(ipv4.ipv4)
52         _icmp = pkt.get_protocol(icmp.icmp)
53
54         if _icmp:
55             self.logger.info("%r", _icmp)
56
57         if _ipv4:
58             self.logger.info("%r", _ipv4)
59
60         if eth:
61             self.logger.info("%r", eth)
62
63         # for p in pkt.protocols:
64         #     if hasattr(p, 'protocol_name') is False:
65         #         break
66         #     print('p: %s' % p.protocol_name)
67
68     @set_ev_cls(snortlib.EventAlert, MAIN_DISPATCHER)
69     def _dump_alert(self, ev):
70         msg = ev.msg
71
72         print('alertmsg: %s' % ''.join(msg.alertmsg))
73
74         self.packet_print(msg.pkt)
75
76     @set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
77     def switch_features_handler(self, ev):
78         datapath = ev.msg.datapath
79         ofproto = datapath.ofproto
80         parser = datapath.ofproto_parser
81
82         # install table-miss flow entry
83         #
84         # We specify NO BUFFER to max_len of the output action due to
85         # OVS bug. At this moment, if we specify a lesser number, e.g.,
86         # 128, OVS will send Packet-In with invalid buffer_id and
87         # truncated packet data. In that case, we cannot output packets
88         # correctly.
89         match = parser.OFPMatch()
90         actions = [parser.OFPActionOutput(ofproto.OFPP_CONTROLLER,
91                                           ofproto.OFPCML_NO_BUFFER)]
92         self.add_flow(datapath, 0, match, actions)
93
94     def add_flow(self, datapath, priority, match, actions):
95         ofproto = datapath.ofproto
96         parser = datapath.ofproto_parser
97
98         inst = [parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,
99                                              actions)]
100
101         mod = parser.OFPFlowMod(datapath=datapath, priority=priority,
102                                 match=match, instructions=inst)
103         datapath.send_msg(mod)
104
105     @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
106     def _packet_in_handler(self, ev):
107         msg = ev.msg
108         datapath = msg.datapath
109         ofproto = datapath.ofproto
110         parser = datapath.ofproto_parser
111         in_port = msg.match['in_port']
112
113         pkt = packet.Packet(msg.data)
114         eth = pkt.get_protocols(ethernet.ethernet)[0]
115
116         dst = eth.dst
117         src = eth.src
118
119         dpid = datapath.id
120         self.mac_to_port.setdefault(dpid, {})
121
122         # self.logger.info("packet in %s %s %s %s", dpid, src, dst, in_port)
123
124         # learn a mac address to avoid FLOOD next time.
125         self.mac_to_port[dpid][src] = in_port
126
127         if dst in self.mac_to_port[dpid]:
128             out_port = self.mac_to_port[dpid][dst]
129         else:
130             out_port = ofproto.OFPP_FLOOD
131
132         actions = [parser.OFPActionOutput(out_port),
133                    parser.OFPActionOutput(self.snort_port)]
134
135         # install a flow to avoid packet_in next time
136         if out_port != ofproto.OFPP_FLOOD:
137             match = parser.OFPMatch(in_port=in_port, eth_dst=dst)
138             self.add_flow(datapath, 1, match, actions)
139
140         data = None
141         if msg.buffer_id == ofproto.OFP_NO_BUFFER:
142             data = msg.data
143
144         out = parser.OFPPacketOut(datapath=datapath, buffer_id=msg.buffer_id,
145                                   in_port=in_port, actions=actions, data=data)
146         datapath.send_msg(out)