Untitled

 avatar
unknown
plain_text
4 years ago
10 kB
7
No Index
def handle_incoming_external_msg(self, of_packet, data_packet):
        '''Handles a packet with destination MAC equal to external side of NAT router.'''
        # TODO Implement this function
        print('handle_incoming_external_msg')

        print('\n')



        switch = of_packet.datapath
        parser = switch.ofproto_parser
        in_port = of_packet.match['in_port']
        match = parser.OFPMatch(in_port=in_port)

        # Drops the packet
        actions = []

        self.add_flow(switch, match, actions, 0)

        return

    def handle_incoming_internal_msg(self, of_packet, data_packet):
        '''Handles a packet with destination MAC equal to internal side of NAT router.'''
        print('--==arp table==--')
        print(self.arp_table)
        print('--==switch table==--')
        print(self.switch_table)
        # TODO Implement this function
        self.debug('handle_incoming_internal_msg')
        switch = of_packet.datapath
        ofproto = switch.ofproto
        parser = switch.ofproto_parser

        eth_packet = data_packet.get_protocol(ethernet.ethernet)
        ip_packet = data_packet.get_protocol(ipv4.ipv4)
        tcp_packet = data_packet.get_protocol(tcp.tcp)
        udp_packet = data_packet.get_protocol(udp.udp)
        icmp_packet = data_packet.get_protocol(icmp.icmp)

        in_port = of_packet.match['in_port']
        udp_set = 0

        # replaced self.is_tcp since, the else case cannot work for an external
        # note udp sends multiple packets to the switch for some reason
        # Internal -> Internal
        if self.is_internal_network(data_packet[1].dst) and data_packet[1].dst != config.nat_internal_ip:
            if (self.is_tcp(data_packet) or self.is_udp(data_packet)):
                if eth_packet.dst in self.switch_table:
                    out_port = self.switch_table[eth_packet.dst]
                else:
                    # If no destination port can be determined, need to request this
                    self.handle_internal_host_requests(of_packet, data_packet)
                    return

                # Match + Action
                actions = [parser.OFPActionOutput(out_port)]
                match = parser.OFPMatch(in_port=in_port, eth_dst=eth_packet.dst)
                if self.is_udp(data_packet):
                    udp_set = 1

                self.add_flow(switch, match, actions, 1)

                data = None
                if of_packet.buffer_id == ofproto.OFP_NO_BUFFER:
                    data = of_packet.data
                self.send_packet(data, of_packet, out_port)



            elif (self.is_icmp(data_packet)):
                if eth_packet.dst in self.switch_table:
                    out_port = self.switch_table[eth_packet.dst]
                else:
                    # If no destination port can be determined, need to request this
                    self.handle_internal_host_requests(of_packet, data_packet)
                    return
                match = parser.OFPMatch(in_port=in_port,
                                        eth_type=ether.ETH_TYPE_IP,
                                        ip_proto=inet.IPPROTO_ICMP,
                                        ipv4_src=ip_packet.src,
                                        ipv4_dst=ip_packet.dst,
                                        icmpv4_type=icmp.ICMP_ECHO_REQUEST)
                actions = [parser.OFPActionSetField(eth_dst=self.arp_table[ip_packet.dst]),
                           parser.OFPActionOutput(out_port)]

                self.add_flow(switch, match, actions,1)
                data = None
                if of_packet.buffer_id == ofproto.OFP_NO_BUFFER:
                    data = of_packet.data
                self.send_packet(data, of_packet, out_port)

        # Internal -> External
        else:
            if ip_packet.src not in self.ip_to_ephem:
                self.ip_to_ephem[ip_packet.src] = self.get_port()

            ephem_port = self.ip_to_ephem[ip_packet.src]

            if not self.is_icmp(data_packet):
                if self.is_tcp(data_packet):
                    srcport = tcp_packet.src_port
                    dstport = tcp_packet.dst_port

                    match = parser.OFPMatch(in_port=in_port,
                                            eth_type=ether.ETH_TYPE_IP,
                                            ip_proto=ip_packet.proto,
                                            ipv4_src=ip_packet.src,
                                            ipv4_dst=ip_packet.dst,
                                            tcp_src=srcport,
                                            tcp_dst=dstport)

                    actions = [parser.OFPActionSetField(ipv4_src=config.nat_external_ip),
                               parser.OFPActionSetField(tcp_src=ephem_port)]

                    match_reply = parser.OFPMatch(eth_type=ether.ETH_TYPE_IP,
                                                  ip_proto=inet.IPPROTO_TCP,
                                                  ipv4_src=ip_packet.dst,
                                                  ipv4_dst=config.nat_external_ip,
                                                  tcp_src=dstport,
                                                  tcp_dst=ephem_port)

                    actions_reply = [parser.OFPActionSetField(eth_dst=eth_packet.src),
                                     parser.OFPActionSetField(ipv4_dst=ip_packet.src),
                                     parser.OFPActionSetField(tcp_dst=srcport),
                                     parser.OFPActionOutput(in_port)]

                else:
                    srcport = udp_packet.src_port
                    dstport = udp_packet.dst_port
                    udp_set = 1

                    match = parser.OFPMatch(in_port=in_port,
                                            eth_type=ether.ETH_TYPE_IP,
                                            ip_proto=ip_packet.proto,
                                            ipv4_src=ip_packet.src,
                                            ipv4_dst=ip_packet.dst,
                                            udp_src=srcport,
                                            udp_dst=dstport)

                    actions = [parser.OFPActionSetField(ipv4_src=config.nat_external_ip),
                               parser.OFPActionSetField(udp_src=ephem_port)]

                    match_reply = parser.OFPMatch(eth_type=ether.ETH_TYPE_IP,
                                                  ip_proto=inet.IPPROTO_UDP,
                                                  ipv4_src=ip_packet.dst,
                                                  ipv4_dst=config.nat_external_ip,
                                                  udp_src=dstport,
                                                  udp_dst=ephem_port)

                    actions_reply = [parser.OFPActionSetField(eth_dst=eth_packet.src),
                                     parser.OFPActionSetField(ipv4_dst=ip_packet.src),
                                     parser.OFPActionSetField(udp_dst=srcport),
                                     parser.OFPActionOutput(in_port)]

                print('sending int->ext ...')
                # do a match+action, where we change src_ip to external nat ip and add to table
                self.router_forward(of_packet, data_packet, config.nat_gateway_ip)

                # matching unique inport and internal mac
                self.add_flow(switch, match_reply, actions_reply,  1)

                if config.nat_gateway_ip in self.arp_table:
                    self.router_forward(of_packet, data_packet, config.nat_gateway_ip, match, actions)


            elif (self.is_icmp(data_packet)):
                print('got here')

                # self.router_forward(of_packet, data_packet, config.nat_gateway_ip)
                # if config.nat_gateway_ip in self.arp_table:

                # lol why does this work

                print("icmp_packet %s" % icmp_packet)
                match = parser.OFPMatch(in_port=in_port,
                                        eth_type=ether.ETH_TYPE_IP,
                                        ip_proto=inet.IPPROTO_ICMP,
                                        ipv4_src=ip_packet.src,
                                        ipv4_dst=ip_packet.dst,
                                        icmpv4_type=icmp.ICMP_ECHO_REQUEST)

                actions = [parser.OFPActionSetField(ipv4_src=config.nat_external_ip)]

                match_reply = parser.OFPMatch(eth_type=ether.ETH_TYPE_IP,
                                              ip_proto=inet.IPPROTO_ICMP,
                                              ipv4_src=ip_packet.dst,
                                              ipv4_dst=config.nat_external_ip,
                                              icmpv4_type=icmp.ICMP_ECHO_REPLY)

                actions_reply = [parser.OFPActionSetField(eth_dst=eth_packet.src),
                                 parser.OFPActionSetField(ipv4_dst=ip_packet.src),
                                 parser.OFPActionOutput(in_port)]

                self.add_flow(switch, match_reply, actions_reply,1)
                self.router_forward(of_packet, data_packet, config.nat_gateway_ip, match, actions)

        return


    def get_port(self):
        """Getting port number sequential increase."""
        next_ephem = 49152
        count = 65535 - 49152 + 1
        while count > 0:
            if (next_ephem == 65535):
                next_ephem = 49152

            ephem_port = next_ephem
            if ephem_port not in self.ports_in_use:
                self.ports_in_use.append(ephem_port)
                return ephem_port
            else:
                next_ephem = next_ephem + 1
                count = count - 1

        # how to return error?
        return -1
Editor is loading...