Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
5fb135ce
Commit
5fb135ce
authored
Oct 12, 2003
by
Bart De Schuymer
Committed by
Stephen Hemminger
Oct 12, 2003
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[EBTABLES]: Add ebt_among match.
parent
247584b5
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
291 additions
and
0 deletions
+291
-0
include/linux/netfilter_bridge/ebt_among.h
include/linux/netfilter_bridge/ebt_among.h
+65
-0
net/bridge/netfilter/Kconfig
net/bridge/netfilter/Kconfig
+10
-0
net/bridge/netfilter/Makefile
net/bridge/netfilter/Makefile
+1
-0
net/bridge/netfilter/ebt_among.c
net/bridge/netfilter/ebt_among.c
+215
-0
No files found.
include/linux/netfilter_bridge/ebt_among.h
0 → 100644
View file @
5fb135ce
#ifndef __LINUX_BRIDGE_EBT_AMONG_H
#define __LINUX_BRIDGE_EBT_AMONG_H
#define EBT_AMONG_DST 0x01
#define EBT_AMONG_SRC 0x02
/* Grzegorz Borowiak <grzes@gnu.univ.gda.pl> 2003
*
* Write-once-read-many hash table, used for checking if a given
* MAC address belongs to a set or not and possibly for checking
* if it is related with a given IPv4 address.
*
* The hash value of an address is its last byte.
*
* In real-world ethernet addresses, values of the last byte are
* evenly distributed and there is no need to consider other bytes.
* It would only slow the routines down.
*
* For MAC address comparison speedup reasons, we introduce a trick.
* MAC address is mapped onto an array of two 32-bit integers.
* This pair of integers is compared with MAC addresses in the
* hash table, which are stored also in form of pairs of integers
* (in `cmp' array). This is quick as it requires only two elementary
* number comparisons in worst case. Further, we take advantage of
* fact that entropy of 3 last bytes of address is larger than entropy
* of 3 first bytes. So first we compare 4 last bytes of addresses and
* if they are the same we compare 2 first.
*
* Yes, it is a memory overhead, but in 2003 AD, who cares?
*/
struct
ebt_mac_wormhash_tuple
{
uint32_t
cmp
[
2
];
uint32_t
ip
;
};
struct
ebt_mac_wormhash
{
int
table
[
257
];
int
poolsize
;
struct
ebt_mac_wormhash_tuple
pool
[
0
];
};
#define ebt_mac_wormhash_size(x) ((x) ? sizeof(struct ebt_mac_wormhash) \
+ (x)->poolsize * sizeof(struct ebt_mac_wormhash_tuple) : 0)
struct
ebt_among_info
{
int
wh_dst_ofs
;
int
wh_src_ofs
;
int
bitmask
;
};
#define EBT_AMONG_DST_NEG 0x1
#define EBT_AMONG_SRC_NEG 0x2
#define ebt_among_wh_dst(x) ((x)->wh_dst_ofs ? \
(struct ebt_mac_wormhash*)((char*)(x) + (x)->wh_dst_ofs) : NULL)
#define ebt_among_wh_src(x) ((x)->wh_src_ofs ? \
(struct ebt_mac_wormhash*)((char*)(x) + (x)->wh_src_ofs) : NULL)
#define EBT_AMONG_MATCH "among"
#endif
net/bridge/netfilter/Kconfig
View file @
5fb135ce
...
...
@@ -55,6 +55,16 @@ config BRIDGE_EBT_802_3
To compile it as a module, choose M here. If unsure, say N.
config BRIDGE_EBT_AMONG
tristate "ebt: among filter support"
depends on BRIDGE_NF_EBTABLES
help
This option adds the among match, which allows matching the MAC source
and/or destination address on a list of addresses. Optionally,
MAC/IP address pairs can be matched, f.e. for anti-spoofing rules.
To compile it as a module, choose M here. If unsure, say N.
config BRIDGE_EBT_ARP
tristate "ebt: ARP filter support"
depends on BRIDGE_NF_EBTABLES
...
...
net/bridge/netfilter/Makefile
View file @
5fb135ce
...
...
@@ -11,6 +11,7 @@ obj-$(CONFIG_BRIDGE_EBT_T_NAT) += ebtable_nat.o
#matches
obj-$(CONFIG_BRIDGE_EBT_802_3)
+=
ebt_802_3.o
obj-$(CONFIG_BRIDGE_EBT_AMONG)
+=
ebt_among.o
obj-$(CONFIG_BRIDGE_EBT_ARP)
+=
ebt_arp.o
obj-$(CONFIG_BRIDGE_EBT_IP)
+=
ebt_ip.o
obj-$(CONFIG_BRIDGE_EBT_LIMIT)
+=
ebt_limit.o
...
...
net/bridge/netfilter/ebt_among.c
0 → 100644
View file @
5fb135ce
/*
* ebt_among
*
* Authors:
* Grzegorz Borowiak <grzes@gnu.univ.gda.pl>
*
* August, 2003
*
*/
#include <linux/netfilter_bridge/ebtables.h>
#include <linux/netfilter_bridge/ebt_among.h>
#include <linux/ip.h>
#include <linux/if_arp.h>
#include <linux/module.h>
static
int
ebt_mac_wormhash_contains
(
const
struct
ebt_mac_wormhash
*
wh
,
const
char
*
mac
,
uint32_t
ip
)
{
/* You may be puzzled as to how this code works.
* Some tricks were used, refer to
* include/linux/netfilter_bridge/ebt_among.h
* as there you can find a solution of this mystery.
*/
const
struct
ebt_mac_wormhash_tuple
*
p
;
int
start
,
limit
,
i
;
uint32_t
cmp
[
2
]
=
{
0
,
0
};
int
key
=
(
const
unsigned
char
)
mac
[
5
];
memcpy
(((
char
*
)
cmp
)
+
2
,
mac
,
6
);
start
=
wh
->
table
[
key
];
limit
=
wh
->
table
[
key
+
1
];
if
(
ip
)
{
for
(
i
=
start
;
i
<
limit
;
i
++
)
{
p
=
&
wh
->
pool
[
i
];
if
(
cmp
[
1
]
==
p
->
cmp
[
1
]
&&
cmp
[
0
]
==
p
->
cmp
[
0
])
{
if
(
p
->
ip
==
0
||
p
->
ip
==
ip
)
{
return
1
;
}
}
}
}
else
{
for
(
i
=
start
;
i
<
limit
;
i
++
)
{
p
=
&
wh
->
pool
[
i
];
if
(
cmp
[
1
]
==
p
->
cmp
[
1
]
&&
cmp
[
0
]
==
p
->
cmp
[
0
])
{
if
(
p
->
ip
==
0
)
{
return
1
;
}
}
}
}
return
0
;
}
static
int
ebt_mac_wormhash_check_integrity
(
const
struct
ebt_mac_wormhash
*
wh
)
{
int
i
;
for
(
i
=
0
;
i
<
256
;
i
++
)
{
if
(
wh
->
table
[
i
]
>
wh
->
table
[
i
+
1
])
return
-
0x100
-
i
;
if
(
wh
->
table
[
i
]
<
0
)
return
-
0x200
-
i
;
if
(
wh
->
table
[
i
]
>
wh
->
poolsize
)
return
-
0x300
-
i
;
}
if
(
wh
->
table
[
256
]
>
wh
->
poolsize
)
return
-
0xc00
;
return
0
;
}
static
int
get_ip_dst
(
const
struct
sk_buff
*
skb
,
uint32_t
*
addr
)
{
if
(
skb
->
mac
.
ethernet
->
h_proto
==
__constant_htons
(
ETH_P_IP
))
{
struct
iphdr
iph
;
if
(
skb_copy_bits
(
skb
,
0
,
&
iph
,
sizeof
(
iph
)))
return
-
1
;
*
addr
=
iph
.
daddr
;
}
else
if
(
skb
->
mac
.
ethernet
->
h_proto
==
__constant_htons
(
ETH_P_ARP
))
{
struct
arphdr
arph
;
if
(
skb_copy_bits
(
skb
,
0
,
&
arph
,
sizeof
(
arph
))
||
arph
.
ar_pln
!=
sizeof
(
uint32_t
)
||
arph
.
ar_hln
!=
ETH_ALEN
)
return
-
1
;
if
(
skb_copy_bits
(
skb
,
sizeof
(
struct
arphdr
)
+
2
*
ETH_ALEN
+
sizeof
(
uint32_t
),
addr
,
sizeof
(
uint32_t
)))
return
-
1
;
}
return
0
;
}
static
int
get_ip_src
(
const
struct
sk_buff
*
skb
,
uint32_t
*
addr
)
{
if
(
skb
->
mac
.
ethernet
->
h_proto
==
__constant_htons
(
ETH_P_IP
))
{
struct
iphdr
iph
;
if
(
skb_copy_bits
(
skb
,
0
,
&
iph
,
sizeof
(
iph
)))
return
-
1
;
*
addr
=
iph
.
saddr
;
}
else
if
(
skb
->
mac
.
ethernet
->
h_proto
==
__constant_htons
(
ETH_P_ARP
))
{
struct
arphdr
arph
;
if
(
skb_copy_bits
(
skb
,
0
,
&
arph
,
sizeof
(
arph
))
||
arph
.
ar_pln
!=
sizeof
(
uint32_t
)
||
arph
.
ar_hln
!=
ETH_ALEN
)
return
-
1
;
if
(
skb_copy_bits
(
skb
,
sizeof
(
struct
arphdr
)
+
ETH_ALEN
,
addr
,
sizeof
(
uint32_t
)))
return
-
1
;
}
return
0
;
}
static
int
ebt_filter_among
(
const
struct
sk_buff
*
skb
,
const
struct
net_device
*
in
,
const
struct
net_device
*
out
,
const
void
*
data
,
unsigned
int
datalen
)
{
struct
ebt_among_info
*
info
=
(
struct
ebt_among_info
*
)
data
;
const
char
*
dmac
,
*
smac
;
const
struct
ebt_mac_wormhash
*
wh_dst
,
*
wh_src
;
uint32_t
dip
=
0
,
sip
=
0
;
wh_dst
=
ebt_among_wh_dst
(
info
);
wh_src
=
ebt_among_wh_src
(
info
);
if
(
wh_src
)
{
smac
=
skb
->
mac
.
ethernet
->
h_source
;
if
(
get_ip_src
(
skb
,
&
sip
))
return
EBT_NOMATCH
;
if
(
!
(
info
->
bitmask
&
EBT_AMONG_SRC_NEG
))
{
/* we match only if it contains */
if
(
!
ebt_mac_wormhash_contains
(
wh_src
,
smac
,
sip
))
return
EBT_NOMATCH
;
}
else
{
/* we match only if it DOES NOT contain */
if
(
ebt_mac_wormhash_contains
(
wh_src
,
smac
,
sip
))
return
EBT_NOMATCH
;
}
}
if
(
wh_dst
)
{
dmac
=
skb
->
mac
.
ethernet
->
h_dest
;
if
(
get_ip_dst
(
skb
,
&
dip
))
return
EBT_NOMATCH
;
if
(
!
(
info
->
bitmask
&
EBT_AMONG_DST_NEG
))
{
/* we match only if it contains */
if
(
!
ebt_mac_wormhash_contains
(
wh_dst
,
dmac
,
dip
))
return
EBT_NOMATCH
;
}
else
{
/* we match only if it DOES NOT contain */
if
(
ebt_mac_wormhash_contains
(
wh_dst
,
dmac
,
dip
))
return
EBT_NOMATCH
;
}
}
return
EBT_MATCH
;
}
static
int
ebt_among_check
(
const
char
*
tablename
,
unsigned
int
hookmask
,
const
struct
ebt_entry
*
e
,
void
*
data
,
unsigned
int
datalen
)
{
struct
ebt_among_info
*
info
=
(
struct
ebt_among_info
*
)
data
;
int
expected_length
=
sizeof
(
struct
ebt_among_info
);
const
struct
ebt_mac_wormhash
*
wh_dst
,
*
wh_src
;
int
err
;
wh_dst
=
ebt_among_wh_dst
(
info
);
wh_src
=
ebt_among_wh_src
(
info
);
expected_length
+=
ebt_mac_wormhash_size
(
wh_dst
);
expected_length
+=
ebt_mac_wormhash_size
(
wh_src
);
if
(
datalen
!=
EBT_ALIGN
(
expected_length
))
{
printk
(
KERN_WARNING
"ebtables: among: wrong size: %d"
"against expected %d, rounded to %d
\n
"
,
datalen
,
expected_length
,
EBT_ALIGN
(
expected_length
));
return
-
EINVAL
;
}
if
(
wh_dst
&&
(
err
=
ebt_mac_wormhash_check_integrity
(
wh_dst
)))
{
printk
(
KERN_WARNING
"ebtables: among: dst integrity fail: %x
\n
"
,
-
err
);
return
-
EINVAL
;
}
if
(
wh_src
&&
(
err
=
ebt_mac_wormhash_check_integrity
(
wh_src
)))
{
printk
(
KERN_WARNING
"ebtables: among: src integrity fail: %x
\n
"
,
-
err
);
return
-
EINVAL
;
}
return
0
;
}
static
struct
ebt_match
filter_among
=
{
.
name
=
EBT_AMONG_MATCH
,
.
match
=
ebt_filter_among
,
.
check
=
ebt_among_check
,
.
me
=
THIS_MODULE
,
};
static
int
__init
init
(
void
)
{
return
ebt_register_match
(
&
filter_among
);
}
static
void
__exit
fini
(
void
)
{
ebt_unregister_match
(
&
filter_among
);
}
module_init
(
init
);
module_exit
(
fini
);
MODULE_LICENSE
(
"GPL"
);
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment