# HG changeset patch # User Sebastien Decugis # Date 1260247123 -32400 # Node ID 0d9c9e004be0d3924bc31b98b3755820482fe1c5 # Parent 79e69f069831e51999726310ad71b3968671e149 Compute common applications after CER reception diff -r 79e69f069831 -r 0d9c9e004be0 freeDiameter/apps.c --- a/freeDiameter/apps.c Tue Dec 08 13:12:48 2009 +0900 +++ b/freeDiameter/apps.c Tue Dec 08 13:38:43 2009 +0900 @@ -99,3 +99,39 @@ return 0; } + +/* Check if two lists have at least one common application */ +int fd_app_check_common(struct fd_list * list1, struct fd_list * list2, int * common_found) +{ + struct fd_list * li1, *li2; + + TRACE_ENTRY("%p %p %p", list1, list2, common_found); + CHECK_PARAMS( list1 && list2 && common_found ); + + /* Both lists are ordered, so advance both pointers at the same time */ + for (li1 = list1->next, li2 = list2->next; (li1 != list1) && (li2 != list2); ) { + struct fd_app * a1 = (struct fd_app *)li1, *a2 = (struct fd_app *)li2; + if (a1->appid < a2->appid) { + li1 = li1->next; + continue; + } + if (a1->appid > a2->appid) { + li2 = li2->next; + continue; + } + /* They are equal, compare the applications */ + if ((a1->flags.auth && a2->flags.auth) || (a1->flags.acct && a2->flags.acct)) { + /* found! */ + *common_found = 1; + return 0; + } + + /* This application is not common, advance both lists */ + li1 = li1->next; + li2 = li2->next; + } + + /* We did not find a common app */ + *common_found = 0; + return 0; +} diff -r 79e69f069831 -r 0d9c9e004be0 freeDiameter/config.c --- a/freeDiameter/config.c Tue Dec 08 13:12:48 2009 +0900 +++ b/freeDiameter/config.c Tue Dec 08 13:38:43 2009 +0900 @@ -110,7 +110,6 @@ app->appid, app->flags.auth ? "Au" : "--", app->flags.acct ? "Ac" : "--", - app->flags.common ? "C" : "-", app->vndid); li = li->next; } diff -r 79e69f069831 -r 0d9c9e004be0 freeDiameter/p_ce.c --- a/freeDiameter/p_ce.c Tue Dec 08 13:12:48 2009 +0900 +++ b/freeDiameter/p_ce.c Tue Dec 08 13:38:43 2009 +0900 @@ -703,12 +703,13 @@ return 0; } -/* Handle the receiver side after winning an election (or timeout on initiator side) */ +/* Handle the receiver side to go to OPEN state (any election is resolved) */ int fd_p_ce_process_receiver(struct fd_peer * peer) { char * ec = NULL; struct msg * msg = NULL; int isi = 0; + int fatal = 0; TRACE_ENTRY("%p", peer); @@ -730,7 +731,16 @@ } /* Check if we have common applications */ - TODO("DIAMETER_NO_COMMON_APPLICATION ?"); + if ( fd_g_config->cnf_flags.no_fwd && (! peer->p_hdr.info.runtime.pir_relay) ) { + int got_common; + CHECK_FCT( fd_app_check_common( &fd_g_config->cnf_apps, &peer->p_hdr.info.runtime.pir_apps, &got_common) ); + if (!got_common) { + TRACE_DEBUG(INFO, "No common application with peer '%s', sending DIAMETER_NO_COMMON_APPLICATION", peer->p_hdr.info.pi_diamid); + ec = "DIAMETER_NO_COMMON_APPLICATION"; + fatal = 1; + goto error_abort; + } + } /* Do we send ISI back ? */ if ( ! fd_cnx_getTLS(peer->p_cnxctx) ) { @@ -807,7 +817,7 @@ fd_p_ce_clear_cnx(peer, NULL); /* Send the error to the peer */ - CHECK_FCT( fd_event_send(peer->p_events, FDEVP_CNX_ERROR, 0, NULL) ); + CHECK_FCT( fd_event_send(peer->p_events, fatal ? FDEVP_TERMINATE : FDEVP_CNX_ERROR, 0, NULL) ); return 0; } diff -r 79e69f069831 -r 0d9c9e004be0 include/freeDiameter/freeDiameter.h --- a/include/freeDiameter/freeDiameter.h Tue Dec 08 13:12:48 2009 +0900 +++ b/include/freeDiameter/freeDiameter.h Tue Dec 08 13:38:43 2009 +0900 @@ -698,7 +698,6 @@ struct { unsigned auth : 1; unsigned acct : 1; - unsigned common : 1; } flags; vendor_id_t vndid; /* if not 0, Vendor-Specific-App-Id AVP will be used */ application_id_t appid; /* The identifier of the application */ @@ -706,5 +705,6 @@ int fd_app_merge(struct fd_list * list, application_id_t aid, vendor_id_t vid, int auth, int acct); int fd_app_check(struct fd_list * list, application_id_t aid, struct fd_app **detail); +int fd_app_check_common(struct fd_list * list1, struct fd_list * list2, int * common_found); #endif /* _FREEDIAMETER_H */