Mercurial > hg > freeDiameter
comparison extensions/rt_ereg/rtereg.c @ 525:ecfa089bd29a
Forgot new files
author | Sebastien Decugis <sdecugis@nict.go.jp> |
---|---|
date | Wed, 01 Sep 2010 14:41:33 +0900 |
parents | |
children | 6fe3e5cf9fb2 |
comparison
equal
deleted
inserted
replaced
524:bc25e91e1e3c | 525:ecfa089bd29a |
---|---|
1 /********************************************************************************************************* | |
2 * Software License Agreement (BSD License) * | |
3 * Author: Sebastien Decugis <sdecugis@nict.go.jp> * | |
4 * * | |
5 * Copyright (c) 2010, WIDE Project and NICT * | |
6 * All rights reserved. * | |
7 * * | |
8 * Redistribution and use of this software in source and binary forms, with or without modification, are * | |
9 * permitted provided that the following conditions are met: * | |
10 * * | |
11 * * Redistributions of source code must retain the above * | |
12 * copyright notice, this list of conditions and the * | |
13 * following disclaimer. * | |
14 * * | |
15 * * Redistributions in binary form must reproduce the above * | |
16 * copyright notice, this list of conditions and the * | |
17 * following disclaimer in the documentation and/or other * | |
18 * materials provided with the distribution. * | |
19 * * | |
20 * * Neither the name of the WIDE Project or NICT nor the * | |
21 * names of its contributors may be used to endorse or * | |
22 * promote products derived from this software without * | |
23 * specific prior written permission of WIDE Project and * | |
24 * NICT. * | |
25 * * | |
26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED * | |
27 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * | |
28 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * | |
29 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * | |
30 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * | |
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * | |
32 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * | |
33 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * | |
34 *********************************************************************************************************/ | |
35 | |
36 /* | |
37 * This extension allows to perform some pattern-matching on an AVP | |
38 * and send the message to a server accordingly. | |
39 * See rt_ereg.conf.sample file for the format of the configuration file. | |
40 */ | |
41 | |
42 #include "rtereg.h" | |
43 | |
44 /* The configuration structure */ | |
45 struct rtereg_conf rtereg_conf; | |
46 | |
47 #ifndef HAVE_REG_STARTEND | |
48 static char * buf = NULL; | |
49 static size_t bufsz; | |
50 static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; | |
51 #endif /* HAVE_REG_STARTEND */ | |
52 | |
53 static int proceed(char * value, size_t len, struct fd_list * candidates) | |
54 { | |
55 int i; | |
56 | |
57 for (i = 0; i < rtereg_conf.rules_nb; i++) { | |
58 /* Does this pattern match the value? */ | |
59 struct rtereg_rule * r = &rtereg_conf.rules[i]; | |
60 int err = 0; | |
61 struct fd_list * c; | |
62 | |
63 #ifdef HAVE_REG_STARTEND | |
64 { | |
65 regmatch_t pmatch[1]; | |
66 memset(pmatch, 0, sizeof(pmatch)); | |
67 pmatch[0].rm_so = 0; | |
68 pmatch[0].rm_eo = len; | |
69 err = regexec(&r->preg, value, 0, pmatch, REG_STARTEND); | |
70 } | |
71 #else /* HAVE_REG_STARTEND */ | |
72 { | |
73 /* We have a 0-terminated string */ | |
74 err = regexec(&r->preg, value, 0, NULL, 0); | |
75 } | |
76 #endif /* HAVE_REG_STARTEND */ | |
77 | |
78 if (err == REG_NOMATCH) | |
79 continue; | |
80 | |
81 if (err != 0) { | |
82 char * errstr; | |
83 size_t bl; | |
84 | |
85 /* Error while compiling the regex */ | |
86 TRACE_DEBUG(INFO, "Error while executing the regular expression '%s':", r->pattern); | |
87 | |
88 /* Get the error message size */ | |
89 bl = regerror(err, &r->preg, NULL, 0); | |
90 | |
91 /* Alloc the buffer for error message */ | |
92 CHECK_MALLOC( errstr = malloc(bl) ); | |
93 | |
94 /* Get the error message content */ | |
95 regerror(err, &r->preg, errstr, bl); | |
96 TRACE_DEBUG(INFO, "\t%s", errstr); | |
97 | |
98 /* Free the buffer, return the error */ | |
99 free(errstr); | |
100 | |
101 return (err == REG_ESPACE) ? ENOMEM : EINVAL; | |
102 } | |
103 | |
104 /* From this point, the expression matched the AVP value */ | |
105 TRACE_DEBUG(FULL, "[rt_ereg] Match: '%s' to value '%.*s' => '%s' += %d", | |
106 r->pattern, | |
107 len, | |
108 value, | |
109 r->server, | |
110 r->score); | |
111 | |
112 for (c = candidates->next; c != candidates; c = c->next) { | |
113 struct rtd_candidate * cand = (struct rtd_candidate *)c; | |
114 | |
115 if (strcmp(r->server, cand->diamid) == 0) { | |
116 cand->score += r->score; | |
117 break; | |
118 } | |
119 } | |
120 }; | |
121 | |
122 return 0; | |
123 } | |
124 | |
125 /* The callback called on new messages */ | |
126 static int rtereg_out(void * cbdata, struct msg * msg, struct fd_list * candidates) | |
127 { | |
128 struct avp * avp = NULL; | |
129 | |
130 TRACE_ENTRY("%p %p %p", cbdata, msg, candidates); | |
131 | |
132 CHECK_PARAMS(msg && candidates); | |
133 | |
134 /* Check if it is worth processing the message */ | |
135 if (FD_IS_LIST_EMPTY(candidates)) { | |
136 return 0; | |
137 } | |
138 | |
139 /* Now search the AVP in the message */ | |
140 CHECK_FCT( fd_msg_search_avp ( msg, rtereg_conf.avp, &avp ) ); | |
141 if (avp != NULL) { | |
142 struct avp_hdr * ahdr = NULL; | |
143 CHECK_FCT( fd_msg_avp_hdr ( avp, &ahdr ) ); | |
144 if (ahdr->avp_value != NULL) { | |
145 int ret; | |
146 | |
147 #ifndef HAVE_REG_STARTEND | |
148 /* Lock the buffer */ | |
149 CHECK_POSIX( pthread_mutex_lock(&mtx) ); | |
150 | |
151 /* Augment the buffer if needed */ | |
152 if (ahdr->avp_value->os.len >= bufsz) { | |
153 CHECK_MALLOC_DO( buf = realloc(buf, ahdr->avp_value->os.len + 1), | |
154 { pthread_mutex_unlock(&mtx); return ENOMEM; } ); | |
155 } | |
156 | |
157 /* Copy the AVP value */ | |
158 memcpy(buf, ahdr->avp_value->os.data, ahdr->avp_value->os.len); | |
159 buf[ahdr->avp_value->os.len] = '\0'; | |
160 | |
161 /* Now apply the rules */ | |
162 ret = proceed(buf, ahdr->avp_value->os.len, candidates); | |
163 | |
164 CHECK_POSIX(pthread_mutex_unlock(&mtx)); | |
165 | |
166 CHECK_FCT(ret); | |
167 #else /* HAVE_REG_STARTEND */ | |
168 CHECK_FCT( proceed(ahdr->avp_value->os.data, ahdr->avp_value->os.len, candidates) ); | |
169 #endif /* HAVE_REG_STARTEND */ | |
170 } | |
171 } | |
172 | |
173 return 0; | |
174 } | |
175 | |
176 /* handler */ | |
177 static struct fd_rt_out_hdl * rtereg_hdl = NULL; | |
178 | |
179 /* entry point */ | |
180 static int rtereg_entry(char * conffile) | |
181 { | |
182 TRACE_ENTRY("%p", conffile); | |
183 | |
184 /* Initialize the configuration */ | |
185 memset(&rtereg_conf, 0, sizeof(rtereg_conf)); | |
186 | |
187 /* Parse the configuration file */ | |
188 CHECK_FCT( rtereg_conf_handle(conffile) ); | |
189 | |
190 /* Register the callback */ | |
191 CHECK_FCT( fd_rt_out_register( rtereg_out, NULL, 1, &rtereg_hdl ) ); | |
192 | |
193 /* We're done */ | |
194 return 0; | |
195 } | |
196 | |
197 /* Unload */ | |
198 void fd_ext_fini(void) | |
199 { | |
200 int i; | |
201 TRACE_ENTRY(); | |
202 | |
203 /* Unregister the cb */ | |
204 CHECK_FCT_DO( fd_rt_out_unregister ( rtereg_hdl, NULL ), /* continue */ ); | |
205 | |
206 /* Destroy the data */ | |
207 if (rtereg_conf.rules) | |
208 for (i = 0; i < rtereg_conf.rules_nb; i++) { | |
209 free(rtereg_conf.rules[i].pattern); | |
210 free(rtereg_conf.rules[i].server); | |
211 regfree(&rtereg_conf.rules[i].preg); | |
212 } | |
213 free(rtereg_conf.rules); | |
214 #ifndef HAVE_REG_STARTEND | |
215 free(buf); | |
216 #endif /* HAVE_REG_STARTEND */ | |
217 | |
218 /* Done */ | |
219 return ; | |
220 } | |
221 | |
222 EXTENSION_ENTRY("rt_ereg", rtereg_entry); |