int
sip_platform_udp_channel_sendto (cpr_socket_t s, char *buf, uint32_t len,
                                 cpr_ip_addr_t *dst_ipaddr, uint16_t dst_port)
{
    static const char *fname = "sip_platform_udp_channel_sendto";
    ssize_t bytesSent;
    cpr_sockaddr_storage sock_addr;
    uint16_t       addr_len;
    cpr_ip_addr_t  dest_ip_addr;

    /*
     * Connect to remote address
     */
    dest_ip_addr = *dst_ipaddr;
    (void) sip_set_sockaddr(&sock_addr, af_family_connect, dest_ip_addr,
                            dst_port, &addr_len);


    /*
     * Check not exceeding max allowed payload size
     */
    if (len >= PKTBUF_SIZ) {
        CCSIP_DEBUG_ERROR(get_debug_string(DEBUG_UDP_PAYLOAD_TOO_LARGE),
                          fname, len, PKTBUF_SIZ);
        return SIP_ERROR;
    }

    while (len > 0) {
        bytesSent = cprSendTo(s, (void *)buf, (size_t)len, 0,
                              (cpr_sockaddr_t *)&sock_addr, addr_len);

        if ((bytesSent == SOCKET_ERROR) && (cpr_errno == CPR_ECONNREFUSED)) {
            /*
             * Will get socket error ECONNREFUSED after an ICMP message
             * resend the message
             */
            CCSIP_DEBUG_TASK(DEB_F_PREFIX"UDP send to error %d\n", DEB_F_PREFIX_ARGS(SIP_SOCK, fname), cpr_errno);
            bytesSent = cprSendTo(s, (void *)buf, (size_t)len, 0,
                                  (cpr_sockaddr_t *)&sock_addr, addr_len);
        }
        if (bytesSent == SOCKET_ERROR) {
            CCSIP_DEBUG_ERROR(get_debug_string(DEBUG_GENERAL_SYSTEMCALL_FAILED),
                              fname, "cprSendTo", cpr_errno);
            return SIP_ERROR;
        }

        len -= bytesSent;
        buf += bytesSent;
    }

    return SIP_OK;
}
int
sip_platform_udp_channel_listen (cpr_ip_mode_e ip_mode, cpr_socket_t *s,
                                 cpr_ip_addr_t *local_ipaddr,
                                 uint16_t local_port)
{
    static const char fname[] = "sip_platform_udp_channel_listen";
    cpr_sockaddr_storage sock_addr;
    uint16_t       addr_len;

    /*
     * If socket passed is is not INVALID_SOCKET close it first
     */

    if (*s != INVALID_SOCKET) {
        if (sipSocketClose(*s, FALSE) != CPR_SUCCESS) {
            CCSIP_DEBUG_ERROR(get_debug_string(DEBUG_GENERAL_SYSTEMCALL_FAILED),
                              fname, "sipSocketClose", cpr_errno);
        }
        sip_platform_task_reset_listen_socket(*s);
    }

    /*
     * Create a socket
     */
    if (ip_mode == CPR_IP_MODE_IPV6 ||
        ip_mode == CPR_IP_MODE_DUAL) {
        af_family_listen = AF_INET6;
    } else {
        af_family_listen = AF_INET;
    }

    *s = cprSocket(af_family_listen, SOCK_DGRAM, 0);
    if (*s == INVALID_SOCKET) {
        CCSIP_DEBUG_ERROR(get_debug_string(DEBUG_GENERAL_SYSTEMCALL_FAILED),
                          fname, "cprSocket unable to open socket", cpr_errno);
        if (ip_mode == CPR_IP_MODE_DUAL) {

            af_family_listen = AF_INET;
            CCSIP_DEBUG_TASK(DEB_F_PREFIX"Socket open failed for IPv6 using IPv4 address.",
                             DEB_F_PREFIX_ARGS(SIP_SDP, fname));

            *s = cprSocket(af_family_listen, SOCK_DGRAM, 0);
            if (*s == INVALID_SOCKET) {
                CCSIP_DEBUG_ERROR(get_debug_string(DEBUG_GENERAL_SYSTEMCALL_FAILED),
                              fname, "cprSocket unable to open socket for IPv4",
                                        cpr_errno);
                return SIP_ERROR;
            }
        }
    }

    (void) sip_set_sockaddr(&sock_addr, af_family_listen, *local_ipaddr,
                            local_port, &addr_len);

    if (cprBind(*s,  (cpr_sockaddr_t *)&sock_addr, addr_len) == CPR_FAILURE) {
        (void) sipSocketClose(*s, FALSE);
        *s = INVALID_SOCKET;
        CCSIP_DEBUG_ERROR(get_debug_string(DEBUG_GENERAL_SYSTEMCALL_FAILED),
                          fname, "cprBind", cpr_errno);
        return SIP_ERROR;
    }
    sip_platform_task_set_listen_socket(*s);

    return SIP_OK;
}
int
sip_platform_udp_channel_create (cpr_ip_mode_e ip_mode, cpr_socket_t *s,
                                 cpr_ip_addr_t *remote_ipaddr,
                                 uint16_t remote_port,
                                 uint32_t local_udp_port)
{
    static const char *fname = "sip_platform_udp_channel_create";
    cpr_sockaddr_storage sock_addr;
    uint16_t       addr_len;
    cpr_sockaddr_storage local_sock_addr;
    cpr_ip_addr_t local_signaladdr;

    int tos_dscp_val = 0; // set to default if there is no config. for dscp

    CPR_IP_ADDR_INIT(local_signaladdr);

    if (*s != INVALID_SOCKET) {
        (void) sipSocketClose(*s, FALSE);
    }

    if (ip_mode == CPR_IP_MODE_IPV6 ||
        ip_mode == CPR_IP_MODE_DUAL) {
        af_family_connect = AF_INET6;
    } else {
        af_family_connect = AF_INET;
    }
    /*
     * Create socket
     */
    *s = cprSocket(af_family_connect, SOCK_DGRAM, 0);
    if (*s == INVALID_SOCKET) {
        CCSIP_DEBUG_ERROR(get_debug_string(DEBUG_GENERAL_SYSTEMCALL_FAILED),
                          fname, "cprSocket unable to open socket",
                          cpr_errno);
        /* Try opening ipv4 socket */
        if (ip_mode == CPR_IP_MODE_DUAL) {

            CCSIP_DEBUG_TASK("%s: cprSocket Open failed for IPv6 trying IPv4",
                            fname);
            af_family_connect = AF_INET;
            *s = cprSocket(af_family_connect, SOCK_DGRAM, 0);
            if (*s == INVALID_SOCKET) {

                CCSIP_DEBUG_ERROR(get_debug_string(DEBUG_GENERAL_SYSTEMCALL_FAILED),
                              fname, "cprSocket unable to open AF_INET socket",
                             cpr_errno);
                return SIP_ERROR;
            }
        }
    }

    sip_config_get_net_device_ipaddr(&local_signaladdr);
    memset(&local_sock_addr, 0, sizeof(local_sock_addr));

    (void) sip_set_sockaddr(&local_sock_addr, af_family_connect, local_signaladdr, 0, &addr_len);
    CCSIP_DEBUG_REG_STATE(DEB_F_PREFIX"local_signaladdr.u.ip4=%x\n",
        DEB_F_PREFIX_ARGS(SIP_SDP, fname), local_signaladdr.u.ip4);

    if(cprBind(*s, (cpr_sockaddr_t *)&local_sock_addr, addr_len)){
       CCSIP_DEBUG_ERROR(SIP_F_PREFIX"UDP bind failed with errno %d\n", fname, cpr_errno);
       (void) sipSocketClose(*s, FALSE);
       *s = INVALID_SOCKET;
       return SIP_ERROR;
    }

    /*
     * Connect to remote address
     */
    (void) sip_set_sockaddr(&sock_addr, af_family_connect, *remote_ipaddr,
                            remote_port, &addr_len);

 /*   if (cprConnect(*s, (cpr_sockaddr_t *)&sock_addr, addr_len) == CPR_FAILURE) {
        CCSIP_DEBUG_ERROR(get_debug_string(DEBUG_GENERAL_SYSTEMCALL_FAILED),
                          fname, "cprConnect", cpr_errno);
        (void) sipSocketClose(*s, FALSE);
        *s = INVALID_SOCKET;
          return SIP_ERROR;
    }
*/
    // set IP tos/dscp value for SIP messaging
    config_get_value(CFGID_DSCP_FOR_CALL_CONTROL, (int *)&tos_dscp_val,
                     sizeof(tos_dscp_val));

    if (cprSetSockOpt(*s, SOL_IP, IP_TOS, (void *)&tos_dscp_val,
                      sizeof(tos_dscp_val)) == CPR_FAILURE) {
        // do NOT take hard action; just log the error and move on
        CCSIP_DEBUG_ERROR(SIP_F_PREFIX"Unable to set IP TOS %d on UDP socket. "
                          "cpr_errno = %d\n", fname, tos_dscp_val, cpr_errno);
    }
    return SIP_OK;
}
Ejemplo n.º 4
0
/*
 * sip_tls_create_connection()
 * Description : This routine is called is response to a create connection
 * request from SIP_SPI to SIP_TLS.
 *
 * Input : spi_msg - Pointer to sipSPIMessage_t containing the create conn
 * parameters.
 *        blocking - connection mode; FALSE - nonblock; TRUE - block
 *
 * Output : Nothing
 */
