Changeset 530:825a2992e3b9 in freeDiameter for extensions/app_radgw/rgw_clients.c
- Timestamp:
- Sep 6, 2010, 2:28:53 PM (14 years ago)
- Branch:
- default
- Phase:
- public
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
extensions/app_radgw/rgw_clients.c
r521 r530 82 82 } key; 83 83 84 /* information of previous msg received, for duplicate checks. */ 84 /* information of previous msg received, for duplicate checks -- we keep the last DUPLICATE_MESSAGES_BUFFER messages on each port. */ 85 #define DUPLICATE_MESSAGES_BUFFER 200 /* This should actually be replaced with a time-based dynamic list! TODO... */ 85 86 struct { 86 uint16_t port; 87 uint8_t id; 88 uint8_t auth[16]; /* we also compare the request authenticator to avoid buggy NASes */ 89 struct radius_msg * ans; /* to be able to resend a lost answer */ 90 } last[2]; /*[0] for auth, [1] for acct. */ 87 int cnt; /* Counts the number of (different) requests we received */ 88 struct { 89 uint16_t port; /* The source UDP port of the request */ 90 uint8_t id; /* The identifier in the request */ 91 uint8_t auth[16]; /* The request authenticator, because some NAS are not using identifier properly. */ 92 struct radius_msg * ans; /* When the answer has been sent already, keep it so we can send it back */ 93 int nbdup; /* count the number of duplicate RADIUS requests we received on this message */ 94 } msg_info[DUPLICATE_MESSAGES_BUFFER]; 95 } duplicates_info[2]; /*[0] for auth, [1] for acct. */ 91 96 }; 92 97 … … 169 174 free(client->sa); 170 175 free(client->key.data); 176 177 /* Free the duplicate info */ 178 for (idx=0; idx <= 1; idx++){ 179 int i = 0; 180 for (i = 0; i < DUPLICATE_MESSAGES_BUFFER; i++) { 181 if (client->duplicates_info[idx].msg_info[i].ans) { 182 /* Free this RADIUS message */ 183 radius_msg_free(client->duplicates_info[idx].msg_info[i].ans); 184 free(client->duplicates_info[idx].msg_info[i].ans); 185 } 186 } 187 } 188 171 189 free(client); 172 190 } … … 269 287 int rgw_clients_check_dup(struct rgw_radius_msg_meta **msg, struct rgw_client *cli) 270 288 { 271 int idx;289 int p, i, dup = 0; 272 290 273 291 TRACE_ENTRY("%p %p", msg, cli); … … 276 294 277 295 if ((*msg)->serv_type == RGW_PLG_TYPE_AUTH) 278 idx= 0;296 p = 0; 279 297 else 280 idx = 1; 281 282 if ((cli->last[idx].id == (*msg)->radius.hdr->identifier) 283 && (cli->last[idx].port == (*msg)->port) 284 && !memcmp(&cli->last[idx].auth[0], &(*msg)->radius.hdr->authenticator[0], 16)) { 285 /* Duplicate! */ 286 TRACE_DEBUG(INFO, "Received duplicated RADIUS message (id: %02hhx, port: %hu).", (*msg)->radius.hdr->identifier, ntohs((*msg)->port)); 287 if (cli->last[idx].ans) { 288 /* Resend the answer */ 289 CHECK_FCT_DO( rgw_servers_send((*msg)->serv_type, cli->last[idx].ans->buf, cli->last[idx].ans->buf_used, cli->sa, (*msg)->port), ); 290 } 291 rgw_msg_free(msg); 292 } else { 293 /* We have not just received this message already */ 294 if (cli->last[idx].port == 0) { /* first message from this client */ 295 /* Just add the new information */ 296 ASSERT(cli->last[idx].ans == NULL); 297 cli->last[idx].id = (*msg)->radius.hdr->identifier; 298 cli->last[idx].port = (*msg)->port; 299 memcpy(&cli->last[idx].auth[0], &(*msg)->radius.hdr->authenticator[0], 16); 300 } else { 301 /* We have got previous message(s), update the info only if answered already */ 302 if (cli->last[idx].ans) { 303 cli->last[idx].id = (*msg)->radius.hdr->identifier; 304 cli->last[idx].port = (*msg)->port; 305 memcpy(&cli->last[idx].auth[0], &(*msg)->radius.hdr->authenticator[0], 16); 306 /* Free the previous answer */ 307 radius_msg_free(cli->last[idx].ans); 308 free(cli->last[idx].ans); 309 cli->last[idx].ans = NULL; 310 } 311 } 298 p = 1; 299 300 /* Check in the previous DUPLICATE_MESSAGES_BUFFER messages if we have received the same identifier / authenticator / port combination */ 301 for (i = cli->duplicates_info[p].cnt - 1; i >= cli->duplicates_info[p].cnt - DUPLICATE_MESSAGES_BUFFER; i--) { 302 if ( (cli->duplicates_info[p].msg_info[i % DUPLICATE_MESSAGES_BUFFER].id == (*msg)->radius.hdr->identifier) 303 && (cli->duplicates_info[p].msg_info[i % DUPLICATE_MESSAGES_BUFFER].port == (*msg)->port) 304 && !memcmp(&cli->duplicates_info[p].msg_info[i % DUPLICATE_MESSAGES_BUFFER].auth[0], &(*msg)->radius.hdr->authenticator[0], 16)) { 305 /* We already received this request */ 306 cli->duplicates_info[p].msg_info[i % DUPLICATE_MESSAGES_BUFFER].nbdup++; 307 dup = 1; 308 TRACE_DEBUG(INFO, "Received duplicated RADIUS message (id: %02hhx, port: %hu, dup #%d).", 309 (*msg)->radius.hdr->identifier, 310 ntohs((*msg)->port), 311 cli->duplicates_info[p].msg_info[i % DUPLICATE_MESSAGES_BUFFER].nbdup); 312 if (cli->duplicates_info[p].msg_info[i % DUPLICATE_MESSAGES_BUFFER].ans) { 313 /* Resend the answer */ 314 CHECK_FCT_DO( rgw_servers_send((*msg)->serv_type, 315 cli->duplicates_info[p].msg_info[i % DUPLICATE_MESSAGES_BUFFER].ans->buf, 316 cli->duplicates_info[p].msg_info[i % DUPLICATE_MESSAGES_BUFFER].ans->buf_used, 317 cli->sa, 318 (*msg)->port), ); 319 } 320 rgw_msg_free(msg); 321 break; 322 } 323 } 324 325 /* If we did no already receive this request, save it for later */ 326 if (!dup) { 327 /* It's a new request, save its data */ 328 int i = cli->duplicates_info[p].cnt % DUPLICATE_MESSAGES_BUFFER; 329 330 cli->duplicates_info[p].msg_info[i].port = (*msg)->port; 331 cli->duplicates_info[p].msg_info[i].id = (*msg)->radius.hdr->identifier; 332 memcpy(&cli->duplicates_info[p].msg_info[i].auth[0], &(*msg)->radius.hdr->authenticator[0], 16); 333 if (cli->duplicates_info[p].msg_info[i].ans) { 334 /* Free the old answer */ 335 radius_msg_free(cli->duplicates_info[p].msg_info[i].ans); 336 free(cli->duplicates_info[p].msg_info[i].ans); 337 cli->duplicates_info[p].msg_info[i].ans = NULL; 338 } 339 cli->duplicates_info[p].msg_info[i].nbdup = 0; 340 341 cli->duplicates_info[p].cnt += 1; 312 342 } 313 343 … … 800 830 int rgw_client_finish_send(struct radius_msg ** msg, struct rgw_radius_msg_meta * req, struct rgw_client * cli) 801 831 { 802 int idx;832 int p,i; 803 833 804 834 TRACE_ENTRY("%p %p %p", msg, req, cli); … … 828 858 /* update the duplicate cache in rgw_clients */ 829 859 if (req->serv_type == RGW_PLG_TYPE_AUTH) 830 idx= 0;860 p = 0; 831 861 else 832 idx = 1; 833 if (cli->last[idx].ans) { 834 /* Free it */ 835 radius_msg_free(cli->last[idx].ans); 836 free(cli->last[idx].ans); 837 } 838 cli->last[idx].ans = *msg; 839 cli->last[idx].id = req->radius.hdr->identifier; 840 cli->last[idx].port = req->port; 841 *msg = NULL; 862 p = 1; 863 for (i = cli->duplicates_info[p].cnt - 1; i >= cli->duplicates_info[p].cnt - DUPLICATE_MESSAGES_BUFFER; i--) { 864 /* Search the entry corresponding to the request */ 865 if ( (cli->duplicates_info[p].msg_info[i % DUPLICATE_MESSAGES_BUFFER].id == req->radius.hdr->identifier) 866 && (cli->duplicates_info[p].msg_info[i % DUPLICATE_MESSAGES_BUFFER].port == req->port) 867 && !memcmp(&cli->duplicates_info[p].msg_info[i % DUPLICATE_MESSAGES_BUFFER].auth[0], &req->radius.hdr->authenticator[0], 16)) { 868 /* This should not happen, but just in case */ 869 if (cli->duplicates_info[p].msg_info[i % DUPLICATE_MESSAGES_BUFFER].ans) { 870 radius_msg_free(cli->duplicates_info[p].msg_info[i % DUPLICATE_MESSAGES_BUFFER].ans); 871 free(cli->duplicates_info[p].msg_info[i % DUPLICATE_MESSAGES_BUFFER].ans); 872 } 873 /* Now save the answer message */ 874 cli->duplicates_info[p].msg_info[i % DUPLICATE_MESSAGES_BUFFER].ans = *msg; 875 *msg = NULL; 876 break; 877 } 878 } 879 880 /* If we have not found the request in our circular buffer, it is probably too small */ 881 if (*msg) { 882 TODO("Implement a dynamic list for RADIUS duplicates detection based on expiry time instead of number of messages"); 883 TRACE_DEBUG(INFO, "The circular buffer has circled before the Diameter answer was received, you should definitely increase DUPLICATE_MESSAGES_BUFFER value."); 884 /* We don't re-save the value */ 885 radius_msg_free(*msg); 886 free(*msg); 887 *msg = NULL; 888 } 842 889 843 890 /* Finished */
Note: See TracChangeset
for help on using the changeset viewer.