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 
31 /** \brief determine if a string is a valid ipv4 address
32  * \retval bool is addr valid?
33  */
34 bool IPv4AddressStringIsValid(const char *str)
35 {
36  int alen = 0;
37  char addr[4][4];
38  int dots = 0;
39 
40  memset(&addr, 0, sizeof(addr));
41 
42  uint32_t len = strlen(str);
43  uint32_t i = 0;
44  for (i = 0; i < len; i++) {
45  if (!(str[i] == '.' || isdigit(str[i]))) {
46  return false;
47  }
48  if (str[i] == '.') {
49  if (dots == 3) {
50  SCLogDebug("too many dots");
51  return false;
52  }
53  addr[dots][alen] = '\0';
54  dots++;
55  alen = 0;
56  } else {
57  if (alen >= 3) {
58  SCLogDebug("too long");
59  return false;
60  }
61  addr[dots][alen++] = str[i];
62  }
63  }
64  if (dots != 3)
65  return false;
66 
67  addr[dots][alen] = '\0';
68  for (int x = 0; x < 4; x++) {
69  uint8_t a;
70  if (StringParseUint8(&a, 10, 0, (const char *)addr[x]) < 0) {
71  SCLogDebug("invalid value for address byte: %s", addr[x]);
72  return false;
73  }
74  }
75  return true;
76 }
77 
78 /** \brief determine if a string is a valid ipv6 address
79  * \retval bool is addr valid?
80  */
81 bool IPv6AddressStringIsValid(const char *str)
82 {
83  int block_size = 0;
84  int sep = 0;
85  bool colon_seen = false;
86 
87  uint32_t len = strlen(str);
88  uint32_t i = 0;
89  for (i = 0; i < len && str[i] != 0; i++) {
90  if (!(str[i] == '.' || str[i] == ':' ||
91  isxdigit(str[i])))
92  return false;
93 
94  if (str[i] == ':') {
95  block_size = 0;
96  colon_seen = true;
97  sep++;
98  } else if (str[i] == '.') {
99  block_size = false;
100  sep++;
101  } else {
102  if (block_size == 4)
103  return false;
104  block_size++;
105  }
106  }
107 
108  if (!colon_seen)
109  return false;
110  if (sep > 7) {
111  SCLogDebug("too many seps %d", sep);
112  return false;
113  }
114  return true;
115 }
116 
117 /**
118  * \brief Validates an IPV4 address and returns the network endian arranged
119  * version of the IPV4 address
120  *
121  * \param addr Pointer to a character string containing an IPV4 address. A
122  * valid IPV4 address is a character string containing a dotted
123  * format of "ddd.ddd.ddd.ddd"
124  *
125  * \retval Pointer to an in_addr instance containing the network endian format
126  * of the IPV4 address
127  * \retval NULL if the IPV4 address is invalid
128  */
129 struct in_addr *ValidateIPV4Address(const char *addr_str)
130 {
131  struct in_addr *addr = NULL;
132 
133  if (!IPv4AddressStringIsValid(addr_str))
134  return NULL;
135 
136  if ( (addr = SCMalloc(sizeof(struct in_addr))) == NULL) {
137  SCLogError(SC_ERR_FATAL, "Fatal error encountered in ValidateIPV4Address. Exiting...");
138  exit(EXIT_FAILURE);
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 addresss
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  */
159 struct 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  SCLogError(SC_ERR_FATAL, "Fatal error encountered in ValidateIPV6Address. Exiting...");
168  exit(EXIT_FAILURE);
169  }
170 
171  if (inet_pton(AF_INET6, addr_str, addr) <= 0) {
172  SCFree(addr);
173  return NULL;
174  }
175 
176  return addr;
177 }
178 
179 /**
180  * \brief Culls the non-netmask portion of the IP address. For example an IP
181  * address 192.168.240.1 would be chopped to 192.168.224.0 against a
182  * netmask value of 19.
183  *
184  * \param stream Pointer the IP address that has to be masked
185  * \param netmask The netmask value (cidr) to which the IP address has to be culled
186  * \param key_bitlen The bitlen of the stream
187  */
188 void MaskIPNetblock(uint8_t *stream, int netmask, int key_bitlen)
189 {
190  uint32_t mask = 0;
191  int i = 0;
192  int bytes = key_bitlen / 8;
193 
194  for (i = 0; i < bytes; i++) {
195  mask = UINT_MAX;
196  if ( ((i + 1) * 8) > netmask) {
197  if ( ((i + 1) * 8 - netmask) < 8)
198  mask = UINT_MAX << ((i + 1) * 8 - netmask);
199  else
200  mask = 0;
201  }
202  stream[i] &= mask;
203  }
204 
205  return;
206 }
util-byte.h
len
uint8_t len
Definition: app-layer-dnp3.h:2
MaskIPNetblock
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:188
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:298
IPv4AddressStringIsValid
bool IPv4AddressStringIsValid(const char *str)
determine if a string is a valid ipv4 address
Definition: util-ip.c:34
ValidateIPV4Address
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:129
util-ip.h
IPv6AddressStringIsValid
bool IPv6AddressStringIsValid(const char *str)
determine if a string is a valid ipv6 address
Definition: util-ip.c:81
ValidateIPV6Address
struct in6_addr * ValidateIPV6Address(const char *addr_str)
Validates an IPV6 address and returns the network endian arranged version of the IPV6 addresss.
Definition: util-ip.c:159
suricata-common.h
SCLogError
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:257
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
str
#define str(s)
Definition: suricata-common.h:273
SCFree
#define SCFree(p)
Definition: util-mem.h:61
SC_ERR_FATAL
@ SC_ERR_FATAL
Definition: util-error.h:203
StringParseUint8
int StringParseUint8(uint8_t *res, int base, uint16_t len, const char *str)
Definition: util-byte.c:359