Changeset 706:4ffbc9f1e922 in freeDiameter for libfdcore/peers.c
- Timestamp:
- Feb 9, 2011, 3:26:58 PM (13 years ago)
- Branch:
- default
- Phase:
- public
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
libfdcore/peers.c
r691 r706 73 73 74 74 p->p_eyec = EYEC_PEER; 75 CHECK_POSIX( pthread_mutex_init(&p->p_state_mtx, NULL) ); 76 75 77 fd_list_init(&p->p_actives, p); 76 78 fd_list_init(&p->p_expiry, p); … … 94 96 struct fd_list * li; 95 97 int ret = 0; 98 96 99 TRACE_ENTRY("%p %p %p %p", info, orig_dbg, cb, cb_data); 97 100 CHECK_PARAMS(info && info->pi_diamid); 98 101 102 if (info->config.pic_realm) { 103 if (!fd_os_is_valid_DiameterIdentity((os0_t)info->config.pic_realm, strlen(info->config.pic_realm))) { 104 TRACE_DEBUG(INFO, "'%s' is not a valid DiameterIdentity.", info->config.pic_realm); 105 return EINVAL; 106 } 107 } 108 99 109 /* Create a structure to contain the new peer information */ 100 110 CHECK_FCT( fd_peer_alloc(&p) ); 101 111 102 112 /* Copy the informations from the parameters received */ 103 CHECK_MALLOC( p->p_hdr.info.pi_diamid = strdup(info->pi_diamid) ); 113 p->p_hdr.info.pi_diamid = info->pi_diamid; 114 CHECK_FCT( fd_os_validate_DiameterIdentity(&p->p_hdr.info.pi_diamid, &p->p_hdr.info.pi_diamidlen, 1) ); 104 115 105 116 memcpy( &p->p_hdr.info.config, &info->config, sizeof(p->p_hdr.info.config) ); 117 106 118 /* Duplicate the strings if provided */ 107 119 if (info->config.pic_realm) { … … 109 121 } 110 122 if (info->config.pic_priority) { 111 CHECK_MALLOC( p->p_hdr.info.config.pic_ realm= strdup(info->config.pic_priority) );123 CHECK_MALLOC( p->p_hdr.info.config.pic_priority = strdup(info->config.pic_priority) ); 112 124 } 113 125 … … 124 136 CHECK_MALLOC( p->p_dbgorig = strdup(orig_dbg) ); 125 137 } else { 126 CHECK_MALLOC( p->p_dbgorig = strdup("un known") );138 CHECK_MALLOC( p->p_dbgorig = strdup("unspecified") ); 127 139 } 128 140 p->p_cb = cb; … … 134 146 for (li = fd_g_peers.next; li != &fd_g_peers; li = li->next) { 135 147 struct fd_peer * next = (struct fd_peer *)li; 136 int cmp = strcasecmp( p->p_hdr.info.pi_diamid, next->p_hdr.info.pi_diamid ); 148 int cmp = fd_os_almostcasecmp( p->p_hdr.info.pi_diamid, p->p_hdr.info.pi_diamidlen, 149 next->p_hdr.info.pi_diamid, next->p_hdr.info.pi_diamidlen ); 137 150 if (cmp > 0) 138 151 continue; … … 162 175 163 176 /* Search for a peer */ 164 int fd_peer_getbyid( char * diamid, struct peer_hdr ** peer )177 int fd_peer_getbyid( DiamId_t diamid, size_t diamidlen, int igncase, struct peer_hdr ** peer ) 165 178 { 166 179 struct fd_list * li; 167 168 TRACE_ENTRY("%p %p", diamid, peer); 169 CHECK_PARAMS( diamid && peer ); 180 TRACE_ENTRY("%p %zd %d %p", diamid, diamidlen, igncase, peer); 181 CHECK_PARAMS( diamid && diamidlen && peer ); 170 182 171 183 *peer = NULL; … … 175 187 for (li = fd_g_peers.next; li != &fd_g_peers; li = li->next) { 176 188 struct fd_peer * next = (struct fd_peer *)li; 177 int cmp = strcasecmp( diamid, next->p_hdr.info.pi_diamid ); 189 int cmp; 190 if (igncase) 191 cmp = fd_os_almostcasecmp( diamid, diamidlen, next->p_hdr.info.pi_diamid, next->p_hdr.info.pi_diamidlen ); 192 else 193 cmp = fd_os_cmp( diamid, diamidlen, next->p_hdr.info.pi_diamid, next->p_hdr.info.pi_diamidlen ); 178 194 if (cmp > 0) 179 195 continue; … … 255 271 256 272 CHECK_FCT_DO( fd_fifo_del(&p->p_tosend), /* continue */ ); 273 CHECK_POSIX_DO( pthread_mutex_destroy(&p->p_state_mtx), /* continue */); 257 274 CHECK_POSIX_DO( pthread_mutex_destroy(&p->p_sr.mtx), /* continue */); 258 275 CHECK_POSIX_DO( pthread_cond_destroy(&p->p_sr.cnd), /* continue */); … … 283 300 CHECK_FCT_DO( pthread_rwlock_wrlock(&fd_g_peers_rw), /* continue */ ); 284 301 for (li = fd_g_peers.next; li != &fd_g_peers; li = li->next) { 285 struct fd_peer * peer = (struct fd_peer *)li; 286 287 fd_cpu_flush_cache(); 288 if (peer->p_hdr.info.runtime.pir_state != STATE_ZOMBIE) { 302 struct fd_peer * peer = (struct fd_peer *)li->o; 303 304 if (fd_peer_getstate(peer) != STATE_ZOMBIE) { 289 305 CHECK_FCT_DO( fd_psm_terminate(peer, "REBOOTING"), /* continue */ ); 290 306 } else { … … 307 323 308 324 /* Allow the PSM(s) to execute */ 309 sched_yield();325 usleep(100000); 310 326 311 327 /* Remove zombie peers */ 312 328 CHECK_FCT_DO( pthread_rwlock_wrlock(&fd_g_peers_rw), /* continue */ ); 313 329 for (li = fd_g_peers.next; li != &fd_g_peers; li = li->next) { 314 struct fd_peer * peer = (struct fd_peer *)li; 315 fd_cpu_flush_cache(); 316 if (peer->p_hdr.info.runtime.pir_state == STATE_ZOMBIE) { 330 struct fd_peer * peer = (struct fd_peer *)li->o; 331 if (fd_peer_getstate(peer) == STATE_ZOMBIE) { 317 332 li = li->prev; /* to avoid breaking the loop */ 318 333 fd_list_unlink(&peer->p_hdr.chain); … … 329 344 CHECK_FCT_DO( pthread_rwlock_wrlock(&fd_g_peers_rw), /* continue */ ); 330 345 while (!FD_IS_LIST_EMPTY(&fd_g_peers)) { 331 struct fd_peer * peer = (struct fd_peer *)(fd_g_peers.next );346 struct fd_peer * peer = (struct fd_peer *)(fd_g_peers.next->o); 332 347 fd_psm_abord(peer); 333 348 fd_list_unlink(&peer->p_hdr.chain); … … 339 354 /* Free memory objects of all peers */ 340 355 while (!FD_IS_LIST_EMPTY(&purge)) { 341 struct fd_peer * peer = (struct fd_peer *)(purge.next );356 struct fd_peer * peer = (struct fd_peer *)(purge.next->o); 342 357 fd_list_unlink(&peer->p_hdr.chain); 343 358 fd_peer_free(&peer); … … 364 379 } 365 380 366 fd_log_debug("> %s\t%s", STATE_STR( peer->p_hdr.info.runtime.pir_state), peer->p_hdr.info.pi_diamid);381 fd_log_debug("> %s\t%s", STATE_STR(fd_peer_getstate(peer)), peer->p_hdr.info.pi_diamid); 367 382 if (details > INFO) { 368 fd_log_debug("\t(rlm:%s)", peer->p_hdr.info.runtime.pir_realm ?: " (unknown)");383 fd_log_debug("\t(rlm:%s)", peer->p_hdr.info.runtime.pir_realm ?: "<unknown>"); 369 384 if (peer->p_hdr.info.runtime.pir_prodname) 370 385 fd_log_debug("\t['%s' %u]", peer->p_hdr.info.runtime.pir_prodname, peer->p_hdr.info.runtime.pir_firmrev); … … 398 413 399 414 for (li = fd_g_peers.next; li != &fd_g_peers; li = li->next) { 400 struct fd_peer * np = (struct fd_peer *)li ;415 struct fd_peer * np = (struct fd_peer *)li->o; 401 416 fd_peer_dump(np, details); 402 417 } … … 404 419 CHECK_FCT_DO( pthread_rwlock_unlock(&fd_g_peers_rw), /* continue */ ); 405 420 } 421 422 static struct dict_object *avp_oh_model = NULL; 423 static pthread_mutex_t cache_avp_lock = PTHREAD_MUTEX_INITIALIZER; 406 424 407 425 /* Handle an incoming CER request on a new connection */ … … 409 427 { 410 428 struct msg * msg; 411 struct dict_object *avp_oh_model;412 avp_code_t code = AC_ORIGIN_HOST;413 429 struct avp *avp_oh; 414 430 struct avp_hdr * avp_hdr; … … 424 440 msg = *cer; 425 441 442 /* If needed, resolve the dictioanry model for Origin-Host */ 443 CHECK_POSIX( pthread_mutex_lock(&cache_avp_lock) ); 444 if (!avp_oh_model) { 445 avp_code_t code = AC_ORIGIN_HOST; 446 int ret; 447 CHECK_FCT_DO( ret = fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_CODE, &code, &avp_oh_model, ENOENT), 448 { CHECK_POSIX( pthread_mutex_unlock(&cache_avp_lock) ); return ret; } ); 449 } 450 CHECK_POSIX( pthread_mutex_unlock(&cache_avp_lock) ); 451 426 452 /* Find the Diameter Identity of the remote peer in the message */ 427 CHECK_FCT( fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_CODE, &code, &avp_oh_model, ENOENT) );428 453 CHECK_FCT( fd_msg_search_avp ( msg, avp_oh_model, &avp_oh ) ); 454 ASSERT(avp_oh); /* otherwise it should not have passed rules validation, right? */ 429 455 CHECK_FCT( fd_msg_avp_hdr ( avp_oh, &avp_hdr ) ); 456 457 /* First, check if the Origin-Host value */ 458 if (!fd_os_is_valid_DiameterIdentity(avp_hdr->avp_value->os.data, avp_hdr->avp_value->os.len)) { 459 TRACE_DEBUG(INFO, "Received new CER with invalid \\0 in its Origin-Host"); 460 CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, cer, MSGFL_ANSW_ERROR ) ); 461 CHECK_FCT( fd_msg_rescode_set(*cer, "ER_DIAMETER_INVALID_AVP_VALUE", 462 "Your Origin-Host contains invalid characters.", avp_oh, 1 ) ); 463 CHECK_FCT( fd_out_send(cer, *cnx, NULL, FD_CNX_ORDERED) ); 464 return EINVAL; 465 } 430 466 431 467 /* Search if we already have this peer id in our list. We take directly the write lock so that we don't need to upgrade if it is a new peer. … … 435 471 436 472 for (li = fd_g_peers.next; li != &fd_g_peers; li = li->next) { 437 peer = (struct fd_peer *)li;438 /* It is probably unwise to use strcasecmp on UTF8 data... To be improved! */439 int cmp = strncasecmp( (char *)avp_hdr->avp_value->os.data, peer->p_hdr.info.pi_diamid, avp_hdr->avp_value->os.len );473 int cmp; 474 peer = (struct fd_peer *)li->o; 475 cmp = fd_os_almostcasecmp( avp_hdr->avp_value->os.data, avp_hdr->avp_value->os.len, peer->p_hdr.info.pi_diamid, peer->p_hdr.info.pi_diamidlen ); 440 476 if (cmp > 0) 441 477 continue; … … 451 487 452 488 /* Set the peer Diameter Id and the responder flag parameters */ 453 CHECK_MALLOC_DO( peer->p_hdr.info.pi_diamid = malloc(avp_hdr->avp_value->os.len + 1), { ret = ENOMEM; goto out; } );454 memcpy(peer->p_hdr.info.pi_diamid, avp_hdr->avp_value->os.data, avp_hdr->avp_value->os.len);455 peer->p_hdr.info.pi_diamid [avp_hdr->avp_value->os.len] = '\0';489 CHECK_MALLOC_DO( peer->p_hdr.info.pi_diamid = os0dup(avp_hdr->avp_value->os.data, avp_hdr->avp_value->os.len), 490 { ret = ENOMEM; goto out; } ); 491 peer->p_hdr.info.pi_diamidlen = avp_hdr->avp_value->os.len; 456 492 CHECK_MALLOC_DO( peer->p_dbgorig = strdup(fd_cnx_getid(*cnx)), { ret = ENOMEM; goto out; } ); 457 493 peer->p_flags.pf_responder = 1; … … 470 506 } else { 471 507 /* Check if the peer is in zombie state */ 472 fd_cpu_flush_cache(); 473 if (peer->p_hdr.info.runtime.pir_state == STATE_ZOMBIE) { 508 if (fd_peer_getstate(peer) == STATE_ZOMBIE) { 474 509 /* Re-activate the peer */ 475 510 if (peer->p_hdr.info.config.pic_flags.exp) 476 511 peer->p_flags.pf_responder = 1; 477 peer->p_hdr.info.runtime.pir_state = STATE_NEW; 512 CHECK_POSIX_DO( pthread_mutex_lock(&peer->p_state_mtx), ); 513 peer->p_state = STATE_NEW; 514 CHECK_POSIX_DO( pthread_mutex_unlock(&peer->p_state_mtx), ); 515 peer->p_flags.pf_localterm = 0; 478 516 CHECK_FCT_DO( ret = fd_psm_begin(peer), goto out ); 479 517 } 480 518 } 481 519 482 520 /* Send the new connection event to the PSM */ 483 521 CHECK_MALLOC_DO( ev_data = malloc(sizeof(struct cnx_incoming)), { ret = ENOMEM; goto out; } );
Note: See TracChangeset
for help on using the changeset viewer.