suricata
util-cidr.c
Go to the documentation of this file.
1/* Copyright (C) 2007-2022 Open Information Security Foundation
2 *
3 * You can copy, redistribute or modify this Program under the terms of
4 * the GNU General Public License version 2 as published by the Free
5 * Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * version 2 along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18/**
19 * \file
20 *
21 * \author Victor Julien <victor@inliniac.net>
22 *
23 * CIDR utility functions
24 */
25
26#include "suricata-common.h"
27#include "util-cidr.h"
28#include "util-debug.h"
29#include "util-unittest.h"
30
31/** \brief Turn 32 bit mask into CIDR
32 *
33 * \retval cidr The cidr value or -1 if the netmask can't be expressed as cidr
34 */
35int CIDRFromMask(uint32_t netmask)
36{
37 netmask = ntohl(netmask);
38 if (netmask == 0) {
39 return 0;
40 }
41 int p = 0;
42 bool seen_1 = false;
43 while (netmask > 0) {
44 if (netmask & 1) {
45 seen_1 = true;
46 p++;
47 } else {
48 if (seen_1) {
49 return -1;
50 }
51 }
52 netmask >>= 1;
53 }
54 return p;
55}
56
57uint32_t CIDRGet(int cidr)
58{
59 if (cidr <= 0 || cidr > 32)
60 return 0;
61 uint32_t netmask = htonl(0xFFFFFFFF << (32UL - (uint32_t)cidr));
62 SCLogDebug("CIDR %d -> netmask %08X", cidr, netmask);
63 return netmask;
64}
65
66/**
67 * \brief Creates a cidr ipv6 netblock, based on the cidr netblock value.
68 *
69 * For example if we send a cidr of 7 as argument, an ipv6 address
70 * mask of the value FE:00:00:00:00:00:00:00 is created and updated
71 * in the argument struct in6_addr *in6.
72 *
73 * \todo I think for the final section: while (cidr > 0), we can simply
74 * replace it with a
75 * if (cidr > 0) {
76 * in6->s6_addr[i] = -1 << (8 - cidr);
77 *
78 * \param cidr The value of the cidr.
79 * \param in6 Pointer to an ipv6 address structure(struct in6_addr) which will
80 * hold the cidr netblock result.
81 */
82void CIDRGetIPv6(int cidr, struct in6_addr *in6)
83{
84 int i = 0;
85
86 memset(in6, 0, sizeof(struct in6_addr));
87
88 while (cidr > 8) {
89 in6->s6_addr[i] = 0xff;
90 cidr -= 8;
91 i++;
92 }
93
94 while (cidr > 0) {
95 in6->s6_addr[i] |= 0x80;
96 if (--cidr > 0)
97 in6->s6_addr[i] = in6->s6_addr[i] >> 1;
98 }
99}
100
101#ifdef UNITTESTS
102
103static int CIDRFromMaskTest01(void)
104{
105 struct in_addr in;
106 int v = inet_pton(AF_INET, "255.255.255.0", &in);
107
108 FAIL_IF(v <= 0);
109 FAIL_IF_NOT(24 == CIDRFromMask(in.s_addr));
110
111 PASS;
112}
113
114static int CIDRFromMaskTest02(void)
115{
116 struct in_addr in;
117 int v = inet_pton(AF_INET, "255.255.0.42", &in);
118
119 FAIL_IF(v <= 0);
120 FAIL_IF_NOT(-1 == CIDRFromMask(in.s_addr));
121
122 PASS;
123}
124
125static int CIDRFromMaskTest03(void)
126{
127 struct in_addr in;
128 int v = inet_pton(AF_INET, "0.0.0.0", &in);
129
130 FAIL_IF(v <= 0);
131 FAIL_IF_NOT(0 == CIDRFromMask(in.s_addr));
132
133 PASS;
134}
135
136static int CIDRFromMaskTest04(void)
137{
138 struct in_addr in;
139 int v = inet_pton(AF_INET, "255.255.255.255", &in);
140
141 FAIL_IF(v <= 0);
142 FAIL_IF_NOT(32 == CIDRFromMask(in.s_addr));
143
144 PASS;
145}
146
147#endif /* UNITTESTS */
148
150{
151#ifdef UNITTESTS
152 UtRegisterTest("CIDRFromMaskTest01", CIDRFromMaskTest01);
153 UtRegisterTest("CIDRFromMaskTest02", CIDRFromMaskTest02);
154 UtRegisterTest("CIDRFromMaskTest03", CIDRFromMaskTest03);
155 UtRegisterTest("CIDRFromMaskTest04", CIDRFromMaskTest04);
156#endif /* UNITTESTS */
157}
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
#define PASS
Pass the test.
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
int CIDRFromMask(uint32_t netmask)
Turn 32 bit mask into CIDR.
Definition util-cidr.c:35
void UtilCIDRTests(void)
Definition util-cidr.c:149
void CIDRGetIPv6(int cidr, struct in6_addr *in6)
Creates a cidr ipv6 netblock, based on the cidr netblock value.
Definition util-cidr.c:82
uint32_t CIDRGet(int cidr)
Definition util-cidr.c:57
#define SCLogDebug(...)
Definition util-debug.h:275