Changeset 530:825a2992e3b9 in freeDiameter
- Timestamp:
- Sep 6, 2010, 2:28:53 PM (14 years ago)
- Branch:
- default
- Phase:
- public
- Location:
- extensions/app_radgw
- Files:
-
- 2 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 */ -
extensions/app_radgw/rgwx_acct.c
r526 r530 827 827 828 828 /* While here, we also add the Accouting-Record-Number AVP. 829 We don't have a dedicated counter nor a state, so we just use the Diameter message End-to-end id here, which fits the conditions on the value. */ 829 The Accounting-Record-Number AVP (AVP Code 485) is of type Unsigned32 830 and identifies this record within one session. As Session-Id AVPs 831 are globally unique, the combination of Session-Id and Accounting- 832 Record-Number AVPs is also globally unique, and can be used in 833 matching accounting records with confirmations. An easy way to 834 produce unique numbers is to set the value to 0 for records of type 835 EVENT_RECORD and START_RECORD, and set the value to 1 for the first 836 INTERIM_RECORD, 2 for the second, and so on until the value for 837 STOP_RECORD is one more than for the last INTERIM_RECORD. 838 839 -- we actually use the end-to-end id of the message here, which remains constant 840 if we send a duplicate, so it has the same properties as the suggested algorithm. 841 Anyway, it assumes that we are not converting twice the same RADIUS message. 842 . */ 830 843 CHECK_FCT( fd_msg_avp_new ( cs->dict.Accounting_Record_Number, 0, &avp ) ); 831 844 value.u32 = e2eid;
Note: See TracChangeset
for help on using the changeset viewer.