1*4dc78e53SAndroid Build Coastguard Worker /* SPDX-License-Identifier: LGPL-2.1-only */
2*4dc78e53SAndroid Build Coastguard Worker /*
3*4dc78e53SAndroid Build Coastguard Worker * lib/route/mdb.c Multicast Database
4*4dc78e53SAndroid Build Coastguard Worker */
5*4dc78e53SAndroid Build Coastguard Worker
6*4dc78e53SAndroid Build Coastguard Worker #include "nl-default.h"
7*4dc78e53SAndroid Build Coastguard Worker
8*4dc78e53SAndroid Build Coastguard Worker #include <linux/if_bridge.h>
9*4dc78e53SAndroid Build Coastguard Worker
10*4dc78e53SAndroid Build Coastguard Worker #include <netlink/netlink.h>
11*4dc78e53SAndroid Build Coastguard Worker #include <netlink/route/mdb.h>
12*4dc78e53SAndroid Build Coastguard Worker #include <netlink/route/nexthop.h>
13*4dc78e53SAndroid Build Coastguard Worker #include <netlink/utils.h>
14*4dc78e53SAndroid Build Coastguard Worker #include <netlink/route/rtnl.h>
15*4dc78e53SAndroid Build Coastguard Worker
16*4dc78e53SAndroid Build Coastguard Worker #include "nl-route.h"
17*4dc78e53SAndroid Build Coastguard Worker #include "nl-aux-route/nl-route.h"
18*4dc78e53SAndroid Build Coastguard Worker #include "nl-priv-dynamic-core/object-api.h"
19*4dc78e53SAndroid Build Coastguard Worker #include "nl-priv-dynamic-core/cache-api.h"
20*4dc78e53SAndroid Build Coastguard Worker
21*4dc78e53SAndroid Build Coastguard Worker /** @cond SKIP */
22*4dc78e53SAndroid Build Coastguard Worker #define MDB_ATTR_IFINDEX 0x000001
23*4dc78e53SAndroid Build Coastguard Worker #define MDB_ATTR_ENTRIES 0x000002
24*4dc78e53SAndroid Build Coastguard Worker
25*4dc78e53SAndroid Build Coastguard Worker struct rtnl_mdb {
26*4dc78e53SAndroid Build Coastguard Worker NLHDR_COMMON
27*4dc78e53SAndroid Build Coastguard Worker uint32_t ifindex;
28*4dc78e53SAndroid Build Coastguard Worker
29*4dc78e53SAndroid Build Coastguard Worker struct nl_list_head mdb_entry_list;
30*4dc78e53SAndroid Build Coastguard Worker };
31*4dc78e53SAndroid Build Coastguard Worker
32*4dc78e53SAndroid Build Coastguard Worker struct rtnl_mdb_entry {
33*4dc78e53SAndroid Build Coastguard Worker struct nl_list_head mdb_list;
34*4dc78e53SAndroid Build Coastguard Worker struct nl_addr *addr;
35*4dc78e53SAndroid Build Coastguard Worker uint32_t ifindex;
36*4dc78e53SAndroid Build Coastguard Worker uint16_t vid;
37*4dc78e53SAndroid Build Coastguard Worker uint16_t proto;
38*4dc78e53SAndroid Build Coastguard Worker uint8_t state;
39*4dc78e53SAndroid Build Coastguard Worker };
40*4dc78e53SAndroid Build Coastguard Worker
41*4dc78e53SAndroid Build Coastguard Worker static struct rtnl_mdb_entry *rtnl_mdb_entry_alloc(void);
42*4dc78e53SAndroid Build Coastguard Worker static void rtnl_mdb_entry_free(struct rtnl_mdb_entry *mdb_entry);
43*4dc78e53SAndroid Build Coastguard Worker
44*4dc78e53SAndroid Build Coastguard Worker static struct nl_cache_ops rtnl_mdb_ops;
45*4dc78e53SAndroid Build Coastguard Worker static struct nl_object_ops mdb_obj_ops;
46*4dc78e53SAndroid Build Coastguard Worker /** @endcond */
47*4dc78e53SAndroid Build Coastguard Worker
mdb_constructor(struct nl_object * obj)48*4dc78e53SAndroid Build Coastguard Worker static void mdb_constructor(struct nl_object *obj)
49*4dc78e53SAndroid Build Coastguard Worker {
50*4dc78e53SAndroid Build Coastguard Worker struct rtnl_mdb *_mdb = (struct rtnl_mdb *) obj;
51*4dc78e53SAndroid Build Coastguard Worker
52*4dc78e53SAndroid Build Coastguard Worker nl_init_list_head(&_mdb->mdb_entry_list);
53*4dc78e53SAndroid Build Coastguard Worker }
54*4dc78e53SAndroid Build Coastguard Worker
mdb_free_data(struct nl_object * obj)55*4dc78e53SAndroid Build Coastguard Worker static void mdb_free_data(struct nl_object *obj)
56*4dc78e53SAndroid Build Coastguard Worker {
57*4dc78e53SAndroid Build Coastguard Worker struct rtnl_mdb *mdb = (struct rtnl_mdb *)obj;
58*4dc78e53SAndroid Build Coastguard Worker struct rtnl_mdb_entry *mdb_entry;
59*4dc78e53SAndroid Build Coastguard Worker struct rtnl_mdb_entry *mdb_entry_safe;
60*4dc78e53SAndroid Build Coastguard Worker
61*4dc78e53SAndroid Build Coastguard Worker nl_list_for_each_entry_safe(mdb_entry, mdb_entry_safe,
62*4dc78e53SAndroid Build Coastguard Worker &mdb->mdb_entry_list, mdb_list)
63*4dc78e53SAndroid Build Coastguard Worker rtnl_mdb_entry_free(mdb_entry);
64*4dc78e53SAndroid Build Coastguard Worker }
65*4dc78e53SAndroid Build Coastguard Worker
mdb_entry_equal(struct rtnl_mdb_entry * a,struct rtnl_mdb_entry * b)66*4dc78e53SAndroid Build Coastguard Worker static int mdb_entry_equal(struct rtnl_mdb_entry *a, struct rtnl_mdb_entry *b)
67*4dc78e53SAndroid Build Coastguard Worker {
68*4dc78e53SAndroid Build Coastguard Worker return a->ifindex == b->ifindex
69*4dc78e53SAndroid Build Coastguard Worker && a->vid == b->vid
70*4dc78e53SAndroid Build Coastguard Worker && a->proto == b->proto
71*4dc78e53SAndroid Build Coastguard Worker && a->state == b->state
72*4dc78e53SAndroid Build Coastguard Worker && nl_addr_cmp(a->addr, b->addr) == 0;
73*4dc78e53SAndroid Build Coastguard Worker }
74*4dc78e53SAndroid Build Coastguard Worker
mdb_compare(struct nl_object * _a,struct nl_object * _b,uint64_t attrs,int flags)75*4dc78e53SAndroid Build Coastguard Worker static uint64_t mdb_compare(struct nl_object *_a, struct nl_object *_b,
76*4dc78e53SAndroid Build Coastguard Worker uint64_t attrs, int flags)
77*4dc78e53SAndroid Build Coastguard Worker {
78*4dc78e53SAndroid Build Coastguard Worker struct rtnl_mdb *a = (struct rtnl_mdb *) _a;
79*4dc78e53SAndroid Build Coastguard Worker struct rtnl_mdb *b = (struct rtnl_mdb *) _b;
80*4dc78e53SAndroid Build Coastguard Worker struct rtnl_mdb_entry *a_entry, *b_entry;
81*4dc78e53SAndroid Build Coastguard Worker uint64_t diff = 0;
82*4dc78e53SAndroid Build Coastguard Worker
83*4dc78e53SAndroid Build Coastguard Worker #define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
84*4dc78e53SAndroid Build Coastguard Worker diff |= _DIFF(MDB_ATTR_IFINDEX, a->ifindex != b->ifindex);
85*4dc78e53SAndroid Build Coastguard Worker #undef _DIFF
86*4dc78e53SAndroid Build Coastguard Worker
87*4dc78e53SAndroid Build Coastguard Worker a_entry = nl_list_entry(a->mdb_entry_list.next, struct rtnl_mdb_entry, mdb_list);
88*4dc78e53SAndroid Build Coastguard Worker b_entry = nl_list_entry(b->mdb_entry_list.next, struct rtnl_mdb_entry, mdb_list);
89*4dc78e53SAndroid Build Coastguard Worker while (1) {
90*4dc78e53SAndroid Build Coastguard Worker if ( &a_entry->mdb_list == &a->mdb_entry_list
91*4dc78e53SAndroid Build Coastguard Worker || &b_entry->mdb_list == &b->mdb_entry_list) {
92*4dc78e53SAndroid Build Coastguard Worker if ( &a_entry->mdb_list != &a->mdb_entry_list
93*4dc78e53SAndroid Build Coastguard Worker || &b_entry->mdb_list != &b->mdb_entry_list)
94*4dc78e53SAndroid Build Coastguard Worker diff |= MDB_ATTR_ENTRIES;
95*4dc78e53SAndroid Build Coastguard Worker break;
96*4dc78e53SAndroid Build Coastguard Worker }
97*4dc78e53SAndroid Build Coastguard Worker if (!mdb_entry_equal(a_entry, b_entry)) {
98*4dc78e53SAndroid Build Coastguard Worker diff |= MDB_ATTR_ENTRIES;
99*4dc78e53SAndroid Build Coastguard Worker break;
100*4dc78e53SAndroid Build Coastguard Worker }
101*4dc78e53SAndroid Build Coastguard Worker a_entry = nl_list_entry(a_entry->mdb_list.next, struct rtnl_mdb_entry, mdb_list);
102*4dc78e53SAndroid Build Coastguard Worker b_entry = nl_list_entry(b_entry->mdb_list.next, struct rtnl_mdb_entry, mdb_list);
103*4dc78e53SAndroid Build Coastguard Worker }
104*4dc78e53SAndroid Build Coastguard Worker
105*4dc78e53SAndroid Build Coastguard Worker return diff;
106*4dc78e53SAndroid Build Coastguard Worker }
107*4dc78e53SAndroid Build Coastguard Worker
mdb_entry_clone(struct rtnl_mdb_entry * src)108*4dc78e53SAndroid Build Coastguard Worker static struct rtnl_mdb_entry *mdb_entry_clone(struct rtnl_mdb_entry *src)
109*4dc78e53SAndroid Build Coastguard Worker {
110*4dc78e53SAndroid Build Coastguard Worker struct rtnl_mdb_entry *dst = rtnl_mdb_entry_alloc();
111*4dc78e53SAndroid Build Coastguard Worker if (!dst)
112*4dc78e53SAndroid Build Coastguard Worker return NULL;
113*4dc78e53SAndroid Build Coastguard Worker
114*4dc78e53SAndroid Build Coastguard Worker dst->ifindex = src->ifindex;
115*4dc78e53SAndroid Build Coastguard Worker dst->state = src->state;
116*4dc78e53SAndroid Build Coastguard Worker dst->vid = src->vid;
117*4dc78e53SAndroid Build Coastguard Worker dst->proto = src->proto;
118*4dc78e53SAndroid Build Coastguard Worker
119*4dc78e53SAndroid Build Coastguard Worker dst->addr = nl_addr_clone(src->addr);
120*4dc78e53SAndroid Build Coastguard Worker if (dst->addr == NULL) {
121*4dc78e53SAndroid Build Coastguard Worker free(dst);
122*4dc78e53SAndroid Build Coastguard Worker return NULL;
123*4dc78e53SAndroid Build Coastguard Worker }
124*4dc78e53SAndroid Build Coastguard Worker
125*4dc78e53SAndroid Build Coastguard Worker return dst;
126*4dc78e53SAndroid Build Coastguard Worker }
127*4dc78e53SAndroid Build Coastguard Worker
mdb_clone(struct nl_object * _dst,struct nl_object * _src)128*4dc78e53SAndroid Build Coastguard Worker static int mdb_clone(struct nl_object *_dst, struct nl_object *_src)
129*4dc78e53SAndroid Build Coastguard Worker {
130*4dc78e53SAndroid Build Coastguard Worker struct rtnl_mdb *dst = nl_object_priv(_dst);
131*4dc78e53SAndroid Build Coastguard Worker struct rtnl_mdb *src = nl_object_priv(_src);
132*4dc78e53SAndroid Build Coastguard Worker struct rtnl_mdb_entry *entry;
133*4dc78e53SAndroid Build Coastguard Worker
134*4dc78e53SAndroid Build Coastguard Worker nl_init_list_head(&dst->mdb_entry_list);
135*4dc78e53SAndroid Build Coastguard Worker
136*4dc78e53SAndroid Build Coastguard Worker nl_list_for_each_entry(entry, &src->mdb_entry_list, mdb_list) {
137*4dc78e53SAndroid Build Coastguard Worker struct rtnl_mdb_entry *copy = mdb_entry_clone(entry);
138*4dc78e53SAndroid Build Coastguard Worker
139*4dc78e53SAndroid Build Coastguard Worker if (!copy)
140*4dc78e53SAndroid Build Coastguard Worker return -NLE_NOMEM;
141*4dc78e53SAndroid Build Coastguard Worker
142*4dc78e53SAndroid Build Coastguard Worker rtnl_mdb_add_entry(dst, copy);
143*4dc78e53SAndroid Build Coastguard Worker }
144*4dc78e53SAndroid Build Coastguard Worker
145*4dc78e53SAndroid Build Coastguard Worker return 0;
146*4dc78e53SAndroid Build Coastguard Worker }
147*4dc78e53SAndroid Build Coastguard Worker
mdb_update(struct nl_object * old_obj,struct nl_object * new_obj)148*4dc78e53SAndroid Build Coastguard Worker static int mdb_update(struct nl_object *old_obj, struct nl_object *new_obj)
149*4dc78e53SAndroid Build Coastguard Worker {
150*4dc78e53SAndroid Build Coastguard Worker struct rtnl_mdb *old = (struct rtnl_mdb *) old_obj;
151*4dc78e53SAndroid Build Coastguard Worker struct rtnl_mdb *new = (struct rtnl_mdb *) new_obj;
152*4dc78e53SAndroid Build Coastguard Worker struct rtnl_mdb_entry *entry, *old_entry;
153*4dc78e53SAndroid Build Coastguard Worker int action = new_obj->ce_msgtype;
154*4dc78e53SAndroid Build Coastguard Worker
155*4dc78e53SAndroid Build Coastguard Worker if (new->ifindex != old->ifindex)
156*4dc78e53SAndroid Build Coastguard Worker return -NLE_OPNOTSUPP;
157*4dc78e53SAndroid Build Coastguard Worker
158*4dc78e53SAndroid Build Coastguard Worker switch (action) {
159*4dc78e53SAndroid Build Coastguard Worker case RTM_NEWMDB:
160*4dc78e53SAndroid Build Coastguard Worker nl_list_for_each_entry(entry, &new->mdb_entry_list, mdb_list) {
161*4dc78e53SAndroid Build Coastguard Worker struct rtnl_mdb_entry *copy = mdb_entry_clone(entry);
162*4dc78e53SAndroid Build Coastguard Worker
163*4dc78e53SAndroid Build Coastguard Worker if (!copy)
164*4dc78e53SAndroid Build Coastguard Worker return -NLE_NOMEM;
165*4dc78e53SAndroid Build Coastguard Worker
166*4dc78e53SAndroid Build Coastguard Worker rtnl_mdb_add_entry(old, copy);
167*4dc78e53SAndroid Build Coastguard Worker }
168*4dc78e53SAndroid Build Coastguard Worker break;
169*4dc78e53SAndroid Build Coastguard Worker case RTM_DELMDB:
170*4dc78e53SAndroid Build Coastguard Worker entry = nl_list_first_entry(&new->mdb_entry_list,
171*4dc78e53SAndroid Build Coastguard Worker struct rtnl_mdb_entry,
172*4dc78e53SAndroid Build Coastguard Worker mdb_list);
173*4dc78e53SAndroid Build Coastguard Worker nl_list_for_each_entry(old_entry, &old->mdb_entry_list, mdb_list) {
174*4dc78e53SAndroid Build Coastguard Worker if ( old_entry->ifindex == entry->ifindex
175*4dc78e53SAndroid Build Coastguard Worker && !nl_addr_cmp(old_entry->addr, entry->addr)) {
176*4dc78e53SAndroid Build Coastguard Worker nl_list_del(&old_entry->mdb_list);
177*4dc78e53SAndroid Build Coastguard Worker break;
178*4dc78e53SAndroid Build Coastguard Worker }
179*4dc78e53SAndroid Build Coastguard Worker }
180*4dc78e53SAndroid Build Coastguard Worker break;
181*4dc78e53SAndroid Build Coastguard Worker }
182*4dc78e53SAndroid Build Coastguard Worker
183*4dc78e53SAndroid Build Coastguard Worker return NLE_SUCCESS;
184*4dc78e53SAndroid Build Coastguard Worker }
185*4dc78e53SAndroid Build Coastguard Worker
186*4dc78e53SAndroid Build Coastguard Worker static struct nla_policy mdb_policy[MDBA_MAX + 1] = {
187*4dc78e53SAndroid Build Coastguard Worker [MDBA_MDB] = {.type = NLA_NESTED},
188*4dc78e53SAndroid Build Coastguard Worker };
189*4dc78e53SAndroid Build Coastguard Worker
190*4dc78e53SAndroid Build Coastguard Worker static struct nla_policy mdb_db_policy[MDBA_MDB_MAX + 1] = {
191*4dc78e53SAndroid Build Coastguard Worker [MDBA_MDB_ENTRY] = {.type = NLA_NESTED},
192*4dc78e53SAndroid Build Coastguard Worker };
193*4dc78e53SAndroid Build Coastguard Worker
mdb_msg_parser(struct nl_cache_ops * ops,struct sockaddr_nl * who,struct nlmsghdr * nlh,struct nl_parser_param * pp)194*4dc78e53SAndroid Build Coastguard Worker static int mdb_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
195*4dc78e53SAndroid Build Coastguard Worker struct nlmsghdr *nlh, struct nl_parser_param *pp)
196*4dc78e53SAndroid Build Coastguard Worker {
197*4dc78e53SAndroid Build Coastguard Worker int err = 0;
198*4dc78e53SAndroid Build Coastguard Worker int rem = 0;
199*4dc78e53SAndroid Build Coastguard Worker struct nlattr *tb[MDBA_MAX + 1];
200*4dc78e53SAndroid Build Coastguard Worker struct br_port_msg *port;
201*4dc78e53SAndroid Build Coastguard Worker struct nlattr *nla;
202*4dc78e53SAndroid Build Coastguard Worker struct br_mdb_entry *e;
203*4dc78e53SAndroid Build Coastguard Worker _nl_auto_rtnl_mdb struct rtnl_mdb *mdb = rtnl_mdb_alloc();
204*4dc78e53SAndroid Build Coastguard Worker
205*4dc78e53SAndroid Build Coastguard Worker if (!mdb)
206*4dc78e53SAndroid Build Coastguard Worker return -NLE_NOMEM;
207*4dc78e53SAndroid Build Coastguard Worker
208*4dc78e53SAndroid Build Coastguard Worker err = nlmsg_parse(nlh, sizeof(struct br_port_msg), tb, MDBA_MAX,
209*4dc78e53SAndroid Build Coastguard Worker mdb_policy);
210*4dc78e53SAndroid Build Coastguard Worker if (err < 0)
211*4dc78e53SAndroid Build Coastguard Worker return err;
212*4dc78e53SAndroid Build Coastguard Worker
213*4dc78e53SAndroid Build Coastguard Worker mdb->ce_msgtype = nlh->nlmsg_type;
214*4dc78e53SAndroid Build Coastguard Worker
215*4dc78e53SAndroid Build Coastguard Worker port = nlmsg_data(nlh);
216*4dc78e53SAndroid Build Coastguard Worker mdb->ifindex = port->ifindex;
217*4dc78e53SAndroid Build Coastguard Worker mdb->ce_mask |= MDB_ATTR_IFINDEX;
218*4dc78e53SAndroid Build Coastguard Worker
219*4dc78e53SAndroid Build Coastguard Worker if (tb[MDBA_MDB]) {
220*4dc78e53SAndroid Build Coastguard Worker struct nlattr *db_attr[MDBA_MDB_MAX+1];
221*4dc78e53SAndroid Build Coastguard Worker
222*4dc78e53SAndroid Build Coastguard Worker err = nla_parse_nested(db_attr, MDBA_MDB_MAX, tb[MDBA_MDB],
223*4dc78e53SAndroid Build Coastguard Worker mdb_db_policy);
224*4dc78e53SAndroid Build Coastguard Worker if (err < 0)
225*4dc78e53SAndroid Build Coastguard Worker return err;
226*4dc78e53SAndroid Build Coastguard Worker rem = nla_len(tb[MDBA_MDB]);
227*4dc78e53SAndroid Build Coastguard Worker
228*4dc78e53SAndroid Build Coastguard Worker for (nla = nla_data(tb[MDBA_MDB]); nla_ok(nla, rem);
229*4dc78e53SAndroid Build Coastguard Worker nla = nla_next(nla, &rem)) {
230*4dc78e53SAndroid Build Coastguard Worker int rm = nla_len(nla);
231*4dc78e53SAndroid Build Coastguard Worker struct nlattr *nla2;
232*4dc78e53SAndroid Build Coastguard Worker
233*4dc78e53SAndroid Build Coastguard Worker for (nla2 = nla_data(nla); nla_ok(nla2, rm);
234*4dc78e53SAndroid Build Coastguard Worker nla2 = nla_next(nla2, &rm)) {
235*4dc78e53SAndroid Build Coastguard Worker _nl_auto_nl_addr struct nl_addr *addr = NULL;
236*4dc78e53SAndroid Build Coastguard Worker struct rtnl_mdb_entry *entry;
237*4dc78e53SAndroid Build Coastguard Worker uint16_t proto;
238*4dc78e53SAndroid Build Coastguard Worker
239*4dc78e53SAndroid Build Coastguard Worker e = nla_data(nla2);
240*4dc78e53SAndroid Build Coastguard Worker
241*4dc78e53SAndroid Build Coastguard Worker proto = ntohs(e->addr.proto);
242*4dc78e53SAndroid Build Coastguard Worker
243*4dc78e53SAndroid Build Coastguard Worker if (proto == ETH_P_IP) {
244*4dc78e53SAndroid Build Coastguard Worker addr = nl_addr_build(
245*4dc78e53SAndroid Build Coastguard Worker AF_INET, &e->addr.u.ip4,
246*4dc78e53SAndroid Build Coastguard Worker sizeof(e->addr.u.ip4));
247*4dc78e53SAndroid Build Coastguard Worker } else if (proto == ETH_P_IPV6) {
248*4dc78e53SAndroid Build Coastguard Worker addr = nl_addr_build(
249*4dc78e53SAndroid Build Coastguard Worker AF_INET6, &e->addr.u.ip6,
250*4dc78e53SAndroid Build Coastguard Worker sizeof(e->addr.u.ip6));
251*4dc78e53SAndroid Build Coastguard Worker } else {
252*4dc78e53SAndroid Build Coastguard Worker addr = nl_addr_build(
253*4dc78e53SAndroid Build Coastguard Worker AF_LLC, e->addr.u.mac_addr,
254*4dc78e53SAndroid Build Coastguard Worker sizeof(e->addr.u.mac_addr));
255*4dc78e53SAndroid Build Coastguard Worker }
256*4dc78e53SAndroid Build Coastguard Worker if (!addr)
257*4dc78e53SAndroid Build Coastguard Worker return -NLE_NOMEM;
258*4dc78e53SAndroid Build Coastguard Worker
259*4dc78e53SAndroid Build Coastguard Worker entry = rtnl_mdb_entry_alloc();
260*4dc78e53SAndroid Build Coastguard Worker if (!entry)
261*4dc78e53SAndroid Build Coastguard Worker return -NLE_NOMEM;
262*4dc78e53SAndroid Build Coastguard Worker
263*4dc78e53SAndroid Build Coastguard Worker mdb->ce_mask |= MDB_ATTR_ENTRIES;
264*4dc78e53SAndroid Build Coastguard Worker
265*4dc78e53SAndroid Build Coastguard Worker entry->ifindex = e->ifindex;
266*4dc78e53SAndroid Build Coastguard Worker entry->vid = e->vid;
267*4dc78e53SAndroid Build Coastguard Worker entry->state = e->state;
268*4dc78e53SAndroid Build Coastguard Worker entry->proto = ntohs(e->addr.proto);
269*4dc78e53SAndroid Build Coastguard Worker entry->addr = _nl_steal_pointer(&addr);
270*4dc78e53SAndroid Build Coastguard Worker rtnl_mdb_add_entry(mdb, entry);
271*4dc78e53SAndroid Build Coastguard Worker }
272*4dc78e53SAndroid Build Coastguard Worker }
273*4dc78e53SAndroid Build Coastguard Worker }
274*4dc78e53SAndroid Build Coastguard Worker
275*4dc78e53SAndroid Build Coastguard Worker return pp->pp_cb((struct nl_object *) mdb, pp);
276*4dc78e53SAndroid Build Coastguard Worker }
277*4dc78e53SAndroid Build Coastguard Worker
mdb_request_update(struct nl_cache * cache,struct nl_sock * sk)278*4dc78e53SAndroid Build Coastguard Worker static int mdb_request_update(struct nl_cache *cache, struct nl_sock *sk)
279*4dc78e53SAndroid Build Coastguard Worker {
280*4dc78e53SAndroid Build Coastguard Worker return nl_rtgen_request(sk, RTM_GETMDB, AF_BRIDGE, NLM_F_DUMP);
281*4dc78e53SAndroid Build Coastguard Worker }
282*4dc78e53SAndroid Build Coastguard Worker
mdb_entry_dump_line(struct rtnl_mdb_entry * entry,struct nl_dump_params * p)283*4dc78e53SAndroid Build Coastguard Worker static void mdb_entry_dump_line(struct rtnl_mdb_entry *entry,
284*4dc78e53SAndroid Build Coastguard Worker struct nl_dump_params *p)
285*4dc78e53SAndroid Build Coastguard Worker {
286*4dc78e53SAndroid Build Coastguard Worker char buf[INET6_ADDRSTRLEN];
287*4dc78e53SAndroid Build Coastguard Worker
288*4dc78e53SAndroid Build Coastguard Worker nl_dump(p, "port %d ", entry->ifindex);
289*4dc78e53SAndroid Build Coastguard Worker nl_dump(p, "vid %d ", entry->vid);
290*4dc78e53SAndroid Build Coastguard Worker nl_dump(p, "proto 0x%04x ", entry->proto);
291*4dc78e53SAndroid Build Coastguard Worker nl_dump(p, "address %s\n", nl_addr2str(entry->addr, buf, sizeof(buf)));
292*4dc78e53SAndroid Build Coastguard Worker }
293*4dc78e53SAndroid Build Coastguard Worker
mdb_dump_line(struct nl_object * obj,struct nl_dump_params * p)294*4dc78e53SAndroid Build Coastguard Worker static void mdb_dump_line(struct nl_object *obj, struct nl_dump_params *p)
295*4dc78e53SAndroid Build Coastguard Worker {
296*4dc78e53SAndroid Build Coastguard Worker struct rtnl_mdb *mdb = (struct rtnl_mdb *) obj;
297*4dc78e53SAndroid Build Coastguard Worker struct rtnl_mdb_entry *_mdb;
298*4dc78e53SAndroid Build Coastguard Worker
299*4dc78e53SAndroid Build Coastguard Worker nl_dump(p, "dev %d \n", mdb->ifindex);
300*4dc78e53SAndroid Build Coastguard Worker
301*4dc78e53SAndroid Build Coastguard Worker nl_list_for_each_entry(_mdb, &mdb->mdb_entry_list, mdb_list) {
302*4dc78e53SAndroid Build Coastguard Worker p->dp_ivar = NH_DUMP_FROM_ONELINE;
303*4dc78e53SAndroid Build Coastguard Worker mdb_entry_dump_line(_mdb, p);
304*4dc78e53SAndroid Build Coastguard Worker }
305*4dc78e53SAndroid Build Coastguard Worker }
306*4dc78e53SAndroid Build Coastguard Worker
mdb_dump_details(struct nl_object * obj,struct nl_dump_params * p)307*4dc78e53SAndroid Build Coastguard Worker static void mdb_dump_details(struct nl_object *obj, struct nl_dump_params *p)
308*4dc78e53SAndroid Build Coastguard Worker {
309*4dc78e53SAndroid Build Coastguard Worker mdb_dump_line(obj, p);
310*4dc78e53SAndroid Build Coastguard Worker }
311*4dc78e53SAndroid Build Coastguard Worker
mdb_dump_stats(struct nl_object * obj,struct nl_dump_params * p)312*4dc78e53SAndroid Build Coastguard Worker static void mdb_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
313*4dc78e53SAndroid Build Coastguard Worker {
314*4dc78e53SAndroid Build Coastguard Worker mdb_dump_details(obj, p);
315*4dc78e53SAndroid Build Coastguard Worker }
316*4dc78e53SAndroid Build Coastguard Worker
rtnl_mdb_put(struct rtnl_mdb * mdb)317*4dc78e53SAndroid Build Coastguard Worker void rtnl_mdb_put(struct rtnl_mdb *mdb)
318*4dc78e53SAndroid Build Coastguard Worker {
319*4dc78e53SAndroid Build Coastguard Worker nl_object_put((struct nl_object *) mdb);
320*4dc78e53SAndroid Build Coastguard Worker }
321*4dc78e53SAndroid Build Coastguard Worker
322*4dc78e53SAndroid Build Coastguard Worker /** @} */
323*4dc78e53SAndroid Build Coastguard Worker
324*4dc78e53SAndroid Build Coastguard Worker /**
325*4dc78e53SAndroid Build Coastguard Worker * @name Cache Management
326*4dc78e53SAndroid Build Coastguard Worker * @{
327*4dc78e53SAndroid Build Coastguard Worker */
rtnl_mdb_alloc_cache(struct nl_sock * sk,struct nl_cache ** result)328*4dc78e53SAndroid Build Coastguard Worker int rtnl_mdb_alloc_cache(struct nl_sock *sk, struct nl_cache **result)
329*4dc78e53SAndroid Build Coastguard Worker {
330*4dc78e53SAndroid Build Coastguard Worker return nl_cache_alloc_and_fill(&rtnl_mdb_ops, sk, result);
331*4dc78e53SAndroid Build Coastguard Worker }
332*4dc78e53SAndroid Build Coastguard Worker
333*4dc78e53SAndroid Build Coastguard Worker /**
334*4dc78e53SAndroid Build Coastguard Worker * Build a neighbour cache including all MDB entries currently configured in the kernel.
335*4dc78e53SAndroid Build Coastguard Worker * @arg sock Netlink socket.
336*4dc78e53SAndroid Build Coastguard Worker * @arg result Pointer to store resulting cache.
337*4dc78e53SAndroid Build Coastguard Worker * @arg flags Flags to apply to cache before filling
338*4dc78e53SAndroid Build Coastguard Worker *
339*4dc78e53SAndroid Build Coastguard Worker * Allocates a new MDB cache, initializes it properly and updates it
340*4dc78e53SAndroid Build Coastguard Worker * to include all Multicast Database entries currently configured in the kernel.
341*4dc78e53SAndroid Build Coastguard Worker *
342*4dc78e53SAndroid Build Coastguard Worker * @return 0 on success or a negative error code.
343*4dc78e53SAndroid Build Coastguard Worker */
rtnl_mdb_alloc_cache_flags(struct nl_sock * sock,struct nl_cache ** result,unsigned int flags)344*4dc78e53SAndroid Build Coastguard Worker int rtnl_mdb_alloc_cache_flags(struct nl_sock *sock, struct nl_cache **result,
345*4dc78e53SAndroid Build Coastguard Worker unsigned int flags)
346*4dc78e53SAndroid Build Coastguard Worker {
347*4dc78e53SAndroid Build Coastguard Worker struct nl_cache *cache;
348*4dc78e53SAndroid Build Coastguard Worker int err;
349*4dc78e53SAndroid Build Coastguard Worker
350*4dc78e53SAndroid Build Coastguard Worker cache = nl_cache_alloc(&rtnl_mdb_ops);
351*4dc78e53SAndroid Build Coastguard Worker if (!cache)
352*4dc78e53SAndroid Build Coastguard Worker return -NLE_NOMEM;
353*4dc78e53SAndroid Build Coastguard Worker
354*4dc78e53SAndroid Build Coastguard Worker nl_cache_set_flags(cache, flags);
355*4dc78e53SAndroid Build Coastguard Worker
356*4dc78e53SAndroid Build Coastguard Worker if (sock && (err = nl_cache_refill(sock, cache)) < 0) {
357*4dc78e53SAndroid Build Coastguard Worker nl_cache_free(cache);
358*4dc78e53SAndroid Build Coastguard Worker return err;
359*4dc78e53SAndroid Build Coastguard Worker }
360*4dc78e53SAndroid Build Coastguard Worker
361*4dc78e53SAndroid Build Coastguard Worker *result = cache;
362*4dc78e53SAndroid Build Coastguard Worker return 0;
363*4dc78e53SAndroid Build Coastguard Worker }
364*4dc78e53SAndroid Build Coastguard Worker
365*4dc78e53SAndroid Build Coastguard Worker /** @} */
366*4dc78e53SAndroid Build Coastguard Worker
367*4dc78e53SAndroid Build Coastguard Worker /**
368*4dc78e53SAndroid Build Coastguard Worker * @name Attributes
369*4dc78e53SAndroid Build Coastguard Worker * @{
370*4dc78e53SAndroid Build Coastguard Worker */
rtnl_mdb_get_ifindex(struct rtnl_mdb * mdb)371*4dc78e53SAndroid Build Coastguard Worker uint32_t rtnl_mdb_get_ifindex(struct rtnl_mdb *mdb)
372*4dc78e53SAndroid Build Coastguard Worker {
373*4dc78e53SAndroid Build Coastguard Worker return mdb->ifindex;
374*4dc78e53SAndroid Build Coastguard Worker }
375*4dc78e53SAndroid Build Coastguard Worker
rtnl_mdb_add_entry(struct rtnl_mdb * mdb,struct rtnl_mdb_entry * entry)376*4dc78e53SAndroid Build Coastguard Worker void rtnl_mdb_add_entry(struct rtnl_mdb *mdb, struct rtnl_mdb_entry *entry)
377*4dc78e53SAndroid Build Coastguard Worker {
378*4dc78e53SAndroid Build Coastguard Worker nl_list_add_tail(&entry->mdb_list, &mdb->mdb_entry_list);
379*4dc78e53SAndroid Build Coastguard Worker }
380*4dc78e53SAndroid Build Coastguard Worker
rtnl_mdb_foreach_entry(struct rtnl_mdb * mdb,void (* cb)(struct rtnl_mdb_entry *,void *),void * arg)381*4dc78e53SAndroid Build Coastguard Worker void rtnl_mdb_foreach_entry(struct rtnl_mdb *mdb,
382*4dc78e53SAndroid Build Coastguard Worker void (*cb)(struct rtnl_mdb_entry *, void *),
383*4dc78e53SAndroid Build Coastguard Worker void *arg)
384*4dc78e53SAndroid Build Coastguard Worker {
385*4dc78e53SAndroid Build Coastguard Worker struct rtnl_mdb_entry *entry;
386*4dc78e53SAndroid Build Coastguard Worker
387*4dc78e53SAndroid Build Coastguard Worker nl_list_for_each_entry(entry, &mdb->mdb_entry_list, mdb_list) {
388*4dc78e53SAndroid Build Coastguard Worker cb(entry, arg);
389*4dc78e53SAndroid Build Coastguard Worker }
390*4dc78e53SAndroid Build Coastguard Worker }
391*4dc78e53SAndroid Build Coastguard Worker
rtnl_mdb_entry_get_ifindex(struct rtnl_mdb_entry * mdb_entry)392*4dc78e53SAndroid Build Coastguard Worker int rtnl_mdb_entry_get_ifindex(struct rtnl_mdb_entry *mdb_entry)
393*4dc78e53SAndroid Build Coastguard Worker {
394*4dc78e53SAndroid Build Coastguard Worker return mdb_entry->ifindex;
395*4dc78e53SAndroid Build Coastguard Worker }
396*4dc78e53SAndroid Build Coastguard Worker
rtnl_mdb_entry_get_vid(struct rtnl_mdb_entry * mdb_entry)397*4dc78e53SAndroid Build Coastguard Worker int rtnl_mdb_entry_get_vid(struct rtnl_mdb_entry *mdb_entry)
398*4dc78e53SAndroid Build Coastguard Worker {
399*4dc78e53SAndroid Build Coastguard Worker return mdb_entry->vid;
400*4dc78e53SAndroid Build Coastguard Worker }
401*4dc78e53SAndroid Build Coastguard Worker
rtnl_mdb_entry_get_state(struct rtnl_mdb_entry * mdb_entry)402*4dc78e53SAndroid Build Coastguard Worker int rtnl_mdb_entry_get_state(struct rtnl_mdb_entry *mdb_entry)
403*4dc78e53SAndroid Build Coastguard Worker {
404*4dc78e53SAndroid Build Coastguard Worker return mdb_entry->state;
405*4dc78e53SAndroid Build Coastguard Worker }
406*4dc78e53SAndroid Build Coastguard Worker
rtnl_mdb_entry_get_addr(struct rtnl_mdb_entry * mdb_entry)407*4dc78e53SAndroid Build Coastguard Worker struct nl_addr *rtnl_mdb_entry_get_addr(struct rtnl_mdb_entry *mdb_entry)
408*4dc78e53SAndroid Build Coastguard Worker {
409*4dc78e53SAndroid Build Coastguard Worker return mdb_entry->addr;
410*4dc78e53SAndroid Build Coastguard Worker }
411*4dc78e53SAndroid Build Coastguard Worker
rtnl_mdb_entry_get_proto(struct rtnl_mdb_entry * mdb_entry)412*4dc78e53SAndroid Build Coastguard Worker uint16_t rtnl_mdb_entry_get_proto(struct rtnl_mdb_entry *mdb_entry)
413*4dc78e53SAndroid Build Coastguard Worker {
414*4dc78e53SAndroid Build Coastguard Worker return mdb_entry->proto;
415*4dc78e53SAndroid Build Coastguard Worker }
416*4dc78e53SAndroid Build Coastguard Worker
417*4dc78e53SAndroid Build Coastguard Worker /** @} */
418*4dc78e53SAndroid Build Coastguard Worker
419*4dc78e53SAndroid Build Coastguard Worker static struct nl_object_ops mdb_obj_ops = {
420*4dc78e53SAndroid Build Coastguard Worker .oo_name = "route/mdb",
421*4dc78e53SAndroid Build Coastguard Worker .oo_size = sizeof(struct rtnl_mdb),
422*4dc78e53SAndroid Build Coastguard Worker .oo_constructor = mdb_constructor,
423*4dc78e53SAndroid Build Coastguard Worker .oo_dump = {
424*4dc78e53SAndroid Build Coastguard Worker [NL_DUMP_LINE] = mdb_dump_line,
425*4dc78e53SAndroid Build Coastguard Worker [NL_DUMP_DETAILS] = mdb_dump_details,
426*4dc78e53SAndroid Build Coastguard Worker [NL_DUMP_STATS] = mdb_dump_stats,
427*4dc78e53SAndroid Build Coastguard Worker },
428*4dc78e53SAndroid Build Coastguard Worker .oo_clone = mdb_clone,
429*4dc78e53SAndroid Build Coastguard Worker .oo_compare = mdb_compare,
430*4dc78e53SAndroid Build Coastguard Worker .oo_update = mdb_update,
431*4dc78e53SAndroid Build Coastguard Worker .oo_free_data = mdb_free_data,
432*4dc78e53SAndroid Build Coastguard Worker };
433*4dc78e53SAndroid Build Coastguard Worker
rtnl_mdb_alloc(void)434*4dc78e53SAndroid Build Coastguard Worker struct rtnl_mdb *rtnl_mdb_alloc(void)
435*4dc78e53SAndroid Build Coastguard Worker {
436*4dc78e53SAndroid Build Coastguard Worker return (struct rtnl_mdb *) nl_object_alloc(&mdb_obj_ops);
437*4dc78e53SAndroid Build Coastguard Worker }
438*4dc78e53SAndroid Build Coastguard Worker
rtnl_mdb_entry_alloc(void)439*4dc78e53SAndroid Build Coastguard Worker static struct rtnl_mdb_entry *rtnl_mdb_entry_alloc(void)
440*4dc78e53SAndroid Build Coastguard Worker {
441*4dc78e53SAndroid Build Coastguard Worker struct rtnl_mdb_entry *mdb;
442*4dc78e53SAndroid Build Coastguard Worker
443*4dc78e53SAndroid Build Coastguard Worker mdb = calloc(1, sizeof(struct rtnl_mdb_entry));
444*4dc78e53SAndroid Build Coastguard Worker if (!mdb)
445*4dc78e53SAndroid Build Coastguard Worker return NULL;
446*4dc78e53SAndroid Build Coastguard Worker
447*4dc78e53SAndroid Build Coastguard Worker nl_init_list_head(&mdb->mdb_list);
448*4dc78e53SAndroid Build Coastguard Worker
449*4dc78e53SAndroid Build Coastguard Worker return mdb;
450*4dc78e53SAndroid Build Coastguard Worker
451*4dc78e53SAndroid Build Coastguard Worker }
452*4dc78e53SAndroid Build Coastguard Worker
rtnl_mdb_entry_free(struct rtnl_mdb_entry * mdb_entry)453*4dc78e53SAndroid Build Coastguard Worker static void rtnl_mdb_entry_free(struct rtnl_mdb_entry *mdb_entry)
454*4dc78e53SAndroid Build Coastguard Worker {
455*4dc78e53SAndroid Build Coastguard Worker nl_list_del(&mdb_entry->mdb_list);
456*4dc78e53SAndroid Build Coastguard Worker nl_addr_put(mdb_entry->addr);
457*4dc78e53SAndroid Build Coastguard Worker free(mdb_entry);
458*4dc78e53SAndroid Build Coastguard Worker }
459*4dc78e53SAndroid Build Coastguard Worker
460*4dc78e53SAndroid Build Coastguard Worker static struct nl_af_group mdb_groups[] = {
461*4dc78e53SAndroid Build Coastguard Worker {AF_BRIDGE, RTNLGRP_MDB},
462*4dc78e53SAndroid Build Coastguard Worker {END_OF_GROUP_LIST},
463*4dc78e53SAndroid Build Coastguard Worker };
464*4dc78e53SAndroid Build Coastguard Worker
465*4dc78e53SAndroid Build Coastguard Worker static struct nl_cache_ops rtnl_mdb_ops = {
466*4dc78e53SAndroid Build Coastguard Worker .co_name = "route/mdb",
467*4dc78e53SAndroid Build Coastguard Worker .co_hdrsize = sizeof(struct br_port_msg),
468*4dc78e53SAndroid Build Coastguard Worker .co_msgtypes = {
469*4dc78e53SAndroid Build Coastguard Worker { RTM_NEWMDB, NL_ACT_NEW, "new"},
470*4dc78e53SAndroid Build Coastguard Worker { RTM_DELMDB, NL_ACT_DEL, "del"},
471*4dc78e53SAndroid Build Coastguard Worker { RTM_GETMDB, NL_ACT_GET, "get"},
472*4dc78e53SAndroid Build Coastguard Worker END_OF_MSGTYPES_LIST,
473*4dc78e53SAndroid Build Coastguard Worker },
474*4dc78e53SAndroid Build Coastguard Worker .co_protocol = NETLINK_ROUTE,
475*4dc78e53SAndroid Build Coastguard Worker .co_groups = mdb_groups,
476*4dc78e53SAndroid Build Coastguard Worker .co_request_update = mdb_request_update,
477*4dc78e53SAndroid Build Coastguard Worker .co_msg_parser = mdb_msg_parser,
478*4dc78e53SAndroid Build Coastguard Worker .co_obj_ops = &mdb_obj_ops,
479*4dc78e53SAndroid Build Coastguard Worker };
480*4dc78e53SAndroid Build Coastguard Worker
mdb_init(void)481*4dc78e53SAndroid Build Coastguard Worker static void _nl_init mdb_init(void)
482*4dc78e53SAndroid Build Coastguard Worker {
483*4dc78e53SAndroid Build Coastguard Worker nl_cache_mngt_register(&rtnl_mdb_ops);
484*4dc78e53SAndroid Build Coastguard Worker }
485*4dc78e53SAndroid Build Coastguard Worker
mdb_exit(void)486*4dc78e53SAndroid Build Coastguard Worker static void _nl_exit mdb_exit(void)
487*4dc78e53SAndroid Build Coastguard Worker {
488*4dc78e53SAndroid Build Coastguard Worker nl_cache_mngt_unregister(&rtnl_mdb_ops);
489*4dc78e53SAndroid Build Coastguard Worker }
490*4dc78e53SAndroid Build Coastguard Worker
491*4dc78e53SAndroid Build Coastguard Worker /** @} */
492