@@ -40,10 +40,11 @@ static DEFINE_MUTEX(brc_serial);
4040/* Userspace communication. */
4141static DEFINE_SPINLOCK (brc_lock ); /* Ensure atomic access to these vars. */
4242static DECLARE_COMPLETION (brc_done ); /* Userspace signaled operation done? */
43- static int brc_err ; /* Error code from userspace. */
43+ static struct sk_buff * brc_reply ; /* Reply from userspace. */
4444static u32 brc_seq ; /* Sequence number for current op. */
4545
46- static int brc_send_command (const char * bridge , const char * port , int op );
46+ static struct sk_buff * brc_send_command (struct sk_buff * , struct nlattr * * attrs );
47+ static int brc_send_simple_command (struct sk_buff * );
4748
4849static int
4950get_dp_ifindices (int * indices , int num )
@@ -75,16 +76,55 @@ get_port_ifindices(struct datapath *dp, int *ifindices, int num)
7576 rcu_read_unlock ();
7677}
7778
79+ static struct sk_buff *
80+ brc_make_request (int op , const char * bridge , const char * port )
81+ {
82+ struct sk_buff * skb = genlmsg_new (NLMSG_GOODSIZE , GFP_KERNEL );
83+ if (!skb )
84+ goto error ;
85+
86+ genlmsg_put (skb , 0 , 0 , & brc_genl_family , 0 , op );
87+ NLA_PUT_STRING (skb , BRC_GENL_A_DP_NAME , bridge );
88+ if (port )
89+ NLA_PUT_STRING (skb , BRC_GENL_A_PORT_NAME , port );
90+ return skb ;
91+
92+ nla_put_failure :
93+ kfree_skb (skb );
94+ error :
95+ return NULL ;
96+ }
97+
98+ static int brc_send_simple_command (struct sk_buff * request )
99+ {
100+ struct nlattr * attrs [BRC_GENL_A_MAX + 1 ];
101+ struct sk_buff * reply ;
102+ int error ;
103+
104+ reply = brc_send_command (request , attrs );
105+ if (IS_ERR (reply ))
106+ return PTR_ERR (reply );
107+
108+ error = nla_get_u32 (attrs [BRC_GENL_A_ERR_CODE ]);
109+ kfree_skb (reply );
110+ return - error ;
111+ }
112+
78113static int brc_add_del_bridge (char __user * uname , int add )
79114{
115+ struct sk_buff * request ;
80116 char name [IFNAMSIZ ];
81117
82118 if (copy_from_user (name , uname , IFNAMSIZ ))
83119 return - EFAULT ;
84120
85121 name [IFNAMSIZ - 1 ] = 0 ;
86- return brc_send_command (name , NULL ,
87- add ? BRC_GENL_C_DP_ADD : BRC_GENL_C_DP_DEL );
122+ request = brc_make_request (add ? BRC_GENL_C_DP_ADD : BRC_GENL_C_DP_DEL ,
123+ name , NULL );
124+ if (!request )
125+ return - ENOMEM ;
126+
127+ return brc_send_simple_command (request );
88128}
89129
90130static int brc_get_bridges (int __user * uindices , int n )
@@ -154,22 +194,23 @@ brc_ioctl_deviceless_stub(struct net *net, unsigned int cmd, void __user *uarg)
154194static int
155195brc_add_del_port (struct net_device * dev , int port_ifindex , int add )
156196{
197+ struct sk_buff * request ;
157198 struct net_device * port ;
158- char dev_name [IFNAMSIZ ], port_name [IFNAMSIZ ];
159199 int err ;
160200
161201 port = __dev_get_by_index (& init_net , port_ifindex );
162202 if (!port )
163203 return - EINVAL ;
164204
165205 /* Save name of dev and port because there's a race between the
166- * rtnl_unlock() and the brc_send_command(). */
167- strcpy (dev_name , dev -> name );
168- strcpy (port_name , port -> name );
206+ * rtnl_unlock() and the brc_send_simple_command(). */
207+ request = brc_make_request (add ? BRC_GENL_C_PORT_ADD : BRC_GENL_C_PORT_DEL ,
208+ dev -> name , port -> name );
209+ if (!request )
210+ return - ENOMEM ;
169211
170212 rtnl_unlock ();
171- err = brc_send_command (dev_name , port_name ,
172- add ? BRC_GENL_C_PORT_ADD : BRC_GENL_C_PORT_DEL );
213+ err = brc_send_simple_command (request );
173214 rtnl_lock ();
174215
175216 return err ;
@@ -220,6 +261,64 @@ brc_get_port_list(struct net_device *dev, int __user *uindices, int num)
220261 return num ;
221262}
222263
264+ /*
265+ * Format up to a page worth of forwarding table entries
266+ * userbuf -- where to copy result
267+ * maxnum -- maximum number of entries desired
268+ * (limited to a page for sanity)
269+ * offset -- number of records to skip
270+ */
271+ static int brc_get_fdb_entries (struct net_device * dev , void __user * userbuf ,
272+ unsigned long maxnum , unsigned long offset )
273+ {
274+ struct nlattr * attrs [BRC_GENL_A_MAX + 1 ];
275+ struct sk_buff * request , * reply ;
276+ int retval ;
277+ int len ;
278+
279+ /* Clamp size to PAGE_SIZE, test maxnum to avoid overflow */
280+ if (maxnum > PAGE_SIZE /sizeof (struct __fdb_entry ))
281+ maxnum = PAGE_SIZE /sizeof (struct __fdb_entry );
282+
283+ request = brc_make_request (BRC_GENL_C_FDB_QUERY , dev -> name , NULL );
284+ if (!request )
285+ return - ENOMEM ;
286+ NLA_PUT_U64 (request , BRC_GENL_A_FDB_COUNT , maxnum );
287+ NLA_PUT_U64 (request , BRC_GENL_A_FDB_SKIP , offset );
288+
289+ rtnl_unlock ();
290+ reply = brc_send_command (request , attrs );
291+ retval = PTR_ERR (reply );
292+ if (IS_ERR (reply ))
293+ goto exit ;
294+
295+ retval = - nla_get_u32 (attrs [BRC_GENL_A_ERR_CODE ]);
296+ if (retval < 0 )
297+ goto exit_free_skb ;
298+
299+ retval = - EINVAL ;
300+ if (!attrs [BRC_GENL_A_FDB_DATA ])
301+ goto exit_free_skb ;
302+ len = nla_len (attrs [BRC_GENL_A_FDB_DATA ]);
303+ if (len % sizeof (struct __fdb_entry ) ||
304+ len / sizeof (struct __fdb_entry ) > maxnum )
305+ goto exit_free_skb ;
306+
307+ retval = len / sizeof (struct __fdb_entry );
308+ if (copy_to_user (userbuf , nla_data (attrs [BRC_GENL_A_FDB_DATA ]), len ))
309+ retval = - EFAULT ;
310+
311+ exit_free_skb :
312+ kfree_skb (reply );
313+ exit :
314+ rtnl_lock ();
315+ return retval ;
316+
317+ nla_put_failure :
318+ kfree_skb (request );
319+ return - ENOMEM ;
320+ }
321+
223322/* Legacy ioctl's through SIOCDEVPRIVATE. Called with rtnl_lock. */
224323static int
225324old_dev_ioctl (struct net_device * dev , struct ifreq * rq , int cmd )
@@ -240,6 +339,10 @@ old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
240339
241340 case BRCTL_GET_PORT_LIST :
242341 return brc_get_port_list (dev , (int __user * )args [1 ], args [2 ]);
342+
343+ case BRCTL_GET_FDB_ENTRIES :
344+ return brc_get_fdb_entries (dev , (void __user * )args [1 ],
345+ args [2 ], args [3 ]);
243346 }
244347
245348 return - EOPNOTSUPP ;
@@ -316,9 +419,12 @@ static struct genl_ops brc_genl_ops_query_dp = {
316419/* Attribute policy: what each attribute may contain. */
317420static struct nla_policy brc_genl_policy [BRC_GENL_A_MAX + 1 ] = {
318421 [BRC_GENL_A_ERR_CODE ] = { .type = NLA_U32 },
422+
319423 [BRC_GENL_A_PROC_DIR ] = { .type = NLA_NUL_STRING },
320424 [BRC_GENL_A_PROC_NAME ] = { .type = NLA_NUL_STRING },
321425 [BRC_GENL_A_PROC_DATA ] = { .type = NLA_NUL_STRING },
426+
427+ [BRC_GENL_A_FDB_DATA ] = { .type = NLA_UNSPEC },
322428};
323429
324430static int
@@ -330,12 +436,22 @@ brc_genl_dp_result(struct sk_buff *skb, struct genl_info *info)
330436 if (!info -> attrs [BRC_GENL_A_ERR_CODE ])
331437 return - EINVAL ;
332438
439+ skb = skb_clone (skb , GFP_KERNEL );
440+ if (!skb )
441+ return - ENOMEM ;
442+
333443 spin_lock_irqsave (& brc_lock , flags );
334444 if (brc_seq == info -> snd_seq ) {
335- brc_err = nla_get_u32 (info -> attrs [BRC_GENL_A_ERR_CODE ]);
445+ brc_seq ++ ;
446+
447+ if (brc_reply )
448+ kfree_skb (brc_reply );
449+ brc_reply = skb ;
450+
336451 complete (& brc_done );
337452 err = 0 ;
338453 } else {
454+ kfree_skb (skb );
339455 err = - ESTALE ;
340456 }
341457 spin_unlock_irqrestore (& brc_lock , flags );
@@ -359,53 +475,52 @@ static struct genl_ops brc_genl_ops_set_proc = {
359475 .dumpit = NULL
360476};
361477
362- static int brc_send_command (const char * bridge , const char * port , int op )
478+ static struct sk_buff * brc_send_command (struct sk_buff * request , struct nlattr * * attrs )
363479{
364480 unsigned long int flags ;
365- struct sk_buff * skb ;
366- void * data ;
481+ struct sk_buff * reply ;
367482 int error ;
368483
369484 mutex_lock (& brc_serial );
370485
371486 /* Increment sequence number first, so that we ignore any replies
372487 * to stale requests. */
373488 spin_lock_irqsave (& brc_lock , flags );
374- brc_seq ++ ;
489+ nlmsg_hdr ( request ) -> nlmsg_seq = ++ brc_seq ;
375490 INIT_COMPLETION (brc_done );
376491 spin_unlock_irqrestore (& brc_lock , flags );
377492
378- /* Compose message. */
379- skb = genlmsg_new (NLMSG_GOODSIZE , GFP_KERNEL );
380- error = - ENOMEM ;
381- if (skb == NULL )
382- goto exit_unlock ;
383- data = genlmsg_put (skb , 0 , brc_seq , & brc_genl_family , 0 , op );
384-
385- NLA_PUT_STRING (skb , BRC_GENL_A_DP_NAME , bridge );
386- if (port )
387- NLA_PUT_STRING (skb , BRC_GENL_A_PORT_NAME , port );
388-
389- genlmsg_end (skb , data );
493+ nlmsg_end (request , nlmsg_hdr (request ));
390494
391495 /* Send message. */
392- error = genlmsg_multicast (skb , 0 , brc_mc_group .id , GFP_KERNEL );
496+ error = genlmsg_multicast (request , 0 , brc_mc_group .id , GFP_KERNEL );
393497 if (error < 0 )
394- goto exit_unlock ;
498+ goto error ;
395499
396500 /* Wait for reply. */
397501 error = - ETIMEDOUT ;
398502 if (!wait_for_completion_timeout (& brc_done , BRC_TIMEOUT ))
399- goto exit_unlock ;
503+ goto error ;
504+
505+ /* Grab reply. */
506+ spin_lock_irqsave (& brc_lock , flags );
507+ reply = brc_reply ;
508+ brc_reply = NULL ;
509+ spin_unlock_irqrestore (& brc_lock , flags );
400510
401- error = - brc_err ;
402- goto exit_unlock ;
511+ mutex_unlock (& brc_serial );
403512
404- nla_put_failure :
405- kfree_skb (skb );
406- exit_unlock :
513+ /* Re-parse message. Can't fail, since it parsed correctly once
514+ * already. */
515+ error = nlmsg_parse (nlmsg_hdr (reply ), GENL_HDRLEN ,
516+ attrs , BRC_GENL_A_MAX , brc_genl_policy );
517+ WARN_ON (error );
518+
519+ return reply ;
520+
521+ error :
407522 mutex_unlock (& brc_serial );
408- return error ;
523+ return ERR_PTR ( error ) ;
409524}
410525
411526int brc_add_dp (struct datapath * dp )
0 commit comments