Coverage Report

Created: 2026-06-15 06:19

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/hostap/src/ap/x_snoop.c
Line
Count
Source
1
/*
2
 * Generic Snooping for Proxy ARP
3
 * Copyright (c) 2014, Qualcomm Atheros, Inc.
4
 *
5
 * This software may be distributed under the terms of the BSD license.
6
 * See README for more details.
7
 */
8
9
#include "utils/includes.h"
10
11
#include "utils/common.h"
12
#include "hostapd.h"
13
#include "sta_info.h"
14
#include "ap_drv_ops.h"
15
#include "x_snoop.h"
16
17
18
int x_snoop_init(struct hostapd_data *hapd)
19
0
{
20
0
  struct hostapd_bss_config *conf = hapd->conf;
21
22
0
  if (!conf->isolate) {
23
0
    wpa_printf(MSG_DEBUG,
24
0
         "x_snoop: ap_isolate must be enabled for x_snoop");
25
0
    return -1;
26
0
  }
27
28
0
  if (conf->bridge[0] == '\0') {
29
0
    wpa_printf(MSG_DEBUG,
30
0
         "x_snoop: Bridge must be configured for x_snoop");
31
0
    return -1;
32
0
  }
33
34
0
  hapd->x_snoop_initialized = true;
35
36
0
  if (hostapd_drv_br_port_set_attr(hapd, DRV_BR_PORT_ATTR_HAIRPIN_MODE,
37
0
           1)) {
38
0
    wpa_printf(MSG_DEBUG,
39
0
         "x_snoop: Failed to enable hairpin_mode on the bridge port");
40
0
    return -1;
41
0
  }
42
43
0
  if (hostapd_drv_br_port_set_attr(hapd, DRV_BR_PORT_ATTR_PROXYARP, 1)) {
44
0
    wpa_printf(MSG_DEBUG,
45
0
         "x_snoop: Failed to enable proxyarp on the bridge port");
46
0
    return -1;
47
0
  }
48
49
0
  if (hostapd_drv_br_set_net_param(hapd, DRV_BR_NET_PARAM_GARP_ACCEPT,
50
0
           1)) {
51
0
    wpa_printf(MSG_DEBUG,
52
0
         "x_snoop: Failed to enable accepting gratuitous ARP on the bridge");
53
0
    return -1;
54
0
  }
55
56
0
#ifdef CONFIG_IPV6
57
0
  if (hostapd_drv_br_set_net_param(hapd, DRV_BR_MULTICAST_SNOOPING, 1)) {
58
0
    wpa_printf(MSG_DEBUG,
59
0
         "x_snoop: Failed to enable multicast snooping on the bridge");
60
0
    return -1;
61
0
  }
62
0
#endif /* CONFIG_IPV6 */
63
64
0
  return 0;
65
0
}
66
67
68
struct l2_packet_data *
69
x_snoop_get_l2_packet(struct hostapd_data *hapd,
70
          void (*handler)(void *ctx, const u8 *src_addr,
71
              const u8 *buf, size_t len),
72
          enum l2_packet_filter_type type)
73
0
{
74
0
  struct hostapd_bss_config *conf = hapd->conf;
75
0
  struct l2_packet_data *l2;
76
77
0
  l2 = l2_packet_init(conf->bridge, NULL, ETH_P_ALL, handler, hapd, 1);
78
0
  if (l2 == NULL) {
79
0
    wpa_printf(MSG_DEBUG,
80
0
         "x_snoop: Failed to initialize L2 packet processing %s",
81
0
         strerror(errno));
82
0
    return NULL;
83
0
  }
84
85
0
  if (l2_packet_set_packet_filter(l2, type)) {
86
0
    wpa_printf(MSG_DEBUG,
87
0
         "x_snoop: Failed to set L2 packet filter for type: %d",
88
0
         type);
89
0
    l2_packet_deinit(l2);
90
0
    return NULL;
91
0
  }
92
93
0
  return l2;
94
0
}
95
96
97
void x_snoop_mcast_to_ucast_convert_send(struct hostapd_data *hapd,
98
           struct sta_info *sta, u8 *buf,
99
           size_t len)
100
0
{
101
0
  int res;
102
0
  u8 addr[ETH_ALEN];
103
0
  u8 *dst_addr = buf;
104
105
0
  if (!(dst_addr[0] & 0x01))
106
0
    return;
107
108
0
  wpa_printf(MSG_EXCESSIVE, "x_snoop: Multicast-to-unicast conversion "
109
0
       MACSTR " -> " MACSTR " (len %u)",
110
0
       MAC2STR(dst_addr), MAC2STR(sta->addr), (unsigned int) len);
111
112
  /* save the multicast destination address for restoring it later */
113
0
  os_memcpy(addr, buf, ETH_ALEN);
114
115
0
  os_memcpy(buf, sta->addr, ETH_ALEN);
116
0
  res = l2_packet_send(hapd->sock_dhcp, NULL, 0, buf, len);
117
0
  if (res < 0) {
118
0
    wpa_printf(MSG_DEBUG,
119
0
         "x_snoop: Failed to send mcast to ucast converted packet to "
120
0
         MACSTR, MAC2STR(sta->addr));
121
0
  }
122
123
  /* restore the multicast destination address */
124
0
  os_memcpy(buf, addr, ETH_ALEN);
125
0
}
126
127
128
void x_snoop_deinit(struct hostapd_data *hapd)
129
0
{
130
0
  if (!hapd->x_snoop_initialized)
131
0
    return;
132
0
  hostapd_drv_br_set_net_param(hapd, DRV_BR_NET_PARAM_GARP_ACCEPT, 0);
133
0
  hostapd_drv_br_port_set_attr(hapd, DRV_BR_PORT_ATTR_PROXYARP, 0);
134
0
  hostapd_drv_br_port_set_attr(hapd, DRV_BR_PORT_ATTR_HAIRPIN_MODE, 0);
135
  hapd->x_snoop_initialized = false;
136
0
}