+ /* (d) Allow ARP replies to the next hop's MAC address. */
+ match_init_catchall(&match);
+ match_set_dl_type(&match, htons(ETH_TYPE_ARP));
+ match_set_dl_dst(&match, remote_mac);
+ match_set_nw_proto(&match, ARP_OP_REPLY);
+ add_rule(ib, &match, IBR_TO_NEXT_HOP_ARP);
+
+ /* (e) Allow ARP requests from the next hop's MAC address. */
+ match_init_catchall(&match);
+ match_set_dl_type(&match, htons(ETH_TYPE_ARP));
+ match_set_dl_src(&match, remote_mac);
+ match_set_nw_proto(&match, ARP_OP_REQUEST);
+ add_rule(ib, &match, IBR_FROM_NEXT_HOP_ARP);
+ }
+
+ for (r = ib->remotes; r < &ib->remotes[ib->n_remotes]; r++) {
+ const struct sockaddr_in *a = &r->remote_addr;
+
+ /* (f) Allow ARP replies containing the remote's IP address as a
+ * target. */
+ match_init_catchall(&match);
+ match_set_dl_type(&match, htons(ETH_TYPE_ARP));
+ match_set_nw_proto(&match, ARP_OP_REPLY);
+ match_set_nw_dst(&match, a->sin_addr.s_addr);
+ add_rule(ib, &match, IBR_TO_REMOTE_ARP);
+
+ /* (g) Allow ARP requests containing the remote's IP address as a
+ * source. */
+ match_init_catchall(&match);
+ match_set_dl_type(&match, htons(ETH_TYPE_ARP));
+ match_set_nw_proto(&match, ARP_OP_REQUEST);
+ match_set_nw_src(&match, a->sin_addr.s_addr);
+ add_rule(ib, &match, IBR_FROM_REMOTE_ARP);
+
+ /* (h) Allow TCP traffic to the remote's IP and port. */
+ match_init_catchall(&match);
+ match_set_dl_type(&match, htons(ETH_TYPE_IP));
+ match_set_nw_proto(&match, IPPROTO_TCP);
+ match_set_nw_dst(&match, a->sin_addr.s_addr);
+ match_set_tp_dst(&match, a->sin_port);
+ add_rule(ib, &match, IBR_TO_REMOTE_TCP);
+
+ /* (i) Allow TCP traffic from the remote's IP and port. */
+ match_init_catchall(&match);
+ match_set_dl_type(&match, htons(ETH_TYPE_IP));
+ match_set_nw_proto(&match, IPPROTO_TCP);
+ match_set_nw_src(&match, a->sin_addr.s_addr);
+ match_set_tp_src(&match, a->sin_port);
+ add_rule(ib, &match, IBR_FROM_REMOTE_TCP);