- /* (c) Allow ARP requests from the local port's MAC address. */
- cls_rule_init_catchall(&rule, IBR_FROM_LOCAL_ARP);
- cls_rule_set_dl_type(&rule, htons(ETH_TYPE_ARP));
- cls_rule_set_dl_src(&rule, ib->installed_local_mac);
- cls_rule_set_nw_proto(&rule, ARP_OP_REQUEST);
- cb(ib, &rule);
- }
-
- for (i = 0; i < ib->n_remote_macs; i++) {
- const uint8_t *remote_mac = &ib->remote_macs[i * ETH_ADDR_LEN];
-
- if (i > 0) {
- const uint8_t *prev_mac = &ib->remote_macs[(i - 1) * ETH_ADDR_LEN];
- if (eth_addr_equals(remote_mac, prev_mac)) {
- /* Skip duplicates. */
- continue;
- }
- }
-
- /* (d) Allow ARP replies to the next hop's MAC address. */
- cls_rule_init_catchall(&rule, IBR_TO_NEXT_HOP_ARP);
- cls_rule_set_dl_type(&rule, htons(ETH_TYPE_ARP));
- cls_rule_set_dl_dst(&rule, remote_mac);
- cls_rule_set_nw_proto(&rule, ARP_OP_REPLY);
- cb(ib, &rule);
-
- /* (e) Allow ARP requests from the next hop's MAC address. */
- cls_rule_init_catchall(&rule, IBR_FROM_NEXT_HOP_ARP);
- cls_rule_set_dl_type(&rule, htons(ETH_TYPE_ARP));
- cls_rule_set_dl_src(&rule, remote_mac);
- cls_rule_set_nw_proto(&rule, ARP_OP_REQUEST);
- cb(ib, &rule);
- }
-
- for (i = 0; i < ib->n_remote_addrs; i++) {
- const struct sockaddr_in *a = &ib->remote_addrs[i];
-
- if (!i || a->sin_addr.s_addr != a[-1].sin_addr.s_addr) {
- /* (f) Allow ARP replies containing the remote's IP address as a
- * target. */
- cls_rule_init_catchall(&rule, IBR_TO_REMOTE_ARP);
- cls_rule_set_dl_type(&rule, htons(ETH_TYPE_ARP));
- cls_rule_set_nw_proto(&rule, ARP_OP_REPLY);
- cls_rule_set_nw_dst(&rule, a->sin_addr.s_addr);
- cb(ib, &rule);
-
- /* (g) Allow ARP requests containing the remote's IP address as a
- * source. */
- cls_rule_init_catchall(&rule, IBR_FROM_REMOTE_ARP);
- cls_rule_set_dl_type(&rule, htons(ETH_TYPE_ARP));
- cls_rule_set_nw_proto(&rule, ARP_OP_REQUEST);
- cls_rule_set_nw_src(&rule, a->sin_addr.s_addr);
- cb(ib, &rule);
- }
-
- if (!i
- || a->sin_addr.s_addr != a[-1].sin_addr.s_addr
- || a->sin_port != a[-1].sin_port) {
- /* (h) Allow TCP traffic to the remote's IP and port. */
- cls_rule_init_catchall(&rule, IBR_TO_REMOTE_TCP);
- cls_rule_set_dl_type(&rule, htons(ETH_TYPE_IP));
- cls_rule_set_nw_proto(&rule, IPPROTO_TCP);
- cls_rule_set_nw_dst(&rule, a->sin_addr.s_addr);
- cls_rule_set_tp_dst(&rule, a->sin_port);
- cb(ib, &rule);
-
- /* (i) Allow TCP traffic from the remote's IP and port. */
- cls_rule_init_catchall(&rule, IBR_FROM_REMOTE_TCP);
- cls_rule_set_dl_type(&rule, htons(ETH_TYPE_IP));
- cls_rule_set_nw_proto(&rule, IPPROTO_TCP);
- cls_rule_set_nw_src(&rule, a->sin_addr.s_addr);
- cls_rule_set_tp_src(&rule, a->sin_port);
- cb(ib, &rule);