2 * paircmp.c Valuepair functions for various attributes
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 * Copyright 2000,2006 The FreeRADIUS server project
21 * Copyright 2000 Alan DeKok <aland@ox.org>
24 #include <freeradius-devel/ident.h>
27 #include <freeradius-devel/radiusd.h>
31 * Compare a Connect-Info and a Connect-Rate
33 static int connectcmp(void *instance,
37 VALUE_PAIR *check_pairs,
38 VALUE_PAIR **reply_pairs)
43 check_pairs = check_pairs; /* shut the compiler up */
44 reply_pairs = reply_pairs;
46 rate = atoi((char *)request->vp_strvalue);
47 return rate - check->vp_integer;
52 * Compare a portno with a range.
54 static int portcmp(void *instance,
55 REQUEST *req UNUSED, VALUE_PAIR *request, VALUE_PAIR *check,
56 VALUE_PAIR *check_pairs, VALUE_PAIR **reply_pairs)
58 char buf[MAX_STRING_LEN];
64 check_pairs = check_pairs; /* shut the compiler up */
65 reply_pairs = reply_pairs;
67 if (!request) return -1;
69 port = request->vp_integer;
71 if ((strchr((char *)check->vp_strvalue, ',') == NULL) &&
72 (strchr((char *)check->vp_strvalue, '-') == NULL)) {
73 return (request->vp_integer - check->vp_integer);
77 strcpy(buf, check->vp_strvalue);
81 next = strchr(s, ',');
82 if (next) *next = '\0';
84 if ((p = strchr(s, '-')) != NULL)
88 lo = strtoul(s, NULL, 10);
89 hi = strtoul(p, NULL, 10);
90 if (lo <= port && port <= hi) {
102 * Compare prefix/suffix.
105 * - if PW_STRIP_USER_NAME is present in check_pairs,
106 * strip the username of prefix/suffix.
107 * - if PW_STRIP_USER_NAME is not present in check_pairs,
108 * add a PW_STRIPPED_USER_NAME to the request.
110 static int presufcmp(UNUSED void *instance,
112 VALUE_PAIR *request, VALUE_PAIR *check,
113 VALUE_PAIR *check_pairs, UNUSED VALUE_PAIR **reply_pairs)
117 char rest[MAX_STRING_LEN];
121 if (!request) return -1;
123 name = request->vp_strvalue;
126 printf("Comparing %s and %s, check->attr is %d\n",
127 name, check->vp_strvalue, check->attribute);
130 len = strlen((char *)check->vp_strvalue);
131 switch (check->attribute) {
133 ret = strncmp(name, check->vp_strvalue, len);
135 strlcpy(rest, name + len, sizeof(rest));
138 namelen = strlen(name);
141 ret = strcmp(name + namelen - len,
142 (char *)check->vp_strvalue);
144 strlcpy(rest, name, namelen - len + 1);
152 * If Strip-User-Name == No, then don't do any more.
154 vp = pairfind(check_pairs, PW_STRIP_USER_NAME, 0);
155 if (vp && !vp->vp_integer) return ret;
158 * See where to put the stripped user name.
160 vp = pairfind(check_pairs, PW_STRIPPED_USER_NAME, 0);
163 * If "request" is NULL, then the memory will be
166 vp = radius_paircreate(req, &request,
167 PW_STRIPPED_USER_NAME, PW_TYPE_STRING);
172 strlcpy((char *)vp->vp_strvalue, rest, sizeof(vp->vp_strvalue));
173 vp->length = strlen(vp->vp_strvalue);
180 * Compare the request packet type.
182 static int packetcmp(void *instance UNUSED, REQUEST *req,
183 VALUE_PAIR *request UNUSED,
185 VALUE_PAIR *check_pairs UNUSED,
186 VALUE_PAIR **reply_pairs UNUSED)
188 if (req->packet->code == check->vp_integer) {
196 * Compare the response packet type.
198 static int responsecmp(void *instance UNUSED,
200 VALUE_PAIR *request UNUSED,
202 VALUE_PAIR *check_pairs UNUSED,
203 VALUE_PAIR **reply_pairs UNUSED)
205 if (req->reply->code == check->vp_integer) {
213 * Generic comparisons, via xlat.
215 static int genericcmp(void *instance UNUSED,
217 VALUE_PAIR *request UNUSED,
219 VALUE_PAIR *check_pairs UNUSED,
220 VALUE_PAIR **reply_pairs UNUSED)
222 if ((check->operator != T_OP_REG_EQ) &&
223 (check->operator != T_OP_REG_EQ)) {
229 snprintf(name, sizeof(name), "%%{%s}", check->name);
231 radius_xlat(value, sizeof(value), name, req, NULL);
232 vp = pairmake(check->name, value, check->operator);
235 * Paircmp returns 0 for failed comparison,
238 rcode = paircmp(check, vp);
241 * We're being called from radius_callback_compare,
242 * which wants 0 for success, and 1 for fail (sigh)
244 * We should really fix the API so that it is
245 * consistent. i.e. the comparison callbacks should
246 * return ONLY the resut of comparing A to B.
247 * The radius_callback_cmp function should then
248 * take care of using the operator to see if the
249 * condition (A OP B) is true or not.
251 * This would also allow "<", etc. to work in the
252 * callback functions...
254 * See rlm_ldap, ...groupcmp() for something that
255 * returns 0 for matched, and 1 for didn't match.
264 * Will do the xlat for us
266 return radius_compare_vps(req, check, NULL);
269 static int generic_attrs[] = {
270 PW_CLIENT_IP_ADDRESS,
271 PW_PACKET_SRC_IP_ADDRESS,
272 PW_PACKET_DST_IP_ADDRESS,
275 PW_REQUEST_PROCESSING_STAGE,
276 PW_PACKET_SRC_IPV6_ADDRESS,
277 PW_PACKET_DST_IPV6_ADDRESS,
283 * Register server-builtin special attributes.
285 void pair_builtincompare_init(void)
289 paircompare_register(PW_NAS_PORT, PW_NAS_PORT, portcmp, NULL);
290 paircompare_register(PW_PREFIX, PW_USER_NAME, presufcmp, NULL);
291 paircompare_register(PW_SUFFIX, PW_USER_NAME, presufcmp, NULL);
292 paircompare_register(PW_CONNECT_RATE, PW_CONNECT_INFO, connectcmp, NULL);
293 paircompare_register(PW_PACKET_TYPE, 0, packetcmp, NULL);
294 paircompare_register(PW_RESPONSE_PACKET_TYPE, 0, responsecmp, NULL);
296 for (i = 0; generic_attrs[i] != 0; i++) {
297 paircompare_register(generic_attrs[i], -1, genericcmp, NULL);
301 void pair_builtincompare_detach(void)
305 paircompare_unregister(PW_NAS_PORT, portcmp);
306 paircompare_unregister(PW_PREFIX, presufcmp);
307 paircompare_unregister(PW_SUFFIX, presufcmp);
308 paircompare_unregister(PW_CONNECT_RATE, connectcmp);
309 paircompare_unregister(PW_PACKET_TYPE, packetcmp);
310 paircompare_unregister(PW_RESPONSE_PACKET_TYPE, responsecmp);
312 for (i = 0; generic_attrs[i] != 0; i++) {
313 paircompare_unregister(generic_attrs[i], genericcmp);