@@ -587,6 +587,43 @@ static bool setsockopt_needs_rtnl(int optname)
587
587
return false;
588
588
}
589
589
590
+ static int set_mcast_msfilter (struct sock * sk , int ifindex ,
591
+ int numsrc , int fmode ,
592
+ struct sockaddr_storage * group ,
593
+ struct sockaddr_storage * list )
594
+ {
595
+ int msize = IP_MSFILTER_SIZE (numsrc );
596
+ struct ip_msfilter * msf ;
597
+ struct sockaddr_in * psin ;
598
+ int err , i ;
599
+
600
+ msf = kmalloc (msize , GFP_KERNEL );
601
+ if (!msf )
602
+ return - ENOBUFS ;
603
+
604
+ psin = (struct sockaddr_in * )group ;
605
+ if (psin -> sin_family != AF_INET )
606
+ goto Eaddrnotavail ;
607
+ msf -> imsf_multiaddr = psin -> sin_addr .s_addr ;
608
+ msf -> imsf_interface = 0 ;
609
+ msf -> imsf_fmode = fmode ;
610
+ msf -> imsf_numsrc = numsrc ;
611
+ for (i = 0 ; i < numsrc ; ++ i ) {
612
+ psin = (struct sockaddr_in * )& list [i ];
613
+
614
+ if (psin -> sin_family != AF_INET )
615
+ goto Eaddrnotavail ;
616
+ msf -> imsf_slist [i ] = psin -> sin_addr .s_addr ;
617
+ }
618
+ err = ip_mc_msfilter (sk , msf , ifindex );
619
+ kfree (msf );
620
+ return err ;
621
+
622
+ Eaddrnotavail :
623
+ kfree (msf );
624
+ return - EADDRNOTAVAIL ;
625
+ }
626
+
590
627
static int do_ip_setsockopt (struct sock * sk , int level ,
591
628
int optname , char __user * optval , unsigned int optlen )
592
629
{
@@ -1079,10 +1116,7 @@ static int do_ip_setsockopt(struct sock *sk, int level,
1079
1116
}
1080
1117
case MCAST_MSFILTER :
1081
1118
{
1082
- struct sockaddr_in * psin ;
1083
- struct ip_msfilter * msf = NULL ;
1084
1119
struct group_filter * gsf = NULL ;
1085
- int msize , i , ifindex ;
1086
1120
1087
1121
if (optlen < GROUP_FILTER_SIZE (0 ))
1088
1122
goto e_inval ;
@@ -1095,7 +1129,6 @@ static int do_ip_setsockopt(struct sock *sk, int level,
1095
1129
err = PTR_ERR (gsf );
1096
1130
break ;
1097
1131
}
1098
-
1099
1132
/* numsrc >= (4G-140)/128 overflow in 32 bits */
1100
1133
if (gsf -> gf_numsrc >= 0x1ffffff ||
1101
1134
gsf -> gf_numsrc > net -> ipv4 .sysctl_igmp_max_msf ) {
@@ -1106,36 +1139,10 @@ static int do_ip_setsockopt(struct sock *sk, int level,
1106
1139
err = - EINVAL ;
1107
1140
goto mc_msf_out ;
1108
1141
}
1109
- msize = IP_MSFILTER_SIZE (gsf -> gf_numsrc );
1110
- msf = kmalloc (msize , GFP_KERNEL );
1111
- if (!msf ) {
1112
- err = - ENOBUFS ;
1113
- goto mc_msf_out ;
1114
- }
1115
- ifindex = gsf -> gf_interface ;
1116
- psin = (struct sockaddr_in * )& gsf -> gf_group ;
1117
- if (psin -> sin_family != AF_INET ) {
1118
- err = - EADDRNOTAVAIL ;
1119
- goto mc_msf_out ;
1120
- }
1121
- msf -> imsf_multiaddr = psin -> sin_addr .s_addr ;
1122
- msf -> imsf_interface = 0 ;
1123
- msf -> imsf_fmode = gsf -> gf_fmode ;
1124
- msf -> imsf_numsrc = gsf -> gf_numsrc ;
1125
- err = - EADDRNOTAVAIL ;
1126
- for (i = 0 ; i < gsf -> gf_numsrc ; ++ i ) {
1127
- psin = (struct sockaddr_in * )& gsf -> gf_slist [i ];
1128
-
1129
- if (psin -> sin_family != AF_INET )
1130
- goto mc_msf_out ;
1131
- msf -> imsf_slist [i ] = psin -> sin_addr .s_addr ;
1132
- }
1133
- kfree (gsf );
1134
- gsf = NULL ;
1135
-
1136
- err = ip_mc_msfilter (sk , msf , ifindex );
1142
+ err = set_mcast_msfilter (sk , gsf -> gf_interface ,
1143
+ gsf -> gf_numsrc , gsf -> gf_fmode ,
1144
+ & gsf -> gf_group , gsf -> gf_slist );
1137
1145
mc_msf_out :
1138
- kfree (msf );
1139
1146
kfree (gsf );
1140
1147
break ;
1141
1148
}
0 commit comments