Changeset 43:2db15632a63d in freeDiameter
- Timestamp:
- Nov 25, 2009, 7:07:09 PM (14 years ago)
- Branch:
- default
- Phase:
- public
- Files:
-
- 1 added
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
freeDiameter/CMakeLists.txt
r37 r43 10 10 SET(FD_COMMON_SRC 11 11 fD.h 12 apps.c 12 13 cnxctx.h 13 14 config.c -
freeDiameter/cnxctx.c
r38 r43 997 997 998 998 /* The magic function does it all */ 999 CHECK_FCT( fd_fifo_move( &conn->cc_incoming, alt_fifo, &conn->cc_alt ) );999 CHECK_FCT( fd_fifo_move( conn->cc_incoming, alt_fifo, &conn->cc_alt ) ); 1000 1000 1001 1001 return 0; … … 1114 1114 1115 1115 CHECK_PARAMS_DO(conn, return); 1116 1117 /* Avoid sending further events to the alt fifo */ 1118 conn->cc_alt = NULL; 1116 1119 1117 1120 /* In case of TLS, stop receiver thread, then close properly the gnutls session */ -
freeDiameter/dict_base_proto.c
r1 r43 211 211 { 212 212 struct dict_application_data data = { 0xffffffff, "Relay" }; 213 #if AI_RELAY != 0xffffffff 214 #error "AI_RELAY definition mismatch" 215 #endif 213 216 CHECK_dict_new( DICT_APPLICATION, &data , NULL, NULL); 214 217 } … … 907 910 struct dict_object * type; 908 911 struct dict_type_data tdata = { AVP_TYPE_UNSIGNED32, "Enumerated*(Inband-Security-Id)" , NULL, NULL}; 909 struct dict_enumval_data t_0 = { "NO_INBAND_SECURITY", { .u32 = 0}};910 struct dict_enumval_data t_1 = { "TLS", { .u32 = 1}};912 struct dict_enumval_data t_0 = { "NO_INBAND_SECURITY", { .u32 = ACV_ISI_NO_INBAND_SECURITY }}; 913 struct dict_enumval_data t_1 = { "TLS", { .u32 = ACV_ISI_TLS }}; 911 914 struct dict_avp_data data = { 912 915 299, /* Code */ -
freeDiameter/dispatch.c
r10 r43 36 36 #include "fD.h" 37 37 38 /* Add an application into the peer's supported apps */ 38 39 int fd_disp_app_support ( struct dict_object * app, struct dict_object * vendor, int auth, int acct ) 39 40 { 41 application_id_t aid = 0; 40 42 vendor_id_t vid = 0; 41 application_id_t aid = 0;42 struct fd_list * li;43 int skip = 0;44 43 45 44 TRACE_ENTRY("%p %p %d %d", app, vendor, auth, acct); … … 54 53 aid = data.application_id; 55 54 } 56 57 58 /* Now insert in the list ordered by appid. Avoid duplicates */ 59 for (li = &fd_g_config->cnf_apps; li->next != &fd_g_config->cnf_apps; li = li->next) { 60 struct fd_app * na = (struct fd_app *)(li->next); 61 if (na->appid < aid) 62 continue; 63 64 if (na->appid > aid) 65 break; 66 67 /* Otherwise, we merge with existing entry -- ignore vendor id in this case */ 68 skip = 1; 69 70 if (auth) 71 na->flags.auth = 1; 72 if (acct) 73 na->flags.acct = 1; 74 break; 55 56 if (vendor) { 57 enum dict_object_type type = 0; 58 struct dict_vendor_data data; 59 CHECK_FCT( fd_dict_gettype(vendor, &type) ); 60 CHECK_PARAMS( type == DICT_VENDOR ); 61 CHECK_FCT( fd_dict_getval(vendor, &data) ); 62 vid = data.vendor_id; 75 63 } 76 64 77 if (!skip) { 78 struct fd_app * new = NULL; 79 80 if (vendor) { 81 enum dict_object_type type = 0; 82 struct dict_vendor_data data; 83 CHECK_FCT( fd_dict_gettype(vendor, &type) ); 84 CHECK_PARAMS( type == DICT_VENDOR ); 85 CHECK_FCT( fd_dict_getval(vendor, &data) ); 86 vid = data.vendor_id; 87 } 88 89 CHECK_MALLOC( new = malloc(sizeof(struct fd_app)) ); 90 memset(new, 0, sizeof(struct fd_app)); 91 fd_list_init(&new->chain, NULL); 92 new->flags.auth = (auth ? 1 : 0); 93 new->flags.acct = (acct ? 1 : 0); 94 new->vndid = vid; 95 new->appid = aid; 96 fd_list_insert_after(li, &new->chain); 97 } 98 99 return 0; 65 return fd_app_merge(&fd_g_config->cnf_apps, aid, vid, auth, acct); 100 66 } -
freeDiameter/endpoints.c
r38 r43 126 126 struct fd_endpoint * ep = (struct fd_endpoint *)li; 127 127 ep->flags &= ~flags; 128 if (ep->flags == 0) { 129 li = li->prev; 130 fd_list_unlink(&ep->chain); 131 free(ep); 132 } 128 133 } 129 134 -
freeDiameter/fD.h
r40 r43 67 67 #endif /* DPR_TIMEOUT */ 68 68 69 /* The Vendor-Id to advertise in CER/CEA */ 70 #ifndef MY_VENDOR_ID 71 #define MY_VENDOR_ID 0 /* Reserved value to tell it must be ignored */ 72 #endif /* MY_VENDOR_ID */ 73 74 75 69 76 /* Configuration */ 70 77 int fd_conf_init(); … … 145 152 /* Data for transitional states before the peer is in OPEN state */ 146 153 struct { 147 struct cnxctx * p_initiator; /* Connection before CEA is received */148 154 struct cnxctx * p_receiver; /* Only used in case of election */ 149 pthread_t p_ini_thr; 155 struct msg * p_cer; /* Only used in case of election */ 156 157 pthread_t p_ini_thr; /* Initiator thread for establishing a connection */ 150 158 struct fd_list p_connparams; /* The list of connection attempts, see p_cnx.c */ 151 159 }; … … 265 273 int fd_p_ce_handle_newCER(struct msg ** msg, struct fd_peer * peer, struct cnxctx ** cnx, int valid); 266 274 int fd_p_ce_handle_newcnx(struct fd_peer * peer, struct cnxctx * initiator); 267 int fd_p_ce_winelection(struct fd_peer * peer); 275 int fd_p_ce_process_receiver(struct fd_peer * peer); 276 void fd_p_ce_clear_cnx(struct fd_peer * peer, struct cnxctx ** cnx_kept); 268 277 int fd_p_dw_handle(struct msg ** msg, int req, struct fd_peer * peer); 269 278 int fd_p_dw_timeout(struct fd_peer * peer); 279 int fd_p_dw_reopen(struct fd_peer * peer); 270 280 int fd_p_dp_handle(struct msg ** msg, int req, struct fd_peer * peer); 271 281 int fd_p_dp_initiate(struct fd_peer * peer); -
freeDiameter/p_ce.c
r40 r43 41 41 static int set_peer_cnx(struct fd_peer * peer, struct cnxctx **cnx) 42 42 { 43 TODO("Save *cnx into peer->p_cnxctx"); 44 TODO("Set fifo of *cnx to peer->p_events"); 45 TODO("If connection is already TLS, read the credentials"); 46 TODO("Read the remote endpoints"); 47 48 return ENOTSUP; 49 } 50 51 static int process_valid_CEA(struct fd_peer * peer, struct msg ** cea) 52 { 53 /* Save info from the CEA into the peer */ 54 55 /* Handshake if needed */ 56 57 /* Save credentials if needed */ 58 59 TODO("..."); 60 return ENOTSUP; 61 43 CHECK_PARAMS( peer->p_cnxctx == NULL ); 44 45 /* Save the connection in peer */ 46 peer->p_cnxctx = *cnx; 47 *cnx = NULL; 48 49 /* Set the events to be sent to the PSM */ 50 CHECK_FCT( fd_cnx_recv_setaltfifo(peer->p_cnxctx, peer->p_events) ); 51 52 /* Read the credentials if possible */ 53 if (fd_cnx_getTLS(peer->p_cnxctx)) { 54 CHECK_FCT( fd_cnx_getcred(peer->p_cnxctx, &peer->p_hdr.info.runtime.pir_cert_list, &peer->p_hdr.info.runtime.pir_cert_list_size) ); 55 } 56 57 /* Read the endpoints, maybe used to reconnect to the peer later */ 58 CHECK_FCT( fd_cnx_getendpoints(peer->p_cnxctx, NULL, &peer->p_hdr.info.pi_endpoints) ); 59 60 /* Read the protocol */ 61 peer->p_hdr.info.runtime.pir_proto = fd_cnx_getproto(peer->p_cnxctx); 62 63 return 0; 64 } 65 66 /* Delete the peer connection, and cleanup associated information */ 67 void fd_p_ce_clear_cnx(struct fd_peer * peer, struct cnxctx ** cnx_kept) 68 { 69 peer->p_hdr.info.runtime.pir_cert_list = NULL; 70 peer->p_hdr.info.runtime.pir_cert_list_size = 0; 71 peer->p_hdr.info.runtime.pir_proto = 0; 72 73 if (peer->p_cnxctx) { 74 if (cnx_kept != NULL) { 75 *cnx_kept = peer->p_cnxctx; 76 } else { 77 fd_cnx_destroy(peer->p_cnxctx); 78 } 79 peer->p_cnxctx = NULL; 80 } 81 } 82 83 /* Election: compare the Diameter Ids, return true if the election is won */ 84 static __inline__ int election_result(struct fd_peer * peer) 85 { 86 int ret = (strcasecmp(peer->p_hdr.info.pi_diamid, fd_g_config->cnf_diamid) < 0); 87 if (ret) { 88 TRACE_DEBUG(INFO, "Election WON against peer '%s'", peer->p_hdr.info.pi_diamid); 89 } else { 90 TRACE_DEBUG(INFO, "Election LOST against peer '%s'", peer->p_hdr.info.pi_diamid); 91 } 92 return ret; 93 } 94 95 /* Add AVPs about local information in a CER or CEA */ 96 static int add_CE_info(struct msg *msg, struct cnxctx * cnx, int isi_tls, int isi_none) 97 { 98 struct dict_object * dictobj = NULL; 99 struct avp * avp = NULL; 100 union avp_value val; 101 struct fd_list *li, local_ep = FD_LIST_INITIALIZER(local_ep); 102 103 /* Add the Origin-* AVPs */ 104 CHECK_FCT( fd_msg_add_origin ( msg, 1 ) ); 105 106 /* Find the model for Host-IP-Address AVP */ 107 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Host-IP-Address", &dictobj, ENOENT ) ); 108 109 /* Get the list of endpoints */ 110 CHECK_FCT( fd_cnx_getendpoints(cnx, &local_ep, NULL) ); 111 112 /* Add the AVP(s) -- not sure what is the purpose... We could probably only add the primary one ? */ 113 for (li = local_ep.next; li != &local_ep; li = li->next) { 114 struct fd_endpoint * ep = (struct fd_endpoint *)li; 115 116 CHECK_FCT( fd_msg_avp_new ( dictobj, 0, &avp ) ); 117 CHECK_FCT( fd_msg_avp_value_encode ( &ep->ss, avp ) ); 118 CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp ) ); 119 } 120 121 122 /* Vendor-Id, Product-Name, and Firmware-Revision AVPs */ 123 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Vendor-Id", &dictobj, ENOENT ) ); 124 CHECK_FCT( fd_msg_avp_new ( dictobj, 0, &avp ) ); 125 val.u32 = MY_VENDOR_ID; 126 CHECK_FCT( fd_msg_avp_setvalue( avp, &val ) ); 127 CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp ) ); 128 129 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Product-Name", &dictobj, ENOENT ) ); 130 CHECK_FCT( fd_msg_avp_new ( dictobj, 0, &avp ) ); 131 val.os.data = (unsigned char *)FD_PROJECT_NAME; 132 val.os.len = strlen(FD_PROJECT_NAME); 133 CHECK_FCT( fd_msg_avp_setvalue( avp, &val ) ); 134 CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp ) ); 135 136 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Firmware-Revision", &dictobj, ENOENT ) ); 137 CHECK_FCT( fd_msg_avp_new ( dictobj, 0, &avp ) ); 138 val.u32 = (uint32_t)(FD_PROJECT_VERSION_MAJOR * 10000 + FD_PROJECT_VERSION_MINOR * 100 + FD_PROJECT_VERSION_REV); 139 CHECK_FCT( fd_msg_avp_setvalue( avp, &val ) ); 140 CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp ) ); 141 142 143 /* Add the Inband-Security-Id AVP if needed */ 144 if (isi_tls || isi_none) { 145 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Inband-Security-Id", &dictobj, ENOENT ) ); 146 147 if (isi_none) { 148 CHECK_FCT( fd_msg_avp_new ( dictobj, 0, &avp ) ); 149 val.u32 = ACV_ISI_NO_INBAND_SECURITY; 150 CHECK_FCT( fd_msg_avp_setvalue( avp, &val ) ); 151 CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp ) ); 152 } 153 154 if (isi_tls) { 155 CHECK_FCT( fd_msg_avp_new ( dictobj, 0, &avp ) ); 156 val.u32 = ACV_ISI_TLS; 157 CHECK_FCT( fd_msg_avp_setvalue( avp, &val ) ); 158 CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp ) ); 159 } 160 } 161 162 /* List of local applications */ 163 { 164 struct dict_object * dictobj_auth = NULL; 165 struct dict_object * dictobj_acct = NULL; 166 struct dict_object * dictobj_vid = NULL; 167 168 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Vendor-Specific-Application-Id", &dictobj, ENOENT ) ); 169 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Vendor-Id", &dictobj_vid, ENOENT ) ); 170 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Auth-Application-Id", &dictobj_auth, ENOENT ) ); 171 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Acct-Application-Id", &dictobj_acct, ENOENT ) ); 172 173 for (li = fd_g_config->cnf_apps.next; li != &fd_g_config->cnf_apps; li = li->next) { 174 struct fd_app * a = (struct fd_app *)(li); 175 176 if (a->flags.auth) { 177 CHECK_FCT( fd_msg_avp_new ( dictobj_auth, 0, &avp ) ); 178 val.u32 = a->appid; 179 CHECK_FCT( fd_msg_avp_setvalue( avp, &val ) ); 180 if (a->vndid != 0) { 181 struct avp * avp2 = NULL; 182 CHECK_FCT( fd_msg_avp_new ( dictobj, 0, &avp2 ) ); 183 CHECK_FCT( fd_msg_avp_add( avp2, MSG_BRW_LAST_CHILD, avp ) ); 184 avp = avp2; 185 CHECK_FCT( fd_msg_avp_new ( dictobj_vid, 0, &avp2 ) ); 186 val.u32 = a->vndid; 187 CHECK_FCT( fd_msg_avp_setvalue( avp, &val ) ); 188 CHECK_FCT( fd_msg_avp_add( avp, MSG_BRW_LAST_CHILD, avp2 ) ); 189 } 190 CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp ) ); 191 } 192 if (a->flags.acct) { 193 CHECK_FCT( fd_msg_avp_new ( dictobj_acct, 0, &avp ) ); 194 val.u32 = a->appid; 195 CHECK_FCT( fd_msg_avp_setvalue( avp, &val ) ); 196 if (a->vndid != 0) { 197 struct avp * avp2 = NULL; 198 CHECK_FCT( fd_msg_avp_new ( dictobj, 0, &avp2 ) ); 199 CHECK_FCT( fd_msg_avp_add( avp2, MSG_BRW_LAST_CHILD, avp ) ); 200 avp = avp2; 201 CHECK_FCT( fd_msg_avp_new ( dictobj_vid, 0, &avp2 ) ); 202 val.u32 = a->vndid; 203 CHECK_FCT( fd_msg_avp_setvalue( avp, &val ) ); 204 CHECK_FCT( fd_msg_avp_add( avp, MSG_BRW_LAST_CHILD, avp2 ) ); 205 } 206 CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp ) ); 207 } 208 } 209 210 /* do not forget the relay application */ 211 if (! fd_g_config->cnf_flags.no_fwd) { 212 CHECK_FCT( fd_msg_avp_new ( dictobj_auth, 0, &avp ) ); 213 val.u32 = AI_RELAY; 214 CHECK_FCT( fd_msg_avp_setvalue( avp, &val ) ); 215 CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp ) ); 216 } 217 } 218 219 /* Add the list of supported vendors */ 220 { 221 uint32_t * array = fd_dict_get_vendorid_list(fd_g_config->cnf_dict); 222 if (array) { 223 int i = 0; 224 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Supported-Vendor-Id", &dictobj, ENOENT ) ); 225 226 while (array[i] != 0) { 227 CHECK_FCT( fd_msg_avp_new ( dictobj, 0, &avp ) ); 228 val.u32 = array[i]; 229 CHECK_FCT( fd_msg_avp_setvalue( avp, &val ) ); 230 CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp ) ); 231 i++; 232 } 233 234 free(array); 235 } 236 } 237 238 return 0; 239 } 240 241 /* Remove any information saved from a previous CER/CEA exchange */ 242 static void cleanup_remote_CE_info(struct fd_peer * peer) 243 { 244 free(peer->p_hdr.info.runtime.pir_realm); 245 peer->p_hdr.info.runtime.pir_realm = NULL; 246 peer->p_hdr.info.runtime.pir_vendorid = 0; 247 peer->p_hdr.info.runtime.pir_orstate = 0; 248 free(peer->p_hdr.info.runtime.pir_prodname); 249 peer->p_hdr.info.runtime.pir_prodname = NULL; 250 peer->p_hdr.info.runtime.pir_firmrev = 0; 251 peer->p_hdr.info.runtime.pir_relay = 0; 252 peer->p_hdr.info.runtime.pir_isi = 0; 253 while (!FD_IS_LIST_EMPTY(&peer->p_hdr.info.runtime.pir_apps)) { 254 struct fd_list * li = peer->p_hdr.info.runtime.pir_apps.next; 255 fd_list_unlink(li); 256 free(li); 257 } 258 259 fd_ep_clearflags( &peer->p_hdr.info.pi_endpoints, EP_FL_ADV /* Remove previously advertised endpoints */ ); 260 } 261 262 /* Extract information sent by the remote peer and save it in our peer structure */ 263 static int save_remote_CE_info(struct msg * msg, struct fd_peer * peer, char ** error_code) 264 { 265 struct avp * avp = NULL; 266 267 cleanup_remote_CE_info(peer); 268 269 CHECK_FCT( fd_msg_browse( msg, MSG_BRW_FIRST_CHILD, &avp, NULL) ); 270 271 /* Loop on all AVPs and save what we are interrested into */ 272 while (avp) { 273 struct avp_hdr * hdr; 274 275 CHECK_FCT( fd_msg_avp_hdr( avp, &hdr ) ); 276 277 if (hdr->avp_flags & AVP_FLAG_VENDOR) { 278 /* Ignore all vendor-specific AVPs in CER/CEA because we don't support any currently */ 279 TRACE_DEBUG(FULL, "Ignored a vendor AVP in CER / CEA"); 280 fd_msg_dump_one(FULL, avp); 281 goto next; 282 } 283 284 switch (hdr->avp_code) { 285 case AC_ORIGIN_HOST: /* Origin-Host */ 286 if (hdr->avp_value == NULL) { 287 /* This is a sanity check */ 288 TRACE_DEBUG(NONE, "Ignored an AVP with unset value in CER/CEA"); 289 fd_msg_dump_one(NONE, avp); 290 ASSERT(0); /* To check if this really happens, and understand why... */ 291 goto next; 292 } 293 294 /* We check that the value matches what we know, otherwise disconnect the peer */ 295 if (strncasecmp(hdr->avp_value->os.data, peer->p_hdr.info.pi_diamid, hdr->avp_value->os.len)) { 296 TRACE_DEBUG(INFO, "Received a message with Origin-Host set to '%.*s' while expecting '%s'\n", 297 hdr->avp_value->os.len, hdr->avp_value->os.data, peer->p_hdr.info.pi_diamid); 298 *error_code = "DIAMETER_UNKNOWN_PEER"; 299 return EINVAL; 300 } 301 302 break; 303 304 case AC_ORIGIN_REALM: /* Origin-Realm */ 305 if (hdr->avp_value == NULL) { 306 /* This is a sanity check */ 307 TRACE_DEBUG(NONE, "Ignored an AVP with unset value in CER/CEA"); 308 fd_msg_dump_one(NONE, avp); 309 ASSERT(0); /* To check if this really happens, and understand why... */ 310 goto next; 311 } 312 313 /* In case of multiple AVPs */ 314 if (peer->p_hdr.info.runtime.pir_realm) { 315 TRACE_DEBUG(INFO, "Ignored multiple instances of the Origin-Realm AVP"); 316 goto next; 317 } 318 319 /* Save the value -- we don't change the case to avoid risking breaking UTF-8 with poor tolower() impls. */ 320 CHECK_MALLOC( peer->p_hdr.info.runtime.pir_realm = calloc( hdr->avp_value->os.len + 1, 1 ) ); 321 memcpy(peer->p_hdr.info.runtime.pir_realm, hdr->avp_value->os.data, hdr->avp_value->os.len); 322 break; 323 324 case AC_HOST_IP_ADDRESS: /* Host-IP-Address */ 325 if (hdr->avp_value == NULL) { 326 /* This is a sanity check */ 327 TRACE_DEBUG(NONE, "Ignored an AVP with unset value in CER/CEA"); 328 fd_msg_dump_one(NONE, avp); 329 ASSERT(0); /* To check if this really happens, and understand why... */ 330 goto next; 331 } 332 { 333 sSS ss; 334 335 /* Get the sockaddr value */ 336 memset(&ss, 0, sizeof(ss)); 337 CHECK_FCT( fd_msg_avp_value_interpret( avp, &ss) ); 338 339 /* Save this endpoint in the list as advertized */ 340 CHECK_FCT( fd_ep_add_merge( &peer->p_hdr.info.pi_endpoints, (sSA *)&ss, sizeof(sSS), EP_FL_ADV ) ); 341 } 342 break; 343 344 case AC_VENDOR_ID: /* Vendor-Id */ 345 if (hdr->avp_value == NULL) { 346 /* This is a sanity check */ 347 TRACE_DEBUG(NONE, "Ignored an AVP with unset value in CER/CEA"); 348 fd_msg_dump_one(NONE, avp); 349 ASSERT(0); /* To check if this really happens, and understand why... */ 350 goto next; 351 } 352 353 /* In case of multiple AVPs */ 354 if (peer->p_hdr.info.runtime.pir_vendorid) { 355 TRACE_DEBUG(INFO, "Ignored multiple instances of the Vendor-Id AVP"); 356 goto next; 357 } 358 359 peer->p_hdr.info.runtime.pir_vendorid = hdr->avp_value->u32; 360 break; 361 362 case AC_PRODUCT_NAME: /* Product-Name */ 363 if (hdr->avp_value == NULL) { 364 /* This is a sanity check */ 365 TRACE_DEBUG(NONE, "Ignored an AVP with unset value in CER/CEA"); 366 fd_msg_dump_one(NONE, avp); 367 ASSERT(0); /* To check if this really happens, and understand why... */ 368 goto next; 369 } 370 371 /* In case of multiple AVPs */ 372 if (peer->p_hdr.info.runtime.pir_prodname) { 373 TRACE_DEBUG(INFO, "Ignored multiple instances of the Product-Name AVP"); 374 goto next; 375 } 376 377 CHECK_MALLOC( peer->p_hdr.info.runtime.pir_prodname = calloc( hdr->avp_value->os.len + 1, 1 ) ); 378 memcpy(peer->p_hdr.info.runtime.pir_prodname, hdr->avp_value->os.data, hdr->avp_value->os.len); 379 break; 380 381 case AC_ORIGIN_STATE_ID: /* Origin-State-Id */ 382 if (hdr->avp_value == NULL) { 383 /* This is a sanity check */ 384 TRACE_DEBUG(NONE, "Ignored an AVP with unset value in CER/CEA"); 385 fd_msg_dump_one(NONE, avp); 386 ASSERT(0); /* To check if this really happens, and understand why... */ 387 goto next; 388 } 389 390 /* In case of multiple AVPs */ 391 if (peer->p_hdr.info.runtime.pir_orstate) { 392 TRACE_DEBUG(INFO, "Ignored multiple instances of the Origin-State-Id AVP"); 393 goto next; 394 } 395 396 peer->p_hdr.info.runtime.pir_orstate = hdr->avp_value->u32; 397 break; 398 399 case AC_SUPPORTED_VENDOR_ID: /* Supported-Vendor-Id */ 400 if (hdr->avp_value == NULL) { 401 /* This is a sanity check */ 402 TRACE_DEBUG(NONE, "Ignored an AVP with unset value in CER/CEA"); 403 fd_msg_dump_one(NONE, avp); 404 ASSERT(0); /* To check if this really happens, and understand why... */ 405 goto next; 406 } 407 408 TRACE_DEBUG(FULL, "'%s' supports a subset of vendor %d features.", peer->p_hdr.info.pi_diamid, hdr->avp_value->u32); 409 break; 410 411 case AC_VENDOR_SPECIFIC_APPLICATION_ID: /* Vendor-Specific-Application-Id (grouped)*/ 412 { 413 struct avp * inavp = NULL; 414 application_id_t aid = 0; 415 vendor_id_t vid = 0; 416 int auth = 0; 417 int acct = 0; 418 419 /* get the first child AVP */ 420 CHECK_FCT( fd_msg_browse(avp, MSG_BRW_FIRST_CHILD, &inavp, NULL) ); 421 422 while (inavp) { 423 struct avp_hdr * inhdr; 424 CHECK_FCT( fd_msg_avp_hdr( inavp, &inhdr ) ); 425 426 if (inhdr->avp_flags & AVP_FLAG_VENDOR) { 427 TRACE_DEBUG(FULL, "Ignored a vendor AVP inside Vendor-Specific-Application-Id AVP"); 428 fd_msg_dump_one(FULL, avp); 429 goto innext; 430 } 431 432 if (inhdr->avp_value == NULL) { 433 /* This is a sanity check */ 434 TRACE_DEBUG(NONE, "Ignored an AVP with unset value in CER/CEA"); 435 fd_msg_dump_one(NONE, avp); 436 ASSERT(0); /* To check if this really happens, and understand why... */ 437 goto innext; 438 } 439 switch (inhdr->avp_code) { 440 case AC_VENDOR_ID: /* Vendor-Id */ 441 vid = inhdr->avp_value->u32; 442 break; 443 case AC_AUTH_APPLICATION_ID: /* Auth-Application-Id */ 444 aid = inhdr->avp_value->u32; 445 auth += 1; 446 break; 447 case AC_ACCT_APPLICATION_ID: /* Acct-Application-Id */ 448 aid = inhdr->avp_value->u32; 449 acct += 1; 450 break; 451 /* ignore other AVPs */ 452 } 453 454 innext: 455 /* Go to next in AVP */ 456 CHECK_FCT( fd_msg_browse(inavp, MSG_BRW_NEXT, &inavp, NULL) ); 457 } 458 459 if (auth + acct != 1) { 460 TRACE_DEBUG(FULL, "Invalid Vendor-Specific-Application-Id AVP received, ignored"); 461 fd_msg_dump_one(FULL, avp); 462 } else { 463 /* Add an entry in the list */ 464 CHECK_FCT( fd_app_merge(&peer->p_hdr.info.runtime.pir_apps, aid, vid, auth, acct) ); 465 } 466 } 467 break; 468 469 case AC_AUTH_APPLICATION_ID: /* Auth-Application-Id */ 470 if (hdr->avp_value == NULL) { 471 /* This is a sanity check */ 472 TRACE_DEBUG(NONE, "Ignored an AVP with unset value in CER/CEA"); 473 fd_msg_dump_one(NONE, avp); 474 ASSERT(0); /* To check if this really happens, and understand why... */ 475 goto next; 476 } 477 478 if (hdr->avp_value->u32 == AI_RELAY) { 479 peer->p_hdr.info.runtime.pir_relay = 1; 480 } else { 481 CHECK_FCT( fd_app_merge(&peer->p_hdr.info.runtime.pir_apps, hdr->avp_value->u32, 0, 1, 0) ); 482 } 483 break; 484 485 case AC_ACCT_APPLICATION_ID: /* Acct-Application-Id */ 486 if (hdr->avp_value == NULL) { 487 /* This is a sanity check */ 488 TRACE_DEBUG(NONE, "Ignored an AVP with unset value in CER/CEA"); 489 fd_msg_dump_one(NONE, avp); 490 ASSERT(0); /* To check if this really happens, and understand why... */ 491 goto next; 492 } 493 494 if (hdr->avp_value->u32 == AI_RELAY) { 495 peer->p_hdr.info.runtime.pir_relay = 1; 496 } else { 497 /* Not clear if the relay application can be inside this AVP... */ 498 CHECK_FCT( fd_app_merge(&peer->p_hdr.info.runtime.pir_apps, hdr->avp_value->u32, 0, 0, 1) ); 499 } 500 break; 501 502 case AC_FIRMWARE_REVISION: /* Firmware-Revision */ 503 if (hdr->avp_value == NULL) { 504 /* This is a sanity check */ 505 TRACE_DEBUG(NONE, "Ignored an AVP with unset value in CER/CEA"); 506 fd_msg_dump_one(NONE, avp); 507 ASSERT(0); /* To check if this really happens, and understand why... */ 508 goto next; 509 } 510 511 peer->p_hdr.info.runtime.pir_firmrev = hdr->avp_value->u32; 512 break; 513 514 case AC_INBAND_SECURITY_ID: /* Inband-Security-Id */ 515 if (hdr->avp_value == NULL) { 516 /* This is a sanity check */ 517 TRACE_DEBUG(NONE, "Ignored an AVP with unset value in CER/CEA"); 518 fd_msg_dump_one(NONE, avp); 519 ASSERT(0); /* To check if this really happens, and understand why... */ 520 goto next; 521 } 522 ASSERT( hdr->avp_value->u32 < 32 ); /* if false, we have to change the code bellow */ 523 peer->p_hdr.info.runtime.pir_isi |= (1 << hdr->avp_value->u32); 524 break; 525 } 526 527 next: 528 /* Go to next AVP */ 529 CHECK_FCT( fd_msg_browse(avp, MSG_BRW_NEXT, &avp, NULL) ); 530 } 531 532 return 0; 533 } 534 535 /* Create a CER message for sending */ 536 static int create_CER(struct fd_peer * peer, struct cnxctx * cnx, struct msg ** cer) 537 { 538 struct dict_object * dictobj = NULL; 539 int isi_tls = 0; 540 int isi_none = 0; 541 542 /* Find CER dictionary object and create an instance */ 543 CHECK_FCT( fd_dict_search ( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Capabilities-Exchange-Request", &dictobj, ENOENT ) ); 544 CHECK_FCT( fd_msg_new ( dictobj, MSGFL_ALLOC_ETEID, cer ) ); 545 546 /* Do we need Inband-Security-Id AVPs ? */ 547 if (!fd_cnx_getTLS(cnx)) { 548 isi_none = peer->p_hdr.info.config.pic_flags.sec & PI_SEC_NONE; /* we add it event if the peer does not use the old mechanism */ 549 isi_tls = peer->p_hdr.info.config.pic_flags.sec & PI_SEC_TLS_OLD; 550 } 551 552 /* Add the information about the local peer */ 553 CHECK_FCT( add_CE_info(*cer, cnx, isi_tls, isi_none) ); 554 555 /* Done! */ 556 return 0; 557 } 558 559 560 /* Continue with the initiator side */ 561 static int to_waitcea(struct fd_peer * peer, struct cnxctx * cnx) 562 { 563 /* We sent a CER on the connection, set the event queue so that we receive the CEA */ 564 CHECK_FCT( set_peer_cnx(peer, &cnx) ); 565 566 /* Change state and reset the timer */ 567 CHECK_FCT( fd_psm_change_state(peer, STATE_WAITCEA) ); 568 fd_psm_next_timeout(peer, 0, CEA_TIMEOUT); 569 570 return 0; 571 } 572 573 /* Reject an incoming connection attempt */ 574 static void receiver_reject(struct cnxctx * recv_cnx, struct msg ** cer, char * rescode, char * errormsg) 575 { 576 /* Create and send the CEA with appropriate error code */ 577 CHECK_FCT_DO( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, cer, MSGFL_ANSW_ERROR ), goto destroy ); 578 CHECK_FCT_DO( fd_msg_rescode_set(*cer, rescode, errormsg, NULL, 1 ), goto destroy ); 579 CHECK_FCT_DO( fd_out_send(cer, recv_cnx, NULL), goto destroy ); 580 581 /* And now destroy this connection */ 582 destroy: 583 fd_cnx_destroy(recv_cnx); 584 if (*cer) { 585 fd_msg_free(*cer); 586 *cer = NULL; 587 } 588 } 589 590 /* We have established a new connection to the remote peer, send CER and eventually process the election */ 591 int fd_p_ce_handle_newcnx(struct fd_peer * peer, struct cnxctx * initiator) 592 { 593 struct msg * cer = NULL; 594 595 /* Send CER on the new connection */ 596 CHECK_FCT( create_CER(peer, initiator, &cer) ); 597 CHECK_FCT( fd_out_send(&cer, initiator, peer) ); 598 599 /* Are we doing an election ? */ 600 if (peer->p_hdr.info.runtime.pir_state == STATE_WAITCNXACK_ELEC) { 601 if (election_result(peer)) { 602 /* Close initiator connection */ 603 fd_cnx_destroy(initiator); 604 605 /* Process with the receiver side */ 606 CHECK_FCT( fd_p_ce_process_receiver(peer) ); 607 608 } else { 609 610 /* Answer an ELECTION LOST to the receiver side */ 611 receiver_reject(peer->p_receiver, &peer->p_cer, "ELECTION_LOST", NULL); 612 peer->p_receiver = NULL; 613 CHECK_FCT( to_waitcea(peer, initiator) ); 614 } 615 } else { 616 /* No election (yet) */ 617 CHECK_FCT( to_waitcea(peer, initiator) ); 618 } 619 620 return 0; 62 621 } 63 622 … … 65 624 int fd_p_ce_msgrcv(struct msg ** msg, int req, struct fd_peer * peer) 66 625 { 626 char * ec; 67 627 TRACE_ENTRY("%p %p", msg, peer); 68 628 CHECK_PARAMS( msg && *msg && CHECK_PEER(peer) ); … … 78 638 79 639 /* Set the error code */ 80 CHECK_FCT( fd_msg_rescode_set(*msg, "DIAMETER_COMMAND_UNSUPPORTED", "No CER in current state", NULL, 1 ) );640 CHECK_FCT( fd_msg_rescode_set(*msg, "DIAMETER_COMMAND_UNSUPPORTED", "No CER allowed in current state", NULL, 1 ) ); 81 641 82 642 /* msg now contains an answer message to send back */ 83 643 CHECK_FCT_DO( fd_out_send(msg, peer->p_cnxctx, peer), /* In case of error the message has already been dumped */ ); 84 85 644 } 86 645 87 646 /* If the state is not WAITCEA, just discard the message */ 88 if ( (req)|| (peer->p_hdr.info.runtime.pir_state != STATE_WAITCEA)) {647 if (req || (peer->p_hdr.info.runtime.pir_state != STATE_WAITCEA)) { 89 648 if (*msg) { 90 649 fd_log_debug("Received CER/CEA message while in state '%s', discarded.\n", STATE_STR(peer->p_hdr.info.runtime.pir_state)); … … 97 656 } 98 657 99 /* Ok, now we can accept the CEA */ 100 TODO("process_valid_CEA"); 101 102 return ENOTSUP; 658 /* Save info from the CEA into the peer */ 659 CHECK_FCT_DO( save_remote_CE_info(*msg, peer, &ec), goto cleanup ); 660 661 /* Handshake if needed, start clear otherwise */ 662 if ( ! fd_cnx_getTLS(peer->p_cnxctx) ) { 663 int todo = peer->p_hdr.info.config.pic_flags.sec & peer->p_hdr.info.runtime.pir_isi ; 664 665 if (todo == PI_SEC_NONE) { 666 /* Ok for clear connection */ 667 TRACE_DEBUG(INFO, "No TLS protection negotiated with peer '%s'.", peer->p_hdr.info.pi_diamid); 668 CHECK_FCT( fd_cnx_start_clear(peer->p_cnxctx, 1) ); 669 } else { 670 671 fd_psm_change_state(peer, STATE_OPEN_HANDSHAKE); 672 CHECK_FCT_DO( fd_cnx_handshake(peer->p_cnxctx, GNUTLS_CLIENT, peer->p_hdr.info.config.pic_priority, NULL), 673 { 674 /* Handshake failed ... */ 675 fd_log_debug("TLS Handshake failed with peer '%s', resetting the connection\n", peer->p_hdr.info.pi_diamid); 676 goto cleanup; 677 } ); 678 679 /* Retrieve the credentials */ 680 CHECK_FCT( fd_cnx_getcred(peer->p_cnxctx, &peer->p_hdr.info.runtime.pir_cert_list, &peer->p_hdr.info.runtime.pir_cert_list_size) ); 681 } 682 } 683 684 /* Move to next state */ 685 if (peer->p_flags.pf_cnx_pb) { 686 fd_psm_change_state(peer, STATE_REOPEN ); 687 CHECK_FCT( fd_p_dw_reopen(peer) ); 688 } else { 689 fd_psm_change_state(peer, STATE_OPEN ); 690 fd_psm_next_timeout(peer, 1, peer->p_hdr.info.config.pic_twtimer ?: fd_g_config->cnf_timer_tw); 691 } 692 693 return 0; 694 695 cleanup: 696 fd_p_ce_clear_cnx(peer, NULL); 697 698 /* Send the error to the peer */ 699 CHECK_FCT( fd_event_send(peer->p_events, FDEVP_CNX_ERROR, 0, NULL) ); 700 701 return 0; 702 } 703 704 /* Handle the receiver side after winning an election (or timeout on initiator side) */ 705 int fd_p_ce_process_receiver(struct fd_peer * peer) 706 { 707 char * ec = NULL; 708 struct msg * msg = NULL; 709 int isi = 0; 710 711 TRACE_ENTRY("%p", peer); 712 713 CHECK_FCT( set_peer_cnx(peer, &peer->p_receiver) ); 714 msg = peer->p_cer; 715 peer->p_cer = NULL; 716 717 /* Parse the content of the received CER */ 718 CHECK_FCT_DO( save_remote_CE_info(msg, peer, &ec), goto error_abort ); 719 720 /* Validate the peer if needed */ 721 if (peer->p_flags.pf_responder) { 722 int res = fd_peer_validate( peer ); 723 if (res < 0) { 724 ec = "DIAMETER_UNKNOWN_PEER"; 725 goto error_abort; 726 } 727 CHECK_FCT( res ); 728 } 729 730 /* Do we send ISI back ? */ 731 if ( ! fd_cnx_getTLS(peer->p_cnxctx) ) { 732 if (peer->p_hdr.info.config.pic_flags.sec & PI_SEC_NONE) 733 isi = PI_SEC_NONE; /* Maybe we should also look at peer->p_hdr.info.runtime.pir_isi here ? */ 734 else 735 isi = PI_SEC_TLS_OLD; 736 } 737 738 /* Reply a CEA */ 739 CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, &msg, 0 ) ); 740 CHECK_FCT( fd_msg_rescode_set(msg, "DIAMETER_SUCCESS", NULL, NULL, 1 ) ); 741 CHECK_FCT( add_CE_info(msg, peer->p_cnxctx, isi & PI_SEC_TLS_OLD, isi & PI_SEC_NONE) ); 742 CHECK_FCT( fd_out_send(&msg, peer->p_cnxctx, peer) ); 743 744 /* Handshake if needed */ 745 if (isi & PI_SEC_TLS_OLD) { 746 fd_psm_change_state(peer, STATE_OPEN_HANDSHAKE); 747 CHECK_FCT_DO( fd_cnx_handshake(peer->p_cnxctx, GNUTLS_SERVER, peer->p_hdr.info.config.pic_priority, NULL), 748 { 749 /* Handshake failed ... */ 750 fd_log_debug("TLS Handshake failed with peer '%s', resetting the connection\n", peer->p_hdr.info.pi_diamid); 751 goto cleanup; 752 } ); 753 754 /* Retrieve the credentials */ 755 CHECK_FCT( fd_cnx_getcred(peer->p_cnxctx, &peer->p_hdr.info.runtime.pir_cert_list, &peer->p_hdr.info.runtime.pir_cert_list_size) ); 756 757 /* Call second validation callback if needed */ 758 if (peer->p_cb2) { 759 TRACE_DEBUG(FULL, "Calling second validation callback for %s", peer->p_hdr.info.pi_diamid); 760 CHECK_FCT_DO( (*peer->p_cb2)( &peer->p_hdr.info ), 761 { 762 TRACE_DEBUG(INFO, "Validation callback rejected the peer %s after handshake", peer->p_hdr.info.pi_diamid); 763 CHECK_FCT( fd_psm_terminate( peer ) ); 764 return 0; 765 } ); 766 } 767 768 } else { 769 if ( ! fd_cnx_getTLS(peer->p_cnxctx) ) { 770 TRACE_DEBUG(INFO, "No TLS protection negotiated with peer '%s'.", peer->p_hdr.info.pi_diamid); 771 CHECK_FCT( fd_cnx_start_clear(peer->p_cnxctx, 1) ); 772 } 773 } 774 775 /* Move to OPEN or REOPEN state */ 776 if (peer->p_flags.pf_cnx_pb) { 777 fd_psm_change_state(peer, STATE_REOPEN ); 778 CHECK_FCT( fd_p_dw_reopen(peer) ); 779 } else { 780 fd_psm_change_state(peer, STATE_OPEN ); 781 fd_psm_next_timeout(peer, 1, peer->p_hdr.info.config.pic_twtimer ?: fd_g_config->cnf_timer_tw); 782 } 783 784 return 0; 785 786 error_abort: 787 if (ec) { 788 /* Create the error message */ 789 CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, &msg, MSGFL_ANSW_ERROR ) ); 790 791 /* Set the error code */ 792 CHECK_FCT( fd_msg_rescode_set(msg, ec, NULL, NULL, 1 ) ); 793 794 /* msg now contains an answer message to send back */ 795 CHECK_FCT_DO( fd_out_send(&msg, peer->p_cnxctx, peer), /* In case of error the message has already been dumped */ ); 796 } 797 798 cleanup: 799 if (msg) { 800 fd_msg_free(msg); 801 } 802 fd_p_ce_clear_cnx(peer, NULL); 803 804 /* Send the error to the peer */ 805 CHECK_FCT( fd_event_send(peer->p_events, FDEVP_CNX_ERROR, 0, NULL) ); 806 807 return 0; 103 808 } 104 809 … … 108 813 switch (peer->p_hdr.info.runtime.pir_state) { 109 814 case STATE_CLOSED: 110 TODO("Handle the CER, validate the peer if needed (and set expiry), set the alt_fifo in the connection, reply a CEA, eventually handshake (OPEN_HANDSHAKE), move to OPEN or REOPEN state"); 111 /* In case of error : DIAMETER_UNKNOWN_PEER */ 815 peer->p_receiver = *cnx; 816 *cnx = NULL; 817 peer->p_cer = *msg; 818 *msg = NULL; 819 CHECK_FCT( fd_p_ce_process_receiver(peer) ); 112 820 break; 113 821 114 822 case STATE_WAITCNXACK: 115 TODO("Save the parameters in the peer, move to STATE_WAITCNXACK_ELEC"); 823 /* Save the parameters in the peer, move to STATE_WAITCNXACK_ELEC */ 824 peer->p_receiver = *cnx; 825 *cnx = NULL; 826 peer->p_cer = *msg; 827 *msg = NULL; 828 CHECK_FCT( fd_psm_change_state(peer, STATE_WAITCNXACK_ELEC) ); 116 829 break; 117 830 118 831 case STATE_WAITCEA: 119 TODO("Election"); 832 if (election_result(peer)) { 833 834 /* Close initiator connection (was already set as principal) */ 835 fd_p_ce_clear_cnx(peer, NULL); 836 837 /* and go on with the receiver side */ 838 peer->p_receiver = *cnx; 839 *cnx = NULL; 840 peer->p_cer = *msg; 841 *msg = NULL; 842 CHECK_FCT( fd_p_ce_process_receiver(peer) ); 843 844 } else { 845 846 /* Answer an ELECTION LOST to the receiver side and continue */ 847 receiver_reject(*cnx, msg, "ELECTION_LOST", "Please answer my CER instead, you won the election."); 848 *cnx = NULL; 849 } 120 850 break; 121 851 122 852 default: 123 TODO("Reply with error CEA"); 124 TODO("Close the connection"); 125 /* reject_incoming_connection */ 126 127 } 128 129 130 return ENOTSUP; 131 } 132 133 static int do_election(struct fd_peer * peer) 134 { 135 TODO("Compare diameter Ids"); 136 137 /* ELECTION_LOST error code ?*/ 138 139 TODO("If we lost the election, we close the received connection and go to WAITCEA"); 140 TODO("If we won the election, we close initiator cnx, then call fd_p_ce_winelection"); 141 142 143 } 144 145 /* We have established a new connection to the remote peer, send CER and eventually do election */ 146 int fd_p_ce_handle_newcnx(struct fd_peer * peer, struct cnxctx * initiator) 147 { 148 /* if not election */ 149 TODO("Set the connection as peer's (setaltfifo)"); 150 TODO("Send CER"); 151 TODO("Move to WAITCEA"); 152 TODO("Change timer to CEA_TIMEOUT"); 153 154 /* if election */ 155 TODO("Send CER on cnx"); 156 TODO("Do the election"); 157 158 return ENOTSUP; 159 } 160 161 /* Handle the receiver side after winning an election (or timeout on initiator side) */ 162 int fd_p_ce_winelection(struct fd_peer * peer) 163 { 164 TODO("Move the receiver side connection to peer principal, set the altfifo"); 165 TODO("Then handle the received CER"); 166 } 853 receiver_reject(*cnx, msg, "DIAMETER_UNABLE_TO_COMPLY", "Invalid state to receive a new connection attempt"); 854 *cnx = NULL; 855 } 856 857 return 0; 858 } -
freeDiameter/p_cnx.c
r39 r43 246 246 return NULL; 247 247 } ); 248 } else { 249 /* Prepare to receive the next message */ 250 CHECK_FCT_DO( fd_cnx_start_clear(cnx, 0), goto fatal_error ); 248 251 } 249 252 -
freeDiameter/p_dw.c
r40 r43 54 54 return ENOTSUP; 55 55 } 56 56 57 /* Handle DW exchanges after the peer has come alive again */ 58 int fd_p_dw_reopen(struct fd_peer * peer) 59 { 60 TODO("..."); 61 62 return ENOTSUP; 63 } 64 65 -
freeDiameter/p_psm.c
r42 r43 250 250 fd_p_cnx_abort(peer, terminate); 251 251 252 if (peer->p_cnxctx) { 253 fd_cnx_destroy(peer->p_cnxctx); 254 peer->p_cnxctx = NULL; 255 } 256 257 if (peer->p_initiator) { 258 fd_cnx_destroy(peer->p_initiator); 259 peer->p_initiator = NULL; 260 } 252 fd_p_ce_clear_cnx(peer, NULL); 261 253 262 254 if (peer->p_receiver) { … … 594 586 struct cnxctx * cnx = ev_data; 595 587 596 /* Release the resources of the thread */588 /* Release the resources of the connecting thread */ 597 589 CHECK_POSIX_DO( pthread_join( peer->p_ini_thr, NULL), /* ignore, it is not a big deal */); 598 590 peer->p_ini_thr = (pthread_t)NULL; … … 642 634 643 635 /* Handle receiver side */ 644 CHECK_FCT_DO( fd_p_ce_ winelection(peer), goto psm_end );636 CHECK_FCT_DO( fd_p_ce_process_receiver(peer), goto psm_end ); 645 637 break; 646 638 } -
include/freeDiameter/freeDiameter.h
r42 r43 336 336 int pir_relay; /* The remote peer advertized the relay application */ 337 337 struct fd_list pir_apps; /* applications advertised by the remote peer, except relay (pi_flags.relay) */ 338 int pir_isi; /* Inband-Security-Id advertised (PI_SEC_* bits) */ 338 339 339 340 int pir_proto; /* The L4 protocol currently used with the peer (IPPROTO_TCP or IPPROTO_SCTP) */ … … 423 424 * after the CER is received. An extension must register such callback with peer_validate_register. 424 425 * 425 * If (info->pi_flags.sec == PI_SEC_TLS_OLD) the extension may instruct the daemon explicitely 426 * to not use TLS by clearing info->pi_flags.inband_tls -- only if inband_none is set. 427 * 428 * If (info->pi_flags.sec == PI_SEC_TLS_OLD) and info->pi_flags.inband_tls is set, 426 * The callback can learn if the peer has sent Inband-Security-Id AVPs in runtime.pir_isi fields. 427 * It can also learn if a handshake has already been performed in runtime.pir_cert_list field. 428 * The callback must set the value of config.pic_flags.sec appropriately to allow a connection without TLS. 429 * 430 * If the old TLS mechanism is used, 429 431 * the extension may also need to check the credentials provided during the TLS 430 432 * exchange (remote certificate). For this purpose, it may set the address of a new callback 431 433 * to be called once the handshake is completed. This new callback receives the information 432 * structure as parameter (with pi _sec_dataset) and returns 0 if the credentials are correct,434 * structure as parameter (with pir_cert_list set) and returns 0 if the credentials are correct, 433 435 * or an error code otherwise. If the error code is received, the connection is closed and the 434 436 * peer is destroyed. … … 545 547 void fd_ep_dump( int indent, struct fd_list * eps ); 546 548 549 /***************************************/ 550 /* Applications lists helpers */ 551 /***************************************/ 552 553 int fd_app_merge(struct fd_list * list, application_id_t aid, vendor_id_t vid, int auth, int acct); 554 int fd_app_find_common(struct fd_list * target, struct fd_list * reference); 555 int fd_app_gotcommon(struct fd_list * apps); 556 547 557 #endif /* _FREEDIAMETER_H */ -
include/freeDiameter/libfreeDiameter.h
r34 r43 718 718 } 719 719 720 721 720 */ 721 722 /* Special function: */ 723 uint32_t * fd_dict_get_vendorid_list(struct dictionary * dict); 722 724 723 725 /* … … 1329 1331 1330 1332 /* Define some hard-coded values */ 1333 /* Application */ 1334 #define AI_RELAY 0xffffffff 1335 1331 1336 /* Commands Codes */ 1332 1337 #define CC_CAPABILITIES_EXCHANGE 257 … … 1369 1374 #define AC_ORIGIN_REALM 296 1370 1375 #define AC_INBAND_SECURITY_ID 299 1376 #define ACV_ISI_NO_INBAND_SECURITY 0 1377 #define ACV_ISI_TLS 1 1371 1378 1372 1379 /* Error codes */ … … 2426 2433 * 2427 2434 * PARAMETERS: 2428 * old : Location of a FIFO that is to be emptied and deleted.2435 * old : Location of a FIFO that is to be emptied. 2429 2436 * new : A FIFO that will receive the old data. 2430 2437 * loc_update : if non NULL, a place to store the pointer to new FIFO atomically with the move. 2431 2438 * 2432 2439 * DESCRIPTION: 2433 * Deletea queue and move its content to another one atomically.2440 * Empties a queue and move its content to another one atomically. 2434 2441 * 2435 2442 * RETURN VALUE: … … 2437 2444 * EINVAL : A parameter is invalid. 2438 2445 */ 2439 int fd_fifo_move ( struct fifo * *old, struct fifo * new, struct fifo ** loc_update );2446 int fd_fifo_move ( struct fifo * old, struct fifo * new, struct fifo ** loc_update ); 2440 2447 2441 2448 /* -
libfreeDiameter/dictionary.c
r7 r43 1529 1529 1530 1530 1531 /* Initialize the sentinel for appl ciations */1531 /* Initialize the sentinel for applications */ 1532 1532 init_object( &new->dict_applications, DICT_APPLICATION ); 1533 1533 new->dict_applications.data.application.application_name = "Diameter Common Messages"; -
libfreeDiameter/fifo.c
r25 r43 183 183 } 184 184 185 /* Move the content of old into new, and update loc_update atomically */186 int fd_fifo_move ( struct fifo * *old, struct fifo * new, struct fifo ** loc_update )185 /* Move the content of old into new, and update loc_update atomically. We leave the old queue empty but valid */ 186 int fd_fifo_move ( struct fifo * old, struct fifo * new, struct fifo ** loc_update ) 187 187 { 188 188 struct fifo * q; … … 190 190 191 191 TRACE_ENTRY("%p %p %p", old, new, loc_update); 192 CHECK_PARAMS( old && CHECK_FIFO( *old ) && CHECK_FIFO( new )); 193 194 q = *old; 195 CHECK_PARAMS( ! q->data ); 192 CHECK_PARAMS( CHECK_FIFO( old ) && CHECK_FIFO( new )); 193 194 CHECK_PARAMS( ! old->data ); 196 195 if (new->high) { 197 196 TODO("Implement support for thresholds in fd_fifo_move..."); … … 199 198 200 199 /* Update loc_update */ 201 *old = NULL;202 200 if (loc_update) 203 201 *loc_update = new; 204 202 205 203 /* Lock the queues */ 206 CHECK_POSIX( pthread_mutex_lock( & q->mtx ) );204 CHECK_POSIX( pthread_mutex_lock( &old->mtx ) ); 207 205 CHECK_POSIX( pthread_mutex_lock( &new->mtx ) ); 208 206 209 207 /* Any waiting thread on the old queue returns an error */ 210 q->eyec = 0xdead;211 while ( q->thrs) {212 CHECK_POSIX( pthread_cond_signal(& q->cond) );213 CHECK_POSIX( pthread_mutex_unlock( & q->mtx ));208 old->eyec = 0xdead; 209 while (old->thrs) { 210 CHECK_POSIX( pthread_cond_signal(&old->cond) ); 211 CHECK_POSIX( pthread_mutex_unlock( &old->mtx )); 214 212 pthread_yield(); 215 CHECK_POSIX( pthread_mutex_lock( & q->mtx ) );213 CHECK_POSIX( pthread_mutex_lock( &old->mtx ) ); 216 214 ASSERT( ++loops < 10 ); /* detect infinite loops */ 217 215 } 218 216 219 217 /* Move all data from old to new */ 220 fd_list_move_end( &new->list, & q->list );221 if ( q->count && (!new->count)) {218 fd_list_move_end( &new->list, &old->list ); 219 if (old->count && (!new->count)) { 222 220 CHECK_POSIX( pthread_cond_signal(&new->cond) ); 223 221 } 224 new->count += q->count; 225 226 /* Destroy old */ 227 CHECK_POSIX( pthread_mutex_unlock( &q->mtx ) ); 228 CHECK_POSIX( pthread_cond_destroy( &q->cond ) ); 229 CHECK_POSIX( pthread_mutex_destroy( &q->mtx ) ); 230 free(q); 231 232 /* Unlock new, we're done */ 222 new->count += old->count; 223 224 /* Reset old */ 225 old->count = 0; 226 old->eyec = FIFO_EYEC; 227 228 /* Unlock, we're done */ 233 229 CHECK_POSIX( pthread_mutex_unlock( &new->mtx ) ); 230 CHECK_POSIX( pthread_mutex_unlock( &old->mtx ) ); 234 231 235 232 return 0;
Note: See TracChangeset
for help on using the changeset viewer.