Skip to content

Commit e986d4d

Browse files
author
Al Viro
committed
set_mcast_msfilter(): take the guts of setsockopt(MCAST_MSFILTER) into a helper
Signed-off-by: Al Viro <[email protected]>
1 parent 0dfe658 commit e986d4d

File tree

1 file changed

+40
-33
lines changed

1 file changed

+40
-33
lines changed

net/ipv4/ip_sockglue.c

Lines changed: 40 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -587,6 +587,43 @@ static bool setsockopt_needs_rtnl(int optname)
587587
return false;
588588
}
589589

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+
590627
static int do_ip_setsockopt(struct sock *sk, int level,
591628
int optname, char __user *optval, unsigned int optlen)
592629
{
@@ -1079,10 +1116,7 @@ static int do_ip_setsockopt(struct sock *sk, int level,
10791116
}
10801117
case MCAST_MSFILTER:
10811118
{
1082-
struct sockaddr_in *psin;
1083-
struct ip_msfilter *msf = NULL;
10841119
struct group_filter *gsf = NULL;
1085-
int msize, i, ifindex;
10861120

10871121
if (optlen < GROUP_FILTER_SIZE(0))
10881122
goto e_inval;
@@ -1095,7 +1129,6 @@ static int do_ip_setsockopt(struct sock *sk, int level,
10951129
err = PTR_ERR(gsf);
10961130
break;
10971131
}
1098-
10991132
/* numsrc >= (4G-140)/128 overflow in 32 bits */
11001133
if (gsf->gf_numsrc >= 0x1ffffff ||
11011134
gsf->gf_numsrc > net->ipv4.sysctl_igmp_max_msf) {
@@ -1106,36 +1139,10 @@ static int do_ip_setsockopt(struct sock *sk, int level,
11061139
err = -EINVAL;
11071140
goto mc_msf_out;
11081141
}
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);
11371145
mc_msf_out:
1138-
kfree(msf);
11391146
kfree(gsf);
11401147
break;
11411148
}

0 commit comments

Comments
 (0)