-
Notifications
You must be signed in to change notification settings - Fork 158
Expand file tree
/
Copy patharp_responder.cc
More file actions
111 lines (95 loc) · 4.1 KB
/
arp_responder.cc
File metadata and controls
111 lines (95 loc) · 4.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
// Copyright (c) 2017, Cloudigo.
// Copyright (c) 2017, Nefeli Networks, Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * Neither the names of the copyright holders nor the names of their
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#include "arp_responder.h"
#include "../utils/arp.h"
using bess::utils::Arp;
using bess::utils::be16_t;
const Commands ArpResponder::cmds = {
{"add", bess::pb::ArpResponderArg::descriptor(),
MODULE_CMD_FUNC(&ArpResponder::CommandAdd), Command::THREAD_UNSAFE}};
CommandResponse ArpResponder::CommandAdd(const bess::pb::ArpResponderArg &arg) {
be32_t ip_addr;
arp_entry entry;
if (!arg.ip().length()) {
return CommandFailure(EINVAL, "IP address is missing");
}
if (!bess::utils::ParseIpv4Address(arg.ip(), &ip_addr)) {
return CommandFailure(EINVAL, "Invalid IP Address: %s", arg.ip().c_str());
}
if (!entry.mac_addr.FromString(arg.mac_addr())) {
return CommandFailure(EINVAL, "Invalid MAC Address: %s",
arg.mac_addr().c_str());
}
entry.ip_addr = ip_addr;
entries_[ip_addr] = entry;
return CommandSuccess();
}
void ArpResponder::ProcessBatch(Context *ctx, bess::PacketBatch *batch) {
int cnt = batch->cnt();
for (int i = 0; i < cnt; i++) {
// we should drop-or-emit each packet
bess::Packet *pkt = batch->pkts()[i];
Ethernet *eth = pkt->head_data<Ethernet *>();
if (eth->ether_type != be16_t(Ethernet::Type::kArp)) {
// Currently drop all non ARP packets
DropPacket(ctx, pkt);
continue;
}
Arp *arp = reinterpret_cast<Arp *>(eth + 1);
if (arp->opcode == be16_t(Arp::Opcode::kRequest)) {
// TODO(galsagie) When learn is added, learn SRC MAC here
// Try to find target IP in cache, if exists convert request to reply
auto it = entries_.find(arp->target_ip_addr);
if (it != entries_.end()) {
const struct arp_entry &entry = it->second;
arp->opcode = be16_t(Arp::Opcode::kReply);
eth->dst_addr = eth->src_addr;
eth->src_addr = entry.mac_addr;
arp->target_hw_addr = arp->sender_hw_addr;
arp->sender_hw_addr = entry.mac_addr;
arp->target_ip_addr = arp->sender_ip_addr;
arp->sender_ip_addr = entry.ip_addr;
EmitPacket(ctx, pkt, 0);
} else {
// Did not find an ARP entry in cache, drop packet
// TODO(galsagie) Optinally emit packet to next module here
DropPacket(ctx, pkt);
}
} else if (arp->opcode == be16_t(Arp::Opcode::kReply)) {
// TODO(galsagie) When learn is added, learn SRC MAC here
DropPacket(ctx, pkt);
} else {
// TODO(galsagie) Other opcodes are not handled yet.
DropPacket(ctx, pkt);
}
}
}
ADD_MODULE(ArpResponder, "arp_responder",
"Respond to ARP requests and learns new MAC's")