1414#include <net/cfg80211.h>
1515#include <uapi/linux/virtio_net.h>
1616
17+ #include <linux/netlink.h>
18+ #include <net/sock.h>
19+
1720MODULE_LICENSE ("Dual MIT/GPL" );
1821MODULE_AUTHOR ("National Cheng Kung University, Taiwan" );
1922MODULE_DESCRIPTION ("virtual cfg80211 driver" );
@@ -60,6 +63,7 @@ struct owl_context {
6063 enum vwifi_state state ; /**< indicate the program state */
6164 struct list_head vif_list ; /**< maintaining all interfaces */
6265 struct list_head ap_list ; /**< maintaining multiple AP */
66+ char * blocklist ; /**< maintaining the blocklist */
6367};
6468
6569/* SME stands for "station management entity" */
@@ -150,6 +154,83 @@ MODULE_PARM_DESC(station, "Number of virtual interfaces running in STA mode.");
150154/* Global context */
151155static struct owl_context * owl = NULL ;
152156
157+ /* Blocklist content */
158+ #define MAX_NETLINK_USER 31
159+ #define MAX_BLACKLIST_SIZE 1024
160+
161+ struct sock * nl_sk = NULL ;
162+
163+ static int blocklist_check (char * dest , char * source )
164+ {
165+ if (!owl -> blocklist || !* (owl -> blocklist ))
166+ return 0 ;
167+
168+ char * user_input =
169+ kmalloc (sizeof (char ) * (strlen (owl -> blocklist ) + 1 ), GFP_KERNEL );
170+ strncpy (user_input , owl -> blocklist , strlen (owl -> blocklist ));
171+
172+ char * token = strsep (& user_input , "\n" );
173+ while (token != NULL ) {
174+ char * blacklist_dest = strsep (& token , " " );
175+ strsep (& token , " " );
176+ char * blacklist_source = token ;
177+ if (strcmp (dest , blacklist_dest ) == 0 &&
178+ strcmp (source , blacklist_source ) == 0 ) {
179+ kfree (user_input );
180+ return 1 ;
181+ }
182+ pr_info ("owl: %s blocks packets from %s\n" , blacklist_dest ,
183+ blacklist_source );
184+ token = strsep (& user_input , "\n" );
185+ }
186+ kfree (user_input );
187+
188+ return 0 ;
189+ }
190+
191+ static void blocklist_load (char * blist )
192+ {
193+ if (!owl -> blocklist ) {
194+ pr_info ("owl->blocklist have to be kmalloc first\n" );
195+ return ;
196+ }
197+ memset (owl -> blocklist , '\0' , MAX_BLACKLIST_SIZE ); /* clear the blocklist */
198+ strncpy (owl -> blocklist , blist , strlen (blist ));
199+ }
200+
201+ static void blocklist_nl_recv (struct sk_buff * skb )
202+ {
203+ struct nlmsghdr * nlh ; /* netlink message header */
204+ int pid ;
205+ struct sk_buff * skb_out ;
206+ char * msg = "vwifi has received your blocklist" ;
207+ int msg_size = strlen (msg );
208+
209+ nlh = (struct nlmsghdr * ) skb -> data ;
210+
211+ blocklist_load ((char * ) nlmsg_data (nlh ));
212+
213+ /* pid of sending process */
214+ pid = nlh -> nlmsg_pid ;
215+
216+ skb_out = nlmsg_new (msg_size , 0 );
217+ if (!skb_out ) {
218+ pr_info ("netlink: Failed to allocate new skb\n" );
219+ return ;
220+ }
221+
222+ nlh = nlmsg_put (skb_out , 0 , 0 , NLMSG_DONE , msg_size , 0 );
223+ NETLINK_CB (skb_out ).dst_group = 0 ; /* unicast group */
224+ strncpy (nlmsg_data (nlh ), msg , msg_size );
225+
226+ if (nlmsg_unicast (nl_sk , skb_out , pid ) < 0 )
227+ pr_info ("netlink: Error while sending back to user\n" );
228+ }
229+
230+ struct netlink_kernel_cfg nl_config = {
231+ .input = blocklist_nl_recv ,
232+ };
233+
153234/**
154235 * enum virtio_vqs - queues for virtio frame transmission and receivement
155236 *
@@ -713,6 +794,13 @@ static netdev_tx_t owl_ndo_start_xmit(struct sk_buff *skb,
713794 }
714795 /* TX by interface of AP mode */
715796 else if (vif -> wdev .iftype == NL80211_IFTYPE_AP ) {
797+ /* Find the source interface name */
798+ char * source_name ;
799+ list_for_each_entry (dest_vif , & vif -> bss_list , bss_list ) {
800+ if (ether_addr_equal (eth_hdr -> h_source , dest_vif -> ndev -> dev_addr ))
801+ source_name = dest_vif -> ndev -> name ;
802+ }
803+
716804 /* Check if the packet is broadcasting */
717805 if (is_broadcast_ether_addr (eth_hdr -> h_dest )) {
718806 list_for_each_entry (dest_vif , & vif -> bss_list , bss_list ) {
@@ -722,6 +810,10 @@ static netdev_tx_t owl_ndo_start_xmit(struct sk_buff *skb,
722810 dest_vif -> ndev -> dev_addr ))
723811 continue ;
724812
813+ /* Don't send packet from dest_vif's blocklist */
814+ if (blocklist_check (dest_vif -> ndev -> name , source_name ))
815+ continue ;
816+
725817 if (__owl_ndo_start_xmit (vif , dest_vif , skb ))
726818 count ++ ;
727819 }
@@ -731,7 +823,8 @@ static netdev_tx_t owl_ndo_start_xmit(struct sk_buff *skb,
731823 list_for_each_entry (dest_vif , & vif -> bss_list , bss_list ) {
732824 if (ether_addr_equal (eth_hdr -> h_dest ,
733825 dest_vif -> ndev -> dev_addr )) {
734- if (__owl_ndo_start_xmit (vif , dest_vif , skb ))
826+ if (!blocklist_check (dest_vif -> ndev -> name , source_name ) &&
827+ __owl_ndo_start_xmit (vif , dest_vif , skb ))
735828 count ++ ;
736829 break ;
737830 }
@@ -1782,6 +1875,7 @@ static void owl_free(void)
17821875 list_for_each_entry_safe (vif , safe , & owl -> vif_list , list )
17831876 owl_delete_interface (vif );
17841877
1878+ kfree (owl -> blocklist );
17851879 kfree (owl );
17861880}
17871881
@@ -2832,6 +2926,7 @@ static int __init vwifi_init(void)
28322926 mutex_init (& owl -> lock );
28332927 INIT_LIST_HEAD (& owl -> vif_list );
28342928 INIT_LIST_HEAD (& owl -> ap_list );
2929+ owl -> blocklist = kmalloc (sizeof (char ) * MAX_BLACKLIST_SIZE , GFP_KERNEL );
28352930
28362931 for (int i = 0 ; i < station ; i ++ ) {
28372932 struct wiphy * wiphy = owcfg80211_add ();
@@ -2841,6 +2936,12 @@ static int __init vwifi_init(void)
28412936 goto interface_add ;
28422937 }
28432938
2939+ nl_sk = netlink_kernel_create (& init_net , MAX_NETLINK_USER , & nl_config );
2940+ if (!nl_sk ) {
2941+ pr_info ("Error creating netlink socket\n" );
2942+ goto cfg80211_add ;
2943+ }
2944+
28442945 err = register_virtio_driver (& virtio_vwifi );
28452946 if (err )
28462947 goto err_register_virtio_driver ;
@@ -2864,6 +2965,7 @@ static void __exit vwifi_exit(void)
28642965
28652966 unregister_virtio_driver (& virtio_vwifi );
28662967 owl_free ();
2968+ netlink_kernel_release (nl_sk );
28672969}
28682970
28692971module_init (vwifi_init );
0 commit comments