The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
paircmp.c
Go to the documentation of this file.
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
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 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/**
18 * $Id: 1557f54d3630aec5efd2f6dbeba317c540c15361 $
19 *
20 * @brief Valuepair functions that are radiusd-specific and as such do not
21 * belong in the library.
22 * @file src/lib/server/paircmp.c
23 *
24 * @ingroup AVP
25 *
26 * @copyright 2000,2006 The FreeRADIUS server project
27 * @copyright 2000 Alan DeKok (aland@freeradius.org)
28 */
29
30RCSID("$Id: 1557f54d3630aec5efd2f6dbeba317c540c15361 $")
31
32#include <freeradius-devel/server/paircmp.h>
33#include <freeradius-devel/server/regex.h>
34#include <freeradius-devel/unlang/xlat.h>
35
36/** Compares check and vp by value.
37 *
38 * Does not call any per-attribute comparison function, but does honour
39 * check.operator. Basically does "vp.value check.op check.value".
40 *
41 * @param[in] request Current request.
42 * @param[in] check rvalue, and operator.
43 * @param[in] vp lvalue.
44 * @return
45 * - 0 if check and vp are equal
46 * - -1 if vp value is less than check value.
47 * - 1 is vp value is more than check value.
48 * - -2 on error.
49 */
50#ifdef HAVE_REGEX
51int paircmp_pairs(request_t *request, fr_pair_t const *check, fr_pair_t *vp)
52#else
54#endif
55{
56 int ret = 0;
57
58 /*
59 * Check for =* and !* and return appropriately
60 */
61 if (check->op == T_OP_CMP_TRUE) return 0;
62 if (check->op == T_OP_CMP_FALSE) return 1;
63
64 if (!vp) {
65 REDEBUG("Non-Unary operations require two operands");
66 return -2;
67 }
68
69#ifdef HAVE_REGEX
70 if ((check->op == T_OP_REG_EQ) || (check->op == T_OP_REG_NE)) {
71 ssize_t slen;
72 regex_t *preg = NULL;
73 uint32_t subcaptures;
74 fr_regmatch_t *regmatch;
75
76 char *expr = NULL, *value = NULL;
77 char const *expr_p, *value_p;
78
79 if (check->vp_type == FR_TYPE_STRING) {
80 expr_p = check->vp_strvalue;
81 } else {
82 fr_value_box_aprint(request, &expr, &check->data, NULL);
83 expr_p = expr;
84 }
85
86 if (vp->vp_type == FR_TYPE_STRING) {
87 value_p = vp->vp_strvalue;
88 } else {
89 fr_value_box_aprint(request, &value, &vp->data, NULL);
90 value_p = value;
91 }
92
93 if (!expr_p || !value_p) {
94 REDEBUG("Error stringifying operand for regular expression");
95
96 regex_error:
97 talloc_free(preg);
98 talloc_free(expr);
100 return -2;
101 }
102
103 /*
104 * Include substring matches.
105 */
106 slen = regex_compile(request, &preg, expr_p, talloc_array_length(expr_p) - 1,
107 NULL, true, true);
108 if (slen <= 0) {
109 REMARKER(expr_p, -slen, "%s", fr_strerror());
110
111 goto regex_error;
112 }
113
114 subcaptures = regex_subcapture_count(preg);
115 if (!subcaptures) subcaptures = REQUEST_MAX_REGEX + 1; /* +1 for %{0} (whole match) capture group */
116 MEM(regmatch = regex_match_data_alloc(NULL, subcaptures));
117
118 /*
119 * Evaluate the expression
120 */
121 slen = regex_exec(preg, value_p, talloc_array_length(value_p) - 1, regmatch);
122 if (slen < 0) {
123 RPERROR("Invalid regex");
124
125 goto regex_error;
126 }
127
128 if (check->op == T_OP_REG_EQ) {
129 /*
130 * Add in %{0}. %{1}, etc.
131 */
132 regex_sub_to_request(request, &preg, &regmatch, &vp->data);
133 ret = (slen == 1) ? 0 : -1;
134 } else {
135 ret = (slen != 1) ? 0 : -1;
136 }
137
138 talloc_free(regmatch);
139 talloc_free(preg);
140 talloc_free(expr);
142
143 goto finish;
144 }
145#endif
146
147 /*
148 * Attributes must be of the same type.
149 *
150 * FIXME: deal with type mismatch properly if one side contain
151 * OCTETS or STRING by converting the other side to
152 * a string
153 *
154 */
155 if (vp->vp_type != check->vp_type) return -1;
156
157 /*
158 * Not a regular expression, compare the types.
159 */
160 switch (check->vp_type) {
161 case FR_TYPE_OCTETS:
162 if (vp->vp_length != check->vp_length) {
163 ret = 1; /* NOT equal */
164 break;
165 }
166 ret = memcmp(vp->vp_strvalue, check->vp_strvalue, vp->vp_length);
167 break;
168
169 case FR_TYPE_STRING:
170 ret = strcmp(vp->vp_strvalue, check->vp_strvalue);
171 break;
172
173 case FR_TYPE_UINT8:
174 ret = vp->vp_uint8 - check->vp_uint8;
175 break;
176
177 case FR_TYPE_UINT16:
178 ret = vp->vp_uint16 - check->vp_uint16;
179 break;
180
181 case FR_TYPE_UINT32:
182 ret = vp->vp_uint32 - check->vp_uint32;
183 break;
184
185 case FR_TYPE_UINT64:
186 /*
187 * Don't want integer overflow!
188 */
189 if (vp->vp_uint64 < check->vp_uint64) {
190 ret = -1;
191 } else if (vp->vp_uint64 > check->vp_uint64) {
192 ret = +1;
193 } else {
194 ret = 0;
195 }
196 break;
197
198 case FR_TYPE_INT32:
199 ret = CMP(vp->vp_int32, check->vp_int32);
200 break;
201
202 case FR_TYPE_DATE:
203 ret = fr_unix_time_cmp(vp->vp_date, check->vp_date);
204 break;
205
207 ret = ntohl(vp->vp_ipv4addr) - ntohl(check->vp_ipv4addr);
208 break;
209
211 ret = memcmp(vp->vp_ip.addr.v6.s6_addr, check->vp_ip.addr.v6.s6_addr,
212 sizeof(vp->vp_ip.addr.v6.s6_addr));
213 break;
214
217 ret = fr_pair_cmp_op(check->op, vp, check);
218 if (ret == -1) return -2; // error
219 if (check->op == T_OP_LT || check->op == T_OP_LE)
220 ret = (ret == 1) ? -1 : 1;
221 else if (check->op == T_OP_GT || check->op == T_OP_GE)
222 ret = (ret == 1) ? 1 : -1;
223 else if (check->op == T_OP_CMP_EQ)
224 ret = (ret == 1) ? 0 : -1;
225 break;
226
227 case FR_TYPE_IFID:
228 ret = memcmp(vp->vp_ifid, check->vp_ifid, sizeof(vp->vp_ifid));
229 break;
230
231 default:
232 break;
233 }
234
235finish:
236 if (ret > 0) return 1;
237 if (ret < 0) return -1;
238 return 0;
239}
#define RCSID(id)
Definition build.h:485
#define CMP(_a, _b)
Same as CMP_PREFER_SMALLER use when you don't really care about ordering, you just want an ordering.
Definition build.h:112
#define UNUSED
Definition build.h:317
#define MEM(x)
Definition debug.h:36
Test enumeration values.
Definition dict_test.h:92
#define RPERROR(fmt,...)
Definition log.h:302
#define REMARKER(_str, _marker_idx, _marker,...)
Output string with error marker, showing where format error occurred.
Definition log.h:498
talloc_free(reap)
@ FR_TYPE_IPV4_ADDR
32 Bit IPv4 Address.
@ FR_TYPE_IPV6_PREFIX
IPv6 Prefix.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_UINT16
16 Bit unsigned integer.
@ FR_TYPE_DATE
Unix time stamp, always has value >2^31.
@ FR_TYPE_UINT8
8 Bit unsigned integer.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_INT32
32 Bit signed integer.
@ FR_TYPE_UINT64
64 Bit unsigned integer.
@ FR_TYPE_IPV6_ADDR
128 Bit IPv6 Address.
@ FR_TYPE_IPV4_PREFIX
IPv4 Prefix.
@ FR_TYPE_IFID
Interface ID.
@ FR_TYPE_OCTETS
Raw octets.
unsigned int uint32_t
long int ssize_t
#define check(_handle, _len_p)
Definition bio.c:44
int paircmp_pairs(UNUSED request_t *request, fr_pair_t const *check, fr_pair_t *vp)
Compares check and vp by value.
Definition paircmp.c:53
#define REDEBUG(fmt,...)
Definition radclient.h:52
fr_pair_t * vp
Stores an attribute, a value and various bits of other data.
Definition pair.h:68
static int8_t fr_unix_time_cmp(fr_unix_time_t a, fr_unix_time_t b)
Compare two fr_unix_time_t values.
Definition time.h:944
@ T_OP_CMP_TRUE
Definition token.h:104
@ T_OP_CMP_FALSE
Definition token.h:105
@ T_OP_REG_EQ
Definition token.h:102
@ T_OP_CMP_EQ
Definition token.h:106
@ T_OP_LE
Definition token.h:100
@ T_OP_GE
Definition token.h:98
@ T_OP_GT
Definition token.h:99
@ T_OP_LT
Definition token.h:101
@ T_OP_REG_NE
Definition token.h:103
#define fr_pair_cmp_op(_op, _a, _b)
Compare two attributes using and operator.
Definition pair.h:666
char const * fr_strerror(void)
Get the last library error.
Definition strerror.c:553
static fr_slen_t fr_value_box_aprint(TALLOC_CTX *ctx, char **out, fr_value_box_t const *data, fr_sbuff_escape_rules_t const *e_rules) 1(fr_value_box_print