cpr_socket_t
sip_tls_create_connection (sipSPIMessage_t *spi_msg, boolean blocking,
        sec_level_t sec)
{
    const char fname[] = "sip_tls_create_connection";
    int idx;
    sipSPICreateConnection_t *create_msg;
    char ipaddr_str[MAX_IPADDR_STR_LEN];
    plat_soc_status_e ret;
    cpr_socket_t sock = INVALID_SOCKET;
    uint16_t sec_port = 0;
    plat_soc_connect_status_e conn_status;
    int tos_dscp_val = 0; // set to default if there is no config. for dscp
#ifdef IPV6_STACK_ENABLED
    int ip_mode = CPR_IP_MODE_IPV4;
#endif
    uint16_t af_listen = AF_INET6;
    cpr_sockaddr_storage sock_addr;
    uint16_t       addr_len;
    int ip_mode = 0; // currently hardcoded to ipv4
    plat_soc_connect_mode_e conn_mode;

#ifdef IPV6_STACK_ENABLED

    config_get_value(CFGID_IP_ADDR_MODE, &ip_mode, sizeof(ip_mode));

    /*
     * Create a socket
     */
    if (ip_mode == CPR_IP_MODE_IPV6 ||
        ip_mode == CPR_IP_MODE_DUAL) {
        af_listen = AF_INET6;
    } else {
#endif
        af_listen = AF_INET;
#ifdef IPV6_STACK_ENABLED
    }
#endif

    sip_tcp_init_conn_table();
    create_msg = &(spi_msg->createConnMsg);
    ipaddr2dotted(ipaddr_str, &create_msg->addr);
    ret = platSecIsServerSecure();
    if (ret != PLAT_SOCK_SECURE) {
        CCSIP_DEBUG_ERROR(SIP_F_PREFIX
                          "Secure connection is not created because"
                          " there is no secure servers\n", fname);
        return INVALID_SOCKET;
    }
    CCSIP_DEBUG_MESSAGE(DEB_F_PREFIX
                        "Creating secure connection\n", DEB_F_PREFIX_ARGS(SIP_TLS, fname));
    /* connect securely via TLS */
    config_get_value(CFGID_DSCP_FOR_CALL_CONTROL, (int *)&tos_dscp_val,
                     sizeof(tos_dscp_val));

    if (sec == AUTHENTICATED) {
        conn_mode = PLAT_SOCK_AUTHENTICATED;
    } else if (sec == ENCRYPTED) {
        conn_mode = PLAT_SOCK_ENCRYPTED;
    } else {
        CCSIP_DEBUG_ERROR(SIP_F_PREFIX
                          "Secure connection is not created. Security mode was"
                          " not encrypyted or authenticated.\n", fname);
        conn_mode = PLAT_SOCK_NON_SECURE;
    }
    sock = platSecSocConnect(ipaddr_str,          /* host  */
                            create_msg->port,    /* port */
                            ip_mode,             /* ip mode, ipv4 = 0, ipv6 = 1, dual = 2 */
                            blocking,            /* 1 - block  */
                            tos_dscp_val, /* TOS value  */
                            conn_mode,   /* The mode (Auth/Encry/None) */
                            &sec_port);          /* local port */

    if (sock < 0) {

        CCSIP_DEBUG_ERROR(SIP_F_PREFIX
                          "Secure connect failed!!\n",fname);
        return INVALID_SOCKET;
    }
    CCSIP_DEBUG_MESSAGE(DEB_F_PREFIX "Secure connect ok", DEB_F_PREFIX_ARGS(SIP_TLS, fname));
    if (!blocking) {
        /* should not call this api in blocking mode */
        conn_status = platSecSockIsConnected(sock);
        if (conn_status == PLAT_SOCK_CONN_FAILED) {
            (void)sipSocketClose(sock, TRUE);
            CCSIP_DEBUG_ERROR(SIP_F_PREFIX
                              "Establish non-blocking mode secure"
                              " connection failed!!\n", fname);
            return INVALID_SOCKET;
        }
    } else {
        conn_status = PLAT_SOCK_CONN_OK;
    }
    if (sip_tcp_set_sock_options(sock) != TRUE) {
        CCSIP_DEBUG_ERROR(SIP_F_PREFIX "Socket set option failure",
                          fname);
    }

    idx = sip_tcp_get_free_conn_entry();
    if (idx == -1) {
        /* Send create connection failed message to SIP_SPI */
        (void)sipSocketClose(sock, TRUE);
        CCSIP_DEBUG_ERROR(SIP_F_PREFIX
                          "Get free TCP connection entry failed\n",
                           fname);
        return INVALID_SOCKET;
    }

    memset(&sock_addr, 0, sizeof(sock_addr));
    (void) sip_set_sockaddr(&sock_addr, af_listen, create_msg->addr,
                            (uint16_t)(create_msg->port), &addr_len);

    sip_tcp_conn_tab[idx].fd = sock;
    sip_tcp_conn_tab[idx].ipaddr = create_msg->addr;
    sip_tcp_conn_tab[idx].port = create_msg->port;
    sip_tcp_conn_tab[idx].context = spi_msg->context;
    sip_tcp_conn_tab[idx].dirtyFlag = FALSE;
    sip_tcp_conn_tab[idx].addr = sock_addr;
    sip_tcp_conn_tab[idx].soc_type = SIP_SOC_TLS;

    if (conn_status == PLAT_SOCK_CONN_OK) {
        sip_tcp_conn_tab[idx].state = SOCK_CONNECTED;
    } else {
        sip_tcp_conn_tab[idx].state = SOCK_CONNECT_PENDING;
    }
    create_msg->local_listener_port = (uint16) sec_port;
    CCSIP_DEBUG_MESSAGE(DEB_F_PREFIX
                        "Local listening port=%d\n", DEB_F_PREFIX_ARGS(SIP_TLS, fname),
                        create_msg->local_listener_port);
    (void)sip_tcp_attach_socket(sock);
    return (sock);
}