Mercurial > hg > freeDiameter
comparison extensions/rt_redirect/redir_out.c @ 1259:82280e745a89
Remove whitespace at end of line.
author | Thomas Klausner <tk@giga.or.at> |
---|---|
date | Mon, 24 Mar 2014 13:13:38 +0100 |
parents | 581bbd48524a |
children | 4f6f61e67599 |
comparison
equal
deleted
inserted
replaced
1258:97caad40b665 | 1259:82280e745a89 |
---|---|
38 | 38 |
39 /* Find the data pertinent to a type in the input data */ | 39 /* Find the data pertinent to a type in the input data */ |
40 static int get_data_to_match(enum redir_h_u type, struct msg *msg, union matchdata * data, int * nodata) | 40 static int get_data_to_match(enum redir_h_u type, struct msg *msg, union matchdata * data, int * nodata) |
41 { | 41 { |
42 TRACE_ENTRY("%d %p %p %p", type, msg, data, nodata); | 42 TRACE_ENTRY("%d %p %p %p", type, msg, data, nodata); |
43 | 43 |
44 /* Initialize the data area */ | 44 /* Initialize the data area */ |
45 memset(data, 0, sizeof(union matchdata)); | 45 memset(data, 0, sizeof(union matchdata)); |
46 *nodata = 0; | 46 *nodata = 0; |
47 | 47 |
48 /* Now, find the appropriate information, depending on type */ | 48 /* Now, find the appropriate information, depending on type */ |
49 switch (type) { | 49 switch (type) { |
50 case DONT_CACHE: | 50 case DONT_CACHE: |
51 data->message.msg = msg; | 51 data->message.msg = msg; |
52 break; | 52 break; |
53 | 53 |
54 case ALL_SESSION: | 54 case ALL_SESSION: |
55 { | 55 { |
56 /* Get the sid from the message */ | 56 /* Get the sid from the message */ |
57 struct session * sess; | 57 struct session * sess; |
58 CHECK_FCT( fd_msg_sess_get(fd_g_config->cnf_dict, msg, &sess, NULL) ); | 58 CHECK_FCT( fd_msg_sess_get(fd_g_config->cnf_dict, msg, &sess, NULL) ); |
62 } else { | 62 } else { |
63 CHECK_FCT( fd_sess_getsid(sess, &data->session.s, &data->session.l) ); | 63 CHECK_FCT( fd_sess_getsid(sess, &data->session.s, &data->session.l) ); |
64 } | 64 } |
65 } | 65 } |
66 break; | 66 break; |
67 | 67 |
68 case ALL_REALM: | 68 case ALL_REALM: |
69 { | 69 { |
70 /* Search the Destination-Realm in the message */ | 70 /* Search the Destination-Realm in the message */ |
71 struct avp * dr; | 71 struct avp * dr; |
72 CHECK_FCT( fd_msg_search_avp(msg, redir_dict_dr, &dr) ); | 72 CHECK_FCT( fd_msg_search_avp(msg, redir_dict_dr, &dr) ); |
79 data->realm.s = ahdr->avp_value->os.data; | 79 data->realm.s = ahdr->avp_value->os.data; |
80 data->realm.l = ahdr->avp_value->os.len; | 80 data->realm.l = ahdr->avp_value->os.len; |
81 } | 81 } |
82 } | 82 } |
83 break; | 83 break; |
84 | 84 |
85 case REALM_AND_APPLICATION: | 85 case REALM_AND_APPLICATION: |
86 { | 86 { |
87 /* Search the Destination-Realm of the message */ | 87 /* Search the Destination-Realm of the message */ |
88 struct avp * dr; | 88 struct avp * dr; |
89 CHECK_FCT( fd_msg_search_avp(msg, redir_dict_dr, &dr) ); | 89 CHECK_FCT( fd_msg_search_avp(msg, redir_dict_dr, &dr) ); |
93 } else { | 93 } else { |
94 struct avp_hdr * ahdr; | 94 struct avp_hdr * ahdr; |
95 CHECK_FCT( fd_msg_avp_hdr( dr, &ahdr ) ); | 95 CHECK_FCT( fd_msg_avp_hdr( dr, &ahdr ) ); |
96 data->realm_app.s = ahdr->avp_value->os.data; | 96 data->realm_app.s = ahdr->avp_value->os.data; |
97 data->realm_app.l = ahdr->avp_value->os.len; | 97 data->realm_app.l = ahdr->avp_value->os.len; |
98 | 98 |
99 /* and then the application */ | 99 /* and then the application */ |
100 { | 100 { |
101 struct msg_hdr * hdr; | 101 struct msg_hdr * hdr; |
102 CHECK_FCT( fd_msg_hdr(msg, &hdr) ); | 102 CHECK_FCT( fd_msg_hdr(msg, &hdr) ); |
103 data->realm_app.a = hdr->msg_appl; | 103 data->realm_app.a = hdr->msg_appl; |
104 /* Should we forbid application 0? */ | 104 /* Should we forbid application 0? */ |
105 } | 105 } |
106 } | 106 } |
107 } | 107 } |
108 break; | 108 break; |
109 | 109 |
110 case ALL_APPLICATION: | 110 case ALL_APPLICATION: |
111 { | 111 { |
112 /* Retrieve the application from the message */ | 112 /* Retrieve the application from the message */ |
113 struct msg_hdr * hdr; | 113 struct msg_hdr * hdr; |
114 CHECK_FCT( fd_msg_hdr(msg, &hdr) ); | 114 CHECK_FCT( fd_msg_hdr(msg, &hdr) ); |
115 data->app.a = hdr->msg_appl; | 115 data->app.a = hdr->msg_appl; |
116 } | 116 } |
117 break; | 117 break; |
118 | 118 |
119 case ALL_HOST: | 119 case ALL_HOST: |
120 /* This is more complex, we need to match with all candidates in each rule, it'll be done later */ | 120 /* This is more complex, we need to match with all candidates in each rule, it'll be done later */ |
121 break; | 121 break; |
122 | 122 |
123 case ALL_USER: | 123 case ALL_USER: |
124 { | 124 { |
125 /* Search the User-Name of the message */ | 125 /* Search the User-Name of the message */ |
126 struct avp * un; | 126 struct avp * un; |
127 CHECK_FCT( fd_msg_search_avp(msg, redir_dict_un, &un) ); | 127 CHECK_FCT( fd_msg_search_avp(msg, redir_dict_un, &un) ); |
134 data->user.s = ahdr->avp_value->os.data; | 134 data->user.s = ahdr->avp_value->os.data; |
135 data->user.l = ahdr->avp_value->os.len; | 135 data->user.l = ahdr->avp_value->os.len; |
136 } | 136 } |
137 } | 137 } |
138 break; | 138 break; |
139 | 139 |
140 default: | 140 default: |
141 ASSERT(0); | 141 ASSERT(0); |
142 return EINVAL; | 142 return EINVAL; |
143 } | 143 } |
144 | 144 |
150 static int apply_rule(struct redir_entry * e, struct msg * msg, struct fd_list * candidates) | 150 static int apply_rule(struct redir_entry * e, struct msg * msg, struct fd_list * candidates) |
151 { | 151 { |
152 struct fd_list * lic, *lirh; | 152 struct fd_list * lic, *lirh; |
153 struct rtd_candidate * c_oh = NULL; | 153 struct rtd_candidate * c_oh = NULL; |
154 int cmp; | 154 int cmp; |
155 | 155 |
156 TRACE_ENTRY("%p %p %p", e, msg, candidates); | 156 TRACE_ENTRY("%p %p %p", e, msg, candidates); |
157 ASSERT( e && msg && candidates ); | 157 ASSERT( e && msg && candidates ); |
158 | 158 |
159 if (FD_IS_LIST_EMPTY(candidates)) { | 159 if (FD_IS_LIST_EMPTY(candidates)) { |
160 TRACE_DEBUG(ANNOYING, "Skip Redirect rule since candidates list is empty"); | 160 TRACE_DEBUG(ANNOYING, "Skip Redirect rule since candidates list is empty"); |
161 return 0; | 161 return 0; |
162 } | 162 } |
163 | 163 |
164 /* Now search common peers between e->target_peers_list and candidates */ | 164 /* Now search common peers between e->target_peers_list and candidates */ |
165 TRACE_DEBUG(ANNOYING, "Message %p matches a Redirect rule (t:%d, @%p), processing candidates list", msg, e->type, e); | 165 TRACE_DEBUG(ANNOYING, "Message %p matches a Redirect rule (t:%d, @%p), processing candidates list", msg, e->type, e); |
166 | 166 |
167 /* First, decrease the score of the host that we received the previous Redirect from, in case it is in the list */ | 167 /* First, decrease the score of the host that we received the previous Redirect from, in case it is in the list */ |
168 for (lic = candidates->next; lic != candidates; lic = lic->next) { | 168 for (lic = candidates->next; lic != candidates; lic = lic->next) { |
169 struct rtd_candidate * cand = (struct rtd_candidate *) lic; | 169 struct rtd_candidate * cand = (struct rtd_candidate *) lic; |
170 | 170 |
171 /* Special case: ALL_HOST rules: we decrease the score of the Origin-Host if present */ | 171 /* Special case: ALL_HOST rules: we decrease the score of the Origin-Host if present */ |
172 if (e->type == ALL_HOST) { | 172 if (e->type == ALL_HOST) { |
173 cmp = fd_os_almostcasesrch(cand->diamid, cand->diamidlen, e->data.host.s, e->data.host.l, NULL); | 173 cmp = fd_os_almostcasesrch(cand->diamid, cand->diamidlen, e->data.host.s, e->data.host.l, NULL); |
174 if (!cmp) { | 174 if (!cmp) { |
175 TRACE_DEBUG(FULL, "Redirect msg %p: peer '%.*s' += %d (previous ALL_HOST Redirect originated from this peer)", msg, (int)cand->diamidlen, cand->diamid, FD_SCORE_SENT_REDIRECT); | 175 TRACE_DEBUG(FULL, "Redirect msg %p: peer '%.*s' += %d (previous ALL_HOST Redirect originated from this peer)", msg, (int)cand->diamidlen, cand->diamid, FD_SCORE_SENT_REDIRECT); |
176 cand->score += FD_SCORE_SENT_REDIRECT; | 176 cand->score += FD_SCORE_SENT_REDIRECT; |
177 c_oh = cand; | 177 c_oh = cand; |
178 continue; | 178 continue; |
179 } | 179 } |
180 } | 180 } |
181 | 181 |
182 cmp = fd_os_cmp(cand->diamid, cand->diamidlen, e->from.s, e->from.l); | 182 cmp = fd_os_cmp(cand->diamid, cand->diamidlen, e->from.s, e->from.l); |
183 if (!cmp) { | 183 if (!cmp) { |
184 TRACE_DEBUG(FULL, "Redirect msg %p: peer '%.*s' += %d (previous Redirect received from this peer)", msg, (int)cand->diamidlen, cand->diamid, FD_SCORE_SENT_REDIRECT); | 184 TRACE_DEBUG(FULL, "Redirect msg %p: peer '%.*s' += %d (previous Redirect received from this peer)", msg, (int)cand->diamidlen, cand->diamid, FD_SCORE_SENT_REDIRECT); |
185 cand->score += FD_SCORE_SENT_REDIRECT; | 185 cand->score += FD_SCORE_SENT_REDIRECT; |
186 } | 186 } |
187 | 187 |
188 } | 188 } |
189 | 189 |
190 if ((e->type == ALL_HOST) && (c_oh == NULL)) { | 190 if ((e->type == ALL_HOST) && (c_oh == NULL)) { |
191 /* The rule does not apply, we're done */ | 191 /* The rule does not apply, we're done */ |
192 return 0; | 192 return 0; |
193 } | 193 } |
194 | 194 |
195 /* for each candidate, if it is found in the target_peers list, we add the rule's score to this candidate */ | 195 /* for each candidate, if it is found in the target_peers list, we add the rule's score to this candidate */ |
196 for (lic = candidates->next; lic != candidates; lic = lic->next) { | 196 for (lic = candidates->next; lic != candidates; lic = lic->next) { |
197 /* the candidates list is not guaranteed to be ordered at this time, so we cannot avoid the two imbricated loops */ | 197 /* the candidates list is not guaranteed to be ordered at this time, so we cannot avoid the two imbricated loops */ |
198 struct rtd_candidate * cand = (struct rtd_candidate *) lic; | 198 struct rtd_candidate * cand = (struct rtd_candidate *) lic; |
199 | 199 |
200 /* Is this candidate in the "Redirect-Host" list ? We must search caseinsentive here. */ | 200 /* Is this candidate in the "Redirect-Host" list ? We must search caseinsentive here. */ |
201 for (lirh = e->target_peers_list.next; lirh != &e->target_peers_list; lirh = lirh->next) { | 201 for (lirh = e->target_peers_list.next; lirh != &e->target_peers_list; lirh = lirh->next) { |
202 struct redir_host * host = lirh->o; | 202 struct redir_host * host = lirh->o; |
203 int cont; | 203 int cont; |
204 | 204 |
205 cmp = fd_os_almostcasesrch( cand->diamid, cand->diamidlen, host->id, host->len, &cont ); | 205 cmp = fd_os_almostcasesrch( cand->diamid, cand->diamidlen, host->id, host->len, &cont ); |
206 | 206 |
207 if (cmp == 0) { | 207 if (cmp == 0) { |
208 TRACE_DEBUG(FULL, "Redirect msg %p: peer '%.*s' += %d (rule t:%d @%p)", msg, (int)cand->diamidlen, cand->diamid, redirects_usages[e->type].score, e->type, e); | 208 TRACE_DEBUG(FULL, "Redirect msg %p: peer '%.*s' += %d (rule t:%d @%p)", msg, (int)cand->diamidlen, cand->diamid, redirects_usages[e->type].score, e->type, e); |
209 cand->score += redirects_usages[e->type].score; | 209 cand->score += redirects_usages[e->type].score; |
210 break; | 210 break; |
211 } | 211 } |
212 if (!cont) | 212 if (!cont) |
213 break; | 213 break; |
214 } | 214 } |
215 } | 215 } |
216 | 216 |
217 return 0; | 217 return 0; |
218 } | 218 } |
219 | 219 |
220 | 220 |
221 /* OUT callback */ | 221 /* OUT callback */ |
222 int redir_out_cb(void * cbdata, struct msg ** pmsg, struct fd_list * candidates) | 222 int redir_out_cb(void * cbdata, struct msg ** pmsg, struct fd_list * candidates) |
223 { | 223 { |
224 int i, ret = 0; | 224 int i, ret = 0; |
225 struct msg * msg = *pmsg; | 225 struct msg * msg = *pmsg; |
226 | 226 |
227 TRACE_ENTRY("%p %p %p", cbdata, msg, candidates); | 227 TRACE_ENTRY("%p %p %p", cbdata, msg, candidates); |
228 | 228 |
229 for (i = 0; i <= H_U_MAX; i++) { | 229 for (i = 0; i <= H_U_MAX; i++) { |
230 /* Lock the line. We write lock in case of DONT_CACHE so we can directly unlink the entry. read in other cases is sufficient */ | 230 /* Lock the line. We write lock in case of DONT_CACHE so we can directly unlink the entry. read in other cases is sufficient */ |
231 if (i == DONT_CACHE) { | 231 if (i == DONT_CACHE) { |
232 CHECK_POSIX( pthread_rwlock_wrlock( &redirects_usages[i].lock ) ); | 232 CHECK_POSIX( pthread_rwlock_wrlock( &redirects_usages[i].lock ) ); |
233 } else { | 233 } else { |
234 CHECK_POSIX( pthread_rwlock_rdlock( &redirects_usages[i].lock ) ); | 234 CHECK_POSIX( pthread_rwlock_rdlock( &redirects_usages[i].lock ) ); |
235 } | 235 } |
236 | 236 |
237 if (!FD_IS_LIST_EMPTY(&redirects_usages[i].sentinel)) { | 237 if (!FD_IS_LIST_EMPTY(&redirects_usages[i].sentinel)) { |
238 union matchdata data; | 238 union matchdata data; |
239 int nodata; /* The message does not allow to apply this rule, skip */ | 239 int nodata; /* The message does not allow to apply this rule, skip */ |
240 | 240 |
241 /* Retrieve the data that may match in the message */ | 241 /* Retrieve the data that may match in the message */ |
242 CHECK_FCT_DO( ret = get_data_to_match(i, msg, &data, &nodata), goto out ); | 242 CHECK_FCT_DO( ret = get_data_to_match(i, msg, &data, &nodata), goto out ); |
243 | 243 |
244 /* If this message may match some of our rules */ | 244 /* If this message may match some of our rules */ |
245 if (!nodata) { | 245 if (!nodata) { |
246 struct fd_list * li; | 246 struct fd_list * li; |
247 /* Attempt each rule we have stored */ | 247 /* Attempt each rule we have stored */ |
248 for (li = redirects_usages[i].sentinel.next; li != &redirects_usages[i].sentinel; li = li->next) { | 248 for (li = redirects_usages[i].sentinel.next; li != &redirects_usages[i].sentinel; li = li->next) { |
249 struct redir_entry * e = li->o; | 249 struct redir_entry * e = li->o; |
250 | 250 |
251 /* Does it match ? */ | 251 /* Does it match ? */ |
252 if (i != ALL_HOST) { /* this one is an exception, we handle it separately */ | 252 if (i != ALL_HOST) { /* this one is an exception, we handle it separately */ |
253 int cmp = redir_entry_cmp_key[i](&data, &e->data); | 253 int cmp = redir_entry_cmp_key[i](&data, &e->data); |
254 if (cmp > 0) | 254 if (cmp > 0) |
255 continue; | 255 continue; |
256 if (cmp < 0) | 256 if (cmp < 0) |
257 break; | 257 break; |
258 } | 258 } |
259 | 259 |
260 /* This rule matches (or we are in ALL_HOST), apply */ | 260 /* This rule matches (or we are in ALL_HOST), apply */ |
261 CHECK_FCT_DO( ret = apply_rule(e, msg, candidates), goto out ); | 261 CHECK_FCT_DO( ret = apply_rule(e, msg, candidates), goto out ); |
262 | 262 |
263 /* If this was a DONT_CACHE rule, we unlink it, so that it will not be used again */ | 263 /* If this was a DONT_CACHE rule, we unlink it, so that it will not be used again */ |
264 if (i == DONT_CACHE) { | 264 if (i == DONT_CACHE) { |
265 li=li->prev; | 265 li=li->prev; |
266 fd_list_unlink( li->next ); | 266 fd_list_unlink( li->next ); |
267 /* We cannot delete here without taking the mutex, which would mean we have first to release the lock... | 267 /* We cannot delete here without taking the mutex, which would mean we have first to release the lock... |
268 just let expiry garbage collet the rule */ | 268 just let expiry garbage collet the rule */ |
269 } | 269 } |
270 } | 270 } |
271 } | 271 } |
272 | 272 |
273 } | 273 } |
274 out: | 274 out: |
275 CHECK_POSIX( pthread_rwlock_unlock( &redirects_usages[i].lock ) ); | 275 CHECK_POSIX( pthread_rwlock_unlock( &redirects_usages[i].lock ) ); |
276 if (ret) | 276 if (ret) |
277 return ret; | 277 return ret; |
278 } | 278 } |
279 | 279 |
280 return 0; | 280 return 0; |
281 } | 281 } |
282 | 282 |