@@ -1003,12 +1003,36 @@ static int arp_rcv(struct sk_buff *skb, struct net_device *dev,
10031003 * User level interface (ioctl)
10041004 */
10051005
1006+ static struct net_device * arp_req_dev_by_name (struct net * net , struct arpreq * r )
1007+ {
1008+ struct net_device * dev ;
1009+
1010+ dev = __dev_get_by_name (net , r -> arp_dev );
1011+ if (!dev )
1012+ return ERR_PTR (- ENODEV );
1013+
1014+ /* Mmmm... It is wrong... ARPHRD_NETROM == 0 */
1015+ if (!r -> arp_ha .sa_family )
1016+ r -> arp_ha .sa_family = dev -> type ;
1017+
1018+ if ((r -> arp_flags & ATF_COM ) && r -> arp_ha .sa_family != dev -> type )
1019+ return ERR_PTR (- EINVAL );
1020+
1021+ return dev ;
1022+ }
1023+
10061024static struct net_device * arp_req_dev (struct net * net , struct arpreq * r )
10071025{
10081026 struct net_device * dev ;
10091027 struct rtable * rt ;
10101028 __be32 ip ;
10111029
1030+ if (r -> arp_dev [0 ])
1031+ return arp_req_dev_by_name (net , r );
1032+
1033+ if (r -> arp_flags & ATF_PUBL )
1034+ return NULL ;
1035+
10121036 ip = ((struct sockaddr_in * )& r -> arp_pa )-> sin_addr .s_addr ;
10131037
10141038 rt = ip_route_output (net , ip , 0 , 0 , 0 , RT_SCOPE_LINK );
@@ -1063,21 +1087,20 @@ static int arp_req_set_public(struct net *net, struct arpreq *r,
10631087 return arp_req_set_proxy (net , dev , 1 );
10641088}
10651089
1066- static int arp_req_set (struct net * net , struct arpreq * r ,
1067- struct net_device * dev )
1090+ static int arp_req_set (struct net * net , struct arpreq * r )
10681091{
10691092 struct neighbour * neigh ;
1093+ struct net_device * dev ;
10701094 __be32 ip ;
10711095 int err ;
10721096
1097+ dev = arp_req_dev (net , r );
1098+ if (IS_ERR (dev ))
1099+ return PTR_ERR (dev );
1100+
10731101 if (r -> arp_flags & ATF_PUBL )
10741102 return arp_req_set_public (net , r , dev );
10751103
1076- if (!dev ) {
1077- dev = arp_req_dev (net , r );
1078- if (IS_ERR (dev ))
1079- return PTR_ERR (dev );
1080- }
10811104 switch (dev -> type ) {
10821105#if IS_ENABLED (CONFIG_FDDI )
10831106 case ARPHRD_FDDI :
@@ -1134,10 +1157,18 @@ static unsigned int arp_state_to_flags(struct neighbour *neigh)
11341157 * Get an ARP cache entry.
11351158 */
11361159
1137- static int arp_req_get (struct arpreq * r , struct net_device * dev )
1160+ static int arp_req_get (struct net * net , struct arpreq * r )
11381161{
11391162 __be32 ip = ((struct sockaddr_in * ) & r -> arp_pa )-> sin_addr .s_addr ;
11401163 struct neighbour * neigh ;
1164+ struct net_device * dev ;
1165+
1166+ if (!r -> arp_dev [0 ])
1167+ return - ENODEV ;
1168+
1169+ dev = arp_req_dev_by_name (net , r );
1170+ if (IS_ERR (dev ))
1171+ return PTR_ERR (dev );
11411172
11421173 neigh = neigh_lookup (& arp_tbl , & ip , dev );
11431174 if (!neigh )
@@ -1201,20 +1232,20 @@ static int arp_req_delete_public(struct net *net, struct arpreq *r,
12011232 return arp_req_set_proxy (net , dev , 0 );
12021233}
12031234
1204- static int arp_req_delete (struct net * net , struct arpreq * r ,
1205- struct net_device * dev )
1235+ static int arp_req_delete (struct net * net , struct arpreq * r )
12061236{
1237+ struct net_device * dev ;
12071238 __be32 ip ;
12081239
1240+ dev = arp_req_dev (net , r );
1241+ if (IS_ERR (dev ))
1242+ return PTR_ERR (dev );
1243+
12091244 if (r -> arp_flags & ATF_PUBL )
12101245 return arp_req_delete_public (net , r , dev );
12111246
12121247 ip = ((struct sockaddr_in * )& r -> arp_pa )-> sin_addr .s_addr ;
1213- if (!dev ) {
1214- dev = arp_req_dev (net , r );
1215- if (IS_ERR (dev ))
1216- return PTR_ERR (dev );
1217- }
1248+
12181249 return arp_invalidate (dev , ip , true);
12191250}
12201251
@@ -1224,7 +1255,6 @@ static int arp_req_delete(struct net *net, struct arpreq *r,
12241255
12251256int arp_ioctl (struct net * net , unsigned int cmd , void __user * arg )
12261257{
1227- struct net_device * dev = NULL ;
12281258 struct arpreq r ;
12291259 __be32 * netmask ;
12301260 int err ;
@@ -1258,35 +1288,19 @@ int arp_ioctl(struct net *net, unsigned int cmd, void __user *arg)
12581288 return - EINVAL ;
12591289
12601290 rtnl_lock ();
1261- if (r .arp_dev [0 ]) {
1262- err = - ENODEV ;
1263- dev = __dev_get_by_name (net , r .arp_dev );
1264- if (!dev )
1265- goto out ;
1266-
1267- /* Mmmm... It is wrong... ARPHRD_NETROM==0 */
1268- if (!r .arp_ha .sa_family )
1269- r .arp_ha .sa_family = dev -> type ;
1270- err = - EINVAL ;
1271- if ((r .arp_flags & ATF_COM ) && r .arp_ha .sa_family != dev -> type )
1272- goto out ;
1273- } else if (cmd == SIOCGARP ) {
1274- err = - ENODEV ;
1275- goto out ;
1276- }
12771291
12781292 switch (cmd ) {
12791293 case SIOCDARP :
1280- err = arp_req_delete (net , & r , dev );
1294+ err = arp_req_delete (net , & r );
12811295 break ;
12821296 case SIOCSARP :
1283- err = arp_req_set (net , & r , dev );
1297+ err = arp_req_set (net , & r );
12841298 break ;
12851299 case SIOCGARP :
1286- err = arp_req_get (& r , dev );
1300+ err = arp_req_get (net , & r );
12871301 break ;
12881302 }
1289- out :
1303+
12901304 rtnl_unlock ();
12911305 if (cmd == SIOCGARP && !err && copy_to_user (arg , & r , sizeof (r )))
12921306 err = - EFAULT ;
0 commit comments