# How to create Complex Wildcard Masks

In one of my previous tutorials I explained how to calculate wildcard bits for access-lists that you can use to match network and subnet addresses. In this tutorial we will dive a bit deeper into the wildcards and I’ll teach you how to match on some more complex patterns.

## Match all even or uneven subnets

We start with something simple, the goal is to match all “even” subnets. This is my list of subnets that I have to play with:

192.168.0.0 /24
192.168.1.0 /24
192.168.2.0 /24
192.168.3.0 /24
192.168.4.0 /24
192.168.5.0 /24
192.168.6.0 /24
192.168.7.0 /24
192.168.8.0 /24

So how are we going to approach this? What kind of wildcard mask do we need to match all the even subnets. To answer this question we have to look at it in binary:

 192.168.0.0 1100 0000 1010 1000 0000 0000 0000 0000 192.168.1.0 1100 0000 1010 1000 0000 0001 0000 0000 192.168.2.0 1100 0000 1010 1000 0000 0010 0000 0000 192.168.3.0 1100 0000 1010 1000 0000 0011 0000 0000 192.168.4.0 1100 0000 1010 1000 0000 0100 0000 0000 192.168.5.0 1100 0000 1010 1000 0000 0101 0000 0000 192.168.6.0 1100 0000 1010 1000 0000 0100 0000 0000 192.168.7.0 1100 0000 1010 1000 0000 0101 0000 0000 192.168.8.0 1100 0000 1010 1000 0000 1000 0000 0000

The first and second octet is the same for all these subnets and we don’t care about the last octet since it’s for hosts. We need to look at the third octet to find a pattern. Let’s take a look at the even subnets:

 0 0000 0000 2 0000 0010 4 0000 0100 6 0000 0110 8 0000 1000

One thing that all these subnets have in common is that the 8th bit is always a 0. Let’s look at the uneven subnets too:

 1 0000 0001 3 0000 0011 5 0000 0101 7 0000 0111

To create an uneven subnet, the 8th bit is always a 1. This is something we can match with a wildcard. Let’s start with a wildcard that matches all even subnets:

 192.168.0.0 1100 0000 1010 1000 0000 0000 0000 0000 192.168.2.0 1100 0000 1010 1000 0000 0010 0000 0000 192.168.4.0 1100 0000 1010 1000 0000 0100 0000 0000 192.168.6.0 1100 0000 1010 1000 0000 0110 0000 0000 192.168.8.0 1100 0000 1010 1000 0000 1000 0000 0000 wildcard 0000 0000 0000 0000 1111 1110 1111 1111

The first two octets are the same for all the subnets so we use all zeroes for the wildcard mask. In the third octet we use a 1 (don’t care) for all bits except for the 8th bit…it has to match. We don’t care at all about the 4th octet.

The wildcard that we can use will be 0.0.254.255.

Want to see a real life example? Let me show you an example of a router that is configured for EIGRP. This is what the routing table looks like, you see all the networks that I used in the example above:

``````R2#show ip route eigrp
D    192.168.8.0/24 [90/409600] via 10.10.10.1, 00:09:51, FastEthernet0/0
D    192.168.4.0/24 [90/409600] via 10.10.10.1, 00:09:51, FastEthernet0/0
D    192.168.5.0/24 [90/409600] via 10.10.10.1, 00:00:03, FastEthernet0/0
D    192.168.6.0/24 [90/409600] via 10.10.10.1, 00:09:51, FastEthernet0/0
D    192.168.7.0/24 [90/409600] via 10.10.10.1, 00:00:03, FastEthernet0/0
D    192.168.0.0/24 [90/409600] via 10.10.10.1, 00:09:51, FastEthernet0/0
D    192.168.1.0/24 [90/409600] via 10.10.10.1, 00:00:03, FastEthernet0/0
D    192.168.2.0/24 [90/409600] via 10.10.10.1, 00:09:51, FastEthernet0/0
D    192.168.3.0/24 [90/409600] via 10.10.10.1, 00:00:03, FastEthernet0/0``````

Now we will make an access-list that uses the wildcard mask that we just found. I use 192.168.0.0 as the network address so it matches all subnets in the 192.168.x.x range.

``````R2(config)#ip access-list standard EVEN
R2(config-std-nacl)#permit 192.168.0.0 0.0.254.255``````

I can use a distribute-list and refer to the access-list to filter incoming routing updates:

``````R2(config)#router eigrp 10
R2(config-router)#distribute-list EVEN in``````

After applying the distribute-list the routing table looks like this:

``````R2#show ip route eigrp
D    192.168.8.0/24 [90/409600] via 10.10.10.1, 00:03:57, FastEthernet0/0
D    192.168.4.0/24 [90/409600] via 10.10.10.1, 00:03:57, FastEthernet0/0
D    192.168.6.0/24 [90/409600] via 10.10.10.1, 00:03:57, FastEthernet0/0
D    192.168.0.0/24 [90/409600] via 10.10.10.1, 00:03:57, FastEthernet0/0
D    192.168.2.0/24 [90/409600] via 10.10.10.1, 00:03:57, FastEthernet0/0``````

Voila! Only the even subnets are here.

