|
41 | 41 | #include "asterisk/sorcery.h"
|
42 | 42 | #include "asterisk/file.h"
|
43 | 43 | #include "asterisk/cli.h"
|
| 44 | +#include "asterisk/callerid.h" |
44 | 45 | #include "asterisk/res_pjsip_cli.h"
|
45 | 46 | #include "asterisk/test.h"
|
46 | 47 | #include "asterisk/res_pjsip_presence_xml.h"
|
@@ -2449,6 +2450,234 @@ int ast_sip_call_codec_str_to_pref(struct ast_flags *pref, const char *pref_str,
|
2449 | 2450 | return 0;
|
2450 | 2451 | }
|
2451 | 2452 |
|
| 2453 | +/*! |
| 2454 | + * \internal |
| 2455 | + * \brief Set an ast_party_id name and number based on an identity header. |
| 2456 | + * \param hdr From, P-Asserted-Identity, or Remote-Party-ID header on incoming message |
| 2457 | + * \param[out] id The ID to set data on |
| 2458 | + */ |
| 2459 | +static void set_id_from_hdr(pjsip_fromto_hdr *hdr, struct ast_party_id *id) |
| 2460 | +{ |
| 2461 | + char cid_name[AST_CHANNEL_NAME]; |
| 2462 | + char cid_num[AST_CHANNEL_NAME]; |
| 2463 | + pjsip_name_addr *id_name_addr = (pjsip_name_addr *) hdr->uri; |
| 2464 | + char *semi; |
| 2465 | + |
| 2466 | + ast_copy_pj_str(cid_name, &id_name_addr->display, sizeof(cid_name)); |
| 2467 | + ast_copy_pj_str(cid_num, ast_sip_pjsip_uri_get_username(hdr->uri), sizeof(cid_num)); |
| 2468 | + |
| 2469 | + /* Always truncate caller-id number at a semicolon. */ |
| 2470 | + semi = strchr(cid_num, ';'); |
| 2471 | + if (semi) { |
| 2472 | + /* |
| 2473 | + * We need to be able to handle URI's looking like |
| 2474 | + * "sip:1235557890;phone-context=national@x.x.x.x;user=phone" |
| 2475 | + * |
| 2476 | + * Where the uri->user field will result in: |
| 2477 | + * "1235557890;phone-context=national" |
| 2478 | + * |
| 2479 | + * People don't care about anything after the semicolon |
| 2480 | + * showing up on their displays even though the RFC |
| 2481 | + * allows the semicolon. |
| 2482 | + */ |
| 2483 | + *semi = '\0'; |
| 2484 | + } |
| 2485 | + |
| 2486 | + ast_free(id->name.str); |
| 2487 | + id->name.str = ast_strdup(cid_name); |
| 2488 | + if (!ast_strlen_zero(cid_name)) { |
| 2489 | + id->name.valid = 1; |
| 2490 | + } |
| 2491 | + ast_free(id->number.str); |
| 2492 | + id->number.str = ast_strdup(cid_num); |
| 2493 | + if (!ast_strlen_zero(cid_num)) { |
| 2494 | + id->number.valid = 1; |
| 2495 | + } |
| 2496 | +} |
| 2497 | + |
| 2498 | +/*! |
| 2499 | + * \internal |
| 2500 | + * \brief Get a P-Asserted-Identity or Remote-Party-ID header from an incoming message |
| 2501 | + * |
| 2502 | + * This function will parse the header as if it were a From header. This allows for us |
| 2503 | + * to easily manipulate the URI, as well as add, modify, or remove parameters from the |
| 2504 | + * header |
| 2505 | + * |
| 2506 | + * \param rdata The incoming message |
| 2507 | + * \param header_name The name of the ID header to find |
| 2508 | + * \retval NULL No ID header present or unable to parse ID header |
| 2509 | + * \retval non-NULL The parsed ID header |
| 2510 | + */ |
| 2511 | +static pjsip_fromto_hdr *get_id_header(pjsip_rx_data *rdata, const pj_str_t *header_name) |
| 2512 | +{ |
| 2513 | + static const pj_str_t from = { "From", 4 }; |
| 2514 | + pj_str_t header_content; |
| 2515 | + pjsip_fromto_hdr *parsed_hdr; |
| 2516 | + pjsip_generic_string_hdr *ident = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, |
| 2517 | + header_name, NULL); |
| 2518 | + int parsed_len; |
| 2519 | + |
| 2520 | + if (!ident) { |
| 2521 | + return NULL; |
| 2522 | + } |
| 2523 | + |
| 2524 | + pj_strdup_with_null(rdata->tp_info.pool, &header_content, &ident->hvalue); |
| 2525 | + |
| 2526 | + parsed_hdr = pjsip_parse_hdr(rdata->tp_info.pool, &from, header_content.ptr, |
| 2527 | + pj_strlen(&header_content), &parsed_len); |
| 2528 | + |
| 2529 | + if (!parsed_hdr) { |
| 2530 | + return NULL; |
| 2531 | + } |
| 2532 | + |
| 2533 | + return parsed_hdr; |
| 2534 | +} |
| 2535 | + |
| 2536 | +/*! |
| 2537 | + * \internal |
| 2538 | + * \brief Set an ast_party_id structure based on data in a P-Asserted-Identity header |
| 2539 | + * |
| 2540 | + * This makes use of \ref set_id_from_hdr for setting name and number. It uses |
| 2541 | + * the contents of a Privacy header in order to set presentation information. |
| 2542 | + * |
| 2543 | + * \param rdata The incoming message |
| 2544 | + * \param[out] id The ID to set |
| 2545 | + * \retval 0 Successfully set the party ID |
| 2546 | + * \retval non-zero Could not set the party ID |
| 2547 | + */ |
| 2548 | +static int set_id_from_pai(pjsip_rx_data *rdata, struct ast_party_id *id) |
| 2549 | +{ |
| 2550 | + static const pj_str_t pai_str = { "P-Asserted-Identity", 19 }; |
| 2551 | + static const pj_str_t privacy_str = { "Privacy", 7 }; |
| 2552 | + pjsip_fromto_hdr *pai_hdr = get_id_header(rdata, &pai_str); |
| 2553 | + pjsip_generic_string_hdr *privacy; |
| 2554 | + |
| 2555 | + if (!pai_hdr) { |
| 2556 | + return -1; |
| 2557 | + } |
| 2558 | + |
| 2559 | + set_id_from_hdr(pai_hdr, id); |
| 2560 | + |
| 2561 | + if (!id->number.valid) { |
| 2562 | + return -1; |
| 2563 | + } |
| 2564 | + |
| 2565 | + privacy = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &privacy_str, NULL); |
| 2566 | + if (!privacy || !pj_stricmp2(&privacy->hvalue, "none")) { |
| 2567 | + id->number.presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED; |
| 2568 | + id->name.presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED; |
| 2569 | + } else { |
| 2570 | + id->number.presentation = AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED; |
| 2571 | + id->name.presentation = AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED; |
| 2572 | + } |
| 2573 | + |
| 2574 | + return 0; |
| 2575 | +} |
| 2576 | + |
| 2577 | +/*! |
| 2578 | + * \internal |
| 2579 | + * \brief Set an ast_party_id structure based on data in a Remote-Party-ID header |
| 2580 | + * |
| 2581 | + * This makes use of \ref set_id_from_hdr for setting name and number. It uses |
| 2582 | + * the privacy and screen parameters in order to set presentation information. |
| 2583 | + * |
| 2584 | + * \param rdata The incoming message |
| 2585 | + * \param[out] id The ID to set |
| 2586 | + * \retval 0 Succesfully set the party ID |
| 2587 | + * \retval non-zero Could not set the party ID |
| 2588 | + */ |
| 2589 | +static int set_id_from_rpid(pjsip_rx_data *rdata, struct ast_party_id *id) |
| 2590 | +{ |
| 2591 | + static const pj_str_t rpid_str = { "Remote-Party-ID", 15 }; |
| 2592 | + static const pj_str_t privacy_str = { "privacy", 7 }; |
| 2593 | + static const pj_str_t screen_str = { "screen", 6 }; |
| 2594 | + pjsip_fromto_hdr *rpid_hdr = get_id_header(rdata, &rpid_str); |
| 2595 | + pjsip_param *screen; |
| 2596 | + pjsip_param *privacy; |
| 2597 | + |
| 2598 | + if (!rpid_hdr) { |
| 2599 | + return -1; |
| 2600 | + } |
| 2601 | + |
| 2602 | + set_id_from_hdr(rpid_hdr, id); |
| 2603 | + |
| 2604 | + if (!id->number.valid) { |
| 2605 | + return -1; |
| 2606 | + } |
| 2607 | + |
| 2608 | + privacy = pjsip_param_find(&rpid_hdr->other_param, &privacy_str); |
| 2609 | + screen = pjsip_param_find(&rpid_hdr->other_param, &screen_str); |
| 2610 | + if (privacy && !pj_stricmp2(&privacy->value, "full")) { |
| 2611 | + id->number.presentation = AST_PRES_RESTRICTED; |
| 2612 | + id->name.presentation = AST_PRES_RESTRICTED; |
| 2613 | + } else { |
| 2614 | + id->number.presentation = AST_PRES_ALLOWED; |
| 2615 | + id->name.presentation = AST_PRES_ALLOWED; |
| 2616 | + } |
| 2617 | + if (screen && !pj_stricmp2(&screen->value, "yes")) { |
| 2618 | + id->number.presentation |= AST_PRES_USER_NUMBER_PASSED_SCREEN; |
| 2619 | + id->name.presentation |= AST_PRES_USER_NUMBER_PASSED_SCREEN; |
| 2620 | + } else { |
| 2621 | + id->number.presentation |= AST_PRES_USER_NUMBER_UNSCREENED; |
| 2622 | + id->name.presentation |= AST_PRES_USER_NUMBER_UNSCREENED; |
| 2623 | + } |
| 2624 | + |
| 2625 | + return 0; |
| 2626 | +} |
| 2627 | + |
| 2628 | +/*! |
| 2629 | + * \internal |
| 2630 | + * \brief Set an ast_party_id structure based on data in a From |
| 2631 | + * |
| 2632 | + * This makes use of \ref set_id_from_hdr for setting name and number. It uses |
| 2633 | + * no information from the message in order to set privacy. It relies on endpoint |
| 2634 | + * configuration for privacy information. |
| 2635 | + * |
| 2636 | + * \param rdata The incoming message |
| 2637 | + * \param[out] id The ID to set |
| 2638 | + * \retval 0 Succesfully set the party ID |
| 2639 | + * \retval non-zero Could not set the party ID |
| 2640 | + */ |
| 2641 | +static int set_id_from_from(struct pjsip_rx_data *rdata, struct ast_party_id *id) |
| 2642 | +{ |
| 2643 | + pjsip_fromto_hdr *from = pjsip_msg_find_hdr(rdata->msg_info.msg, |
| 2644 | + PJSIP_H_FROM, rdata->msg_info.msg->hdr.next); |
| 2645 | + |
| 2646 | + if (!from) { |
| 2647 | + /* This had better not happen */ |
| 2648 | + return -1; |
| 2649 | + } |
| 2650 | + |
| 2651 | + set_id_from_hdr(from, id); |
| 2652 | + |
| 2653 | + if (!id->number.valid) { |
| 2654 | + return -1; |
| 2655 | + } |
| 2656 | + |
| 2657 | + return 0; |
| 2658 | +} |
| 2659 | + |
| 2660 | +int ast_sip_set_id_connected_line(struct pjsip_rx_data *rdata, struct ast_party_id *id) |
| 2661 | +{ |
| 2662 | + return !set_id_from_pai(rdata, id) || !set_id_from_rpid(rdata, id) ? 0 : -1; |
| 2663 | +} |
| 2664 | + |
| 2665 | +int ast_sip_set_id_from_invite(struct pjsip_rx_data *rdata, struct ast_party_id *id, struct ast_party_id *default_id, int trust_inbound) |
| 2666 | +{ |
| 2667 | + if (trust_inbound && (!set_id_from_pai(rdata, id) || !set_id_from_rpid(rdata, id))) { |
| 2668 | + /* Trusted: Check PAI and RPID */ |
| 2669 | + ast_free(id->tag); |
| 2670 | + id->tag = ast_strdup(default_id->tag); |
| 2671 | + return 0; |
| 2672 | + } |
| 2673 | + /* Not trusted: check the endpoint config or use From. */ |
| 2674 | + ast_party_id_copy(id, default_id); |
| 2675 | + if (!default_id->number.valid) { |
| 2676 | + set_id_from_from(rdata, id); |
| 2677 | + } |
| 2678 | + return 0; |
| 2679 | +} |
| 2680 | + |
2452 | 2681 | /*!
|
2453 | 2682 | * \brief Set name and number information on an identity header.
|
2454 | 2683 | *
|
|
0 commit comments