suricata
util-ip.c
Go to the documentation of this file.
1/* Copyright (C) 2007-2013 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 Anoop Saldanha <anoopsaldanha@gmail.com>
22 * \author Duarte Silva <duarte.silva@serializing.me>
23 *
24 * IP addresses related utility functions
25 */
26
27#include "suricata-common.h"
28#include "util-ip.h"
29#include "util-byte.h"
30#include "util-debug.h"
31
32/** \brief determine if a string is a valid ipv4 address
33 * \retval bool is addr valid?
34 */
36{
37 int alen = 0;
38 char addr[4][4];
39 int dots = 0;
40
41 memset(&addr, 0, sizeof(addr));
42
43 size_t len = strlen(str);
44 size_t i = 0;
45 for (i = 0; i < len; i++) {
46 if (!(str[i] == '.' || isdigit(str[i]))) {
47 return false;
48 }
49 if (str[i] == '.') {
50 if (dots == 3) {
51 SCLogDebug("too many dots");
52 return false;
53 }
54 addr[dots][alen] = '\0';
55 dots++;
56 alen = 0;
57 } else {
58 if (alen >= 3) {
59 SCLogDebug("too long");
60 return false;
61 }
62 addr[dots][alen++] = str[i];
63 }
64 }
65 if (dots != 3)
66 return false;
67
68 addr[dots][alen] = '\0';
69 for (int x = 0; x < 4; x++) {
70 uint8_t a;
71 if (StringParseUint8(&a, 10, 0, (const char *)addr[x]) < 0) {
72 SCLogDebug("invalid value for address byte: %s", addr[x]);
73 return false;
74 }
75 }
76 return true;
77}
78
79/** \brief determine if a string is a valid ipv6 address
80 * \retval bool is addr valid?
81 */
83{
84 int block_size = 0;
85 int sep = 0;
86 bool colon_seen = false;
87
88 size_t len = strlen(str);
89 size_t i = 0;
90 for (i = 0; i < len && str[i] != 0; i++) {
91 if (!(str[i] == '.' || str[i] == ':' ||
92 isxdigit(str[i])))
93 return false;
94
95 if (str[i] == ':') {
96 block_size = 0;
97 colon_seen = true;
98 sep++;
99 } else if (str[i] == '.') {
100 block_size = false;
101 sep++;
102 } else {
103 if (block_size == 4)
104 return false;
105 block_size++;
106 }
107 }
108
109 if (!colon_seen)
110 return false;
111 if (sep > 7) {
112 SCLogDebug("too many seps %d", sep);
113 return false;
114 }
115 return true;
116}
117
118/**
119 * \brief Validates an IPV4 address and returns the network endian arranged
120 * version of the IPV4 address
121 *
122 * \param addr Pointer to a character string containing an IPV4 address. A
123 * valid IPV4 address is a character string containing a dotted
124 * format of "ddd.ddd.ddd.ddd"
125 *
126 * \retval Pointer to an in_addr instance containing the network endian format
127 * of the IPV4 address
128 * \retval NULL if the IPV4 address is invalid
129 */
130struct in_addr *ValidateIPV4Address(const char *addr_str)
131{
132 struct in_addr *addr = NULL;
133
134 if (!IPv4AddressStringIsValid(addr_str))
135 return NULL;
136
137 if ( (addr = SCMalloc(sizeof(struct in_addr))) == NULL) {
138 FatalError("Fatal error encountered in ValidateIPV4Address. Exiting...");
139 }
140
141 if (inet_pton(AF_INET, addr_str, addr) <= 0) {
142 SCFree(addr);
143 return NULL;
144 }
145
146 return addr;
147}
148
149/**
150 * \brief Validates an IPV6 address and returns the network endian arranged
151 * version of the IPV6 address
152 *
153 * \param addr Pointer to a character string containing an IPV6 address
154 *
155 * \retval Pointer to a in6_addr instance containing the network endian format
156 * of the IPV6 address
157 * \retval NULL if the IPV6 address is invalid
158 */
159struct in6_addr *ValidateIPV6Address(const char *addr_str)
160{
161 struct in6_addr *addr = NULL;
162
163 if (!IPv6AddressStringIsValid(addr_str))
164 return NULL;
165
166 if ( (addr = SCMalloc(sizeof(struct in6_addr))) == NULL) {
167 FatalError("Fatal error encountered in ValidateIPV6Address. Exiting...");
168 }
169
170 if (inet_pton(AF_INET6, addr_str, addr) <= 0) {
171 SCFree(addr);
172 return NULL;
173 }
174
175 return addr;
176}
177
178/**
179 * \brief Culls the non-netmask portion of the IP address. For example an IP
180 * address 192.168.240.1 would be chopped to 192.168.224.0 against a
181 * netmask value of 19.
182 *
183 * \param stream Pointer the IP address that has to be masked
184 * \param netmask The netmask value (cidr) to which the IP address has to be culled
185 * \param key_bitlen The bitlen of the stream
186 */
187void MaskIPNetblock(uint8_t *stream, int netmask, int key_bitlen)
188{
189 uint32_t mask = 0;
190 int i = 0;
191 int bytes = key_bitlen / 8;
192
193 for (i = 0; i < bytes; i++) {
194 mask = UINT_MAX;
195 if ( ((i + 1) * 8) > netmask) {
196 if ( ((i + 1) * 8 - netmask) < 8)
197 mask = UINT_MAX << ((i + 1) * 8 - netmask);
198 else
199 mask = 0;
200 }
201 stream[i] &= mask;
202 }
203}
uint8_t len
#define str(s)
int StringParseUint8(uint8_t *res, int base, size_t len, const char *str)
Definition util-byte.c:361
#define FatalError(...)
Definition util-debug.h:510
#define SCLogDebug(...)
Definition util-debug.h:275
bool IPv6AddressStringIsValid(const char *str)
determine if a string is a valid ipv6 address
Definition util-ip.c:82
struct in_addr * ValidateIPV4Address(const char *addr_str)
Validates an IPV4 address and returns the network endian arranged version of the IPV4 address.
Definition util-ip.c:130
struct in6_addr * ValidateIPV6Address(const char *addr_str)
Validates an IPV6 address and returns the network endian arranged version of the IPV6 address.
Definition util-ip.c:159
void MaskIPNetblock(uint8_t *stream, int netmask, int key_bitlen)
Culls the non-netmask portion of the IP address. For example an IP address 192.168....
Definition util-ip.c:187
bool IPv4AddressStringIsValid(const char *str)
determine if a string is a valid ipv4 address
Definition util-ip.c:35
#define SCMalloc(sz)
Definition util-mem.h:47
#define SCFree(p)
Definition util-mem.h:61