📄 xlat.c
字号:
/* * xlat.c Translate strings. This is the first version of xlat * incorporated to RADIUS * * Version: $Id: xlat.c,v 1.72.2.3 2004/09/09 14:31:07 aland Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Copyright 2000 The FreeRADIUS server project * Copyright 2000 Alan DeKok <aland@ox.org> */static const char rcsid[] ="$Id: xlat.c,v 1.72.2.3 2004/09/09 14:31:07 aland Exp $";#include "autoconf.h"#include "libradius.h"#include <stdio.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#include "radiusd.h"#include "rad_assert.h"typedef struct xlat_t { char module[MAX_STRING_LEN]; int length; void *instance; RAD_XLAT_FUNC do_xlat; int internal; /* not allowed to re-define these */} xlat_t;static rbtree_t *xlat_root = NULL;/* * Define all xlat's in the structure. */static const char *internal_xlat[] = {"check", "request", "reply", "proxy-request", "proxy-reply", NULL};#if REQUEST_MAX_REGEX > 8#error Please fix the following line#endifstatic int xlat_inst[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 }; /* up to 8 for regex *//* * Convert the value on a VALUE_PAIR to string */static int valuepair2str(char * out,int outlen,VALUE_PAIR * pair, int type, RADIUS_ESCAPE_STRING func){ char buffer[MAX_STRING_LEN * 4]; if (pair != NULL) { vp_prints_value(buffer, sizeof(buffer), pair, 0); return func(out, outlen, buffer); } switch (type) { case PW_TYPE_STRING : strNcpy(out,"_",outlen); break; case PW_TYPE_INTEGER : strNcpy(out,"0",outlen); break; case PW_TYPE_IPADDR : strNcpy(out,"?.?.?.?",outlen); break; case PW_TYPE_DATE : strNcpy(out,"0",outlen); break; default : strNcpy(out,"unknown_type",outlen); } return strlen(out);}/* * Dynamically translate for check:, request:, reply:, etc. */static int xlat_packet(void *instance, REQUEST *request, char *fmt, char *out, size_t outlen, RADIUS_ESCAPE_STRING func){ DICT_ATTR *da; VALUE_PAIR *vp; VALUE_PAIR *vps = NULL; RADIUS_PACKET *packet = NULL; switch (*(int*) instance) { case 0: vps = request->config_items; break; case 1: vps = request->packet->vps; packet = request->packet; break; case 2: vps = request->reply->vps; packet = request->reply; break; case 3: if (request->proxy) vps = request->proxy->vps; packet = request->proxy; break; case 4: if (request->proxy_reply) vps = request->proxy_reply->vps; packet = request->proxy_reply; break; default: /* WTF? */ return 0; } /* * The "format" string is the attribute name. */ da = dict_attrbyname(fmt); if (!da) return 0; vp = pairfind(vps, da->attr); if (!vp) { /* * Some "magic" handlers, which are never in VP's, but * which are in the packet. * * FIXME: Add SRC/DST IP address! */ if (packet) { switch (da->attr) { case PW_PACKET_TYPE: { DICT_VALUE *dval; dval = dict_valbyattr(da->attr, packet->code); if (dval) { snprintf(out, outlen, "%s", dval->name); } else { snprintf(out, outlen, "%d", packet->code); } return strlen(out); } break; default: break; } } /* * Not found, die. */ return 0; } if (!vps) return 0; /* silently fail */ /* * Convert the VP to a string, and return it. */ return valuepair2str(out, outlen, vp, da->type, func);}#ifdef HAVE_REGEX_H/* * Pull %{0} to %{8} out of the packet. */static int xlat_regex(void *instance, REQUEST *request, char *fmt, char *out, size_t outlen, RADIUS_ESCAPE_STRING func){ char *regex; /* * We cheat: fmt is "0" to "8", but those numbers * are already in the "instance". */ fmt = fmt; /* -Wunused */ func = func; /* -Wunused FIXME: do escaping? */ regex = request_data_get(request, request, REQUEST_DATA_REGEX | *(int *)instance); if (!regex) return 0; /* * Copy UP TO "freespace" bytes, including * a zero byte. */ strNcpy(out, regex, outlen); free(regex); /* was strdup'd */ return strlen(out);}#endif /* HAVE_REGEX_H *//* * Compare two xlat_t structs, based ONLY on the module name. */static int xlat_cmp(const void *a, const void *b){ if (((const xlat_t *)a)->length != ((const xlat_t *)b)->length) { return ((const xlat_t *)a)->length - ((const xlat_t *)b)->length; } return memcmp(((const xlat_t *)a)->module, ((const xlat_t *)b)->module, ((const xlat_t *)a)->length);}/* * find the appropriate registered xlat function. */static xlat_t *xlat_find(const char *module){ char *p; xlat_t my_xlat; strNcpy(my_xlat.module, module, sizeof(my_xlat.module)); /* * We get passed the WHOLE string, and all we want here * is the first piece. */ p = strchr(my_xlat.module, ':'); if (p) *p = '\0'; my_xlat.length = strlen(my_xlat.module); return rbtree_finddata(xlat_root, &my_xlat);}/* * Register an xlat function. */int xlat_register(const char *module, RAD_XLAT_FUNC func, void *instance){ xlat_t *c; xlat_t my_xlat; if ((module == NULL) || (strlen(module) == 0)) { DEBUG("xlat_register: Invalid module name"); return -1; } /* * First time around, build up the tree... * * FIXME: This code should be hoisted out of this function, * and into a global "initialization". But it isn't critical... */ if (!xlat_root) { int i;#ifdef HAVE_REGEX_H char buffer[2];#endif xlat_root = rbtree_create(xlat_cmp, free, 0); if (!xlat_root) { DEBUG("xlat_register: Failed to create tree."); return -1; } /* * Register the internal packet xlat's. */ for (i = 0; internal_xlat[i] != NULL; i++) { xlat_register(internal_xlat[i], xlat_packet, &xlat_inst[i]); c = xlat_find(internal_xlat[i]); rad_assert(c != NULL); c->internal = TRUE; }#ifdef HAVE_REGEX_H /* * Register xlat's for regexes. */ buffer[1] = '\0'; for (i = 0; i <= REQUEST_MAX_REGEX; i++) { buffer[0] = '0' + i; xlat_register(buffer, xlat_regex, &xlat_inst[i]); c = xlat_find(buffer); rad_assert(c != NULL); c->internal = TRUE; }#endif /* HAVE_REGEX_H */ } /* * If it already exists, replace the instance. */ strNcpy(my_xlat.module, module, sizeof(my_xlat.module)); my_xlat.length = strlen(my_xlat.module); c = rbtree_finddata(xlat_root, &my_xlat); if (c) { if (c->internal) { DEBUG("xlat_register: Cannot re-define internal xlat"); return -1; } c->do_xlat = func; c->instance = instance; return 0; } /* * Doesn't exist. Create it. */ c = rad_malloc(sizeof(xlat_t)); memset(c, 0, sizeof(*c)); c->do_xlat = func; strNcpy(c->module, module, sizeof(c->module)); c->length = strlen(c->module); c->instance = instance; rbtree_insert(xlat_root, c); return 0;}/* * Unregister an xlat function. * * We can only have one function to call per name, so the * passing of "func" here is extraneous. */void xlat_unregister(const char *module, RAD_XLAT_FUNC func){ rbnode_t *node; xlat_t my_xlat; func = func; /* -Wunused */ strNcpy(my_xlat.module, module, sizeof(my_xlat.module)); my_xlat.length = strlen(my_xlat.module); node = rbtree_find(xlat_root, &my_xlat); if (!node) return; rbtree_delete(xlat_root, node);}/* * Decode an attribute name into a string. */static void decode_attribute(const char **from, char **to, int freespace, int *open, REQUEST *request, RADIUS_ESCAPE_STRING func){ char attrname[256]; const char *p; char *q, *pa; int stop=0, found=0, retlen=0; int openbraces = *open; xlat_t *c; p = *from; q = *to; pa = &attrname[0]; *q = '\0'; /* * Skip the '{' at the front of 'p' * Increment open braces */ p++; openbraces++; /* * Copy over the rest of the string. */ while ((*p) && (!stop)) { switch(*p) { /* * Allow braces inside things, too. */ case '\\': p++; /* skip it */ *pa++ = *p++; break; case '{':
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -