Line data Source code
1 : /* 2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved. 3 : * Copyright Contributors to the OpenSDN project 4 : */ 5 : #include "base/os.h" 6 : #include <netinet/icmp6.h> 7 : #include <vr_defs.h> 8 : #include <cmn/agent_cmn.h> 9 : #include <oper/interface_common.h> 10 : #include <oper/vn.h> 11 : #include <pkt/pkt_init.h> 12 : #include <services/icmpv6_error_proto.h> 13 : #include <services/icmpv6_error_handler.h> 14 : #include <services/icmpv6_handler.h> 15 : #include <services/services_init.h> 16 : #include <services/icmpv6_proto.h> 17 : 18 : 19 : extern SandeshTraceBufferPtr Icmpv6TraceBuf; 20 : 21 0 : Icmpv6ErrorHandler::Icmpv6ErrorHandler(Agent *agent, Icmpv6ErrorProto *proto, 22 : boost::shared_ptr<PktInfo> info, 23 0 : boost::asio::io_context *io) : 24 0 : ProtoHandler(agent, info, *io), proto_(proto) { 25 0 : } 26 : 27 0 : Icmpv6ErrorHandler::~Icmpv6ErrorHandler() { 28 0 : } 29 : 30 0 : bool Icmpv6ErrorHandler::ValidatePacket() { 31 0 : if (pkt_info_->len < (sizeof(struct ether_header) + sizeof(struct ip6_hdr))) 32 0 : return false; 33 0 : return true; 34 : } 35 : 36 0 : bool Icmpv6ErrorHandler::Run() { 37 : 38 0 : if (ValidatePacket() == false) { 39 0 : proto_->increment_drops(); 40 0 : return true; 41 : } 42 : 43 0 : VmInterface *vm_itf = dynamic_cast<VmInterface *> 44 0 : (agent()->interface_table()->FindInterface(GetInterfaceIndex())); 45 0 : if (vm_itf == NULL || vm_itf->layer3_forwarding() == false || 46 0 : vm_itf->IsActive() == false) { 47 0 : proto_->increment_interface_errors(); 48 0 : return true; 49 : } 50 0 : return SendIcmpv6Error(vm_itf); 51 : } 52 : 53 : // Generate ICMP error 54 0 : bool Icmpv6ErrorHandler::SendIcmpv6Error(VmInterface *intf) { 55 : 56 0 : char *buff = (char *)pkt_info_->pkt; 57 0 : uint16_t buff_len = pkt_info_->packet_buffer()->data_len(); 58 : char data[ICMPV6_PAYLOAD_LEN]; 59 0 : int len = ntohs(pkt_info_->ip6->ip6_plen); 60 : 61 0 : if (len > ICMPV6_PAYLOAD_LEN) 62 0 : len = ICMPV6_PAYLOAD_LEN; 63 : 64 0 : memcpy(data, pkt_info_->ip6, len); 65 : 66 0 : Ip6Address source_address; 67 0 : boost::system::error_code ec; 68 0 : const VnIpam *ipam = intf->vn()->GetIpam(pkt_info_->ip_saddr.to_v6()); 69 0 : if (ipam != NULL) { 70 0 : if (ipam->default_gw.is_v6()) 71 0 : source_address = ipam->default_gw.to_v6(); 72 : } 73 : // If source address is not found, use vhost address mapped v6 address. 74 : // vrouter forwards the icmp error packets as part of the original flow. 75 0 : if (source_address.is_unspecified()) 76 0 : source_address = Ip6Address::v4_mapped(agent()->router_id()); 77 : 78 : uint32_t interface = 79 0 : (pkt_info_->agent_hdr.cmd == AgentHdr::TRAP_TOR_CONTROL_PKT) ? 80 0 : pkt_info_->agent_hdr.cmd_param : GetInterfaceIndex(); 81 : 82 0 : uint16_t eth_len = EthHdr(buff, buff_len, interface, 83 : agent()->vhost_interface()->mac(), 84 0 : MacAddress(pkt_info_->eth->ether_shost), 85 0 : ETHERTYPE_IPV6); 86 : 87 0 : pkt_info_->ip6 = (struct ip6_hdr *)(buff + eth_len); 88 0 : Ip6Hdr(pkt_info_->ip6, len+ICMP_UNREACH_HDR_LEN, IPV6_ICMP_NEXT_HEADER, 89 0 : 255, source_address.to_bytes().data(), 90 0 : pkt_info_->ip_saddr.to_v6().to_bytes().data()); 91 : 92 0 : icmp6_hdr *icmp = pkt_info_->transp.icmp6 = 93 0 : (icmp6_hdr *)(pkt_info_->pkt + eth_len 94 0 : + sizeof(ip6_hdr)); 95 0 : icmp->icmp6_type = ICMP6_PACKET_TOO_BIG; 96 0 : icmp->icmp6_code = 0; 97 0 : icmp->icmp6_mtu = htonl(pkt_info_->agent_hdr.mtu); 98 0 : icmp->icmp6_cksum = 0; 99 0 : memcpy(buff + sizeof(ip6_hdr) + eth_len+ICMP_UNREACH_HDR_LEN, data, len); 100 0 : icmp->icmp6_cksum = 101 0 : Icmpv6Csum(source_address.to_bytes().data(), 102 0 : pkt_info_->ip_saddr.to_v6().to_bytes().data(), 103 0 : icmp, len + ICMP_UNREACH_HDR_LEN); 104 0 : pkt_info_->set_len(len + sizeof(ip6_hdr) + eth_len+ICMP_UNREACH_HDR_LEN); 105 : 106 : uint16_t command = 107 0 : (pkt_info_->agent_hdr.cmd == AgentHdr::TRAP_TOR_CONTROL_PKT) ? 108 0 : (uint16_t)AgentHdr::TX_ROUTE : AgentHdr::TX_SWITCH; 109 : 110 0 : Send(GetInterfaceIndex(), pkt_info_->vrf, command, 111 : PktHandler::ICMPV6); 112 0 : return true; 113 : }