2121#include <net/netlink.h>
2222#include <net/sock.h>
2323
24- static int __always_unused mctp_neigh_add (struct mctp_dev * mdev , mctp_eid_t eid ,
25- enum mctp_neigh_source source ,
26- size_t lladdr_len , const void * lladdr )
24+ static int mctp_neigh_add (struct mctp_dev * mdev , mctp_eid_t eid ,
25+ enum mctp_neigh_source source ,
26+ size_t lladdr_len , const void * lladdr )
2727{
2828 struct net * net = dev_net (mdev -> dev );
2929 struct mctp_neigh * neigh ;
@@ -85,6 +85,196 @@ void mctp_neigh_remove_dev(struct mctp_dev *mdev)
8585 mutex_unlock (& net -> mctp .neigh_lock );
8686}
8787
88+ // TODO: add a "source" flag so netlink can only delete static neighbours?
89+ static int mctp_neigh_remove (struct mctp_dev * mdev , mctp_eid_t eid )
90+ {
91+ struct net * net = dev_net (mdev -> dev );
92+ struct mctp_neigh * neigh , * tmp ;
93+ bool dropped = false;
94+
95+ mutex_lock (& net -> mctp .neigh_lock );
96+ list_for_each_entry_safe (neigh , tmp , & net -> mctp .neighbours , list ) {
97+ if (neigh -> dev == mdev && neigh -> eid == eid ) {
98+ list_del_rcu (& neigh -> list );
99+ /* TODO: immediate RTM_DELNEIGH */
100+ call_rcu (& neigh -> rcu , __mctp_neigh_free );
101+ dropped = true;
102+ }
103+ }
104+
105+ mutex_unlock (& net -> mctp .neigh_lock );
106+ return dropped ? 0 : - ENOENT ;
107+ }
108+
109+ static const struct nla_policy nd_mctp_policy [NDA_MAX + 1 ] = {
110+ [NDA_DST ] = { .type = NLA_U8 },
111+ [NDA_LLADDR ] = { .type = NLA_BINARY , .len = MAX_ADDR_LEN },
112+ };
113+
114+ static int mctp_rtm_newneigh (struct sk_buff * skb , struct nlmsghdr * nlh ,
115+ struct netlink_ext_ack * extack )
116+ {
117+ struct net * net = sock_net (skb -> sk );
118+ struct net_device * dev ;
119+ struct mctp_dev * mdev ;
120+ struct ndmsg * ndm ;
121+ struct nlattr * tb [NDA_MAX + 1 ];
122+ int rc ;
123+ mctp_eid_t eid ;
124+ void * lladdr ;
125+ int lladdr_len ;
126+
127+ rc = nlmsg_parse (nlh , sizeof (* ndm ), tb , NDA_MAX , nd_mctp_policy ,
128+ extack );
129+ if (rc < 0 ) {
130+ NL_SET_ERR_MSG (extack , "lladdr too large?" );
131+ return rc ;
132+ }
133+
134+ if (!tb [NDA_DST ]) {
135+ NL_SET_ERR_MSG (extack , "Neighbour EID must be specified" );
136+ return - EINVAL ;
137+ }
138+
139+ if (!tb [NDA_LLADDR ]) {
140+ NL_SET_ERR_MSG (extack , "Neighbour lladdr must be specified" );
141+ return - EINVAL ;
142+ }
143+
144+ eid = nla_get_u8 (tb [NDA_DST ]);
145+ if (!mctp_address_ok (eid )) {
146+ NL_SET_ERR_MSG (extack , "Invalid neighbour EID" );
147+ return - EINVAL ;
148+ }
149+
150+ lladdr = nla_data (tb [NDA_LLADDR ]);
151+ lladdr_len = nla_len (tb [NDA_LLADDR ]);
152+
153+ ndm = nlmsg_data (nlh );
154+
155+ dev = __dev_get_by_index (net , ndm -> ndm_ifindex );
156+ if (!dev )
157+ return - ENODEV ;
158+
159+ mdev = mctp_dev_get_rtnl (dev );
160+ if (!mdev )
161+ return - ENODEV ;
162+
163+ if (lladdr_len != dev -> addr_len ) {
164+ NL_SET_ERR_MSG (extack , "Wrong lladdr length" );
165+ return - EINVAL ;
166+ }
167+
168+ return mctp_neigh_add (mdev , eid , MCTP_NEIGH_STATIC ,
169+ lladdr_len , lladdr );
170+ }
171+
172+ static int mctp_rtm_delneigh (struct sk_buff * skb , struct nlmsghdr * nlh ,
173+ struct netlink_ext_ack * extack )
174+ {
175+ struct net * net = sock_net (skb -> sk );
176+ struct nlattr * tb [NDA_MAX + 1 ];
177+ struct net_device * dev ;
178+ struct mctp_dev * mdev ;
179+ struct ndmsg * ndm ;
180+ int rc ;
181+ mctp_eid_t eid ;
182+
183+ rc = nlmsg_parse (nlh , sizeof (* ndm ), tb , NDA_MAX , nd_mctp_policy ,
184+ extack );
185+ if (rc < 0 ) {
186+ NL_SET_ERR_MSG (extack , "incorrect format" );
187+ return rc ;
188+ }
189+
190+ if (!tb [NDA_DST ]) {
191+ NL_SET_ERR_MSG (extack , "Neighbour EID must be specified" );
192+ return - EINVAL ;
193+ }
194+ eid = nla_get_u8 (tb [NDA_DST ]);
195+
196+ ndm = nlmsg_data (nlh );
197+ dev = __dev_get_by_index (net , ndm -> ndm_ifindex );
198+ if (!dev )
199+ return - ENODEV ;
200+
201+ mdev = mctp_dev_get_rtnl (dev );
202+ if (!mdev )
203+ return - ENODEV ;
204+
205+ return mctp_neigh_remove (mdev , eid );
206+ }
207+
208+ static int mctp_fill_neigh (struct sk_buff * skb , u32 portid , u32 seq , int event ,
209+ unsigned int flags , struct mctp_neigh * neigh )
210+ {
211+ struct net_device * dev = neigh -> dev -> dev ;
212+ struct nlmsghdr * nlh ;
213+ struct ndmsg * hdr ;
214+
215+ nlh = nlmsg_put (skb , portid , seq , event , sizeof (* hdr ), flags );
216+ if (!nlh )
217+ return - EMSGSIZE ;
218+
219+ hdr = nlmsg_data (nlh );
220+ hdr -> ndm_family = AF_MCTP ;
221+ hdr -> ndm_ifindex = dev -> ifindex ;
222+ hdr -> ndm_state = 0 ; // TODO other state bits?
223+ if (neigh -> source == MCTP_NEIGH_STATIC )
224+ hdr -> ndm_state |= NUD_PERMANENT ;
225+ hdr -> ndm_flags = 0 ;
226+ hdr -> ndm_type = RTN_UNICAST ; // TODO: is loopback RTN_LOCAL?
227+
228+ if (nla_put_u8 (skb , NDA_DST , neigh -> eid ))
229+ goto cancel ;
230+
231+ if (nla_put (skb , NDA_LLADDR , dev -> addr_len , neigh -> ha ))
232+ goto cancel ;
233+
234+ nlmsg_end (skb , nlh );
235+
236+ return 0 ;
237+ cancel :
238+ nlmsg_cancel (skb , nlh );
239+ return - EMSGSIZE ;
240+ }
241+
242+ static int mctp_rtm_getneigh (struct sk_buff * skb , struct netlink_callback * cb )
243+ {
244+ struct net * net = sock_net (skb -> sk );
245+ int rc , idx , req_ifindex ;
246+ struct mctp_neigh * neigh ;
247+ struct ndmsg * ndmsg ;
248+ struct {
249+ int idx ;
250+ } * cbctx = (void * )cb -> ctx ;
251+
252+ ndmsg = nlmsg_data (cb -> nlh );
253+ req_ifindex = ndmsg -> ndm_ifindex ;
254+
255+ idx = 0 ;
256+ rcu_read_lock ();
257+ list_for_each_entry_rcu (neigh , & net -> mctp .neighbours , list ) {
258+ if (idx < cbctx -> idx )
259+ goto cont ;
260+
261+ rc = 0 ;
262+ if (req_ifindex == 0 || req_ifindex == neigh -> dev -> dev -> ifindex )
263+ rc = mctp_fill_neigh (skb , NETLINK_CB (cb -> skb ).portid ,
264+ cb -> nlh -> nlmsg_seq ,
265+ RTM_NEWNEIGH , NLM_F_MULTI , neigh );
266+
267+ if (rc )
268+ break ;
269+ cont :
270+ idx ++ ;
271+ }
272+ rcu_read_unlock ();
273+
274+ cbctx -> idx = idx ;
275+ return skb -> len ;
276+ }
277+
88278int mctp_neigh_lookup (struct mctp_dev * mdev , mctp_eid_t eid , void * ret_hwaddr )
89279{
90280 struct net * net = dev_net (mdev -> dev );
@@ -111,6 +301,7 @@ static int __net_init mctp_neigh_net_init(struct net *net)
111301 struct netns_mctp * ns = & net -> mctp ;
112302
113303 INIT_LIST_HEAD (& ns -> neighbours );
304+ mutex_init (& ns -> neigh_lock );
114305 return 0 ;
115306}
116307
@@ -132,10 +323,20 @@ static struct pernet_operations mctp_net_ops = {
132323
133324int __init mctp_neigh_init (void )
134325{
326+ rtnl_register_module (THIS_MODULE , PF_MCTP , RTM_NEWNEIGH ,
327+ mctp_rtm_newneigh , NULL , 0 );
328+ rtnl_register_module (THIS_MODULE , PF_MCTP , RTM_DELNEIGH ,
329+ mctp_rtm_delneigh , NULL , 0 );
330+ rtnl_register_module (THIS_MODULE , PF_MCTP , RTM_GETNEIGH ,
331+ NULL , mctp_rtm_getneigh , 0 );
332+
135333 return register_pernet_subsys (& mctp_net_ops );
136334}
137335
138336void __exit mctp_neigh_exit (void )
139337{
140338 unregister_pernet_subsys (& mctp_net_ops );
339+ rtnl_unregister (PF_MCTP , RTM_GETNEIGH );
340+ rtnl_unregister (PF_MCTP , RTM_DELNEIGH );
341+ rtnl_unregister (PF_MCTP , RTM_NEWNEIGH );
141342}
0 commit comments