@@ -1003,6 +1003,55 @@ 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+ bool getarp )
1008+ {
1009+ struct net_device * dev ;
1010+
1011+ if (getarp )
1012+ dev = dev_get_by_name_rcu (net , r -> arp_dev );
1013+ else
1014+ dev = __dev_get_by_name (net , r -> arp_dev );
1015+ if (!dev )
1016+ return ERR_PTR (- ENODEV );
1017+
1018+ /* Mmmm... It is wrong... ARPHRD_NETROM == 0 */
1019+ if (!r -> arp_ha .sa_family )
1020+ r -> arp_ha .sa_family = dev -> type ;
1021+
1022+ if ((r -> arp_flags & ATF_COM ) && r -> arp_ha .sa_family != dev -> type )
1023+ return ERR_PTR (- EINVAL );
1024+
1025+ return dev ;
1026+ }
1027+
1028+ static struct net_device * arp_req_dev (struct net * net , struct arpreq * r )
1029+ {
1030+ struct net_device * dev ;
1031+ struct rtable * rt ;
1032+ __be32 ip ;
1033+
1034+ if (r -> arp_dev [0 ])
1035+ return arp_req_dev_by_name (net , r , false);
1036+
1037+ if (r -> arp_flags & ATF_PUBL )
1038+ return NULL ;
1039+
1040+ ip = ((struct sockaddr_in * )& r -> arp_pa )-> sin_addr .s_addr ;
1041+
1042+ rt = ip_route_output (net , ip , 0 , 0 , 0 , RT_SCOPE_LINK );
1043+ if (IS_ERR (rt ))
1044+ return ERR_CAST (rt );
1045+
1046+ dev = rt -> dst .dev ;
1047+ ip_rt_put (rt );
1048+
1049+ if (!dev )
1050+ return ERR_PTR (- EINVAL );
1051+
1052+ return dev ;
1053+ }
1054+
10061055/*
10071056 * Set (create) an ARP cache entry.
10081057 */
@@ -1023,18 +1072,17 @@ static int arp_req_set_proxy(struct net *net, struct net_device *dev, int on)
10231072static int arp_req_set_public (struct net * net , struct arpreq * r ,
10241073 struct net_device * dev )
10251074{
1026- __be32 ip = ((struct sockaddr_in * )& r -> arp_pa )-> sin_addr .s_addr ;
10271075 __be32 mask = ((struct sockaddr_in * )& r -> arp_netmask )-> sin_addr .s_addr ;
10281076
1029- if (mask && mask != htonl (0xFFFFFFFF ))
1030- return - EINVAL ;
10311077 if (!dev && (r -> arp_flags & ATF_COM )) {
10321078 dev = dev_getbyhwaddr_rcu (net , r -> arp_ha .sa_family ,
10331079 r -> arp_ha .sa_data );
10341080 if (!dev )
10351081 return - ENODEV ;
10361082 }
10371083 if (mask ) {
1084+ __be32 ip = ((struct sockaddr_in * )& r -> arp_pa )-> sin_addr .s_addr ;
1085+
10381086 if (!pneigh_lookup (& arp_tbl , net , & ip , dev , 1 ))
10391087 return - ENOBUFS ;
10401088 return 0 ;
@@ -1043,30 +1091,20 @@ static int arp_req_set_public(struct net *net, struct arpreq *r,
10431091 return arp_req_set_proxy (net , dev , 1 );
10441092}
10451093
1046- static int arp_req_set (struct net * net , struct arpreq * r ,
1047- struct net_device * dev )
1094+ static int arp_req_set (struct net * net , struct arpreq * r )
10481095{
1049- __be32 ip ;
10501096 struct neighbour * neigh ;
1097+ struct net_device * dev ;
1098+ __be32 ip ;
10511099 int err ;
10521100
1101+ dev = arp_req_dev (net , r );
1102+ if (IS_ERR (dev ))
1103+ return PTR_ERR (dev );
1104+
10531105 if (r -> arp_flags & ATF_PUBL )
10541106 return arp_req_set_public (net , r , dev );
10551107
1056- ip = ((struct sockaddr_in * )& r -> arp_pa )-> sin_addr .s_addr ;
1057- if (r -> arp_flags & ATF_PERM )
1058- r -> arp_flags |= ATF_COM ;
1059- if (!dev ) {
1060- struct rtable * rt = ip_route_output (net , ip , 0 , 0 , 0 ,
1061- RT_SCOPE_LINK );
1062-
1063- if (IS_ERR (rt ))
1064- return PTR_ERR (rt );
1065- dev = rt -> dst .dev ;
1066- ip_rt_put (rt );
1067- if (!dev )
1068- return - EINVAL ;
1069- }
10701108 switch (dev -> type ) {
10711109#if IS_ENABLED (CONFIG_FDDI )
10721110 case ARPHRD_FDDI :
@@ -1088,12 +1126,18 @@ static int arp_req_set(struct net *net, struct arpreq *r,
10881126 break ;
10891127 }
10901128
1129+ ip = ((struct sockaddr_in * )& r -> arp_pa )-> sin_addr .s_addr ;
1130+
10911131 neigh = __neigh_lookup_errno (& arp_tbl , & ip , dev );
10921132 err = PTR_ERR (neigh );
10931133 if (!IS_ERR (neigh )) {
10941134 unsigned int state = NUD_STALE ;
1095- if (r -> arp_flags & ATF_PERM )
1135+
1136+ if (r -> arp_flags & ATF_PERM ) {
1137+ r -> arp_flags |= ATF_COM ;
10961138 state = NUD_PERMANENT ;
1139+ }
1140+
10971141 err = neigh_update (neigh , (r -> arp_flags & ATF_COM ) ?
10981142 r -> arp_ha .sa_data : NULL , state ,
10991143 NEIGH_UPDATE_F_OVERRIDE |
@@ -1117,27 +1161,40 @@ static unsigned int arp_state_to_flags(struct neighbour *neigh)
11171161 * Get an ARP cache entry.
11181162 */
11191163
1120- static int arp_req_get (struct arpreq * r , struct net_device * dev )
1164+ static int arp_req_get (struct net * net , struct arpreq * r )
11211165{
11221166 __be32 ip = ((struct sockaddr_in * ) & r -> arp_pa )-> sin_addr .s_addr ;
11231167 struct neighbour * neigh ;
1124- int err = - ENXIO ;
1168+ struct net_device * dev ;
1169+
1170+ if (!r -> arp_dev [0 ])
1171+ return - ENODEV ;
1172+
1173+ dev = arp_req_dev_by_name (net , r , true);
1174+ if (IS_ERR (dev ))
1175+ return PTR_ERR (dev );
11251176
11261177 neigh = neigh_lookup (& arp_tbl , & ip , dev );
1127- if (neigh ) {
1128- if (!(READ_ONCE (neigh -> nud_state ) & NUD_NOARP )) {
1129- read_lock_bh (& neigh -> lock );
1130- memcpy (r -> arp_ha .sa_data , neigh -> ha ,
1131- min (dev -> addr_len , sizeof (r -> arp_ha .sa_data_min )));
1132- r -> arp_flags = arp_state_to_flags (neigh );
1133- read_unlock_bh (& neigh -> lock );
1134- r -> arp_ha .sa_family = dev -> type ;
1135- strscpy (r -> arp_dev , dev -> name , sizeof (r -> arp_dev ));
1136- err = 0 ;
1137- }
1178+ if (!neigh )
1179+ return - ENXIO ;
1180+
1181+ if (READ_ONCE (neigh -> nud_state ) & NUD_NOARP ) {
11381182 neigh_release (neigh );
1183+ return - ENXIO ;
11391184 }
1140- return err ;
1185+
1186+ read_lock_bh (& neigh -> lock );
1187+ memcpy (r -> arp_ha .sa_data , neigh -> ha ,
1188+ min (dev -> addr_len , sizeof (r -> arp_ha .sa_data_min )));
1189+ r -> arp_flags = arp_state_to_flags (neigh );
1190+ read_unlock_bh (& neigh -> lock );
1191+
1192+ neigh_release (neigh );
1193+
1194+ r -> arp_ha .sa_family = dev -> type ;
1195+ netdev_copy_name (dev , r -> arp_dev );
1196+
1197+ return 0 ;
11411198}
11421199
11431200int arp_invalidate (struct net_device * dev , __be32 ip , bool force )
@@ -1168,37 +1225,31 @@ int arp_invalidate(struct net_device *dev, __be32 ip, bool force)
11681225static int arp_req_delete_public (struct net * net , struct arpreq * r ,
11691226 struct net_device * dev )
11701227{
1171- __be32 ip = ((struct sockaddr_in * ) & r -> arp_pa )-> sin_addr .s_addr ;
11721228 __be32 mask = ((struct sockaddr_in * )& r -> arp_netmask )-> sin_addr .s_addr ;
11731229
1174- if (mask == htonl ( 0xFFFFFFFF ))
1175- return pneigh_delete ( & arp_tbl , net , & ip , dev ) ;
1230+ if (mask ) {
1231+ __be32 ip = (( struct sockaddr_in * ) & r -> arp_pa ) -> sin_addr . s_addr ;
11761232
1177- if ( mask )
1178- return - EINVAL ;
1233+ return pneigh_delete ( & arp_tbl , net , & ip , dev );
1234+ }
11791235
11801236 return arp_req_set_proxy (net , dev , 0 );
11811237}
11821238
1183- static int arp_req_delete (struct net * net , struct arpreq * r ,
1184- struct net_device * dev )
1239+ static int arp_req_delete (struct net * net , struct arpreq * r )
11851240{
1241+ struct net_device * dev ;
11861242 __be32 ip ;
11871243
1244+ dev = arp_req_dev (net , r );
1245+ if (IS_ERR (dev ))
1246+ return PTR_ERR (dev );
1247+
11881248 if (r -> arp_flags & ATF_PUBL )
11891249 return arp_req_delete_public (net , r , dev );
11901250
11911251 ip = ((struct sockaddr_in * )& r -> arp_pa )-> sin_addr .s_addr ;
1192- if (!dev ) {
1193- struct rtable * rt = ip_route_output (net , ip , 0 , 0 , 0 ,
1194- RT_SCOPE_LINK );
1195- if (IS_ERR (rt ))
1196- return PTR_ERR (rt );
1197- dev = rt -> dst .dev ;
1198- ip_rt_put (rt );
1199- if (!dev )
1200- return - EINVAL ;
1201- }
1252+
12021253 return arp_invalidate (dev , ip , true);
12031254}
12041255
@@ -1208,9 +1259,9 @@ static int arp_req_delete(struct net *net, struct arpreq *r,
12081259
12091260int arp_ioctl (struct net * net , unsigned int cmd , void __user * arg )
12101261{
1211- int err ;
12121262 struct arpreq r ;
1213- struct net_device * dev = NULL ;
1263+ __be32 * netmask ;
1264+ int err ;
12141265
12151266 switch (cmd ) {
12161267 case SIOCDARP :
@@ -1233,42 +1284,34 @@ int arp_ioctl(struct net *net, unsigned int cmd, void __user *arg)
12331284 if (!(r .arp_flags & ATF_PUBL ) &&
12341285 (r .arp_flags & (ATF_NETMASK | ATF_DONTPUB )))
12351286 return - EINVAL ;
1287+
1288+ netmask = & ((struct sockaddr_in * )& r .arp_netmask )-> sin_addr .s_addr ;
12361289 if (!(r .arp_flags & ATF_NETMASK ))
1237- ((struct sockaddr_in * )& r .arp_netmask )-> sin_addr .s_addr =
1238- htonl (0xFFFFFFFFUL );
1239- rtnl_lock ();
1240- if (r .arp_dev [0 ]) {
1241- err = - ENODEV ;
1242- dev = __dev_get_by_name (net , r .arp_dev );
1243- if (!dev )
1244- goto out ;
1245-
1246- /* Mmmm... It is wrong... ARPHRD_NETROM==0 */
1247- if (!r .arp_ha .sa_family )
1248- r .arp_ha .sa_family = dev -> type ;
1249- err = - EINVAL ;
1250- if ((r .arp_flags & ATF_COM ) && r .arp_ha .sa_family != dev -> type )
1251- goto out ;
1252- } else if (cmd == SIOCGARP ) {
1253- err = - ENODEV ;
1254- goto out ;
1255- }
1290+ * netmask = htonl (0xFFFFFFFFUL );
1291+ else if (* netmask && * netmask != htonl (0xFFFFFFFFUL ))
1292+ return - EINVAL ;
12561293
12571294 switch (cmd ) {
12581295 case SIOCDARP :
1259- err = arp_req_delete (net , & r , dev );
1296+ rtnl_lock ();
1297+ err = arp_req_delete (net , & r );
1298+ rtnl_unlock ();
12601299 break ;
12611300 case SIOCSARP :
1262- err = arp_req_set (net , & r , dev );
1301+ rtnl_lock ();
1302+ err = arp_req_set (net , & r );
1303+ rtnl_unlock ();
12631304 break ;
12641305 case SIOCGARP :
1265- err = arp_req_get (& r , dev );
1306+ rcu_read_lock ();
1307+ err = arp_req_get (net , & r );
1308+ rcu_read_unlock ();
1309+
1310+ if (!err && copy_to_user (arg , & r , sizeof (r )))
1311+ err = - EFAULT ;
12661312 break ;
12671313 }
1268- out :
1269- rtnl_unlock ();
1270- if (cmd == SIOCGARP && !err && copy_to_user (arg , & r , sizeof (r )))
1271- err = - EFAULT ;
1314+
12721315 return err ;
12731316}
12741317
0 commit comments