|
35 | 35 | #include <linux/list.h>
|
36 | 36 | #include <linux/lockdep.h>
|
37 | 37 | #include <linux/netdevice.h>
|
| 38 | +#include <linux/netlink.h> |
38 | 39 | #include <linux/rculist.h>
|
39 | 40 | #include <linux/rcupdate.h>
|
40 | 41 | #include <linux/seq_file.h>
|
|
45 | 46 | #include <linux/string.h>
|
46 | 47 | #include <linux/workqueue.h>
|
47 | 48 | #include <net/arp.h>
|
| 49 | +#include <net/genetlink.h> |
| 50 | +#include <net/netlink.h> |
| 51 | +#include <net/sock.h> |
| 52 | +#include <uapi/linux/batman_adv.h> |
48 | 53 |
|
49 | 54 | #include "hard-interface.h"
|
50 | 55 | #include "hash.h"
|
51 | 56 | #include "log.h"
|
| 57 | +#include "netlink.h" |
52 | 58 | #include "originator.h"
|
53 | 59 | #include "packet.h"
|
| 60 | +#include "soft-interface.h" |
54 | 61 | #include "sysfs.h"
|
55 | 62 | #include "translation-table.h"
|
56 | 63 |
|
@@ -2051,6 +2058,168 @@ int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset)
|
2051 | 2058 | return 0;
|
2052 | 2059 | }
|
2053 | 2060 |
|
| 2061 | +/** |
| 2062 | + * batadv_bla_claim_dump_entry - dump one entry of the claim table |
| 2063 | + * to a netlink socket |
| 2064 | + * @msg: buffer for the message |
| 2065 | + * @portid: netlink port |
| 2066 | + * @seq: Sequence number of netlink message |
| 2067 | + * @primary_if: primary interface |
| 2068 | + * @claim: entry to dump |
| 2069 | + * |
| 2070 | + * Return: 0 or error code. |
| 2071 | + */ |
| 2072 | +static int |
| 2073 | +batadv_bla_claim_dump_entry(struct sk_buff *msg, u32 portid, u32 seq, |
| 2074 | + struct batadv_hard_iface *primary_if, |
| 2075 | + struct batadv_bla_claim *claim) |
| 2076 | +{ |
| 2077 | + u8 *primary_addr = primary_if->net_dev->dev_addr; |
| 2078 | + u16 backbone_crc; |
| 2079 | + bool is_own; |
| 2080 | + void *hdr; |
| 2081 | + int ret = -EINVAL; |
| 2082 | + |
| 2083 | + hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, |
| 2084 | + NLM_F_MULTI, BATADV_CMD_GET_BLA_CLAIM); |
| 2085 | + if (!hdr) { |
| 2086 | + ret = -ENOBUFS; |
| 2087 | + goto out; |
| 2088 | + } |
| 2089 | + |
| 2090 | + is_own = batadv_compare_eth(claim->backbone_gw->orig, |
| 2091 | + primary_addr); |
| 2092 | + |
| 2093 | + spin_lock_bh(&claim->backbone_gw->crc_lock); |
| 2094 | + backbone_crc = claim->backbone_gw->crc; |
| 2095 | + spin_unlock_bh(&claim->backbone_gw->crc_lock); |
| 2096 | + |
| 2097 | + if (is_own) |
| 2098 | + if (nla_put_flag(msg, BATADV_ATTR_BLA_OWN)) { |
| 2099 | + genlmsg_cancel(msg, hdr); |
| 2100 | + goto out; |
| 2101 | + } |
| 2102 | + |
| 2103 | + if (nla_put(msg, BATADV_ATTR_BLA_ADDRESS, ETH_ALEN, claim->addr) || |
| 2104 | + nla_put_u16(msg, BATADV_ATTR_BLA_VID, claim->vid) || |
| 2105 | + nla_put(msg, BATADV_ATTR_BLA_BACKBONE, ETH_ALEN, |
| 2106 | + claim->backbone_gw->orig) || |
| 2107 | + nla_put_u16(msg, BATADV_ATTR_BLA_CRC, |
| 2108 | + backbone_crc)) { |
| 2109 | + genlmsg_cancel(msg, hdr); |
| 2110 | + goto out; |
| 2111 | + } |
| 2112 | + |
| 2113 | + genlmsg_end(msg, hdr); |
| 2114 | + ret = 0; |
| 2115 | + |
| 2116 | +out: |
| 2117 | + return ret; |
| 2118 | +} |
| 2119 | + |
| 2120 | +/** |
| 2121 | + * batadv_bla_claim_dump_bucket - dump one bucket of the claim table |
| 2122 | + * to a netlink socket |
| 2123 | + * @msg: buffer for the message |
| 2124 | + * @portid: netlink port |
| 2125 | + * @seq: Sequence number of netlink message |
| 2126 | + * @primary_if: primary interface |
| 2127 | + * @head: bucket to dump |
| 2128 | + * @idx_skip: How many entries to skip |
| 2129 | + * |
| 2130 | + * Return: always 0. |
| 2131 | + */ |
| 2132 | +static int |
| 2133 | +batadv_bla_claim_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq, |
| 2134 | + struct batadv_hard_iface *primary_if, |
| 2135 | + struct hlist_head *head, int *idx_skip) |
| 2136 | +{ |
| 2137 | + struct batadv_bla_claim *claim; |
| 2138 | + int idx = 0; |
| 2139 | + |
| 2140 | + rcu_read_lock(); |
| 2141 | + hlist_for_each_entry_rcu(claim, head, hash_entry) { |
| 2142 | + if (idx++ < *idx_skip) |
| 2143 | + continue; |
| 2144 | + if (batadv_bla_claim_dump_entry(msg, portid, seq, |
| 2145 | + primary_if, claim)) { |
| 2146 | + *idx_skip = idx - 1; |
| 2147 | + goto unlock; |
| 2148 | + } |
| 2149 | + } |
| 2150 | + |
| 2151 | + *idx_skip = idx; |
| 2152 | +unlock: |
| 2153 | + rcu_read_unlock(); |
| 2154 | + return 0; |
| 2155 | +} |
| 2156 | + |
| 2157 | +/** |
| 2158 | + * batadv_bla_claim_dump - dump claim table to a netlink socket |
| 2159 | + * @msg: buffer for the message |
| 2160 | + * @cb: callback structure containing arguments |
| 2161 | + * |
| 2162 | + * Return: message length. |
| 2163 | + */ |
| 2164 | +int batadv_bla_claim_dump(struct sk_buff *msg, struct netlink_callback *cb) |
| 2165 | +{ |
| 2166 | + struct batadv_hard_iface *primary_if = NULL; |
| 2167 | + int portid = NETLINK_CB(cb->skb).portid; |
| 2168 | + struct net *net = sock_net(cb->skb->sk); |
| 2169 | + struct net_device *soft_iface; |
| 2170 | + struct batadv_hashtable *hash; |
| 2171 | + struct batadv_priv *bat_priv; |
| 2172 | + int bucket = cb->args[0]; |
| 2173 | + struct hlist_head *head; |
| 2174 | + int idx = cb->args[1]; |
| 2175 | + int ifindex; |
| 2176 | + int ret = 0; |
| 2177 | + |
| 2178 | + ifindex = batadv_netlink_get_ifindex(cb->nlh, |
| 2179 | + BATADV_ATTR_MESH_IFINDEX); |
| 2180 | + if (!ifindex) |
| 2181 | + return -EINVAL; |
| 2182 | + |
| 2183 | + soft_iface = dev_get_by_index(net, ifindex); |
| 2184 | + if (!soft_iface || !batadv_softif_is_valid(soft_iface)) { |
| 2185 | + ret = -ENODEV; |
| 2186 | + goto out; |
| 2187 | + } |
| 2188 | + |
| 2189 | + bat_priv = netdev_priv(soft_iface); |
| 2190 | + hash = bat_priv->bla.claim_hash; |
| 2191 | + |
| 2192 | + primary_if = batadv_primary_if_get_selected(bat_priv); |
| 2193 | + if (!primary_if || primary_if->if_status != BATADV_IF_ACTIVE) { |
| 2194 | + ret = -ENOENT; |
| 2195 | + goto out; |
| 2196 | + } |
| 2197 | + |
| 2198 | + while (bucket < hash->size) { |
| 2199 | + head = &hash->table[bucket]; |
| 2200 | + |
| 2201 | + if (batadv_bla_claim_dump_bucket(msg, portid, |
| 2202 | + cb->nlh->nlmsg_seq, |
| 2203 | + primary_if, head, &idx)) |
| 2204 | + break; |
| 2205 | + bucket++; |
| 2206 | + } |
| 2207 | + |
| 2208 | + cb->args[0] = bucket; |
| 2209 | + cb->args[1] = idx; |
| 2210 | + |
| 2211 | + ret = msg->len; |
| 2212 | + |
| 2213 | +out: |
| 2214 | + if (primary_if) |
| 2215 | + batadv_hardif_put(primary_if); |
| 2216 | + |
| 2217 | + if (soft_iface) |
| 2218 | + dev_put(soft_iface); |
| 2219 | + |
| 2220 | + return ret; |
| 2221 | +} |
| 2222 | + |
2054 | 2223 | /**
|
2055 | 2224 | * batadv_bla_backbone_table_seq_print_text - print the backbone table in a seq
|
2056 | 2225 | * file
|
|
0 commit comments