|
Lines 66-71
Link Here
|
| 66 |
* Alexey Kuznetsov: new arp state machine; |
66 |
* Alexey Kuznetsov: new arp state machine; |
| 67 |
* now it is in net/core/neighbour.c. |
67 |
* now it is in net/core/neighbour.c. |
| 68 |
* Krzysztof Halasa: Added Frame Relay ARP support. |
68 |
* Krzysztof Halasa: Added Frame Relay ARP support. |
|
|
69 |
* Julian Anastasov: "hidden" flag: hide the |
| 70 |
* interface and don't reply for it |
| 71 |
* Julian Anastasov: ARP filtering via netlink |
| 69 |
*/ |
72 |
*/ |
| 70 |
|
73 |
|
| 71 |
#include <linux/types.h> |
74 |
#include <linux/types.h> |
|
Lines 87-92
Link Here
|
| 87 |
#include <linux/skbuff.h> |
90 |
#include <linux/skbuff.h> |
| 88 |
#include <linux/proc_fs.h> |
91 |
#include <linux/proc_fs.h> |
| 89 |
#include <linux/stat.h> |
92 |
#include <linux/stat.h> |
|
|
93 |
#include <linux/netlink.h> |
| 90 |
#include <linux/init.h> |
94 |
#include <linux/init.h> |
| 91 |
#ifdef CONFIG_SYSCTL |
95 |
#ifdef CONFIG_SYSCTL |
| 92 |
#include <linux/sysctl.h> |
96 |
#include <linux/sysctl.h> |
|
Lines 190-195
struct neigh_table arp_tbl = {
Link Here
|
| 190 |
gc_thresh3: 1024, |
194 |
gc_thresh3: 1024, |
| 191 |
}; |
195 |
}; |
| 192 |
|
196 |
|
|
|
197 |
struct arpf_node { |
| 198 |
struct arpf_node * at_next; |
| 199 |
u32 at_pref; |
| 200 |
u32 at_from; |
| 201 |
u32 at_from_mask; |
| 202 |
u32 at_to; |
| 203 |
u32 at_to_mask; |
| 204 |
u32 at_src; |
| 205 |
atomic_t at_packets; |
| 206 |
atomic_t at_refcnt; |
| 207 |
unsigned at_flags; |
| 208 |
unsigned char at_from_len; |
| 209 |
unsigned char at_to_len; |
| 210 |
unsigned char at_action; |
| 211 |
char at_dead; |
| 212 |
unsigned char at_llfrom_len; |
| 213 |
unsigned char at_llto_len; |
| 214 |
unsigned char at_llsrc_len; |
| 215 |
unsigned char at_lldst_len; |
| 216 |
unsigned char at_iif_len; |
| 217 |
unsigned char at_oif_len; |
| 218 |
unsigned short at__pad1; |
| 219 |
unsigned char at_llfrom[MAX_ADDR_LEN]; |
| 220 |
unsigned char at_llto[MAX_ADDR_LEN]; |
| 221 |
unsigned char at_llsrc[MAX_ADDR_LEN]; |
| 222 |
unsigned char at_lldst[MAX_ADDR_LEN]; |
| 223 |
char at_iif[IFNAMSIZ]; |
| 224 |
char at_oif[IFNAMSIZ]; |
| 225 |
}; |
| 226 |
|
| 227 |
static struct arpf_node *arp_tabs[3]; |
| 228 |
|
| 229 |
static kmem_cache_t *arpf_cachep; |
| 230 |
|
| 231 |
static rwlock_t arpf_lock = RW_LOCK_UNLOCKED; |
| 232 |
|
| 233 |
static void |
| 234 |
arpf_send(int table, struct sk_buff *skb, u32 sip, u32 tip, |
| 235 |
unsigned char *from_hw, unsigned char *to_hw, |
| 236 |
struct net_device *idev, struct net_device *odev); |
| 237 |
|
| 193 |
int arp_mc_map(u32 addr, u8 *haddr, struct net_device *dev, int dir) |
238 |
int arp_mc_map(u32 addr, u8 *haddr, struct net_device *dev, int dir) |
| 194 |
{ |
239 |
{ |
| 195 |
switch (dev->type) { |
240 |
switch (dev->type) { |
|
Lines 317-337
static void arp_error_report(struct neig
Link Here
|
| 317 |
static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb) |
362 |
static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb) |
| 318 |
{ |
363 |
{ |
| 319 |
u32 saddr; |
364 |
u32 saddr; |
|
|
365 |
int from_skb; |
| 366 |
struct in_device *in_dev2 = NULL; |
| 367 |
struct net_device *dev2 = NULL; |
| 320 |
u8 *dst_ha = NULL; |
368 |
u8 *dst_ha = NULL; |
| 321 |
struct net_device *dev = neigh->dev; |
369 |
struct net_device *dev = neigh->dev; |
| 322 |
u32 target = *(u32*)neigh->primary_key; |
370 |
u32 target = *(u32*)neigh->primary_key; |
| 323 |
int probes = atomic_read(&neigh->probes); |
371 |
int probes = atomic_read(&neigh->probes); |
|
|
372 |
unsigned char tha[MAX_ADDR_LEN]; |
| 324 |
|
373 |
|
| 325 |
if (skb && inet_addr_type(skb->nh.iph->saddr) == RTN_LOCAL) |
374 |
from_skb = (skb && |
|
|
375 |
(dev2 = ip_dev_find(skb->nh.iph->saddr)) != NULL && |
| 376 |
(in_dev2 = in_dev_get(dev2)) != NULL && |
| 377 |
!IN_DEV_HIDDEN(in_dev2)); |
| 378 |
if (dev2) { |
| 379 |
if (in_dev2) in_dev_put(in_dev2); |
| 380 |
dev_put(dev2); |
| 381 |
} |
| 382 |
if (from_skb) |
| 326 |
saddr = skb->nh.iph->saddr; |
383 |
saddr = skb->nh.iph->saddr; |
| 327 |
else |
384 |
else |
| 328 |
saddr = inet_select_addr(dev, target, RT_SCOPE_LINK); |
385 |
saddr = inet_select_addr(dev, target, RT_SCOPE_LINK); |
| 329 |
|
386 |
|
|
|
387 |
if (!saddr) |
| 388 |
return; |
| 330 |
if ((probes -= neigh->parms->ucast_probes) < 0) { |
389 |
if ((probes -= neigh->parms->ucast_probes) < 0) { |
| 331 |
if (!(neigh->nud_state&NUD_VALID)) |
390 |
if (!(neigh->nud_state&NUD_VALID)) |
| 332 |
printk(KERN_DEBUG "trying to ucast probe in NUD_INVALID\n"); |
391 |
printk(KERN_DEBUG "trying to ucast probe in NUD_INVALID\n"); |
| 333 |
dst_ha = neigh->ha; |
392 |
dst_ha = tha; |
| 334 |
read_lock_bh(&neigh->lock); |
393 |
read_lock_bh(&neigh->lock); |
|
|
394 |
memcpy(dst_ha, neigh->ha, dev->addr_len); |
| 395 |
read_unlock_bh(&neigh->lock); |
| 335 |
} else if ((probes -= neigh->parms->app_probes) < 0) { |
396 |
} else if ((probes -= neigh->parms->app_probes) < 0) { |
| 336 |
#ifdef CONFIG_ARPD |
397 |
#ifdef CONFIG_ARPD |
| 337 |
neigh_app_ns(neigh); |
398 |
neigh_app_ns(neigh); |
|
Lines 339-348
static void arp_solicit(struct neighbour
Link Here
|
| 339 |
return; |
400 |
return; |
| 340 |
} |
401 |
} |
| 341 |
|
402 |
|
| 342 |
arp_send(ARPOP_REQUEST, ETH_P_ARP, target, dev, saddr, |
403 |
arpf_send(ARPA_TABLE_OUTPUT,skb,saddr,target,NULL,dst_ha,NULL,dev); |
| 343 |
dst_ha, dev->dev_addr, NULL); |
|
|
| 344 |
if (dst_ha) |
| 345 |
read_unlock_bh(&neigh->lock); |
| 346 |
} |
404 |
} |
| 347 |
|
405 |
|
| 348 |
static int arp_filter(__u32 sip, __u32 tip, struct net_device *dev) |
406 |
static int arp_filter(__u32 sip, __u32 tip, struct net_device *dev) |
|
Lines 754-762
int arp_process(struct sk_buff *skb)
Link Here
|
| 754 |
|
812 |
|
| 755 |
/* Special case: IPv4 duplicate address detection packet (RFC2131) */ |
813 |
/* Special case: IPv4 duplicate address detection packet (RFC2131) */ |
| 756 |
if (sip == 0) { |
814 |
if (sip == 0) { |
| 757 |
if (arp->ar_op == htons(ARPOP_REQUEST) && |
815 |
int reply; |
| 758 |
inet_addr_type(tip) == RTN_LOCAL) |
816 |
struct net_device *dev2 = NULL; |
| 759 |
arp_send(ARPOP_REPLY,ETH_P_ARP,tip,dev,tip,sha,dev->dev_addr,dev->dev_addr); |
817 |
struct in_device *in_dev2 = NULL; |
|
|
818 |
|
| 819 |
reply = |
| 820 |
(arp->ar_op == htons(ARPOP_REQUEST) && |
| 821 |
(dev2 = ip_dev_find(tip)) != NULL && |
| 822 |
(dev2 == dev || |
| 823 |
((in_dev2 = in_dev_get(dev2)) != NULL && |
| 824 |
!IN_DEV_HIDDEN(in_dev2)))); |
| 825 |
if (dev2) { |
| 826 |
if (in_dev2) in_dev_put(in_dev2); |
| 827 |
dev_put(dev2); |
| 828 |
if (reply) |
| 829 |
arpf_send(ARPA_TABLE_INPUT,skb,sip,tip,sha,tha,dev,NULL); |
| 830 |
} |
| 760 |
goto out; |
831 |
goto out; |
| 761 |
} |
832 |
} |
| 762 |
|
833 |
|
|
Lines 770-779
int arp_process(struct sk_buff *skb)
Link Here
|
| 770 |
n = neigh_event_ns(&arp_tbl, sha, &sip, dev); |
841 |
n = neigh_event_ns(&arp_tbl, sha, &sip, dev); |
| 771 |
if (n) { |
842 |
if (n) { |
| 772 |
int dont_send = 0; |
843 |
int dont_send = 0; |
|
|
844 |
if (ipv4_devconf.hidden && |
| 845 |
skb->pkt_type != PACKET_HOST) { |
| 846 |
struct net_device *dev2 = NULL; |
| 847 |
struct in_device *in_dev2 = NULL; |
| 848 |
|
| 849 |
dont_send |= |
| 850 |
((dev2 = ip_dev_find(tip)) != NULL && |
| 851 |
dev2 != dev && |
| 852 |
(in_dev2=in_dev_get(dev2)) != NULL && |
| 853 |
IN_DEV_HIDDEN(in_dev2)); |
| 854 |
if (dev2) { |
| 855 |
if (in_dev2) in_dev_put(in_dev2); |
| 856 |
dev_put(dev2); |
| 857 |
} |
| 858 |
} |
| 773 |
if (IN_DEV_ARPFILTER(in_dev)) |
859 |
if (IN_DEV_ARPFILTER(in_dev)) |
| 774 |
dont_send |= arp_filter(sip,tip,dev); |
860 |
dont_send |= arp_filter(sip,tip,dev); |
| 775 |
if (!dont_send) |
861 |
if (!dont_send) |
| 776 |
arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr,sha); |
862 |
arpf_send(ARPA_TABLE_INPUT,skb, |
|
|
863 |
sip,tip,sha,tha,dev,NULL); |
| 777 |
|
864 |
|
| 778 |
neigh_release(n); |
865 |
neigh_release(n); |
| 779 |
} |
866 |
} |
|
Lines 789-795
int arp_process(struct sk_buff *skb)
Link Here
|
| 789 |
if (skb->stamp.tv_sec == 0 || |
876 |
if (skb->stamp.tv_sec == 0 || |
| 790 |
skb->pkt_type == PACKET_HOST || |
877 |
skb->pkt_type == PACKET_HOST || |
| 791 |
in_dev->arp_parms->proxy_delay == 0) { |
878 |
in_dev->arp_parms->proxy_delay == 0) { |
| 792 |
arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr,sha); |
879 |
arpf_send(ARPA_TABLE_FORWARD,skb, |
|
|
880 |
sip,tip,sha,tha,dev, |
| 881 |
rt->u.dst.dev); |
| 793 |
} else { |
882 |
} else { |
| 794 |
pneigh_enqueue(&arp_tbl, in_dev->arp_parms, skb); |
883 |
pneigh_enqueue(&arp_tbl, in_dev->arp_parms, skb); |
| 795 |
in_dev_put(in_dev); |
884 |
in_dev_put(in_dev); |
|
Lines 1221-1226
void arp_ifdown(struct net_device *dev)
Link Here
|
| 1221 |
} |
1310 |
} |
| 1222 |
|
1311 |
|
| 1223 |
|
1312 |
|
|
|
1313 |
static void arpf_destroy(struct arpf_node *afp) |
| 1314 |
{ |
| 1315 |
if (!afp->at_dead) { |
| 1316 |
printk(KERN_ERR "Destroying alive arp table node %p from %08lx\n", afp, |
| 1317 |
*(((unsigned long*)&afp)-1)); |
| 1318 |
return; |
| 1319 |
} |
| 1320 |
kmem_cache_free(arpf_cachep, afp); |
| 1321 |
} |
| 1322 |
|
| 1323 |
static inline void arpf_put(struct arpf_node *afp) |
| 1324 |
{ |
| 1325 |
if (atomic_dec_and_test(&afp->at_refcnt)) |
| 1326 |
arpf_destroy(afp); |
| 1327 |
} |
| 1328 |
|
| 1329 |
static inline struct arpf_node * |
| 1330 |
arpf_lookup(int table, struct sk_buff *skb, u32 sip, u32 tip, |
| 1331 |
unsigned char *from_hw, unsigned char *to_hw, |
| 1332 |
struct net_device *idev, struct net_device *odev) |
| 1333 |
{ |
| 1334 |
int sz_iif = idev? strlen(idev->name) : 0; |
| 1335 |
int sz_oif = odev? strlen(odev->name) : 0; |
| 1336 |
int alen; |
| 1337 |
struct arpf_node *afp; |
| 1338 |
|
| 1339 |
if (ARPA_TABLE_OUTPUT != table) { |
| 1340 |
alen = idev->addr_len; |
| 1341 |
} else { |
| 1342 |
if (!from_hw) from_hw = odev->dev_addr; |
| 1343 |
if (!to_hw) to_hw = odev->broadcast; |
| 1344 |
alen = odev->addr_len; |
| 1345 |
} |
| 1346 |
|
| 1347 |
read_lock(&arpf_lock); |
| 1348 |
for (afp = arp_tabs[table]; afp; afp = afp->at_next) { |
| 1349 |
if ((tip ^ afp->at_to) & afp->at_to_mask) |
| 1350 |
continue; |
| 1351 |
if ((sip ^ afp->at_from) & afp->at_from_mask) |
| 1352 |
continue; |
| 1353 |
if (afp->at_llfrom_len && |
| 1354 |
(afp->at_llfrom_len > alen || |
| 1355 |
memcmp(from_hw, afp->at_llfrom, afp->at_llfrom_len))) |
| 1356 |
continue; |
| 1357 |
if (afp->at_llto_len && |
| 1358 |
(afp->at_llto_len > alen || |
| 1359 |
memcmp(to_hw, afp->at_llto, afp->at_llto_len))) |
| 1360 |
continue; |
| 1361 |
if (afp->at_iif_len && |
| 1362 |
(afp->at_iif_len > sz_iif || |
| 1363 |
memcmp(afp->at_iif, idev->name, afp->at_iif_len) || |
| 1364 |
(sz_iif != afp->at_iif_len && |
| 1365 |
!(afp->at_flags & ARPM_F_WILDIIF)))) |
| 1366 |
continue; |
| 1367 |
if (afp->at_oif_len && |
| 1368 |
(afp->at_oif_len > sz_oif || |
| 1369 |
memcmp(afp->at_oif, odev->name, afp->at_oif_len) || |
| 1370 |
(sz_oif != afp->at_oif_len && |
| 1371 |
!(afp->at_flags & ARPM_F_WILDOIF)))) |
| 1372 |
continue; |
| 1373 |
if (afp->at_flags & ARPM_F_BROADCAST && |
| 1374 |
skb->pkt_type == PACKET_HOST) |
| 1375 |
continue; |
| 1376 |
if (afp->at_flags & ARPM_F_UNICAST && |
| 1377 |
skb->pkt_type != PACKET_HOST) |
| 1378 |
continue; |
| 1379 |
if (afp->at_llsrc_len && afp->at_llsrc_len != alen) |
| 1380 |
continue; |
| 1381 |
if (afp->at_lldst_len && afp->at_lldst_len != alen) |
| 1382 |
continue; |
| 1383 |
atomic_inc(&afp->at_packets); |
| 1384 |
break; |
| 1385 |
} |
| 1386 |
read_unlock(&arpf_lock); |
| 1387 |
return afp; |
| 1388 |
} |
| 1389 |
|
| 1390 |
static void |
| 1391 |
arpf_send(int table, struct sk_buff *skb, u32 sip, u32 tip, |
| 1392 |
unsigned char *from_hw, unsigned char *to_hw, |
| 1393 |
struct net_device *idev, struct net_device *odev) |
| 1394 |
{ |
| 1395 |
struct arpf_node *afp = NULL; |
| 1396 |
|
| 1397 |
if (!arp_tabs[table] || |
| 1398 |
!(afp = arpf_lookup(table, skb, sip, tip, |
| 1399 |
from_hw, to_hw, idev, odev))) { |
| 1400 |
switch (table) { |
| 1401 |
case ARPA_TABLE_INPUT: |
| 1402 |
if (!sip) { |
| 1403 |
arp_send(ARPOP_REPLY, ETH_P_ARP, tip, idev, tip, |
| 1404 |
from_hw, idev->dev_addr, |
| 1405 |
idev->dev_addr); |
| 1406 |
break; |
| 1407 |
} |
| 1408 |
/* continue */ |
| 1409 |
case ARPA_TABLE_FORWARD: |
| 1410 |
arp_send(ARPOP_REPLY, ETH_P_ARP, sip, idev, tip, |
| 1411 |
from_hw, idev->dev_addr, from_hw); |
| 1412 |
break; |
| 1413 |
case ARPA_TABLE_OUTPUT: |
| 1414 |
arp_send(ARPOP_REQUEST, ETH_P_ARP, tip, odev, sip, |
| 1415 |
to_hw, odev->dev_addr, NULL); |
| 1416 |
break; |
| 1417 |
} |
| 1418 |
return; |
| 1419 |
} |
| 1420 |
|
| 1421 |
/* deny? */ |
| 1422 |
if (!afp->at_action) goto out; |
| 1423 |
|
| 1424 |
switch (table) { |
| 1425 |
case ARPA_TABLE_INPUT: |
| 1426 |
if (!sip) { |
| 1427 |
arp_send(ARPOP_REPLY, ETH_P_ARP, tip, idev, tip, |
| 1428 |
from_hw, |
| 1429 |
afp->at_llsrc_len?afp->at_llsrc:idev->dev_addr, |
| 1430 |
afp->at_llsrc_len?afp->at_llsrc:idev->dev_addr); |
| 1431 |
break; |
| 1432 |
} |
| 1433 |
/* continue */ |
| 1434 |
case ARPA_TABLE_FORWARD: |
| 1435 |
arp_send(ARPOP_REPLY, ETH_P_ARP, sip, idev, tip, |
| 1436 |
afp->at_lldst_len?afp->at_lldst:from_hw, |
| 1437 |
afp->at_llsrc_len?afp->at_llsrc:idev->dev_addr, |
| 1438 |
afp->at_lldst_len?afp->at_lldst:from_hw); |
| 1439 |
break; |
| 1440 |
case ARPA_TABLE_OUTPUT: |
| 1441 |
if (afp->at_flags & ARPM_F_PREFSRC && afp->at_src == 0) { |
| 1442 |
struct rtable *rt; |
| 1443 |
|
| 1444 |
if (ip_route_output(&rt, tip, 0, 0, odev->ifindex) < 0) |
| 1445 |
break; |
| 1446 |
sip = rt->rt_src; |
| 1447 |
ip_rt_put(rt); |
| 1448 |
if (!sip) |
| 1449 |
break; |
| 1450 |
} |
| 1451 |
arp_send(ARPOP_REQUEST, ETH_P_ARP, tip, odev, afp->at_src?:sip, |
| 1452 |
afp->at_lldst_len?afp->at_lldst:to_hw, |
| 1453 |
afp->at_llsrc_len?afp->at_llsrc:odev->dev_addr, |
| 1454 |
NULL); |
| 1455 |
break; |
| 1456 |
} |
| 1457 |
|
| 1458 |
out: |
| 1459 |
arpf_put(afp); |
| 1460 |
} |
| 1461 |
|
| 1462 |
static int |
| 1463 |
arpf_fill_node(struct sk_buff *skb, u32 pid, u32 seq, unsigned flags, |
| 1464 |
int event, int table, struct arpf_node *afp) |
| 1465 |
{ |
| 1466 |
struct arpmsg *am; |
| 1467 |
struct nlmsghdr *nlh; |
| 1468 |
unsigned char *b = skb->tail; |
| 1469 |
u32 packets = atomic_read(&afp->at_packets); |
| 1470 |
|
| 1471 |
nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*am)); |
| 1472 |
nlh->nlmsg_flags = flags; |
| 1473 |
am = NLMSG_DATA(nlh); |
| 1474 |
am->arpm_family = AF_UNSPEC; |
| 1475 |
am->arpm_table = table; |
| 1476 |
am->arpm_action = afp->at_action; |
| 1477 |
am->arpm_from_len = afp->at_from_len; |
| 1478 |
am->arpm_to_len = afp->at_to_len; |
| 1479 |
am->arpm_pref = afp->at_pref; |
| 1480 |
am->arpm_flags = afp->at_flags; |
| 1481 |
if (afp->at_from_len) |
| 1482 |
RTA_PUT(skb, ARPA_FROM, 4, &afp->at_from); |
| 1483 |
if (afp->at_to_len) |
| 1484 |
RTA_PUT(skb, ARPA_TO, 4, &afp->at_to); |
| 1485 |
if (afp->at_src || afp->at_flags & ARPM_F_PREFSRC) |
| 1486 |
RTA_PUT(skb, ARPA_SRC, 4, &afp->at_src); |
| 1487 |
if (afp->at_iif[0]) |
| 1488 |
RTA_PUT(skb, ARPA_IIF, sizeof(afp->at_iif), afp->at_iif); |
| 1489 |
if (afp->at_oif[0]) |
| 1490 |
RTA_PUT(skb, ARPA_OIF, sizeof(afp->at_oif), afp->at_oif); |
| 1491 |
if (afp->at_llfrom_len) |
| 1492 |
RTA_PUT(skb, ARPA_LLFROM, afp->at_llfrom_len, afp->at_llfrom); |
| 1493 |
if (afp->at_llto_len) |
| 1494 |
RTA_PUT(skb, ARPA_LLTO, afp->at_llto_len, afp->at_llto); |
| 1495 |
if (afp->at_llsrc_len) |
| 1496 |
RTA_PUT(skb, ARPA_LLSRC, afp->at_llsrc_len, afp->at_llsrc); |
| 1497 |
if (afp->at_lldst_len) |
| 1498 |
RTA_PUT(skb, ARPA_LLDST, afp->at_lldst_len, afp->at_lldst); |
| 1499 |
RTA_PUT(skb, ARPA_PACKETS, 4, &packets); |
| 1500 |
nlh->nlmsg_len = skb->tail - b; |
| 1501 |
return skb->len; |
| 1502 |
|
| 1503 |
nlmsg_failure: |
| 1504 |
rtattr_failure: |
| 1505 |
skb_trim(skb, b - skb->data); |
| 1506 |
return -1; |
| 1507 |
} |
| 1508 |
|
| 1509 |
static int |
| 1510 |
arpmsg_notify(struct sk_buff *oskb, struct nlmsghdr *n, int table, |
| 1511 |
struct arpf_node *afp, int event) |
| 1512 |
{ |
| 1513 |
struct sk_buff *skb; |
| 1514 |
u32 pid = oskb ? NETLINK_CB(oskb).pid : 0; |
| 1515 |
int size = NLMSG_SPACE(sizeof(struct arpmsg)+256); |
| 1516 |
|
| 1517 |
skb = alloc_skb(size, GFP_KERNEL); |
| 1518 |
if (!skb) |
| 1519 |
return -ENOBUFS; |
| 1520 |
|
| 1521 |
if (arpf_fill_node(skb, pid, n->nlmsg_seq, 0, event, table, afp) <= 0) { |
| 1522 |
kfree_skb(skb); |
| 1523 |
return -EINVAL; |
| 1524 |
} |
| 1525 |
|
| 1526 |
return rtnetlink_send(skb, pid, RTMGRP_ARP, n->nlmsg_flags&NLM_F_ECHO); |
| 1527 |
} |
| 1528 |
|
| 1529 |
static inline int |
| 1530 |
arpf_str_size(int a, struct rtattr **rta, int maxlen) |
| 1531 |
{ |
| 1532 |
int size = 0; |
| 1533 |
|
| 1534 |
if (rta[a-1] && (size = RTA_PAYLOAD(rta[a-1]))) { |
| 1535 |
if (size > maxlen) |
| 1536 |
size = maxlen; |
| 1537 |
} |
| 1538 |
return size; |
| 1539 |
} |
| 1540 |
|
| 1541 |
static inline int |
| 1542 |
arpf_get_str(int a, struct rtattr **rta, unsigned char *p, |
| 1543 |
int maxlen, unsigned char *l) |
| 1544 |
{ |
| 1545 |
int size = arpf_str_size(a, rta, maxlen); |
| 1546 |
|
| 1547 |
if (size) { |
| 1548 |
memcpy(p, RTA_DATA(rta[a-1]), size); |
| 1549 |
*l = size; |
| 1550 |
} |
| 1551 |
return size; |
| 1552 |
} |
| 1553 |
|
| 1554 |
#define ARPF_MATCH_U32(ind, field) ( \ |
| 1555 |
(!rta[ind-1] && r->at_ ## field == 0) || \ |
| 1556 |
(rta[ind-1] && \ |
| 1557 |
*(u32*) RTA_DATA(rta[ind-1]) == r->at_ ## field)) |
| 1558 |
|
| 1559 |
#define ARPF_MATCH_STR(ind, field) ( \ |
| 1560 |
(!rta[ind-1] && r->at_ ## field ## _len == 0) || \ |
| 1561 |
(rta[ind-1] && r->at_ ## field ## _len && \ |
| 1562 |
r->at_ ## field ## _len < RTA_PAYLOAD(rta[ind-1]) && \ |
| 1563 |
strcmp(RTA_DATA(rta[ind-1]), r->at_ ## field) == 0)) |
| 1564 |
|
| 1565 |
#define ARPF_MATCH_DATA(ind, field) ( \ |
| 1566 |
(!rta[ind-1] && r->at_ ## field ## _len == 0) || \ |
| 1567 |
(rta[ind-1] && r->at_ ## field ## _len && \ |
| 1568 |
r->at_ ## field ## _len == RTA_PAYLOAD(rta[ind-1]) && \ |
| 1569 |
memcmp(RTA_DATA(rta[ind-1]), &r->at_ ## field, \ |
| 1570 |
r->at_ ## field ## _len) == 0)) |
| 1571 |
|
| 1572 |
/* RTM_NEWARPRULE/RTM_DELARPRULE/RTM_GETARPRULE */ |
| 1573 |
|
| 1574 |
int arpf_rule_ctl(struct sk_buff *skb, struct nlmsghdr* n, void *arg) |
| 1575 |
{ |
| 1576 |
struct rtattr **rta = arg; |
| 1577 |
struct arpmsg *am = NLMSG_DATA(n); |
| 1578 |
struct arpf_node *r, **rp, **prevp = 0, **delp = 0, *newp = 0; |
| 1579 |
unsigned pref = 1; |
| 1580 |
int size, ret = -EINVAL; |
| 1581 |
|
| 1582 |
if (am->arpm_table >= sizeof(arp_tabs)/sizeof(arp_tabs[0])) |
| 1583 |
goto out; |
| 1584 |
if (!((~am->arpm_flags) & (ARPM_F_BROADCAST|ARPM_F_UNICAST))) |
| 1585 |
goto out; |
| 1586 |
if (am->arpm_action > 1) |
| 1587 |
goto out; |
| 1588 |
if (am->arpm_to_len > 32 || am->arpm_from_len > 32) |
| 1589 |
goto out; |
| 1590 |
if (am->arpm_flags & ARPM_F_WILDIIF && |
| 1591 |
(!rta[ARPA_IIF-1] || !RTA_PAYLOAD(rta[ARPA_IIF-1]) || |
| 1592 |
!*(char*)RTA_DATA(rta[ARPA_IIF-1]))) |
| 1593 |
am->arpm_flags &= ~ARPM_F_WILDIIF; |
| 1594 |
if (am->arpm_flags & ARPM_F_WILDOIF && |
| 1595 |
(!rta[ARPA_OIF-1] || !RTA_PAYLOAD(rta[ARPA_OIF-1]) || |
| 1596 |
!*(char*)RTA_DATA(rta[ARPA_OIF-1]))) |
| 1597 |
am->arpm_flags &= ~ARPM_F_WILDOIF; |
| 1598 |
switch (am->arpm_table) { |
| 1599 |
case ARPA_TABLE_INPUT: |
| 1600 |
if (rta[ARPA_SRC-1] || rta[ARPA_OIF-1]) |
| 1601 |
goto out; |
| 1602 |
break; |
| 1603 |
case ARPA_TABLE_OUTPUT: |
| 1604 |
if (rta[ARPA_IIF-1]) |
| 1605 |
goto out; |
| 1606 |
if (am->arpm_flags & (ARPM_F_BROADCAST|ARPM_F_UNICAST)) |
| 1607 |
goto out; |
| 1608 |
break; |
| 1609 |
case ARPA_TABLE_FORWARD: |
| 1610 |
if (rta[ARPA_SRC-1]) |
| 1611 |
goto out; |
| 1612 |
break; |
| 1613 |
} |
| 1614 |
if (rta[ARPA_SRC-1] && !*(u32*) RTA_DATA(rta[ARPA_SRC-1])) |
| 1615 |
am->arpm_flags |= ARPM_F_PREFSRC; |
| 1616 |
else |
| 1617 |
am->arpm_flags &= ~ARPM_F_PREFSRC; |
| 1618 |
|
| 1619 |
for (rp = &arp_tabs[am->arpm_table]; (r=*rp) != NULL; rp=&r->at_next) { |
| 1620 |
if (pref < r->at_pref) |
| 1621 |
prevp = rp; |
| 1622 |
if (am->arpm_pref == r->at_pref || |
| 1623 |
(!am->arpm_pref && |
| 1624 |
am->arpm_to_len == r->at_to_len && |
| 1625 |
am->arpm_from_len == r->at_from_len && |
| 1626 |
!((am->arpm_flags ^ r->at_flags) & |
| 1627 |
(ARPM_F_BROADCAST | ARPM_F_UNICAST | |
| 1628 |
ARPM_F_WILDIIF | ARPM_F_WILDOIF)) && |
| 1629 |
ARPF_MATCH_U32(ARPA_TO, to) && |
| 1630 |
ARPF_MATCH_U32(ARPA_FROM, from) && |
| 1631 |
ARPF_MATCH_DATA(ARPA_LLFROM, llfrom) && |
| 1632 |
ARPF_MATCH_DATA(ARPA_LLTO, llto) && |
| 1633 |
ARPF_MATCH_STR(ARPA_IIF, iif) && |
| 1634 |
ARPF_MATCH_STR(ARPA_OIF, oif) && |
| 1635 |
(n->nlmsg_type != RTM_DELARPRULE || |
| 1636 |
/* DEL matches more keys */ |
| 1637 |
(am->arpm_flags == r->at_flags && |
| 1638 |
am->arpm_action == r->at_action && |
| 1639 |
ARPF_MATCH_U32(ARPA_SRC, src) && |
| 1640 |
ARPF_MATCH_DATA(ARPA_LLSRC, llsrc) && |
| 1641 |
ARPF_MATCH_DATA(ARPA_LLDST, lldst) |
| 1642 |
) |
| 1643 |
) |
| 1644 |
) |
| 1645 |
) |
| 1646 |
break; |
| 1647 |
if (am->arpm_pref && r->at_pref > am->arpm_pref) { |
| 1648 |
r = NULL; |
| 1649 |
break; |
| 1650 |
} |
| 1651 |
pref = r->at_pref+1; |
| 1652 |
} |
| 1653 |
|
| 1654 |
/* |
| 1655 |
* r=NULL: *rp != NULL (stopped before next pref), pref: not valid |
| 1656 |
* *rp == NULL (not found), pref: ready to use |
| 1657 |
* r!=NULL: found, pref: not valid |
| 1658 |
* |
| 1659 |
* prevp=NULL: no free slot |
| 1660 |
* prevp!=NULL: free slot for rule |
| 1661 |
*/ |
| 1662 |
|
| 1663 |
if (n->nlmsg_type == RTM_DELARPRULE) { |
| 1664 |
if (!r) |
| 1665 |
return -ESRCH; |
| 1666 |
delp = rp; |
| 1667 |
goto dequeue; |
| 1668 |
} |
| 1669 |
|
| 1670 |
if (r) { |
| 1671 |
/* Existing rule */ |
| 1672 |
ret = -EEXIST; |
| 1673 |
if (n->nlmsg_flags&NLM_F_EXCL) |
| 1674 |
goto out; |
| 1675 |
|
| 1676 |
if (n->nlmsg_flags&NLM_F_REPLACE) { |
| 1677 |
pref = r->at_pref; |
| 1678 |
prevp = delp = rp; |
| 1679 |
goto replace; |
| 1680 |
} |
| 1681 |
} |
| 1682 |
|
| 1683 |
if (n->nlmsg_flags&NLM_F_APPEND) { |
| 1684 |
if (r) { |
| 1685 |
pref = r->at_pref+1; |
| 1686 |
for (rp=&r->at_next; (r=*rp) != NULL; rp=&r->at_next) { |
| 1687 |
if (pref != r->at_pref) |
| 1688 |
break; |
| 1689 |
pref ++; |
| 1690 |
} |
| 1691 |
ret = -EBUSY; |
| 1692 |
if (!pref) |
| 1693 |
goto out; |
| 1694 |
} else if (am->arpm_pref) |
| 1695 |
pref = am->arpm_pref; |
| 1696 |
prevp = rp; |
| 1697 |
} |
| 1698 |
|
| 1699 |
if (!(n->nlmsg_flags&NLM_F_CREATE)) { |
| 1700 |
ret = -ENOENT; |
| 1701 |
if (n->nlmsg_flags&NLM_F_EXCL || r) |
| 1702 |
ret = 0; |
| 1703 |
goto out; |
| 1704 |
} |
| 1705 |
|
| 1706 |
if (!(n->nlmsg_flags&NLM_F_APPEND)) { |
| 1707 |
if (!prevp) { |
| 1708 |
ret = -EBUSY; |
| 1709 |
if (r || *rp || |
| 1710 |
(!am->arpm_pref && arp_tabs[am->arpm_table])) |
| 1711 |
goto out; |
| 1712 |
prevp = rp; |
| 1713 |
pref = am->arpm_pref? : 99; |
| 1714 |
} else { |
| 1715 |
if (r || !am->arpm_pref) { |
| 1716 |
pref = (*prevp)->at_pref - 1; |
| 1717 |
if (am->arpm_pref && am->arpm_pref < pref) |
| 1718 |
pref = am->arpm_pref; |
| 1719 |
} else { |
| 1720 |
prevp = rp; |
| 1721 |
pref = am->arpm_pref; |
| 1722 |
} |
| 1723 |
} |
| 1724 |
} |
| 1725 |
|
| 1726 |
replace: |
| 1727 |
|
| 1728 |
ret = -ENOMEM; |
| 1729 |
r = kmem_cache_alloc(arpf_cachep, SLAB_KERNEL); |
| 1730 |
if (!r) |
| 1731 |
return ret; |
| 1732 |
memset(r, 0, sizeof(*r)); |
| 1733 |
|
| 1734 |
arpf_get_str(ARPA_LLFROM, rta, r->at_llfrom, MAX_ADDR_LEN, |
| 1735 |
&r->at_llfrom_len); |
| 1736 |
arpf_get_str(ARPA_LLTO, rta, r->at_llto, MAX_ADDR_LEN, |
| 1737 |
&r->at_llto_len); |
| 1738 |
arpf_get_str(ARPA_LLSRC, rta, r->at_llsrc, MAX_ADDR_LEN, |
| 1739 |
&r->at_llsrc_len); |
| 1740 |
arpf_get_str(ARPA_LLDST, rta, r->at_lldst, MAX_ADDR_LEN, |
| 1741 |
&r->at_lldst_len); |
| 1742 |
|
| 1743 |
if (delp) |
| 1744 |
r->at_next = (*delp)->at_next; |
| 1745 |
else if (*prevp) |
| 1746 |
r->at_next = *prevp; |
| 1747 |
|
| 1748 |
r->at_pref = pref; |
| 1749 |
r->at_from_len = am->arpm_from_len; |
| 1750 |
r->at_from_mask = inet_make_mask(r->at_from_len); |
| 1751 |
if (rta[ARPA_FROM-1]) |
| 1752 |
r->at_from = *(u32*) RTA_DATA(rta[ARPA_FROM-1]); |
| 1753 |
r->at_from &= r->at_from_mask; |
| 1754 |
r->at_to_len = am->arpm_to_len; |
| 1755 |
r->at_to_mask = inet_make_mask(r->at_to_len); |
| 1756 |
if (rta[ARPA_TO-1]) |
| 1757 |
r->at_to = *(u32*) RTA_DATA(rta[ARPA_TO-1]); |
| 1758 |
r->at_to &= r->at_to_mask; |
| 1759 |
if (rta[ARPA_SRC-1]) |
| 1760 |
r->at_src = *(u32*) RTA_DATA(rta[ARPA_SRC-1]); |
| 1761 |
if (rta[ARPA_PACKETS-1]) { |
| 1762 |
u32 packets = *(u32*) RTA_DATA(rta[ARPA_PACKETS-1]); |
| 1763 |
atomic_set(&r->at_packets, packets); |
| 1764 |
} |
| 1765 |
atomic_set(&r->at_refcnt, 1); |
| 1766 |
r->at_flags = am->arpm_flags; |
| 1767 |
r->at_action = am->arpm_action; |
| 1768 |
|
| 1769 |
if (rta[ARPA_IIF-1] && (size = RTA_PAYLOAD(rta[ARPA_IIF-1]))) { |
| 1770 |
if (size >= sizeof(r->at_iif)) |
| 1771 |
size = sizeof(r->at_iif)-1; |
| 1772 |
memcpy(r->at_iif, RTA_DATA(rta[ARPA_IIF-1]), size); |
| 1773 |
r->at_iif_len = strlen(r->at_iif); |
| 1774 |
} |
| 1775 |
if (rta[ARPA_OIF-1] && (size = RTA_PAYLOAD(rta[ARPA_OIF-1]))) { |
| 1776 |
if (size >= sizeof(r->at_oif)) |
| 1777 |
size = sizeof(r->at_oif)-1; |
| 1778 |
memcpy(r->at_oif, RTA_DATA(rta[ARPA_OIF-1]), size); |
| 1779 |
r->at_oif_len = strlen(r->at_oif); |
| 1780 |
} |
| 1781 |
|
| 1782 |
newp = r; |
| 1783 |
|
| 1784 |
dequeue: |
| 1785 |
|
| 1786 |
if (delp) { |
| 1787 |
r = *delp; |
| 1788 |
write_lock_bh(&arpf_lock); |
| 1789 |
if (newp) { |
| 1790 |
if (!rta[ARPA_PACKETS-1]) |
| 1791 |
atomic_set(&newp->at_packets, |
| 1792 |
atomic_read(&r->at_packets)); |
| 1793 |
*delp = newp; |
| 1794 |
} else { |
| 1795 |
*delp = r->at_next; |
| 1796 |
} |
| 1797 |
r->at_dead = 1; |
| 1798 |
write_unlock_bh(&arpf_lock); |
| 1799 |
arpmsg_notify(skb, n, am->arpm_table, r, RTM_DELARPRULE); |
| 1800 |
arpf_put(r); |
| 1801 |
prevp = 0; |
| 1802 |
} |
| 1803 |
|
| 1804 |
if (newp) { |
| 1805 |
if (prevp) { |
| 1806 |
write_lock_bh(&arpf_lock); |
| 1807 |
*prevp = newp; |
| 1808 |
write_unlock_bh(&arpf_lock); |
| 1809 |
} |
| 1810 |
arpmsg_notify(skb, n, am->arpm_table, newp, RTM_NEWARPRULE); |
| 1811 |
} |
| 1812 |
|
| 1813 |
ret = 0; |
| 1814 |
|
| 1815 |
out: |
| 1816 |
return ret; |
| 1817 |
} |
| 1818 |
|
| 1819 |
int arpf_dump_table(int t, struct sk_buff *skb, struct netlink_callback *cb) |
| 1820 |
{ |
| 1821 |
int idx, ret = -1; |
| 1822 |
struct arpf_node *afp; |
| 1823 |
int s_idx = cb->args[1]; |
| 1824 |
|
| 1825 |
for (idx=0, afp = arp_tabs[t]; afp; afp = afp->at_next, idx++) { |
| 1826 |
if (idx < s_idx) |
| 1827 |
continue; |
| 1828 |
if (arpf_fill_node(skb, NETLINK_CB(cb->skb).pid, |
| 1829 |
cb->nlh->nlmsg_seq, NLM_F_MULTI, RTM_NEWARPRULE, t, afp) < 0) |
| 1830 |
goto out; |
| 1831 |
} |
| 1832 |
|
| 1833 |
ret = skb->len; |
| 1834 |
|
| 1835 |
out: |
| 1836 |
cb->args[1] = idx; |
| 1837 |
|
| 1838 |
return ret; |
| 1839 |
} |
| 1840 |
|
| 1841 |
int arpf_dump_rules(struct sk_buff *skb, struct netlink_callback *cb) |
| 1842 |
{ |
| 1843 |
int idx; |
| 1844 |
int s_idx = cb->args[0]; |
| 1845 |
|
| 1846 |
read_lock_bh(&arpf_lock); |
| 1847 |
for (idx = 0; idx < sizeof(arp_tabs)/sizeof(arp_tabs[0]); idx++) { |
| 1848 |
if (idx < s_idx) |
| 1849 |
continue; |
| 1850 |
if (idx > s_idx) |
| 1851 |
memset(&cb->args[1], 0, sizeof(cb->args)-1*sizeof(cb->args[0])); |
| 1852 |
if (arpf_dump_table(idx, skb, cb) < 0) |
| 1853 |
break; |
| 1854 |
} |
| 1855 |
read_unlock_bh(&arpf_lock); |
| 1856 |
cb->args[0] = idx; |
| 1857 |
|
| 1858 |
return skb->len; |
| 1859 |
} |
| 1860 |
|
| 1224 |
/* |
1861 |
/* |
| 1225 |
* Called once on startup. |
1862 |
* Called once on startup. |
| 1226 |
*/ |
1863 |
*/ |
|
Lines 1233-1238
static struct packet_type arp_packet_typ
Link Here
|
| 1233 |
|
1870 |
|
| 1234 |
void __init arp_init (void) |
1871 |
void __init arp_init (void) |
| 1235 |
{ |
1872 |
{ |
|
|
1873 |
struct rtnetlink_link *link_p = rtnetlink_links[PF_UNSPEC]; |
| 1874 |
|
| 1875 |
arpf_cachep = kmem_cache_create("ip_arpf_cache", |
| 1876 |
sizeof(struct arpf_node), 0, |
| 1877 |
SLAB_HWCACHE_ALIGN, NULL, NULL); |
| 1878 |
if (!arpf_cachep) |
| 1879 |
panic("IP: failed to allocate ip_arpf_cache\n"); |
| 1880 |
|
| 1881 |
if (link_p) { |
| 1882 |
link_p[RTM_NEWARPRULE-RTM_BASE].doit = arpf_rule_ctl; |
| 1883 |
link_p[RTM_DELARPRULE-RTM_BASE].doit = arpf_rule_ctl; |
| 1884 |
link_p[RTM_GETARPRULE-RTM_BASE].dumpit = arpf_dump_rules; |
| 1885 |
} |
| 1886 |
|
| 1236 |
neigh_table_init(&arp_tbl); |
1887 |
neigh_table_init(&arp_tbl); |
| 1237 |
|
1888 |
|
| 1238 |
dev_add_pack(&arp_packet_type); |
1889 |
dev_add_pack(&arp_packet_type); |