We can also use the same wildcard but apply it the other way around so it matches all the uneven subnets:

 192.168.1.0 1100 0000 1010 1000 0000 0001 0000 0000 192.168.3.0 1100 0000 1010 1000 0000 0011 0000 0000 192.168.5.0 1100 0000 1010 1000 0000 0101 0000 0000 192.168.7.0 1100 0000 1010 1000 0000 0111 0000 0000 wildcard 0000 0000 0000 0000 1111 1110 1111 1111

We use the exact same wildcard mask but we will use another subnet address in the access-list (192.168.1.0):

 192.168.1.0 1100 0000 1010 1000 0000 0001 0000 0000 wildcard 0000 0000 0000 0000 1111 1110 1111 1111

When we use this subnet as the network address then the 8th bit of the 3rd octet has to be a 1. This is what the access-list will look like:

``````R2(config)#ip access-list standard UNEVEN
R2(config-std-nacl)#deny 192.168.1.0 0.0.254.255
R2(config-std-nacl)#permit any``````

We deny all the uneven subnets and permit everything else. Let’s apply it so you can see it in action:

``````R2(config)#router eigrp 10
R2(config-router)#no distribute-list EVEN in
R2(config-router)#distribute-list UNEVEN in``````

The results will be the same:

``````R2#show ip route eigrp
D    192.168.8.0/24 [90/409600] via 10.10.10.1, 00:00:02, FastEthernet0/0
D    192.168.4.0/24 [90/409600] via 10.10.10.1, 00:00:02, FastEthernet0/0
D    192.168.6.0/24 [90/409600] via 10.10.10.1, 00:00:02, FastEthernet0/0
D    192.168.0.0/24 [90/409600] via 10.10.10.1, 00:00:02, FastEthernet0/0
D    192.168.2.0/24 [90/409600] via 10.10.10.1, 00:00:02, FastEthernet0/0``````

Are you following me so far? Let’s try a more complex example!

## Matching “random” subnets

This is an example that you might encounter on a test. Let me show you a couple of subnets:

192.168.10.0 /24
192.168.26.0 /24
192.168.42.0 /24
192.168.58.0 /24

These subnets look random to us but on a binary level they have something in common. To see this, we need to dive into the binary world:

## Forum Replies

1. Hi Bruce,

I used the .10 in the third octet since that’s the first network we try to match. With the 0.0.48.255 wildcard bits we only match on those 4 networks. Let’s zoom in on those 4 networks and the wildcard:

10 = 0000 1010
26 = 0001 1010
42 = 0010 1010
56 = 0011 1010

wc = 0011 0000

by setting all bits to “0” we lock them, only the 3th and 4th bit is allowed to change:

00
01
10
11

Those are the only 4 combinations you can make, resulting in network 192.168.10.0, 192.168.26.0, 192.168.42.0 and 192.168.56.0…nothing else is matched.

Now look at your wildcard (

... Continue reading in our forum

2. Hey Rene,
I wanted to ask about using access-lists to solve that classic problem of filtering odd or even routes. Suppose you were asked to create a filter that would allow a route if it were odd in the 2nd octet, and even in the 3rd octet. Obviously, you can accomplish it with this:

ip access-list standard ACL_ALLOWODDEVEN
deny 0.0.0.0 255.254.255.255
deny 0.0.1.0 255.255.254.255
permit any

But what isn’t obvious to me, is why the following does NOT work:

ip access-list standard ACL_COMBO
deny 0.0.1.0 255.254.254.255
permit any

I thought they accomplis

... Continue reading in our forum

3. Hi Andrew,

These questions can be tricky…we’ll have to look at some binary numbers, especially the 2nd and 3th octect:

2nd + 3rd = 00000000 00000001
wildcard = 11111110 11111110

So the only bits we care about are the 8th bit (has to be 0) and the 16th bit (has to be a 1).

10.0.0.1
10.0.1.1
10.1.0.1
10.1.1.1
10.2.0.1
10.2.1.1

Then here’s all that is left afterwards:

10.0.0.1
10.1.0.1
10.1.1.1
10.2.0.1

Let’s look at all addressses’ 2nd and 3th octet in binary:

10.0.0.1 = 00000000 00000000
10.0.1.1 = 00000000 0000

... Continue reading in our forum

4. I must be slow today. I have read over your analysis many times, but I am still not understanding this. Let’s continue to use your range of 10 addresses for the example.

If I take the entire set of 10. addresses, and run them through the ACL_ODDEVEN filter, just one is left:
10.1.0.1

If I take the entire set of 10. addresses, and run them through the ACL_COMBO filter, a total of four is left (which is what you found above):
10.0.0.1
10.1.0.1 <------ Also the result of ACL_ODDEVEN
10.1.1.1
10.2.0.1

If we look at the results of the ACL_COMBO in binary (just th

... Continue reading in our forum

5. Ok, I feel like a dope. I finally broke down and charted out what was happening in a spreadsheet. After doing this it became clear.

Basically, it comes down to this–the ACL_COMBO is doing an “AND” while the ACL_ALLOWEVENODD is doing an “OR”.

Part of the confusion here is that we are using the ACLs to deny, or filter out, routes (so the logic is flipped). The ACL_COMBO is written too restrictively (hence the resulting filtered set is too large).

ACL_COMBO is saying “You are denied only if the last bit of the second octet is a zero AND the last bit of the 3rd

... Continue reading in our forum

19 more replies! Ask a question or join the discussion by visiting our Community Forum