1515// See the License for the specific language governing permissions and
1616// limitations under the License.
1717
18- // #define DEBUG // Allow debugging
19- // #define DEBUG2 // Allow debug lvl 2
18+ #define DEBUG // Allow debugging
19+ #define DEBUG2 // Allow debug lvl 2
2020
2121#include < net/ip4/ip4.hpp>
2222#include < net/ip4/packet_ip4.hpp>
@@ -32,33 +32,90 @@ namespace net {
3232 packets_rx_ {Statman::get ().create (Stat::UINT64, inet.ifname () + " .ip4.packets_rx" ).get_uint64 ()},
3333 packets_tx_ {Statman::get ().create (Stat::UINT64, inet.ifname () + " .ip4.packets_tx" ).get_uint64 ()},
3434 packets_dropped_ {Statman::get ().create (Stat::UINT32, inet.ifname () + " .ip4.packets_dropped" ).get_uint32 ()},
35- stack_ {inet}
35+ stack_ {inet},
36+ upstream_filter_ {this , &IP4::filter_upstream},
37+ downstream_filter_{this , &IP4::filter_downstream}
3638 { }
3739
40+
41+ IP4::IP_packet_ptr IP4::drop (IP_packet_ptr ptr, Direction direction, Drop_reason reason) {
42+ packets_dropped_++;
43+
44+ if (drop_handler_)
45+ drop_handler_ (std::move (ptr), direction, reason);
46+
47+ return nullptr ;
48+ }
49+
50+
51+ IP4::IP_packet_ptr IP4::filter_upstream (IP4::IP_packet_ptr packet)
52+ {
53+
54+ IP4::Direction up = IP4::Direction::Upstream;
55+
56+ // RFC-1122 3.2.1.1, Silently discard Version != 4
57+ if (UNLIKELY (not packet->is_ipv4 ()))
58+ return drop (std::move (packet), up, Drop_reason::Wrong_version);
59+
60+ // RFC-1122 3.2.1.2, Verify IP checksum, silently discard bad dgram
61+ if (UNLIKELY (packet->compute_checksum () != 0 ))
62+ return drop (std::move (packet), up, Drop_reason::Wrong_checksum);
63+
64+ // RFC-1122 3.2.1.3, Silently discard datagram with bad src addr
65+ if (UNLIKELY (packet->ip_src ().is_illegal_src ()))
66+ return drop (std::move (packet), up, Drop_reason::Bad_source);
67+
68+
69+ return packet;
70+
71+ };
72+
73+
74+ IP4::IP_packet_ptr IP4::filter_downstream (IP4::IP_packet_ptr packet)
75+ {
76+
77+ // RFC-1122 3.2.1.7, MUST NOT send packet with TTL of 0
78+ if (packet->ip_ttl () == 0 )
79+ return drop (std::move (packet), Direction::Downstream, Drop_reason::TTL0);
80+
81+ // RFC-1122 3.2.1.7, MUST NOT send packet addressed to 127.*
82+ if (packet->ip_dst ().part (0 ) == 127 )
83+ drop (std::move (packet), Direction::Downstream, Drop_reason::Bad_destination);
84+
85+ return packet;
86+ }
87+
88+
3889 void IP4::receive (Packet_ptr pckt)
3990 {
4091 // Cast to IP4 Packet
4192 auto packet = static_unique_ptr_cast<net::PacketIP4>(std::move (pckt));
4293
43- // Stat increment packets received
44- packets_rx_++;
45-
46- debug2 (" \t Source IP: %s Dest.IP: %s Type: 0x%x\n " ,
94+ debug (" <IP4> received packet \n " );
95+ debug2 (" \t * Source IP: %s Dest.IP: %s Type: 0x%x\n " ,
4796 packet->ip_src ().str ().c_str (),
4897 packet->ip_dst ().str ().c_str (),
4998 packet->ip_protocol ());
5099
51- // Drop if my ip address doesn't match destination ip address or broadcast
100+
101+ // Stat increment packets received
102+ packets_rx_++;
103+
104+ packet = upstream_filter_ (std::move (packet));
105+ if (UNLIKELY (packet == nullptr )) return ;
106+
107+ // Drop / forward if my ip address doesn't match dest. or broadcast
52108 if (UNLIKELY (packet->ip_dst () != local_ip ()
53- and (packet->ip_dst () | stack_.netmask ()) != ADDR_BCAST
54- and local_ip () != ADDR_ANY)) {
109+ and (packet->ip_dst () | stack_.netmask ()) != ADDR_BCAST
110+ and local_ip () != ADDR_ANY
111+ and not stack_.is_loopback (packet->ip_dst ()))) {
55112
56113 if (forward_packet_) {
57114 forward_packet_ (stack_, std::move (packet));
58115 debug (" Packet forwarded \n " );
59116 } else {
60117 debug (" Packet dropped \n " );
61- packets_dropped_++ ;
118+ drop ( std::move (packet), Direction::Upstream, Drop_reason::Bad_destination) ;
62119 }
63120
64121 return ;
@@ -79,6 +136,7 @@ namespace net {
79136 break ;
80137 default :
81138 debug (" \t Type: UNKNOWN %hhu\n " , packet->ip_protocol ());
139+ drop (std::move (packet), Direction::Upstream, Drop_reason::Unknown_proto);
82140 break ;
83141 }
84142 }
@@ -97,8 +155,15 @@ namespace net {
97155 {
98156 auto ip4_pckt = static_unique_ptr_cast<PacketIP4>(std::move (pckt));
99157
158+ // Send loopback packets right back
159+ if (UNLIKELY (stack_.is_loopback (ip4_pckt->ip_dst ()))) {
160+ debug (" <IP4> Destination address is loopback \n " );
161+ IP4::receive (std::move (ip4_pckt));
162+ return ;
163+ }
164+
100165 addr next_hop;
101- // Keep IP when broadcasting to all
166+
102167 if (ip4_pckt->ip_dst () != IP4::ADDR_BCAST)
103168 {
104169 // Create local and target subnets
@@ -114,11 +179,15 @@ namespace net {
114179 stack_.ip_addr ().str ().c_str (),
115180 stack_.gateway ().str ().c_str (),
116181 next_hop.str ().c_str ());
117- }
118- else {
182+
183+ } else {
119184 next_hop = IP4::ADDR_BCAST;
120185 }
121186
187+ // Filter illegal egress packets
188+ ip4_pckt = upstream_filter_ (std::move (ip4_pckt));
189+ if (ip4_pckt == nullptr ) return ;
190+
122191 // Stat increment packets transmitted
123192 packets_tx_++;
124193
0 commit comments