@@ -81,6 +81,7 @@ struct netlink_sock {
81
81
};
82
82
83
83
#define NETLINK_KERNEL_SOCKET 0x1
84
+ #define NETLINK_RECV_PKTINFO 0x2
84
85
85
86
static inline struct netlink_sock * nlk_sk (struct sock * sk )
86
87
{
@@ -946,6 +947,94 @@ void netlink_set_err(struct sock *ssk, u32 pid, u32 group, int code)
946
947
read_unlock (& nl_table_lock );
947
948
}
948
949
950
+ static int netlink_setsockopt (struct socket * sock , int level , int optname ,
951
+ char __user * optval , int optlen )
952
+ {
953
+ struct sock * sk = sock -> sk ;
954
+ struct netlink_sock * nlk = nlk_sk (sk );
955
+ int val = 0 , err ;
956
+
957
+ if (level != SOL_NETLINK )
958
+ return - ENOPROTOOPT ;
959
+
960
+ if (optlen >= sizeof (int ) &&
961
+ get_user (val , (int __user * )optval ))
962
+ return - EFAULT ;
963
+
964
+ switch (optname ) {
965
+ case NETLINK_PKTINFO :
966
+ if (val )
967
+ nlk -> flags |= NETLINK_RECV_PKTINFO ;
968
+ else
969
+ nlk -> flags &= ~NETLINK_RECV_PKTINFO ;
970
+ err = 0 ;
971
+ break ;
972
+ case NETLINK_ADD_MEMBERSHIP :
973
+ case NETLINK_DROP_MEMBERSHIP : {
974
+ unsigned int subscriptions ;
975
+ int old , new = optname == NETLINK_ADD_MEMBERSHIP ? 1 : 0 ;
976
+
977
+ if (!netlink_capable (sock , NL_NONROOT_RECV ))
978
+ return - EPERM ;
979
+ if (!val || val - 1 >= nlk -> ngroups )
980
+ return - EINVAL ;
981
+ netlink_table_grab ();
982
+ old = test_bit (val - 1 , nlk -> groups );
983
+ subscriptions = nlk -> subscriptions - old + new ;
984
+ if (new )
985
+ __set_bit (val - 1 , nlk -> groups );
986
+ else
987
+ __clear_bit (val - 1 , nlk -> groups );
988
+ netlink_update_subscriptions (sk , subscriptions );
989
+ netlink_table_ungrab ();
990
+ err = 0 ;
991
+ break ;
992
+ }
993
+ default :
994
+ err = - ENOPROTOOPT ;
995
+ }
996
+ return err ;
997
+ }
998
+
999
+ static int netlink_getsockopt (struct socket * sock , int level , int optname ,
1000
+ char __user * optval , int __user * optlen )
1001
+ {
1002
+ struct sock * sk = sock -> sk ;
1003
+ struct netlink_sock * nlk = nlk_sk (sk );
1004
+ int len , val , err ;
1005
+
1006
+ if (level != SOL_NETLINK )
1007
+ return - ENOPROTOOPT ;
1008
+
1009
+ if (get_user (len , optlen ))
1010
+ return - EFAULT ;
1011
+ if (len < 0 )
1012
+ return - EINVAL ;
1013
+
1014
+ switch (optname ) {
1015
+ case NETLINK_PKTINFO :
1016
+ if (len < sizeof (int ))
1017
+ return - EINVAL ;
1018
+ len = sizeof (int );
1019
+ val = nlk -> flags & NETLINK_RECV_PKTINFO ? 1 : 0 ;
1020
+ put_user (len , optlen );
1021
+ put_user (val , optval );
1022
+ err = 0 ;
1023
+ break ;
1024
+ default :
1025
+ err = - ENOPROTOOPT ;
1026
+ }
1027
+ return err ;
1028
+ }
1029
+
1030
+ static void netlink_cmsg_recv_pktinfo (struct msghdr * msg , struct sk_buff * skb )
1031
+ {
1032
+ struct nl_pktinfo info ;
1033
+
1034
+ info .group = NETLINK_CB (skb ).dst_group ;
1035
+ put_cmsg (msg , SOL_NETLINK , NETLINK_PKTINFO , sizeof (info ), & info );
1036
+ }
1037
+
949
1038
static inline void netlink_rcv_wake (struct sock * sk )
950
1039
{
951
1040
struct netlink_sock * nlk = nlk_sk (sk );
@@ -1091,6 +1180,8 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock,
1091
1180
netlink_dump (sk );
1092
1181
1093
1182
scm_recv (sock , msg , siocb -> scm , flags );
1183
+ if (nlk -> flags & NETLINK_RECV_PKTINFO )
1184
+ netlink_cmsg_recv_pktinfo (msg , skb );
1094
1185
1095
1186
out :
1096
1187
netlink_rcv_wake (sk );
@@ -1465,8 +1556,8 @@ static struct proto_ops netlink_ops = {
1465
1556
.ioctl = sock_no_ioctl ,
1466
1557
.listen = sock_no_listen ,
1467
1558
.shutdown = sock_no_shutdown ,
1468
- .setsockopt = sock_no_setsockopt ,
1469
- .getsockopt = sock_no_getsockopt ,
1559
+ .setsockopt = netlink_setsockopt ,
1560
+ .getsockopt = netlink_getsockopt ,
1470
1561
.sendmsg = netlink_sendmsg ,
1471
1562
.recvmsg = netlink_recvmsg ,
1472
1563
.mmap = sock_no_mmap ,
0 commit comments