OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
icmp_handler.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #include <stdint.h>
6 #include <vr_defs.h>
7 #include <cmn/agent_cmn.h>
8 #include <pkt/pkt_init.h>
10 #include <oper/interface_common.h>
11 #include <services/icmp_proto.h>
12 #include <boost/scoped_array.hpp>
13 
14 IcmpHandler::IcmpHandler(Agent *agent, boost::shared_ptr<PktInfo> info,
15  boost::asio::io_context &io)
16  : ProtoHandler(agent, info, io), icmp_(pkt_info_->transp.icmp) {
17  icmp_len_ = ntohs(pkt_info_->ip->ip_len) - (pkt_info_->ip->ip_hl * 4);
18 }
19 
21 }
22 
24 
25  IcmpProto *icmp_proto = agent()->GetIcmpProto();
26  Interface *itf =
28  if (itf == NULL) {
29  icmp_proto->IncrStatsIntfNotInst();
30  return true;
31  }
32  VmInterface *vm_itf = static_cast<VmInterface *>(itf);
33  if (!vm_itf->layer3_forwarding()) {
34  icmp_proto->IncrStatsNoL3Fwd();
35  return true;
36  }
37  switch (icmp_->icmp_type) {
38  case ICMP_ECHO:
39  if (CheckPacket()) {
40  icmp_proto->IncrStatsGwPing();
41  SendResponse(vm_itf);
42  } else
43  icmp_proto->IncrStatsGwPingErr();
44  return true;
45 
46  default:
47  icmp_proto->IncrStatsDrop();
48  return true;
49  }
50 }
51 
53  if (pkt_info_->len < (sizeof(struct ether_header) + ntohs(pkt_info_->ip->ip_len)))
54  return false;
55 
56  uint16_t checksum = icmp_->icmp_cksum;
57  icmp_->icmp_cksum = 0;
58  if (checksum == Csum((uint16_t *)icmp_, icmp_len_, 0))
59  return true;
60 
61  return false;
62 }
63 
65  // Max size of buffer
66  char *ptr = (char *)pkt_info_->pkt;
67  uint16_t buf_len = pkt_info_->max_pkt_len;
68 
69  // Copy the ICMP payload
70  boost::scoped_array<char> icmp_payload(new char[icmp_len_]);
71  memcpy(icmp_payload.get(), icmp_, icmp_len_);
72 
73  uint16_t len = 0;
74 
75  // Form ICMP Packet with following
76  // EthHdr - IP Header - ICMP Header
77  len += EthHdr(ptr + len, buf_len - len,
78  MacAddress(pkt_info_->eth->ether_dhost),
79  MacAddress(pkt_info_->eth->ether_shost),
80  ETHERTYPE_IP, vm_intf->tx_vlan_id());
81 
82  uint16_t ip_len = sizeof(struct ip) + icmp_len_;
83 
84  len += IpHdr(ptr + len, buf_len - len, ip_len,
85  htonl(pkt_info_->ip_daddr.to_v4().to_ulong()),
86  htonl(pkt_info_->ip_saddr.to_v4().to_ulong()),
87  IPPROTO_ICMP, DEFAULT_IP_ID, DEFAULT_IP_TTL);
88 
89  // Restore the ICMP header copied earlier
90  struct icmp *hdr = (struct icmp *) (ptr + len);
91  memcpy(ptr + len, icmp_payload.get(), icmp_len_);
92  len += icmp_len_;
93 
94  // Change type to reply
95  hdr->icmp_type = ICMP_ECHOREPLY;
96  // Recompute ICMP checksum
97  IcmpChecksum((char *)hdr, icmp_len_);
98  pkt_info_->set_len(len);
99 
100  uint32_t interface =
101  ((pkt_info_->agent_hdr.cmd == AgentHdr::TRAP_TOR_CONTROL_PKT) ?
102  pkt_info_->agent_hdr.cmd_param : GetInterfaceIndex());
103  uint16_t command =
104  ((pkt_info_->agent_hdr.cmd == AgentHdr::TRAP_TOR_CONTROL_PKT) ?
106  Send(interface, pkt_info_->vrf, command, PktHandler::ICMP);
107 }
#define DEFAULT_IP_TTL
Definition: pkt_handler.h:44
#define DEFAULT_IP_ID
Definition: pkt_handler.h:48
void IncrStatsDrop()
Definition: icmp_proto.h:33
InterfaceTable * interface_table() const
Definition: agent.h:465
uint16_t Csum(uint16_t *, std::size_t, uint32_t) const
Agent * agent() const
Definition: proto_handler.h:80
boost::shared_ptr< PktInfo > pkt_info_
Definition: proto_handler.h:92
IcmpHandler(Agent *agent, boost::shared_ptr< PktInfo > info, boost::asio::io_context &io)
Definition: icmp_handler.cc:14
struct icmp * icmp_
Definition: icmp_handler.h:23
uint16_t tx_vlan_id() const
int EthHdr(const MacAddress &src, const MacAddress &dest, const uint16_t proto)
void IncrStatsGwPing()
Definition: icmp_proto.h:31
Definition: agent.h:358
uint32_t GetInterfaceIndex() const
Definition: proto_handler.h:82
bool CheckPacket()
Definition: icmp_handler.cc:52
void Send(uint32_t itf, uint32_t vrf, uint16_t, PktHandler::PktModuleName)
bool layer3_forwarding() const
void IncrStatsNoL3Fwd()
Definition: icmp_proto.h:35
void SendResponse(VmInterface *vm_intf)
Definition: icmp_handler.cc:64
virtual ~IcmpHandler()
Definition: icmp_handler.cc:20
void IcmpChecksum(char *buff, uint16_t buf_len)
void IncrStatsIntfNotInst()
Definition: icmp_proto.h:34
IcmpProto * GetIcmpProto() const
Definition: agent.h:993
const Interface * FindInterface(size_t index) const
Definition: interface.cc:323
void IncrStatsGwPingErr()
Definition: icmp_proto.h:32
void IpHdr(uint16_t len, in_addr_t src, in_addr_t dest, uint8_t protocol, uint16_t id, uint8_t ttl)
uint16_t icmp_len_
Definition: icmp_handler.h:24