LCOV - code coverage report
Current view: top level - media/webrtc/signaling/src/sdp/sipcc - sdp_token.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 922 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 31 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* This Source Code Form is subject to the terms of the Mozilla Public
       2             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       3             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       4             : 
       5             : #include <errno.h>
       6             : 
       7             : #include "sdp_os_defs.h"
       8             : #include "sdp.h"
       9             : #include "sdp_private.h"
      10             : 
      11             : #include "CSFLog.h"
      12             : #include "prprf.h"
      13             : 
      14             : static const char *logTag = "sdp_token";
      15             : 
      16             : #define MCAST_STRING_LEN 4
      17             : 
      18             : 
      19           0 : sdp_result_e sdp_parse_version (sdp_t *sdp_p, uint16_t level, const char *ptr)
      20             : {
      21           0 :     sdp_result_e result = SDP_FAILURE;
      22             : 
      23           0 :     sdp_p->version = (uint16_t)sdp_getnextnumtok(ptr, &ptr, " \t", &result);
      24           0 :     if ((result != SDP_SUCCESS) || (sdp_p->version != SDP_CURRENT_VERSION)) {
      25           0 :         sdp_parse_error(sdp_p,
      26             :             "%s Invalid version (%u) found, parse failed.",
      27           0 :             sdp_p->debug_str, (unsigned)sdp_p->version);
      28           0 :         sdp_p->conf_p->num_invalid_param++;
      29           0 :         return (SDP_INVALID_PARAMETER);
      30             :     }
      31             : 
      32           0 :     if (sdp_p->debug_flag[SDP_DEBUG_TRACE]) {
      33           0 :         SDP_PRINT("%s Parse version line successful, version %u",
      34             :                   sdp_p->debug_str, (unsigned)sdp_p->version);
      35             :     }
      36           0 :     return (SDP_SUCCESS);
      37             : }
      38             : 
      39           0 : sdp_result_e sdp_build_version (sdp_t *sdp_p, uint16_t level, flex_string *fs)
      40             : {
      41           0 :     if (sdp_p->version == SDP_INVALID_VALUE) {
      42           0 :         if (sdp_p->conf_p->version_reqd == TRUE) {
      43           0 :             CSFLogError(logTag, "%s Invalid version for v= line, "
      44             :                         "build failed.", sdp_p->debug_str);
      45           0 :             sdp_p->conf_p->num_invalid_param++;
      46           0 :             return (SDP_INVALID_PARAMETER);
      47             :         } else {
      48             :             /* v= line is not required. */
      49           0 :             return (SDP_SUCCESS);
      50             :         }
      51             :     }
      52             : 
      53           0 :     flex_string_sprintf(fs, "v=%u\r\n", (unsigned)sdp_p->version);
      54             : 
      55           0 :     if (sdp_p->debug_flag[SDP_DEBUG_TRACE]) {
      56           0 :         SDP_PRINT("%s Built v= version line", sdp_p->debug_str);
      57             :     }
      58           0 :     return (SDP_SUCCESS);
      59             : }
      60             : 
      61           0 : static sdp_result_e sdp_verify_unsigned(const char *ptr, uint64_t max_value)
      62             : {
      63             :     uint64_t numeric_value;
      64             :     /* Checking for only numbers since PR_sscanf will ignore trailing
      65             :        characters */
      66           0 :     size_t end = strspn(ptr, "0123456789");
      67             : 
      68           0 :     if (ptr[end] != '\0')
      69           0 :         return SDP_INVALID_PARAMETER;
      70             : 
      71           0 :     if (PR_sscanf(ptr, "%llu", &numeric_value) != 1)
      72           0 :         return SDP_INVALID_PARAMETER;
      73             : 
      74           0 :     if (numeric_value > max_value)
      75           0 :         return SDP_INVALID_PARAMETER;
      76             : 
      77           0 :     return SDP_SUCCESS;
      78             : }
      79             : 
      80           0 : sdp_result_e sdp_parse_owner (sdp_t *sdp_p, uint16_t level, const char *ptr)
      81             : {
      82             :     int          i;
      83             :     sdp_result_e result;
      84             :     char         tmp[SDP_MAX_STRING_LEN];
      85             :     /* The spec says this:
      86             : 
      87             :         The numeric value of the session id
      88             :         and version in the o line MUST be representable with a 64 bit signed
      89             :         integer.  The initial value of the version MUST be less than
      90             :         (2**62)-1, to avoid rollovers.
      91             :     */
      92           0 :     const uint64_t max_value_sessid = ((((uint64_t) 1) << 63) - 1);
      93             :     /* Do not check that this is 2^62 - 1; that's just the limit on
      94             :      * the initial version, not every version number. */
      95           0 :     const uint64_t max_value_version = ((((uint64_t) 1) << 63) - 1);
      96             : 
      97           0 :     if (sdp_p->owner_name[0] != '\0') {
      98           0 :         sdp_p->conf_p->num_invalid_token_order++;
      99           0 :         sdp_parse_error(sdp_p,
     100             :             "%s Warning: More than one o= line specified.",
     101           0 :             sdp_p->debug_str);
     102             :     }
     103             : 
     104             :     /* Find the owner name. */
     105           0 :     ptr = sdp_getnextstrtok(ptr, sdp_p->owner_name, sizeof(sdp_p->owner_name), " \t", &result);
     106           0 :     if (result != SDP_SUCCESS) {
     107           0 :         sdp_parse_error(sdp_p,
     108             :             "%s No owner name specified for o=.",
     109           0 :             sdp_p->debug_str);
     110           0 :         sdp_p->conf_p->num_invalid_param++;
     111           0 :         return (SDP_INVALID_PARAMETER);
     112             :     }
     113             : 
     114             :     /* Find the owner session id.  This is a numeric field but is
     115             :      * stored as a string since it may be 64 bit.
     116             :      */
     117           0 :     ptr = sdp_getnextstrtok(ptr, sdp_p->owner_sessid, sizeof(sdp_p->owner_sessid), " \t", &result);
     118           0 :     if (result == SDP_SUCCESS) {
     119             :         /* Make sure the sessid is numeric, even though we store it as
     120             :          * a string.
     121             :          */
     122           0 :         result = sdp_verify_unsigned(sdp_p->owner_sessid, max_value_sessid);
     123             :     }
     124           0 :     if (result != SDP_SUCCESS) {
     125           0 :         sdp_parse_error(sdp_p,
     126             :             "%s Invalid owner session id specified for o=.",
     127           0 :             sdp_p->debug_str);
     128           0 :         sdp_p->conf_p->num_invalid_param++;
     129           0 :         return (SDP_INVALID_PARAMETER);
     130             :     }
     131             : 
     132             :     /* Find the owner version. */
     133           0 :     ptr = sdp_getnextstrtok(ptr, sdp_p->owner_version, sizeof(sdp_p->owner_version), " \t", &result);
     134           0 :     if (result == SDP_SUCCESS) {
     135             :         /* Make sure the version is numeric, even though we store it as
     136             :          * a string.
     137             :          */
     138           0 :         result = sdp_verify_unsigned(sdp_p->owner_version, max_value_version);
     139             :     }
     140           0 :     if (result != SDP_SUCCESS) {
     141           0 :         sdp_parse_error(sdp_p,
     142             :             "%s Invalid owner version specified for o=.",
     143           0 :             sdp_p->debug_str);
     144           0 :         sdp_p->conf_p->num_invalid_param++;
     145           0 :         return (SDP_INVALID_PARAMETER);
     146             :     }
     147             : 
     148             :     /* Find the owner network type. */
     149           0 :     ptr = sdp_getnextstrtok(ptr, tmp, sizeof(tmp), " \t", &result);
     150           0 :     if (result != SDP_SUCCESS) {
     151           0 :         sdp_parse_error(sdp_p,
     152             :             "%s No owner network type specified for o=.",
     153           0 :             sdp_p->debug_str);
     154           0 :         sdp_p->conf_p->num_invalid_param++;
     155           0 :         return (SDP_INVALID_PARAMETER);
     156             :     }
     157           0 :     sdp_p->owner_network_type = SDP_NT_UNSUPPORTED;
     158           0 :     for (i=0; i < SDP_MAX_NETWORK_TYPES; i++) {
     159           0 :         if (cpr_strncasecmp(tmp, sdp_nettype[i].name,
     160           0 :                         sdp_nettype[i].strlen) == 0) {
     161           0 :             if (sdp_p->conf_p->nettype_supported[i] == TRUE) {
     162           0 :                 sdp_p->owner_network_type = (sdp_nettype_e)i;
     163             :             }
     164             :         }
     165             :     }
     166           0 :     if (sdp_p->owner_network_type == SDP_NT_UNSUPPORTED) {
     167           0 :         sdp_parse_error(sdp_p,
     168             :             "%s Owner network type unsupported (%s)",
     169           0 :             sdp_p->debug_str, tmp);
     170           0 :         sdp_p->conf_p->num_invalid_param++;
     171           0 :         return (SDP_INVALID_PARAMETER);
     172             :     }
     173             : 
     174             :     /* Find the owner address type. */
     175           0 :     ptr = sdp_getnextstrtok(ptr, tmp, sizeof(tmp), " \t", &result);
     176           0 :     if (result != SDP_SUCCESS) {
     177           0 :         sdp_parse_error(sdp_p,
     178             :             "%s No owner address type specified for o=.",
     179           0 :             sdp_p->debug_str);
     180           0 :         sdp_p->conf_p->num_invalid_param++;
     181           0 :         return (SDP_INVALID_PARAMETER);
     182             :     }
     183           0 :     sdp_p->owner_addr_type = SDP_AT_UNSUPPORTED;
     184           0 :     for (i=0; i < SDP_MAX_ADDR_TYPES; i++) {
     185           0 :         if (cpr_strncasecmp(tmp, sdp_addrtype[i].name,
     186           0 :                         sdp_addrtype[i].strlen) == 0) {
     187           0 :             if (sdp_p->conf_p->addrtype_supported[i] == TRUE) {
     188           0 :                 sdp_p->owner_addr_type = (sdp_addrtype_e)i;
     189             :             }
     190             :         }
     191             :     }
     192           0 :     if ((sdp_p->owner_addr_type == SDP_AT_UNSUPPORTED) &&
     193           0 :         (sdp_p->owner_network_type != SDP_NT_ATM)) {
     194           0 :         sdp_parse_error(sdp_p,
     195             :             "%s Owner address type unsupported (%s)",
     196           0 :             sdp_p->debug_str, tmp);
     197           0 :         sdp_p->conf_p->num_invalid_param++;
     198           0 :         return (SDP_INVALID_PARAMETER);
     199             :     }
     200             : 
     201             :     /* Find the owner address. */
     202           0 :     ptr = sdp_getnextstrtok(ptr, sdp_p->owner_addr, sizeof(sdp_p->owner_addr), " \t", &result);
     203           0 :     if (result != SDP_SUCCESS) {
     204           0 :         sdp_parse_error(sdp_p,
     205           0 :             "%s No owner address specified.", sdp_p->debug_str);
     206           0 :         sdp_p->conf_p->num_invalid_param++;
     207           0 :         return (SDP_INVALID_PARAMETER);
     208             :     }
     209             : 
     210           0 :     if (sdp_p->debug_flag[SDP_DEBUG_TRACE]) {
     211           0 :         SDP_PRINT("%s Parse owner: name %s, session id %s, version %s",
     212             :                   sdp_p->debug_str, sdp_p->owner_name, sdp_p->owner_sessid,
     213             :                   sdp_p->owner_version);
     214           0 :         SDP_PRINT("%s              network %s, address type %s, "
     215             :                   "address %s", sdp_p->debug_str,
     216             :                   sdp_get_network_name(sdp_p->owner_network_type),
     217             :                   sdp_get_address_name(sdp_p->owner_addr_type),
     218             :                   sdp_p->owner_addr);
     219             :     }
     220           0 :     return (SDP_SUCCESS);
     221             : }
     222             : 
     223           0 : sdp_result_e sdp_build_owner (sdp_t *sdp_p, uint16_t level, flex_string *fs)
     224             : {
     225           0 :     if ((sdp_p->owner_name[0] == '\0') ||
     226           0 :         (sdp_p->owner_network_type >= SDP_MAX_NETWORK_TYPES) ||
     227           0 :         (sdp_p->owner_addr_type >= SDP_MAX_ADDR_TYPES) ||
     228           0 :         (sdp_p->owner_addr[0] == '\0')) {
     229             : 
     230           0 :         if((sdp_p->owner_network_type == SDP_NT_ATM) &&
     231           0 :            (sdp_p->owner_addr_type == SDP_AT_INVALID)) {
     232           0 :           flex_string_sprintf(fs, "o=%s %s %s %s - -\r\n",
     233           0 :                     sdp_p->owner_name, sdp_p->owner_sessid,
     234           0 :                     sdp_p->owner_version,
     235             :                     sdp_get_network_name(sdp_p->owner_network_type));
     236             :         }
     237             : 
     238           0 :         if (sdp_p->conf_p->owner_reqd == TRUE) {
     239           0 :             CSFLogError(logTag, "%s Invalid params for o= owner line, "
     240             :                         "build failed.", sdp_p->debug_str);
     241           0 :             sdp_p->conf_p->num_invalid_param++;
     242           0 :             return (SDP_INVALID_PARAMETER);
     243             :         } else {
     244             :             /* o= line is not required. */
     245           0 :             return (SDP_SUCCESS);
     246             :         }
     247             :     }
     248             : 
     249           0 :     flex_string_sprintf(fs, "o=%s %s %s %s %s %s\r\n",
     250           0 :                     sdp_p->owner_name, sdp_p->owner_sessid,
     251           0 :                     sdp_p->owner_version,
     252             :                     sdp_get_network_name(sdp_p->owner_network_type),
     253             :                     sdp_get_address_name(sdp_p->owner_addr_type),
     254           0 :                     sdp_p->owner_addr);
     255             : 
     256           0 :     if (sdp_p->debug_flag[SDP_DEBUG_TRACE]) {
     257           0 :         SDP_PRINT("%s Built o= owner line", sdp_p->debug_str);
     258             :     }
     259           0 :     return (SDP_SUCCESS);
     260             : }
     261             : 
     262           0 : sdp_result_e sdp_parse_sessname (sdp_t *sdp_p, uint16_t level, const char *ptr)
     263             : {
     264             :     int   str_len;
     265             :     char *endptr;
     266             : 
     267           0 :     if (sdp_p->sessname[0] != '\0') {
     268           0 :         sdp_p->conf_p->num_invalid_token_order++;
     269           0 :         sdp_parse_error(sdp_p,
     270             :             "%s Warning: More than one s= line specified.",
     271           0 :             sdp_p->debug_str);
     272             :     }
     273             : 
     274           0 :     endptr = sdp_findchar(ptr, "\r\n");
     275           0 :     if (ptr == endptr) {
     276           0 :         sdp_parse_error(sdp_p,
     277             :             "%s Warning: No session name specified.",
     278           0 :             sdp_p->debug_str);
     279             :     }
     280           0 :     str_len = MIN(endptr - ptr, SDP_MAX_STRING_LEN);
     281           0 :     sstrncpy(sdp_p->sessname, ptr, str_len+1);
     282             : 
     283           0 :     if (sdp_p->debug_flag[SDP_DEBUG_TRACE]) {
     284           0 :         SDP_PRINT("%s Parse session name, %s",
     285             :                   sdp_p->debug_str, sdp_p->sessname);
     286             :     }
     287           0 :     return (SDP_SUCCESS);
     288             : }
     289             : 
     290           0 : sdp_result_e sdp_build_sessname (sdp_t *sdp_p, uint16_t level, flex_string *fs)
     291             : {
     292           0 :     if (sdp_p->sessname[0] == '\0') {
     293           0 :         if (sdp_p->conf_p->session_name_reqd == TRUE) {
     294           0 :             CSFLogError(logTag, "%s No param defined for s= session name line, "
     295             :                         "build failed.", sdp_p->debug_str);
     296           0 :             sdp_p->conf_p->num_invalid_param++;
     297           0 :             return (SDP_INVALID_PARAMETER);
     298             :         } else {
     299             :             /* s= line is not required. */
     300           0 :             return (SDP_SUCCESS);
     301             :         }
     302             :     }
     303             : 
     304           0 :     flex_string_sprintf(fs, "s=%s\r\n", sdp_p->sessname);
     305             : 
     306           0 :     if (sdp_p->debug_flag[SDP_DEBUG_TRACE]) {
     307           0 :         SDP_PRINT("%s Built s= session name line", sdp_p->debug_str);
     308             :     }
     309           0 :     return (SDP_SUCCESS);
     310             : }
     311             : 
     312             : /* We don't want to store the session info, but we do want to validate
     313             :  * that at most one i= line exists at each level and if the line exists
     314             :  * there should be a parameter.
     315             :  */
     316           0 : sdp_result_e sdp_parse_sessinfo (sdp_t *sdp_p, uint16_t level, const char *ptr)
     317             : {
     318             :     char *endptr;
     319             :     sdp_mca_t *mca_p;
     320             : 
     321           0 :     if (level == SDP_SESSION_LEVEL) {
     322           0 :         if (sdp_p->sessinfo_found == TRUE) {
     323           0 :             sdp_p->conf_p->num_invalid_token_order++;
     324           0 :             sdp_parse_error(sdp_p,
     325             :                 "%s Warning: More than one i= line specified.",
     326           0 :                 sdp_p->debug_str);
     327             :         }
     328           0 :         sdp_p->sessinfo_found = TRUE;
     329             :     } else {
     330           0 :         mca_p = sdp_find_media_level(sdp_p, level);
     331           0 :         if (mca_p == NULL) {
     332           0 :             return (SDP_FAILURE);
     333             :         }
     334           0 :         if (mca_p->sessinfo_found == TRUE) {
     335           0 :             sdp_p->conf_p->num_invalid_token_order++;
     336           0 :             sdp_parse_error(sdp_p,
     337             :                 "%s Warning: More than one i= line specified"
     338           0 :                 " for media line %u.", sdp_p->debug_str, (unsigned)level);
     339             :         }
     340           0 :         mca_p->sessinfo_found = TRUE;
     341             :     }
     342             : 
     343           0 :     endptr = sdp_findchar(ptr, "\n");
     344           0 :     if (ptr == endptr) {
     345           0 :         sdp_parse_error(sdp_p,
     346             :             "%s Warning: No session info specified.",
     347           0 :             sdp_p->debug_str);
     348             :     }
     349             : 
     350           0 :     if (sdp_p->debug_flag[SDP_DEBUG_TRACE]) {
     351           0 :         SDP_PRINT("%s Parsed session info line.", sdp_p->debug_str);
     352             :     }
     353           0 :     return (SDP_SUCCESS);
     354             : }
     355             : 
     356           0 : sdp_result_e sdp_build_sessinfo (sdp_t *sdp_p, uint16_t level, flex_string *fs)
     357             : {
     358             :     /* Build session info line not supported. */
     359           0 :     return (SDP_SUCCESS);
     360             : }
     361             : 
     362           0 : sdp_result_e sdp_parse_uri (sdp_t *sdp_p, uint16_t level, const char *ptr)
     363             : {
     364             :     char *endptr;
     365             : 
     366           0 :     if (sdp_p->uri_found == TRUE) {
     367           0 :         sdp_p->conf_p->num_invalid_token_order++;
     368           0 :         sdp_parse_error(sdp_p,
     369             :             "%s Warning: More than one u= line specified.",
     370           0 :             sdp_p->debug_str);
     371             :     }
     372           0 :     sdp_p->uri_found = TRUE;
     373             : 
     374           0 :     endptr = sdp_findchar(ptr, "\n");
     375           0 :     if (ptr == endptr) {
     376           0 :         sdp_parse_error(sdp_p,
     377           0 :             "%s Warning: No URI info specified.", sdp_p->debug_str);
     378             :     }
     379             : 
     380           0 :     if (sdp_p->debug_flag[SDP_DEBUG_TRACE]) {
     381           0 :         SDP_PRINT("%s Parsed URI line.", sdp_p->debug_str);
     382             :     }
     383           0 :     return (SDP_SUCCESS);
     384             : }
     385             : 
     386           0 : sdp_result_e sdp_build_uri (sdp_t *sdp_p, uint16_t level, flex_string *fs)
     387             : {
     388             :     /* Build URI line not supported. */
     389           0 :     return (SDP_SUCCESS);
     390             : }
     391             : 
     392           0 : sdp_result_e sdp_parse_email (sdp_t *sdp_p, uint16_t level, const char *ptr)
     393             : {
     394             :     char *endptr;
     395             : 
     396           0 :     endptr = sdp_findchar(ptr, "\n");
     397           0 :     if (ptr == endptr) {
     398           0 :         sdp_parse_error(sdp_p,
     399           0 :             "%s Warning: No email info specified.", sdp_p->debug_str);
     400             :     }
     401             : 
     402           0 :     if (sdp_p->debug_flag[SDP_DEBUG_TRACE]) {
     403           0 :         SDP_PRINT("%s Parse email line", sdp_p->debug_str);
     404             :     }
     405           0 :     return (SDP_SUCCESS);
     406             : }
     407             : 
     408           0 : sdp_result_e sdp_build_email (sdp_t *sdp_p, uint16_t level, flex_string *fs)
     409             : {
     410             :     /* Build email line not supported. */
     411           0 :     return (SDP_SUCCESS);
     412             : }
     413             : 
     414           0 : sdp_result_e sdp_parse_phonenum (sdp_t *sdp_p, uint16_t level, const char *ptr)
     415             : {
     416             :     char *endptr;
     417             : 
     418           0 :     endptr = sdp_findchar(ptr, "\n");
     419           0 :     if (ptr == endptr) {
     420           0 :         sdp_parse_error(sdp_p,
     421             :             "%s Warning: No phone number info specified.",
     422           0 :             sdp_p->debug_str);
     423             :     }
     424             : 
     425           0 :     if (sdp_p->debug_flag[SDP_DEBUG_TRACE]) {
     426           0 :         SDP_PRINT("%s Parse phone number line", sdp_p->debug_str);
     427             :     }
     428           0 :     return (SDP_SUCCESS);
     429             : }
     430             : 
     431           0 : sdp_result_e sdp_build_phonenum (sdp_t *sdp_p, uint16_t level, flex_string *fs)
     432             : {
     433             :     /* Build phone number line not supported. */
     434           0 :     return (SDP_SUCCESS);
     435             : }
     436             : 
     437           0 : sdp_result_e sdp_parse_connection (sdp_t *sdp_p, uint16_t level, const char *ptr)
     438             : {
     439             :     int           i;
     440             :     const char   *slash_ptr;
     441             :     sdp_result_e  result;
     442             :     sdp_conn_t   *conn_p;
     443             :     sdp_mca_t    *mca_p;
     444             :     char          tmp[SDP_MAX_STRING_LEN];
     445             :     char mcast_str[MCAST_STRING_LEN];
     446             :     int  mcast_bits;
     447             :     unsigned long strtoul_result;
     448             :     char *strtoul_end;
     449             : 
     450           0 :     if (level == SDP_SESSION_LEVEL) {
     451           0 :         conn_p = &(sdp_p->default_conn);
     452             :     } else {
     453           0 :         mca_p = sdp_find_media_level(sdp_p, level);
     454           0 :         if (mca_p == NULL) {
     455           0 :             return (SDP_FAILURE);
     456             :         }
     457           0 :         conn_p = &(mca_p->conn);
     458             :     }
     459             : 
     460             :     /* See if the c= line is already defined at this level. We don't
     461             :      * currently support multihoming and so we only support one c= at
     462             :      * each level.
     463             :      */
     464           0 :     if (conn_p->nettype != SDP_NT_INVALID) {
     465           0 :         sdp_p->conf_p->num_invalid_token_order++;
     466           0 :         sdp_parse_error(sdp_p,
     467             :             "%s c= line specified twice at same level, "
     468           0 :             "parse failed.", sdp_p->debug_str);
     469           0 :         return (SDP_INVALID_TOKEN_ORDERING);
     470             :     }
     471             : 
     472             :     /* Find the connection network type. */
     473           0 :     ptr = sdp_getnextstrtok(ptr, tmp, sizeof(tmp), " \t", &result);
     474           0 :     if (result != SDP_SUCCESS) {
     475           0 :         sdp_parse_error(sdp_p,
     476             :             "%s No connection network type specified for c=.",
     477           0 :             sdp_p->debug_str);
     478           0 :         sdp_p->conf_p->num_invalid_param++;
     479           0 :         return (SDP_INVALID_PARAMETER);
     480             :     }
     481           0 :     conn_p->nettype = SDP_NT_UNSUPPORTED;
     482           0 :     for (i=0; i < SDP_MAX_NETWORK_TYPES; i++) {
     483           0 :         if (cpr_strncasecmp(tmp, sdp_nettype[i].name,
     484           0 :                         sdp_nettype[i].strlen) == 0) {
     485           0 :             if (sdp_p->conf_p->nettype_supported[i] == TRUE) {
     486           0 :                 conn_p->nettype = (sdp_nettype_e)i;
     487             :             }
     488             :         }
     489             :     }
     490           0 :     if (conn_p->nettype == SDP_NT_UNSUPPORTED) {
     491           0 :         sdp_parse_error(sdp_p,
     492             :             "%s Warning: Connection network type unsupported "
     493           0 :             "(%s) for c=.", sdp_p->debug_str, tmp);
     494             :     }
     495             : 
     496             :     /* Find the connection address type. */
     497           0 :     ptr = sdp_getnextstrtok(ptr, tmp, sizeof(tmp), " \t", &result);
     498           0 :     if (result != SDP_SUCCESS) {
     499           0 :         if (conn_p->nettype == SDP_NT_ATM) {
     500             :             /* If the nettype is ATM, addr type and addr are not reqd */
     501           0 :             if (sdp_p->debug_flag[SDP_DEBUG_TRACE]) {
     502           0 :                 SDP_PRINT("%s Parse connection: network %s", sdp_p->debug_str,
     503             :                           sdp_get_network_name(conn_p->nettype));
     504             :             }
     505           0 :             return (SDP_SUCCESS);
     506             :         } else {
     507           0 :             sdp_parse_error(sdp_p,
     508             :                 "%s No connection address type specified for "
     509           0 :                 "c=.", sdp_p->debug_str);
     510           0 :             sdp_p->conf_p->num_invalid_param++;
     511           0 :             return (SDP_INVALID_PARAMETER);
     512             :         }
     513             :     }
     514           0 :     conn_p->addrtype = SDP_AT_UNSUPPORTED;
     515           0 :     for (i=0; i < SDP_MAX_ADDR_TYPES; i++) {
     516           0 :         if (cpr_strncasecmp(tmp, sdp_addrtype[i].name,
     517           0 :                         sdp_addrtype[i].strlen) == 0) {
     518           0 :             if (sdp_p->conf_p->addrtype_supported[i] == TRUE) {
     519           0 :                 conn_p->addrtype = (sdp_addrtype_e)i;
     520             :             }
     521             :         }
     522             :     }
     523           0 :     if (conn_p->addrtype == SDP_AT_UNSUPPORTED) {
     524           0 :         sdp_parse_error(sdp_p,
     525             :             "%s Warning: Connection address type unsupported "
     526           0 :             "(%s) for c=.", sdp_p->debug_str, tmp);
     527             :     }
     528             : 
     529             :     /* Find the connection address. */
     530           0 :     ptr = sdp_getnextstrtok(ptr, conn_p->conn_addr, sizeof(conn_p->conn_addr), " \t", &result);
     531           0 :     if (result != SDP_SUCCESS) {
     532           0 :         sdp_parse_error(sdp_p,
     533             :             "%s No connection address specified for c=.",
     534           0 :             sdp_p->debug_str);
     535           0 :         sdp_p->conf_p->num_invalid_param++;
     536           0 :         return (SDP_INVALID_PARAMETER);
     537             :     }
     538             :     /* We currently only support addrs containing '/'s for EPN addrs.
     539             :      * For other addrs this would indicate multicast addrs. */
     540             :     /* Multicast host group addresses are defined to be the IP addresses
     541             :      * whose high-order four bits are 1110, giving an address range from
     542             :      * 224.0.0.0 through 239.255.255.255
     543             :      */
     544             :     /* multicast addr check */
     545           0 :     sstrncpy (mcast_str, conn_p->conn_addr, MCAST_STRING_LEN);
     546             : 
     547           0 :     if (conn_p->addrtype == SDP_AT_IP4) {
     548           0 :         errno = 0;
     549           0 :         strtoul_result = strtoul(mcast_str, &strtoul_end, 10);
     550             : 
     551           0 :         if (errno || mcast_str == strtoul_end || strtoul_result > 255) {
     552           0 :             sdp_parse_error(sdp_p,
     553             :                             "%s Error parsing address %s for mcast.",
     554           0 :                             sdp_p->debug_str, mcast_str);
     555           0 :             sdp_p->conf_p->num_invalid_param++;
     556           0 :             return SDP_INVALID_PARAMETER;
     557             :         }
     558             : 
     559             : 
     560           0 :         mcast_bits = (int) strtoul_result;
     561           0 :         if ((mcast_bits >= SDP_MIN_MCAST_ADDR_HI_BIT_VAL ) &&
     562             :             (mcast_bits <= SDP_MAX_MCAST_ADDR_HI_BIT_VAL)) {
     563           0 :             SDP_PRINT("%s Parsed to be a multicast address with mcast bits %d",
     564             :                       sdp_p->debug_str, mcast_bits);
     565           0 :             conn_p->is_multicast = TRUE;
     566             :         }
     567             :     }
     568             : 
     569           0 :     if (conn_p->addrtype != SDP_AT_EPN) {
     570           0 :         slash_ptr = sdp_findchar(conn_p->conn_addr, "/");
     571           0 :         if (slash_ptr[0] != '\0') {
     572             :             /* this used to rely on the above busted multicast check */
     573           0 :             SDP_PRINT("%s An address with slash %s",
     574             :                       sdp_p->debug_str, conn_p->conn_addr);
     575           0 :             conn_p->conn_addr[slash_ptr - conn_p->conn_addr] = '\0';
     576           0 :             slash_ptr++;
     577           0 :             slash_ptr = sdp_getnextstrtok(slash_ptr, tmp, sizeof(tmp),
     578             :                                           "/", &result);
     579           0 :             if (result != SDP_SUCCESS) {
     580           0 :                 sdp_parse_error(sdp_p,
     581             :                                 "%s No ttl value specified for this multicast addr with a slash",
     582           0 :                                 sdp_p->debug_str);
     583           0 :                 sdp_p->conf_p->num_invalid_param++;
     584           0 :                 return (SDP_INVALID_PARAMETER);
     585             :             }
     586             : 
     587           0 :             errno = 0;
     588           0 :             strtoul_result = strtoul(tmp, &strtoul_end, 10);
     589             : 
     590           0 :             if (errno || tmp == strtoul_end || conn_p->ttl > SDP_MAX_TTL_VALUE) {
     591           0 :                 sdp_parse_error(sdp_p,
     592             :                                 "%s Invalid TTL: Value must be in the range 0-255 ",
     593           0 :                                 sdp_p->debug_str);
     594           0 :                 sdp_p->conf_p->num_invalid_param++;
     595           0 :                 return (SDP_INVALID_PARAMETER);
     596             :             }
     597             : 
     598           0 :             conn_p->ttl = (int) strtoul_result;
     599             : 
     600             :             /* search for num of addresses */
     601             :             /*sa_ignore NO_NULL_CHK
     602             :               {ptr is valid since the pointer was checked earlier and the
     603             :               function would have exited if NULL.}*/
     604           0 :             slash_ptr = sdp_findchar(slash_ptr, "/");
     605           0 :             if (slash_ptr != NULL &&
     606           0 :                 slash_ptr[0] != '\0') {
     607           0 :                 SDP_PRINT("%s Found a num addr field for multicast addr %s ",
     608             :                           sdp_p->debug_str,slash_ptr);
     609           0 :                 slash_ptr++;
     610             : 
     611           0 :                 errno = 0;
     612           0 :                 strtoul_result = strtoul(slash_ptr, &strtoul_end, 10);
     613             : 
     614           0 :                 if (errno || slash_ptr == strtoul_end || strtoul_result == 0) {
     615           0 :                     sdp_parse_error(sdp_p,
     616             :                                     "%s Invalid Num of addresses: Value must be > 0 ",
     617           0 :                                     sdp_p->debug_str);
     618           0 :                     sdp_p->conf_p->num_invalid_param++;
     619           0 :                     return SDP_INVALID_PARAMETER;
     620             :                 }
     621             : 
     622           0 :                 conn_p->num_of_addresses = (int) strtoul_result;
     623             :             }
     624             :         }
     625             :     }
     626             : 
     627             :     /* See if the address is the choose param and if it's allowed. */
     628           0 :     if ((sdp_p->conf_p->allow_choose[SDP_CHOOSE_CONN_ADDR] == FALSE) &&
     629           0 :         (strcmp(conn_p->conn_addr, "$") == 0)) {
     630           0 :         sdp_parse_error(sdp_p,
     631             :             "%s Warning: Choose parameter for connection "
     632           0 :             "address specified but not allowed.", sdp_p->debug_str);
     633             :     }
     634             : 
     635           0 :     if (sdp_p->debug_flag[SDP_DEBUG_TRACE]) {
     636           0 :         SDP_PRINT("%s Parse connection: network %s, address type %s, "
     637             :                   "address %s ttl= %u num of addresses = %u",
     638             :                   sdp_p->debug_str,
     639             :                   sdp_get_network_name(conn_p->nettype),
     640             :                   sdp_get_address_name(conn_p->addrtype),
     641             :                   conn_p->conn_addr, (unsigned)conn_p->ttl, (unsigned)conn_p->num_of_addresses);
     642             :     }
     643           0 :     return (SDP_SUCCESS);
     644             : }
     645             : 
     646           0 : sdp_result_e sdp_build_connection (sdp_t *sdp_p, uint16_t level, flex_string *fs)
     647             : {
     648             :     sdp_mca_t  *mca_p;
     649             :     sdp_conn_t *conn_p;
     650             : 
     651           0 :     if (level == SDP_SESSION_LEVEL) {
     652           0 :         conn_p = &(sdp_p->default_conn);
     653             :     } else {
     654           0 :         mca_p = sdp_find_media_level(sdp_p, level);
     655           0 :         if (mca_p == NULL) {
     656           0 :             return (SDP_FAILURE);
     657             :         }
     658           0 :         conn_p = &(mca_p->conn);
     659             :     }
     660             : 
     661           0 :     if((conn_p->nettype == SDP_NT_ATM ) &&
     662           0 :        (conn_p->addrtype == SDP_AT_INVALID)) {
     663             :         /*allow c= line to be built without address type and address fields
     664             :          * This is a special case for ATM PVC*/
     665           0 :         flex_string_sprintf(fs, "c=%s\r\n",
     666             :                     sdp_get_network_name(conn_p->nettype));
     667           0 :         return SDP_SUCCESS;
     668             :     }
     669           0 :     if ((conn_p->nettype >= SDP_MAX_NETWORK_TYPES) ||
     670           0 :         (conn_p->addrtype >= SDP_MAX_ADDR_TYPES) ||
     671           0 :         (conn_p->conn_addr[0] == '\0')) {
     672             :         /* Connection info isn't set - don't need to build the token. */
     673           0 :         return (SDP_SUCCESS);
     674             :     }
     675             : 
     676           0 :     if (conn_p->is_multicast) {
     677           0 :         if (conn_p->num_of_addresses > 1) {
     678           0 :             flex_string_sprintf(fs, "c=%s %s %s/%u/%u\r\n",
     679             :                              sdp_get_network_name(conn_p->nettype),
     680             :                              sdp_get_address_name(conn_p->addrtype),
     681           0 :                              conn_p->conn_addr,
     682           0 :                              (unsigned)conn_p->ttl,
     683           0 :                              (unsigned)conn_p->num_of_addresses);
     684             :         } else {
     685           0 :             flex_string_sprintf(fs, "c=%s %s %s/%u\r\n",
     686             :                              sdp_get_network_name(conn_p->nettype),
     687             :                              sdp_get_address_name(conn_p->addrtype),
     688           0 :                              conn_p->conn_addr,
     689           0 :                              (unsigned)conn_p->ttl);
     690             :         }
     691             :     } else {
     692             : 
     693           0 :         flex_string_sprintf(fs, "c=%s %s %s\r\n",
     694             :                          sdp_get_network_name(conn_p->nettype),
     695             :                          sdp_get_address_name(conn_p->addrtype),
     696           0 :                          conn_p->conn_addr);
     697             :     }
     698             : 
     699           0 :     if (sdp_p->debug_flag[SDP_DEBUG_TRACE]) {
     700           0 :         SDP_PRINT("%s Built c= connection line", sdp_p->debug_str);
     701             :     }
     702           0 :     return (SDP_SUCCESS);
     703             : }
     704             : 
     705             : /*
     706             :  * sdp_parse_bandwidth
     707             :  *
     708             :  * This function parses a bandwidth field. The parsing is done in accordance
     709             :  * to the following ABNF:
     710             :  *
     711             :  * bandwidth-fields =    *("b=" bwtype ":" bandwidth CRLF)
     712             :  * bwtype =              1*(alpha-numeric)
     713             :  * bandwidth =           1*(DIGIT)
     714             :  *
     715             :  * It currently supports three types of valid bwtypes - AS, CT and TIAS
     716             :  */
     717           0 : sdp_result_e sdp_parse_bandwidth (sdp_t *sdp_p, uint16_t level, const char *ptr)
     718             : {
     719             :     int                  i;
     720             :     sdp_mca_t            *mca_p;
     721             :     sdp_bw_t             *bw_p;
     722             :     sdp_bw_data_t        *bw_data_p;
     723             :     sdp_bw_data_t        *new_bw_data_p;
     724             :     sdp_result_e         result;
     725             :     char                 tmp[SDP_MAX_STRING_LEN];
     726           0 :     sdp_bw_modifier_e    bw_modifier = SDP_BW_MODIFIER_UNSUPPORTED;
     727           0 :     int                  bw_val = 0;
     728             : 
     729           0 :     if (level == SDP_SESSION_LEVEL) {
     730           0 :         bw_p = &(sdp_p->bw);
     731             :     } else {
     732           0 :         mca_p = sdp_find_media_level(sdp_p, level);
     733           0 :         if (mca_p == NULL) {
     734           0 :             return (SDP_FAILURE);
     735             :         }
     736           0 :         bw_p = &(mca_p->bw);
     737             :     }
     738             : 
     739           0 :     if (sdp_p->debug_flag[SDP_DEBUG_TRACE]) {
     740           0 :         SDP_PRINT("%s Parse bandwidth line", sdp_p->debug_str);
     741             :     }
     742             : 
     743             :     /* Find the bw type (AS, CT or TIAS) */
     744           0 :     ptr = sdp_getnextstrtok(ptr, tmp, sizeof(tmp), ":", &result);
     745           0 :     if (result != SDP_SUCCESS) {
     746           0 :         sdp_parse_error(sdp_p,
     747             :             "%s No bandwidth type specified for b= ",
     748           0 :             sdp_p->debug_str);
     749           0 :         sdp_p->conf_p->num_invalid_param++;
     750           0 :         return (SDP_INVALID_PARAMETER);
     751             :     }
     752           0 :     for (i=0; i < SDP_MAX_BW_MODIFIER_VAL; i++) {
     753           0 :         if (cpr_strncasecmp(tmp, sdp_bw_modifier_val[i].name,
     754           0 :                         sdp_bw_modifier_val[i].strlen) == 0) {
     755           0 :             bw_modifier  = (sdp_bw_modifier_e)i;
     756           0 :             break;
     757             :         }
     758             :     }
     759             : 
     760           0 :     if (bw_modifier == SDP_BW_MODIFIER_UNSUPPORTED) {
     761             :         /* We don't understand this parameter, so according to RFC4566 sec 5.8
     762             :          * ignore it. */
     763           0 :         return (SDP_SUCCESS);
     764             :     }
     765             : 
     766             :     /* Find the BW type value */
     767             :     /*sa_ignore NO_NULL_CHK
     768             :       {ptr is valid since the pointer was checked earlier and the
     769             :        function would have exited if NULL.}*/
     770           0 :     if (*ptr == ':') {
     771           0 :         ptr++;
     772           0 :         bw_val = sdp_getnextnumtok(ptr, &ptr, " \t", &result);
     773           0 :         if ((result != SDP_SUCCESS)) {
     774           0 :             sdp_parse_error(sdp_p,
     775             :                 "%s Error: No BW Value specified ",
     776           0 :                 sdp_p->debug_str);
     777           0 :             sdp_p->conf_p->num_invalid_param++;
     778           0 :             return (SDP_INVALID_PARAMETER);
     779             :         }
     780             :     }
     781             : 
     782             :     /*
     783             :      * Allocate a new sdp_bw_data_t instance and set it's values from the
     784             :      * input parameters.
     785             :      */
     786           0 :     new_bw_data_p = (sdp_bw_data_t*)SDP_MALLOC(sizeof(sdp_bw_data_t));
     787           0 :     if (new_bw_data_p == NULL) {
     788           0 :         sdp_p->conf_p->num_invalid_param++;
     789           0 :         return (SDP_NO_RESOURCE);
     790             :     }
     791           0 :     new_bw_data_p->next_p = NULL;
     792           0 :     new_bw_data_p->bw_modifier = bw_modifier;
     793           0 :     new_bw_data_p->bw_val = bw_val;
     794             : 
     795             :     /*
     796             :      * Enqueue the sdp_bw_data_t instance at the end of the list of
     797             :      * sdp_bw_data_t instances.
     798             :      */
     799           0 :     if (bw_p->bw_data_list == NULL) {
     800           0 :         bw_p->bw_data_list = new_bw_data_p;
     801             :     } else {
     802           0 :         for (bw_data_p = bw_p->bw_data_list;
     803           0 :              bw_data_p->next_p != NULL;
     804           0 :              bw_data_p = bw_data_p->next_p) {
     805             :             ; // Empty For
     806             :         }
     807           0 :         bw_data_p->next_p = new_bw_data_p;
     808             :     }
     809           0 :     bw_p->bw_data_count++;
     810             : 
     811           0 :     if (sdp_p->debug_flag[SDP_DEBUG_TRACE]) {
     812           0 :         SDP_PRINT("%s Parsed bw type %s, value %d", sdp_p->debug_str,
     813             :                      sdp_get_bw_modifier_name(new_bw_data_p->bw_modifier),
     814             :                      new_bw_data_p->bw_val);
     815             :     }
     816             : 
     817           0 :     return (SDP_SUCCESS);
     818             : }
     819             : 
     820             : /*
     821             :  * sdp_build_bandwidth
     822             :  *
     823             :  * Builds *all* the bandwith lines for the specified level.
     824             :  */
     825           0 : sdp_result_e sdp_build_bandwidth (sdp_t *sdp_p, uint16_t level, flex_string *fs)
     826             : {
     827             :     sdp_bw_t            *bw_p;
     828             :     sdp_bw_data_t       *bw_data_p;
     829             :     sdp_mca_t           *mca_p;
     830             : 
     831           0 :     if (level == SDP_SESSION_LEVEL) {
     832           0 :         bw_p = &(sdp_p->bw);
     833             :     } else {
     834           0 :         mca_p = sdp_find_media_level(sdp_p, level);
     835           0 :         if (mca_p == NULL) {
     836           0 :             return (SDP_FAILURE);
     837             :         }
     838           0 :         bw_p = &(mca_p->bw);
     839             :     }
     840             : 
     841           0 :     bw_data_p = bw_p->bw_data_list;
     842           0 :     while (bw_data_p) {
     843           0 :         flex_string_sprintf(fs, "b=%s:%d\r\n",
     844             :                          sdp_get_bw_modifier_name(bw_data_p->bw_modifier),
     845             :                          bw_data_p->bw_val);
     846             : 
     847           0 :         if (sdp_p->debug_flag[SDP_DEBUG_TRACE]) {
     848           0 :            SDP_PRINT("%s Built b=%s:%d bandwidth line", sdp_p->debug_str,
     849             :                      sdp_get_bw_modifier_name(bw_data_p->bw_modifier),
     850             :                      bw_data_p->bw_val);
     851             :         }
     852             : 
     853           0 :         bw_data_p = bw_data_p->next_p;
     854             :     }
     855             : 
     856           0 :     return (SDP_SUCCESS);
     857             : }
     858             : 
     859           0 : sdp_result_e sdp_parse_timespec (sdp_t *sdp_p, uint16_t level, const char *ptr)
     860             : {
     861             :     char            *tmpptr;
     862             :     sdp_result_e     result;
     863             :     sdp_timespec_t  *timespec_p;
     864             :     sdp_timespec_t  *next_timespec_p;
     865             : 
     866           0 :     timespec_p = (sdp_timespec_t *)SDP_MALLOC(sizeof(sdp_timespec_t));
     867           0 :     if (timespec_p == NULL) {
     868           0 :         sdp_p->conf_p->num_no_resource++;
     869           0 :         return (SDP_NO_RESOURCE);
     870             :     }
     871             : 
     872             :     /* Validate start and stop times. */
     873           0 :     ptr = sdp_getnextstrtok(ptr, timespec_p->start_time, sizeof(timespec_p->start_time), " \t", &result);
     874           0 :     if (result == SDP_SUCCESS) {
     875             :         /* Make sure the start_time is numeric, even though we store it as
     876             :          * a string.
     877             :          */
     878           0 :         (void)sdp_getnextnumtok(timespec_p->start_time,
     879             :                                 (const char **)&tmpptr, " \t", &result);
     880             :     }
     881           0 :     if (result != SDP_SUCCESS) {
     882           0 :         sdp_parse_error(sdp_p,
     883             :             "%s Invalid timespec start time specified.",
     884           0 :             sdp_p->debug_str);
     885           0 :         sdp_p->conf_p->num_invalid_param++;
     886           0 :         SDP_FREE(timespec_p);
     887           0 :         return (SDP_INVALID_PARAMETER);
     888             :     }
     889             : 
     890           0 :     ptr = sdp_getnextstrtok(ptr, timespec_p->stop_time, sizeof(timespec_p->stop_time), " \t", &result);
     891           0 :     if (result == SDP_SUCCESS) {
     892             :         /* Make sure the start_time is numeric, even though we store it as
     893             :          * a string.
     894             :          */
     895           0 :         (void)sdp_getnextnumtok(timespec_p->stop_time,
     896             :                                 (const char **)&tmpptr, " \t", &result);
     897             :     }
     898           0 :     if (result != SDP_SUCCESS) {
     899           0 :         sdp_parse_error(sdp_p,
     900             :             "%s Invalid timespec stop time specified.",
     901           0 :             sdp_p->debug_str);
     902           0 :         sdp_p->conf_p->num_invalid_param++;
     903           0 :         SDP_FREE(timespec_p);
     904           0 :         return (SDP_INVALID_PARAMETER);
     905             :     }
     906             : 
     907             :     /* Link the new timespec in to the end of the list. */
     908           0 :     if (sdp_p->timespec_p == NULL) {
     909           0 :         sdp_p->timespec_p = timespec_p;
     910             :     } else {
     911           0 :         next_timespec_p = sdp_p->timespec_p;
     912           0 :         while (next_timespec_p->next_p != NULL) {
     913           0 :             next_timespec_p = next_timespec_p->next_p;
     914             :         }
     915           0 :         next_timespec_p->next_p = timespec_p;
     916             :     }
     917             : 
     918           0 :     if (sdp_p->debug_flag[SDP_DEBUG_TRACE]) {
     919           0 :         SDP_PRINT("%s Parsed timespec line", sdp_p->debug_str);
     920             :     }
     921           0 :     return (SDP_SUCCESS);
     922             : }
     923             : 
     924           0 : sdp_result_e sdp_build_timespec (sdp_t *sdp_p, uint16_t level, flex_string *fs)
     925             : {
     926           0 :     if ((sdp_p->timespec_p == NULL) ||
     927           0 :         (sdp_p->timespec_p->start_time[0] == '\0') ||
     928           0 :         (sdp_p->timespec_p->stop_time[0] == '\0')) {
     929           0 :         if (sdp_p->conf_p->timespec_reqd == TRUE) {
     930           0 :             CSFLogError(logTag, "%s Invalid params for t= time spec line, "
     931             :                         "build failed.", sdp_p->debug_str);
     932           0 :             sdp_p->conf_p->num_invalid_param++;
     933           0 :             return (SDP_INVALID_PARAMETER);
     934             :         } else {
     935             :             /* t= line not required. */
     936           0 :             return (SDP_SUCCESS);
     937             :         }
     938             :     }
     939             : 
     940             :     /* Note: We only support one t= line currently. */
     941           0 :     flex_string_sprintf(fs, "t=%s %s\r\n", sdp_p->timespec_p->start_time,
     942           0 :                     sdp_p->timespec_p->stop_time);
     943             : 
     944           0 :     if (sdp_p->debug_flag[SDP_DEBUG_TRACE]) {
     945           0 :         SDP_PRINT("%s Built t= timespec line", sdp_p->debug_str);
     946             :     }
     947           0 :     return (SDP_SUCCESS);
     948             : }
     949             : 
     950           0 : sdp_result_e sdp_parse_repeat_time (sdp_t *sdp_p, uint16_t level, const char *ptr)
     951             : {
     952             :     char *endptr;
     953             : 
     954           0 :     endptr = sdp_findchar(ptr, "\n");
     955           0 :     if (ptr == endptr) {
     956           0 :         sdp_parse_error(sdp_p,
     957             :             "%s Warning: No repeat time parameters "
     958           0 :             "specified.", sdp_p->debug_str);
     959             :     }
     960             : 
     961           0 :     if (sdp_p->debug_flag[SDP_DEBUG_TRACE]) {
     962           0 :         SDP_PRINT("%s Parsed repeat time line", sdp_p->debug_str);
     963             :     }
     964           0 :     return (SDP_SUCCESS);
     965             : }
     966             : 
     967           0 : sdp_result_e sdp_build_repeat_time (sdp_t *sdp_p, uint16_t level, flex_string *fs)
     968             : {
     969             :     /* Build repeat time line not supported. */
     970           0 :     return (SDP_SUCCESS);
     971             : }
     972             : 
     973           0 : sdp_result_e sdp_parse_timezone_adj (sdp_t *sdp_p, uint16_t level, const char *ptr)
     974             : {
     975             :     char *endptr;
     976             : 
     977           0 :     endptr = sdp_findchar(ptr, "\n");
     978           0 :     if (ptr == endptr) {
     979           0 :         sdp_parse_error(sdp_p,
     980             :             "%s Warning: No timezone parameters specified.",
     981           0 :             sdp_p->debug_str);
     982             :     }
     983             : 
     984           0 :     if (sdp_p->debug_flag[SDP_DEBUG_TRACE]) {
     985           0 :         SDP_PRINT("%s Parse timezone adustment line", sdp_p->debug_str);
     986             :     }
     987           0 :     return (SDP_SUCCESS);
     988             : }
     989             : 
     990           0 : sdp_result_e sdp_build_timezone_adj (sdp_t *sdp_p, uint16_t level, flex_string *fs)
     991             : {
     992             :     /* Build timezone adjustment line not supported. */
     993           0 :     return (SDP_SUCCESS);
     994             : }
     995             : 
     996           0 : sdp_result_e sdp_parse_encryption (sdp_t *sdp_p, uint16_t level, const char *ptr)
     997             : {
     998             :     int                  i;
     999             :     sdp_result_e         result;
    1000             :     sdp_encryptspec_t   *encrypt_p;
    1001             :     sdp_mca_t           *mca_p;
    1002             :     char                 tmp[SDP_MAX_STRING_LEN];
    1003             : 
    1004           0 :     if (level == SDP_SESSION_LEVEL) {
    1005           0 :         encrypt_p = &(sdp_p->encrypt);
    1006             :     } else {
    1007           0 :         mca_p = sdp_find_media_level(sdp_p, level);
    1008           0 :         if (mca_p == NULL) {
    1009           0 :             return (SDP_FAILURE);
    1010             :         }
    1011           0 :         encrypt_p = &(mca_p->encrypt);
    1012             :     }
    1013           0 :     encrypt_p->encrypt_key[0] = '\0';
    1014             : 
    1015             :     /* Find the encryption type. */
    1016           0 :     ptr = sdp_getnextstrtok(ptr, tmp, sizeof(tmp), ":", &result);
    1017           0 :     if (result != SDP_SUCCESS) {
    1018           0 :         sdp_parse_error(sdp_p,
    1019             :             "%s No encryption type specified for k=.",
    1020           0 :             sdp_p->debug_str);
    1021           0 :         sdp_p->conf_p->num_invalid_param++;
    1022           0 :         return (SDP_INVALID_PARAMETER);
    1023             :     }
    1024           0 :     encrypt_p->encrypt_type = SDP_ENCRYPT_UNSUPPORTED;
    1025           0 :     for (i=0; i < SDP_MAX_ENCRYPT_TYPES; i++) {
    1026           0 :         if (cpr_strncasecmp(tmp, sdp_encrypt[i].name,
    1027           0 :                         sdp_encrypt[i].strlen) == 0) {
    1028           0 :             encrypt_p->encrypt_type = (sdp_encrypt_type_e)i;
    1029           0 :             break;
    1030             :         }
    1031             :     }
    1032           0 :     if (encrypt_p->encrypt_type == SDP_ENCRYPT_UNSUPPORTED) {
    1033           0 :         sdp_parse_error(sdp_p,
    1034             :             "%s Warning: Encryption type unsupported (%s).",
    1035           0 :             sdp_p->debug_str, tmp);
    1036             :     }
    1037             : 
    1038             :     /* Find the encryption key. */
    1039           0 :     encrypt_p->encrypt_key[0] = '\0';
    1040             :     /*sa_ignore NO_NULL_CHK
    1041             :       {ptr is valid since the pointer was checked earlier and the
    1042             :        function would have exited if NULL.}*/
    1043           0 :     if (*ptr == ':')
    1044           0 :         ptr++;
    1045           0 :     if (encrypt_p->encrypt_type != SDP_ENCRYPT_PROMPT) {
    1046           0 :         ptr = sdp_getnextstrtok(ptr, encrypt_p->encrypt_key, sizeof(encrypt_p->encrypt_key), " \t", &result);
    1047           0 :         if ((result != SDP_SUCCESS) &&
    1048           0 :             ((encrypt_p->encrypt_type == SDP_ENCRYPT_CLEAR) ||
    1049           0 :              (encrypt_p->encrypt_type == SDP_ENCRYPT_BASE64) ||
    1050           0 :              (encrypt_p->encrypt_type == SDP_ENCRYPT_URI))) {
    1051           0 :             sdp_parse_error(sdp_p,
    1052             :                 "%s Warning: No encryption key specified "
    1053           0 :                 "as required.", sdp_p->debug_str);
    1054           0 :             sdp_p->conf_p->num_invalid_param++;
    1055           0 :             return (SDP_INVALID_PARAMETER);
    1056             :         }
    1057             :     }
    1058             : 
    1059           0 :     if (sdp_p->debug_flag[SDP_DEBUG_TRACE]) {
    1060           0 :         SDP_PRINT("%s Parse encryption type %s, key %s", sdp_p->debug_str,
    1061             :                    sdp_get_encrypt_name(encrypt_p->encrypt_type),
    1062             :                    encrypt_p->encrypt_key);
    1063             :     }
    1064           0 :     return (SDP_SUCCESS);
    1065             : }
    1066             : 
    1067             : /* If the encryption info is valid, we build it.  Else skip it. */
    1068           0 : sdp_result_e sdp_build_encryption (sdp_t *sdp_p, uint16_t level, flex_string *fs)
    1069             : {
    1070             :     sdp_encryptspec_t   *encrypt_p;
    1071             :     sdp_mca_t           *mca_p;
    1072             : 
    1073           0 :     if (level == SDP_SESSION_LEVEL) {
    1074           0 :         encrypt_p = &(sdp_p->encrypt);
    1075             :     } else {
    1076           0 :         mca_p = sdp_find_media_level(sdp_p, level);
    1077           0 :         if (mca_p == NULL) {
    1078           0 :             return (SDP_FAILURE);
    1079             :         }
    1080           0 :         encrypt_p = &(mca_p->encrypt);
    1081             :     }
    1082             : 
    1083           0 :     if ((encrypt_p->encrypt_type >= SDP_MAX_ENCRYPT_TYPES) ||
    1084           0 :         ((encrypt_p->encrypt_type != SDP_ENCRYPT_PROMPT) &&
    1085           0 :          (encrypt_p->encrypt_key[0] == '\0'))) {
    1086             :         /* Encryption info isn't set - don't need to build the token. */
    1087           0 :         return (SDP_SUCCESS);
    1088             :     }
    1089             : 
    1090           0 :     flex_string_sprintf(fs, "k=%s",
    1091             :                      sdp_get_encrypt_name(encrypt_p->encrypt_type));
    1092             : 
    1093           0 :     if (encrypt_p->encrypt_type == SDP_ENCRYPT_PROMPT) {
    1094             :         /* There is no key to print. */
    1095           0 :         flex_string_sprintf(fs, "\r\n");
    1096             :     } else {
    1097           0 :         flex_string_sprintf(fs, ":%s\r\n", encrypt_p->encrypt_key);
    1098             :     }
    1099             : 
    1100           0 :     if (sdp_p->debug_flag[SDP_DEBUG_TRACE]) {
    1101           0 :         SDP_PRINT("%s Built k= encryption line", sdp_p->debug_str);
    1102             :     }
    1103           0 :     return (SDP_SUCCESS);
    1104             : }
    1105             : 
    1106           0 : sdp_result_e sdp_parse_media (sdp_t *sdp_p, uint16_t level, const char *ptr)
    1107             : {
    1108             :     uint16_t                   i;
    1109           0 :     uint16_t                   num_port_params=0;
    1110             :     int32_t                 num[SDP_MAX_PORT_PARAMS];
    1111           0 :     tinybool              valid_param = FALSE;
    1112             :     sdp_result_e          result;
    1113             :     sdp_mca_t            *mca_p;
    1114             :     sdp_mca_t            *next_mca_p;
    1115             :     char                  tmp[SDP_MAX_STRING_LEN];
    1116             :     char                  port[SDP_MAX_STRING_LEN];
    1117             :     const char           *port_ptr;
    1118             :     int32_t                 sctp_port;
    1119             : 
    1120             :     /* Allocate resource for new media stream. */
    1121           0 :     mca_p = sdp_alloc_mca(sdp_p->parse_line);
    1122           0 :     if (mca_p == NULL) {
    1123           0 :         sdp_p->conf_p->num_no_resource++;
    1124           0 :         return (SDP_NO_RESOURCE);
    1125             :     }
    1126             : 
    1127             :     /* Find the media type. */
    1128           0 :     ptr = sdp_getnextstrtok(ptr, tmp, sizeof(tmp), " \t", &result);
    1129           0 :     if (result != SDP_SUCCESS) {
    1130           0 :         sdp_parse_error(sdp_p,
    1131             :             "%s No media type specified, parse failed.",
    1132           0 :             sdp_p->debug_str);
    1133           0 :         SDP_FREE(mca_p);
    1134           0 :         sdp_p->conf_p->num_invalid_param++;
    1135           0 :         return (SDP_INVALID_PARAMETER);
    1136             :     }
    1137           0 :     mca_p->media = SDP_MEDIA_UNSUPPORTED;
    1138           0 :     for (i=0; i < SDP_MAX_MEDIA_TYPES; i++) {
    1139           0 :         if (cpr_strncasecmp(tmp, sdp_media[i].name,
    1140           0 :                         sdp_media[i].strlen) == 0) {
    1141           0 :             mca_p->media = (sdp_media_e)i;
    1142             :         }
    1143             :     }
    1144           0 :     if (mca_p->media == SDP_MEDIA_UNSUPPORTED) {
    1145           0 :         sdp_parse_error(sdp_p,
    1146             :             "%s Warning: Media type unsupported (%s).",
    1147           0 :             sdp_p->debug_str, tmp);
    1148             :     }
    1149             : 
    1150             :     /* Find the port token parameters, but don't process it until
    1151             :      * we determine the transport protocol as that determines what
    1152             :      * port number formats are valid.
    1153             :      */
    1154           0 :     ptr = sdp_getnextstrtok(ptr, port, sizeof(port), " \t", &result);
    1155           0 :     if (result != SDP_SUCCESS) {
    1156           0 :         sdp_parse_error(sdp_p,
    1157             :             "%s No port specified in m= media line, "
    1158           0 :             "parse failed.", sdp_p->debug_str);
    1159           0 :         SDP_FREE(mca_p);
    1160           0 :         sdp_p->conf_p->num_invalid_param++;
    1161           0 :         return (SDP_INVALID_PARAMETER);
    1162             :     }
    1163           0 :     port_ptr = port;
    1164           0 :     for (i=0; i < SDP_MAX_PORT_PARAMS; i++) {
    1165           0 :         if (sdp_getchoosetok(port_ptr, &port_ptr, "/ \t", &result) == TRUE) {
    1166           0 :             num[i] = SDP_CHOOSE_PARAM;
    1167             :         } else {
    1168           0 :             num[i] = sdp_getnextnumtok(port_ptr, (const char **)&port_ptr,
    1169             :                                        "/ \t", &result);
    1170           0 :             if (result != SDP_SUCCESS) {
    1171           0 :                 break;
    1172             :             }
    1173             :         }
    1174           0 :         num_port_params++;
    1175             :     }
    1176             : 
    1177             :     /* Find the transport protocol type. */
    1178           0 :     ptr = sdp_getnextstrtok(ptr, tmp, sizeof(tmp), " \t", &result);
    1179           0 :     if (result != SDP_SUCCESS) {
    1180           0 :         sdp_parse_error(sdp_p,
    1181             :             "%s No transport protocol type specified, "
    1182           0 :             "parse failed.", sdp_p->debug_str);
    1183           0 :         SDP_FREE(mca_p);
    1184           0 :         sdp_p->conf_p->num_invalid_param++;
    1185           0 :         return (SDP_INVALID_PARAMETER);
    1186             :     }
    1187           0 :     mca_p->transport = SDP_TRANSPORT_UNSUPPORTED;
    1188           0 :     for (i=0; i < SDP_MAX_TRANSPORT_TYPES; i++) {
    1189           0 :         if (cpr_strncasecmp(tmp, sdp_transport[i].name,
    1190           0 :                         sdp_transport[i].strlen) == 0) {
    1191           0 :             mca_p->transport = (sdp_transport_e)i;
    1192           0 :             break;
    1193             :         }
    1194             :     }
    1195             : 
    1196           0 :     if (mca_p->transport == SDP_TRANSPORT_UNSUPPORTED) {
    1197             :         /* If we don't recognize or don't support the transport type,
    1198             :          * just store the first num as the port.
    1199             :          */
    1200           0 :         mca_p->port = num[0];
    1201           0 :         sdp_parse_error(sdp_p,
    1202             :             "%s Warning: Transport protocol type unsupported "
    1203           0 :             "(%s).", sdp_p->debug_str, tmp);
    1204             :     }
    1205             : 
    1206             :     /* Check for each of the possible port formats according to the
    1207             :      * type of transport protocol specified.
    1208             :      */
    1209           0 :     valid_param = FALSE;
    1210           0 :     switch (num_port_params) {
    1211             :     case 1:
    1212           0 :         if ((mca_p->transport == SDP_TRANSPORT_RTPAVP) ||
    1213           0 :             (mca_p->transport == SDP_TRANSPORT_RTPSAVP) ||
    1214           0 :             (mca_p->transport == SDP_TRANSPORT_RTPSAVPF) ||
    1215           0 :             (mca_p->transport == SDP_TRANSPORT_UDPTLSRTPSAVP) ||
    1216           0 :             (mca_p->transport == SDP_TRANSPORT_UDPTLSRTPSAVPF) ||
    1217           0 :             (mca_p->transport == SDP_TRANSPORT_TCPTLSRTPSAVP) ||
    1218           0 :             (mca_p->transport == SDP_TRANSPORT_TCPTLSRTPSAVPF) ||
    1219           0 :             (mca_p->transport == SDP_TRANSPORT_UDP) ||
    1220           0 :             (mca_p->transport == SDP_TRANSPORT_TCP) ||
    1221           0 :             (mca_p->transport == SDP_TRANSPORT_UDPTL) ||
    1222           0 :             (mca_p->transport == SDP_TRANSPORT_UDPSPRT) ||
    1223           0 :             (mca_p->transport == SDP_TRANSPORT_LOCAL) ||
    1224           0 :             (mca_p->transport == SDP_TRANSPORT_DTLSSCTP) ||
    1225           0 :             (mca_p->transport == SDP_TRANSPORT_UDPDTLSSCTP) ||
    1226           0 :             (mca_p->transport == SDP_TRANSPORT_TCPDTLSSCTP)) {
    1227             :             /* Port format is simply <port>.  Make sure that either
    1228             :              * the choose param is allowed or that the choose value
    1229             :              * wasn't specified.
    1230             :              */
    1231           0 :             if ((sdp_p->conf_p->allow_choose[SDP_CHOOSE_PORTNUM]) ||
    1232           0 :                 (num[0] != SDP_CHOOSE_PARAM)) {
    1233           0 :                 mca_p->port        = num[0];
    1234           0 :                 mca_p->port_format = SDP_PORT_NUM_ONLY;
    1235           0 :                 valid_param        = TRUE;
    1236             :             }
    1237           0 :         } else if (mca_p->transport == SDP_TRANSPORT_AAL1AVP) {
    1238             :             /* Port format is simply <vcci>, choose param is not allowed.
    1239             :              */
    1240           0 :             if (num[0] != SDP_CHOOSE_PARAM) {
    1241           0 :                 mca_p->vcci        = num[0];
    1242           0 :                 mca_p->port_format = SDP_PORT_VCCI;
    1243           0 :                 valid_param        = TRUE;
    1244             :             }
    1245           0 :         } else if ((mca_p->transport == SDP_TRANSPORT_AAL2_ITU) ||
    1246           0 :             (mca_p->transport == SDP_TRANSPORT_AAL2_ATMF) ||
    1247           0 :             (mca_p->transport == SDP_TRANSPORT_AAL2_CUSTOM)) {
    1248             :             /* Port format is simply <port>, and choose param is allowed,
    1249             :              * according to AAL2 definitions.
    1250             :              */
    1251           0 :             mca_p->port        = num[0];
    1252           0 :             mca_p->port_format = SDP_PORT_NUM_ONLY;
    1253           0 :             valid_param        = TRUE;
    1254             :         }
    1255           0 :         break;
    1256             :     case 2:
    1257           0 :         if ((mca_p->transport == SDP_TRANSPORT_RTPAVP) ||
    1258           0 :             (mca_p->transport == SDP_TRANSPORT_RTPSAVP) ||
    1259           0 :             (mca_p->transport == SDP_TRANSPORT_RTPSAVPF) ||
    1260           0 :             (mca_p->transport == SDP_TRANSPORT_UDPTLSRTPSAVP) ||
    1261           0 :             (mca_p->transport == SDP_TRANSPORT_UDPTLSRTPSAVPF) ||
    1262           0 :             (mca_p->transport == SDP_TRANSPORT_TCPTLSRTPSAVP) ||
    1263           0 :             (mca_p->transport == SDP_TRANSPORT_TCPTLSRTPSAVPF) ||
    1264           0 :             (mca_p->transport == SDP_TRANSPORT_UDP) ||
    1265           0 :             (mca_p->transport == SDP_TRANSPORT_LOCAL)) {
    1266             :             /* Port format is <port>/<num of ports>. Make sure choose
    1267             :              * params were not specified.
    1268             :              */
    1269           0 :             if ((num[0] != SDP_CHOOSE_PARAM) &&
    1270           0 :                 (num[1] != SDP_CHOOSE_PARAM)) {
    1271           0 :                 mca_p->port        = num[0];
    1272           0 :                 mca_p->num_ports   = num[1];
    1273           0 :                 mca_p->port_format = SDP_PORT_NUM_COUNT;
    1274           0 :                 valid_param        = TRUE;
    1275             :             }
    1276           0 :         } else if (mca_p->transport == SDP_TRANSPORT_UDPTL) {
    1277             :             /* Port format is <port>/<num of ports>. Make sure choose
    1278             :              * params were not specified.  For UDPTL, only "1" may
    1279             :              * be specified for number of ports.
    1280             :              */
    1281           0 :             if ((num[0] != SDP_CHOOSE_PARAM) &&
    1282           0 :                 (num[1] == 1)) {
    1283           0 :                 mca_p->port        = num[0];
    1284           0 :                 mca_p->num_ports   = 1;
    1285           0 :                 mca_p->port_format = SDP_PORT_NUM_COUNT;
    1286           0 :                 valid_param        = TRUE;
    1287             :             }
    1288           0 :         } else if (mca_p->transport == SDP_TRANSPORT_CES10) {
    1289             :             /* Port format is <vpi>/<vci>. Make sure choose
    1290             :              * params were not specified.
    1291             :              */
    1292           0 :             if ((num[0] != SDP_CHOOSE_PARAM) &&
    1293           0 :                 (num[1] != SDP_CHOOSE_PARAM)) {
    1294           0 :                 mca_p->vpi         = num[0];
    1295           0 :                 mca_p->vci         = num[1];
    1296           0 :                 mca_p->port_format = SDP_PORT_VPI_VCI;
    1297           0 :                 valid_param        = TRUE;
    1298             :             }
    1299           0 :         } else if ((mca_p->transport == SDP_TRANSPORT_AAL2_ITU) ||
    1300           0 :                    (mca_p->transport == SDP_TRANSPORT_AAL2_ATMF) ||
    1301           0 :                    (mca_p->transport == SDP_TRANSPORT_AAL2_CUSTOM)) {
    1302             :             /* Port format is either <vcci>/<cid> or $/$.  If one
    1303             :              * param is '$' the other must be also.  The choose params
    1304             :              * are allowed by default and don't need to be allowed
    1305             :              * through the appl config.
    1306             :              */
    1307           0 :             if (((num[0] != SDP_CHOOSE_PARAM) &&
    1308           0 :                  (num[1] != SDP_CHOOSE_PARAM)) ||
    1309           0 :                 ((num[0] == SDP_CHOOSE_PARAM) &&
    1310           0 :                  (num[1] == SDP_CHOOSE_PARAM))) {
    1311           0 :                 mca_p->vcci        = num[0];
    1312           0 :                 mca_p->cid         = num[1];
    1313           0 :                 mca_p->port_format = SDP_PORT_VCCI_CID;
    1314           0 :                 valid_param        = TRUE;
    1315             :             }
    1316             :         }
    1317           0 :         break;
    1318             :     case 3:
    1319           0 :         if (mca_p->transport == SDP_TRANSPORT_AAL1AVP) {
    1320             :             /* Port format is <port>/<vpi>/<vci>. Make sure choose
    1321             :              * params were not specified.
    1322             :              */
    1323           0 :             if ((num[0] != SDP_CHOOSE_PARAM) &&
    1324           0 :                 (num[1] != SDP_CHOOSE_PARAM) &&
    1325           0 :                 (num[2] != SDP_CHOOSE_PARAM)) {
    1326           0 :                 mca_p->port        = num[0];
    1327           0 :                 mca_p->vpi         = num[1];
    1328           0 :                 mca_p->vci         = num[2];
    1329           0 :                 mca_p->port_format = SDP_PORT_NUM_VPI_VCI;
    1330           0 :                 valid_param        = TRUE;
    1331             :             }
    1332             :         }
    1333           0 :         break;
    1334             :     case 4:
    1335           0 :         if ((mca_p->transport == SDP_TRANSPORT_AAL2_ITU) ||
    1336           0 :             (mca_p->transport == SDP_TRANSPORT_AAL2_ATMF) ||
    1337           0 :             (mca_p->transport == SDP_TRANSPORT_AAL2_CUSTOM)) {
    1338             :             /* Port format is <port>/<vpi>/<vci>/<cid>. Make sure choose
    1339             :              * params were not specified.
    1340             :              */
    1341           0 :             if ((num[0] != SDP_CHOOSE_PARAM) &&
    1342           0 :                 (num[1] != SDP_CHOOSE_PARAM) &&
    1343           0 :                 (num[2] != SDP_CHOOSE_PARAM) &&
    1344           0 :                 (num[3] != SDP_CHOOSE_PARAM)) {
    1345           0 :                 mca_p->port        = num[0];
    1346           0 :                 mca_p->vpi         = num[1];
    1347           0 :                 mca_p->vci         = num[2];
    1348           0 :                 mca_p->cid         = num[3];
    1349           0 :                 mca_p->port_format = SDP_PORT_NUM_VPI_VCI_CID;
    1350           0 :                 valid_param        = TRUE;
    1351             :             }
    1352             :         }
    1353           0 :         break;
    1354             :     }
    1355           0 :     if (valid_param == FALSE) {
    1356           0 :         sdp_parse_error(sdp_p,
    1357             :             "%s Invalid port format (%s) specified for transport "
    1358           0 :             "protocol (%s), parse failed.", sdp_p->debug_str,
    1359             :             port, sdp_get_transport_name(mca_p->transport));
    1360           0 :         sdp_p->conf_p->num_invalid_param++;
    1361           0 :         SDP_FREE(mca_p);
    1362           0 :         return (SDP_INVALID_PARAMETER);
    1363             :     }
    1364             : 
    1365             :     /* Find payload formats. AAL2 media lines allow multiple
    1366             :      * transport/profile types per line, so these are handled differently. */
    1367           0 :     if ((mca_p->transport == SDP_TRANSPORT_AAL2_ITU) ||
    1368           0 :         (mca_p->transport == SDP_TRANSPORT_AAL2_ATMF) ||
    1369           0 :         (mca_p->transport == SDP_TRANSPORT_AAL2_CUSTOM)) {
    1370             : 
    1371           0 :         if (sdp_parse_multiple_profile_payload_types(sdp_p, mca_p, ptr) !=
    1372             :             SDP_SUCCESS) {
    1373           0 :             sdp_p->conf_p->num_invalid_param++;
    1374           0 :             SDP_FREE(mca_p);
    1375           0 :             return (SDP_INVALID_PARAMETER);
    1376             :         }
    1377             :     /* Parse DTLS/SCTP port */
    1378           0 :     } else if ((mca_p->transport == SDP_TRANSPORT_DTLSSCTP) ||
    1379           0 :                (mca_p->transport == SDP_TRANSPORT_UDPDTLSSCTP) ||
    1380           0 :                (mca_p->transport == SDP_TRANSPORT_TCPDTLSSCTP)) {
    1381           0 :         ptr = sdp_getnextstrtok(ptr, port, sizeof(port), " \t", &result);
    1382           0 :         if (result != SDP_SUCCESS) {
    1383           0 :             sdp_parse_error(sdp_p,
    1384             :                 "%s No sctp port specified in m= media line, "
    1385           0 :                 "parse failed.", sdp_p->debug_str);
    1386           0 :             SDP_FREE(mca_p);
    1387           0 :             sdp_p->conf_p->num_invalid_param++;
    1388           0 :             return (SDP_INVALID_PARAMETER);
    1389             :         }
    1390           0 :         port_ptr = port;
    1391             : 
    1392           0 :         if ((mca_p->transport == SDP_TRANSPORT_UDPDTLSSCTP) ||
    1393           0 :             (mca_p->transport == SDP_TRANSPORT_TCPDTLSSCTP)) {
    1394           0 :             if (cpr_strncasecmp(port_ptr, "webrtc-datachannel",
    1395             :                                 sizeof("webrtc-datachannel")) != 0) {
    1396           0 :                 sdp_parse_error(sdp_p,
    1397             :                     "%s No webrtc-datachannel token in m= media line, "
    1398           0 :                     "parse failed.", sdp_p->debug_str);
    1399           0 :                 SDP_FREE(mca_p);
    1400           0 :                 sdp_p->conf_p->num_invalid_param++;
    1401           0 :                 return (SDP_INVALID_PARAMETER);
    1402             :             }
    1403           0 :             mca_p->sctp_fmt = SDP_SCTP_MEDIA_FMT_WEBRTC_DATACHANNEL;
    1404           0 :         } else if (sdp_getchoosetok(port_ptr, &port_ptr, "/ \t", &result)) {
    1405           0 :             sctp_port = SDP_CHOOSE_PARAM;
    1406             :         } else {
    1407           0 :             sctp_port = sdp_getnextnumtok(port_ptr, (const char **)&port_ptr,
    1408             :                                            "/ \t", &result);
    1409           0 :             if (result != SDP_SUCCESS) {
    1410           0 :                 sdp_parse_error(sdp_p,
    1411             :                     "%s No sctp port specified in m= media line, "
    1412           0 :                     "parse failed.", sdp_p->debug_str);
    1413           0 :                 SDP_FREE(mca_p);
    1414           0 :                 sdp_p->conf_p->num_invalid_param++;
    1415           0 :                 return (SDP_INVALID_PARAMETER);
    1416             :             }
    1417           0 :             mca_p->sctpport = sctp_port;
    1418             :         }
    1419             :     } else {
    1420             :         /* Transport is a non-AAL2 type and not SCTP.  Parse payloads
    1421             :            normally. */
    1422           0 :         sdp_parse_payload_types(sdp_p, mca_p, ptr);
    1423             :     }
    1424             : 
    1425             : 
    1426             :     /* Media line params are valid.  Add it into the SDP. */
    1427           0 :     sdp_p->mca_count++;
    1428           0 :     if (sdp_p->mca_p == NULL) {
    1429           0 :         sdp_p->mca_p = mca_p;
    1430             :     } else {
    1431           0 :         for (next_mca_p = sdp_p->mca_p; next_mca_p->next_p != NULL;
    1432           0 :              next_mca_p = next_mca_p->next_p) {
    1433             :             ; // Empty For
    1434             :         }
    1435           0 :         next_mca_p->next_p = mca_p;
    1436             :     }
    1437             : 
    1438           0 :     if (sdp_p->debug_flag[SDP_DEBUG_TRACE]) {
    1439             : 
    1440           0 :         SDP_PRINT("%s Parsed media type %s, ", sdp_p->debug_str,
    1441             :                   sdp_get_media_name(mca_p->media));
    1442           0 :         switch (mca_p->port_format) {
    1443             :         case SDP_PORT_NUM_ONLY:
    1444           0 :             SDP_PRINT("Port num %d, ", mca_p->port);
    1445           0 :             break;
    1446             : 
    1447             :         case SDP_PORT_NUM_COUNT:
    1448           0 :             SDP_PRINT("Port num %d, count %d, ",
    1449             :                       mca_p->port, mca_p->num_ports);
    1450           0 :             break;
    1451             :         case SDP_PORT_VPI_VCI:
    1452           0 :             SDP_PRINT("VPI/VCI %d/%u, ", mca_p->vpi, mca_p->vci);
    1453           0 :             break;
    1454             :         case SDP_PORT_VCCI:
    1455           0 :             SDP_PRINT("VCCI %d, ", mca_p->vcci);
    1456           0 :             break;
    1457             :         case SDP_PORT_NUM_VPI_VCI:
    1458           0 :             SDP_PRINT("Port %d, VPI/VCI %d/%u, ", mca_p->port,
    1459             :                       mca_p->vpi, mca_p->vci);
    1460           0 :             break;
    1461             :         case SDP_PORT_VCCI_CID:
    1462           0 :             SDP_PRINT("VCCI %d, CID %d, ", mca_p->vcci, mca_p->cid);
    1463           0 :             break;
    1464             :         case SDP_PORT_NUM_VPI_VCI_CID:
    1465           0 :             SDP_PRINT("Port %d, VPI/VCI %d/%u, CID %d, ", mca_p->port,
    1466             :                       mca_p->vpi, mca_p->vci, mca_p->cid);
    1467           0 :             break;
    1468             :         default:
    1469           0 :             SDP_PRINT("Port format not valid, ");
    1470           0 :             break;
    1471             :         }
    1472             : 
    1473           0 :         if ((mca_p->transport >= SDP_TRANSPORT_AAL2_ITU) &&
    1474           0 :             (mca_p->transport <= SDP_TRANSPORT_AAL2_CUSTOM)) {
    1475           0 :             for (i=0; i < mca_p->media_profiles_p->num_profiles; i++) {
    1476           0 :                 SDP_PRINT("Profile %s, Num payloads %u ",
    1477             :                    sdp_get_transport_name(mca_p->media_profiles_p->profile[i]),
    1478             :                    (unsigned)mca_p->media_profiles_p->num_payloads[i]);
    1479             :             }
    1480             :         } else {
    1481           0 :             SDP_PRINT("Transport %s, Num payloads %u",
    1482             :                       sdp_get_transport_name(mca_p->transport),
    1483             :                       (unsigned)mca_p->num_payloads);
    1484             :         }
    1485             :     }
    1486           0 :     return (SDP_SUCCESS);
    1487             : }
    1488             : 
    1489           0 : sdp_result_e sdp_build_media (sdp_t *sdp_p, uint16_t level, flex_string *fs)
    1490             : {
    1491             :     int                   i, j;
    1492             :     sdp_mca_t            *mca_p;
    1493           0 :     tinybool              invalid_params=FALSE;
    1494             :     sdp_media_profiles_t *profile_p;
    1495             : 
    1496             :     /* Find the right media line */
    1497           0 :     mca_p = sdp_find_media_level(sdp_p, level);
    1498           0 :     if (mca_p == NULL) {
    1499           0 :         return (SDP_FAILURE);
    1500             :     }
    1501             : 
    1502             :     /* Validate params for this media line */
    1503           0 :     if ((mca_p->media >= SDP_MAX_MEDIA_TYPES) ||
    1504           0 :         (mca_p->port_format >= SDP_MAX_PORT_FORMAT_TYPES) ||
    1505           0 :         (mca_p->transport >= SDP_MAX_TRANSPORT_TYPES)) {
    1506           0 :         invalid_params = TRUE;
    1507             :     }
    1508             : 
    1509           0 :     if (invalid_params == TRUE) {
    1510           0 :         CSFLogError(logTag, "%s Invalid params for m= media line, "
    1511             :                     "build failed.", sdp_p->debug_str);
    1512           0 :         sdp_p->conf_p->num_invalid_param++;
    1513           0 :         return (SDP_INVALID_PARAMETER);
    1514             :     }
    1515             : 
    1516             :     /* Build the media type */
    1517           0 :     flex_string_sprintf(fs, "m=%s ", sdp_get_media_name(mca_p->media));
    1518             : 
    1519             :     /* Build the port based on the specified port format */
    1520           0 :     if (mca_p->port_format == SDP_PORT_NUM_ONLY) {
    1521           0 :         if (mca_p->port == SDP_CHOOSE_PARAM) {
    1522           0 :             flex_string_sprintf(fs, "$ ");
    1523             :         } else {
    1524           0 :             flex_string_sprintf(fs, "%u ", (unsigned)mca_p->port);
    1525             :         }
    1526           0 :     } else if (mca_p->port_format == SDP_PORT_NUM_COUNT) {
    1527           0 :         flex_string_sprintf(fs, "%u/%u ", (unsigned)mca_p->port,
    1528           0 :                         (unsigned)mca_p->num_ports);
    1529           0 :     } else if (mca_p->port_format == SDP_PORT_VPI_VCI) {
    1530           0 :         flex_string_sprintf(fs, "%u/%u ",
    1531           0 :                          (unsigned)mca_p->vpi, (unsigned)mca_p->vci);
    1532           0 :     } else if (mca_p->port_format == SDP_PORT_VCCI) {
    1533           0 :         flex_string_sprintf(fs, "%u ", (unsigned)mca_p->vcci);
    1534           0 :     } else if (mca_p->port_format == SDP_PORT_NUM_VPI_VCI) {
    1535           0 :         flex_string_sprintf(fs, "%u/%u/%u ", (unsigned)mca_p->port,
    1536           0 :                          (unsigned)mca_p->vpi, (unsigned)mca_p->vci);
    1537           0 :     } else if (mca_p->port_format == SDP_PORT_VCCI_CID) {
    1538           0 :         if ((mca_p->vcci == SDP_CHOOSE_PARAM) &&
    1539           0 :             (mca_p->cid == SDP_CHOOSE_PARAM)) {
    1540           0 :             flex_string_sprintf(fs, "$/$ ");
    1541           0 :         } else if ((mca_p->vcci == SDP_CHOOSE_PARAM) ||
    1542           0 :                    (mca_p->cid == SDP_CHOOSE_PARAM)) {
    1543             :             /* If one is set but not the other, this is an error. */
    1544           0 :             CSFLogError(logTag, "%s Invalid params for m= port parameter, "
    1545             :                         "build failed.", sdp_p->debug_str);
    1546           0 :             sdp_p->conf_p->num_invalid_param++;
    1547           0 :             return (SDP_INVALID_PARAMETER);
    1548             :         } else {
    1549           0 :             flex_string_sprintf(fs, "%u/%u ",
    1550           0 :                              (unsigned)mca_p->vcci, (unsigned)mca_p->cid);
    1551             :         }
    1552           0 :     } else if (mca_p->port_format == SDP_PORT_NUM_VPI_VCI_CID) {
    1553           0 :         flex_string_sprintf(fs, "%u/%u/%u/%u ", (unsigned)mca_p->port,
    1554           0 :                         (unsigned)mca_p->vpi, (unsigned)mca_p->vci, (unsigned)mca_p->cid);
    1555             :     }
    1556             : 
    1557             :     /* If the media line has AAL2 profiles, build them differently. */
    1558           0 :     if ((mca_p->transport == SDP_TRANSPORT_AAL2_ITU) ||
    1559           0 :         (mca_p->transport == SDP_TRANSPORT_AAL2_ATMF) ||
    1560           0 :         (mca_p->transport == SDP_TRANSPORT_AAL2_CUSTOM)) {
    1561           0 :         profile_p = mca_p->media_profiles_p;
    1562           0 :         for (i=0; i < profile_p->num_profiles; i++) {
    1563           0 :             flex_string_sprintf(fs, "%s",
    1564             :                              sdp_get_transport_name(profile_p->profile[i]));
    1565             : 
    1566           0 :             for (j=0; j < profile_p->num_payloads[i]; j++) {
    1567           0 :                 flex_string_sprintf(fs, " %u",
    1568           0 :                                  (unsigned)profile_p->payload_type[i][j]);
    1569             :             }
    1570           0 :             flex_string_sprintf(fs, " ");
    1571             :         }
    1572           0 :         flex_string_sprintf(fs, "\n");
    1573           0 :         if (sdp_p->debug_flag[SDP_DEBUG_TRACE]) {
    1574           0 :             SDP_PRINT("%s Built m= media line", sdp_p->debug_str);
    1575             :         }
    1576           0 :         return (SDP_SUCCESS);
    1577             :     }
    1578             : 
    1579             :     /* Build the transport name */
    1580           0 :     flex_string_sprintf(fs, "%s",
    1581             :                      sdp_get_transport_name(mca_p->transport));
    1582             : 
    1583           0 :     if(mca_p->transport != SDP_TRANSPORT_DTLSSCTP) {
    1584             : 
    1585             :         /* Build the format lists */
    1586           0 :         for (i=0; i < mca_p->num_payloads; i++) {
    1587           0 :             if (mca_p->payload_indicator[i] == SDP_PAYLOAD_ENUM) {
    1588           0 :                 flex_string_sprintf(fs, " %s",
    1589           0 :                                  sdp_get_payload_name((sdp_payload_e)mca_p->payload_type[i]));
    1590             :             } else {
    1591           0 :                 flex_string_sprintf(fs, " %u", (unsigned)mca_p->payload_type[i]);
    1592             :             }
    1593             :         }
    1594             :     } else {
    1595             :         /* Add port to SDP if transport is DTLS/SCTP */
    1596           0 :         flex_string_sprintf(fs, " %u", (unsigned)mca_p->sctpport);
    1597             :     }
    1598             : 
    1599           0 :     flex_string_sprintf(fs, "\r\n");
    1600             : 
    1601           0 :     if (sdp_p->debug_flag[SDP_DEBUG_TRACE]) {
    1602           0 :         SDP_PRINT("%s Built m= media line", sdp_p->debug_str);
    1603             :     }
    1604           0 :     return (SDP_SUCCESS);
    1605             : }
    1606             : 
    1607             : 
    1608             : /* Function:    sdp_parse_payload_types
    1609             :  * Description: Parse a list of payload types.  The list may be part of
    1610             :  *              a media line or part of a capability line.
    1611             :  * Parameters:  sdp_ptr      The SDP handle returned by sdp_init_description.
    1612             :  *              mca_p        The mca structure the payload types should be
    1613             :  *                           added to.
    1614             :  *              ptr          The pointer to the list of payloads.
    1615             :  * Returns:     Nothing.
    1616             :  */
    1617           0 : void sdp_parse_payload_types (sdp_t *sdp_p, sdp_mca_t *mca_p, const char *ptr)
    1618             : {
    1619             :     uint16_t           i;
    1620             :     uint16_t           num_payloads;
    1621             :     sdp_result_e  result;
    1622             :     tinybool      valid_payload;
    1623             :     char          tmp[SDP_MAX_STRING_LEN];
    1624             :     char         *tmp2;
    1625             : 
    1626           0 :     for (num_payloads = 0; (num_payloads < SDP_MAX_PAYLOAD_TYPES); ) {
    1627           0 :         ptr = sdp_getnextstrtok(ptr, tmp, sizeof(tmp), " \t", &result);
    1628           0 :         if (result != SDP_SUCCESS) {
    1629             :             /* If there are no more payload types, we're finished */
    1630           0 :             break;
    1631             :         }
    1632           0 :         mca_p->payload_type[num_payloads] = (uint16_t)sdp_getnextnumtok(tmp,
    1633             :                                                         (const char **)&tmp2,
    1634             :                                                         " \t", &result);
    1635           0 :         if (result == SDP_SUCCESS) {
    1636           0 :             if ((mca_p->media == SDP_MEDIA_IMAGE) &&
    1637           0 :                 (mca_p->transport == SDP_TRANSPORT_UDPTL)) {
    1638           0 :                 sdp_parse_error(sdp_p,
    1639             :                     "%s Warning: Numeric payload type not "
    1640             :                     "valid for media %s with transport %s.",
    1641           0 :                     sdp_p->debug_str,
    1642             :                     sdp_get_media_name(mca_p->media),
    1643             :                     sdp_get_transport_name(mca_p->transport));
    1644             :             } else {
    1645           0 :                 mca_p->payload_indicator[num_payloads] = SDP_PAYLOAD_NUMERIC;
    1646           0 :                 mca_p->num_payloads++;
    1647           0 :                 num_payloads++;
    1648             :             }
    1649           0 :             continue;
    1650             :         }
    1651             : 
    1652           0 :         valid_payload = FALSE;
    1653           0 :         for (i=0; i < SDP_MAX_STRING_PAYLOAD_TYPES; i++) {
    1654           0 :             if (cpr_strncasecmp(tmp, sdp_payload[i].name,
    1655           0 :                             sdp_payload[i].strlen) == 0) {
    1656           0 :                 valid_payload = TRUE;
    1657           0 :                 break;
    1658             :             }
    1659             :         }
    1660           0 :         if (valid_payload == TRUE) {
    1661             :             /* We recognized the payload type.  Make sure it
    1662             :              * is valid for this media line. */
    1663           0 :             valid_payload = FALSE;
    1664           0 :             if ((mca_p->media == SDP_MEDIA_IMAGE) &&
    1665           0 :                 (mca_p->transport == SDP_TRANSPORT_UDPTL) &&
    1666             :                 (i == SDP_PAYLOAD_T38)) {
    1667           0 :                 valid_payload = TRUE;
    1668           0 :             } else if ((mca_p->media == SDP_MEDIA_APPLICATION) &&
    1669           0 :                        (mca_p->transport == SDP_TRANSPORT_UDP) &&
    1670             :                        (i == SDP_PAYLOAD_XTMR)) {
    1671           0 :                 valid_payload = TRUE;
    1672           0 :             } else if ((mca_p->media == SDP_MEDIA_APPLICATION) &&
    1673           0 :                        (mca_p->transport == SDP_TRANSPORT_TCP) &&
    1674             :                        (i == SDP_PAYLOAD_T120)) {
    1675           0 :                 valid_payload = TRUE;
    1676             :             }
    1677             : 
    1678           0 :             if (valid_payload == TRUE) {
    1679           0 :                 mca_p->payload_indicator[num_payloads] = SDP_PAYLOAD_ENUM;
    1680           0 :                 mca_p->payload_type[num_payloads] = i;
    1681           0 :                 mca_p->num_payloads++;
    1682           0 :                 num_payloads++;
    1683             :             } else {
    1684           0 :                 sdp_parse_error(sdp_p,
    1685             :                     "%s Warning: Payload type %s not valid for "
    1686             :                     "media %s with transport %s.",
    1687           0 :                     sdp_p->debug_str,
    1688             :                     sdp_get_payload_name((sdp_payload_e)i),
    1689             :                     sdp_get_media_name(mca_p->media),
    1690             :                     sdp_get_transport_name(mca_p->transport));
    1691             :             }
    1692             :         } else {
    1693             :             /* Payload type wasn't recognized. */
    1694           0 :             sdp_parse_error(sdp_p,
    1695             :                 "%s Warning: Payload type "
    1696           0 :                 "unsupported (%s).", sdp_p->debug_str, tmp);
    1697             :         }
    1698             :     }
    1699           0 :     if (mca_p->num_payloads == 0) {
    1700           0 :         sdp_parse_error(sdp_p,
    1701             :             "%s Warning: No payload types specified.",
    1702           0 :             sdp_p->debug_str);
    1703             :     }
    1704           0 : }
    1705             : 
    1706             : 
    1707             : /* Function:    sdp_parse_multiple_profile_payload_types
    1708             :  * Description: Parse a list of payload types.  The list may be part of
    1709             :  *              a media line or part of a capability line.
    1710             :  * Parameters:  sdp_ptr      The SDP handle returned by sdp_init_description.
    1711             :  *              mca_p        The mca structure the payload types should be
    1712             :  *                           added to.
    1713             :  *              ptr          The pointer to the list of payloads.
    1714             :  * Returns:     Nothing.
    1715             :  */
    1716           0 : sdp_result_e sdp_parse_multiple_profile_payload_types (sdp_t *sdp_p,
    1717             :                                                  sdp_mca_t *mca_p,
    1718             :                                                  const char *ptr)
    1719             : {
    1720             :     uint16_t                   i;
    1721             :     uint16_t                   prof;
    1722             :     uint16_t                   payload;
    1723             :     sdp_result_e          result;
    1724             :     sdp_media_profiles_t *profile_p;
    1725             :     char                  tmp[SDP_MAX_STRING_LEN];
    1726             :     char                 *tmp2;
    1727             : 
    1728             :     /* If the transport type is any of the AAL2 formats, then we
    1729             :      * need to look for multiple AAL2 profiles and their associated
    1730             :      * payload lists. */
    1731           0 :     mca_p->media_profiles_p = (sdp_media_profiles_t *) \
    1732           0 :         SDP_MALLOC(sizeof(sdp_media_profiles_t));
    1733           0 :     if (mca_p->media_profiles_p == NULL) {
    1734           0 :         sdp_p->conf_p->num_no_resource++;
    1735           0 :         SDP_FREE(mca_p);
    1736           0 :         return (SDP_NO_RESOURCE);
    1737             :     }
    1738           0 :     profile_p = mca_p->media_profiles_p;
    1739             :     /* Set the first profile to the one already detected. */
    1740           0 :     profile_p->num_profiles = 1;
    1741           0 :     prof = 0;
    1742           0 :     payload = 0;
    1743           0 :     profile_p->profile[prof] = mca_p->transport;
    1744           0 :     profile_p->num_payloads[prof] = 0;
    1745             : 
    1746             :     /* Now find the payload type lists and any other profile types */
    1747             :     while (TRUE) {
    1748           0 :         ptr = sdp_getnextstrtok(ptr, tmp, sizeof(tmp), " \t", &result);
    1749           0 :         if (result != SDP_SUCCESS) {
    1750             :             /* If there are no more payload types, we're finished */
    1751           0 :             break;
    1752             :         }
    1753             : 
    1754             :         /* See if the next token is a new profile type. */
    1755           0 :         if (prof < SDP_MAX_PROFILES) {
    1756           0 :             profile_p->profile[prof+1] = SDP_TRANSPORT_UNSUPPORTED;
    1757           0 :             for (i=SDP_TRANSPORT_AAL2_ITU;
    1758           0 :                  i <= SDP_TRANSPORT_AAL2_CUSTOM; i++) {
    1759           0 :                 if (cpr_strncasecmp(tmp, sdp_transport[i].name,
    1760           0 :                                 sdp_transport[i].strlen) == 0) {
    1761           0 :                     profile_p->profile[prof+1] = (sdp_transport_e)i;
    1762           0 :                     break;
    1763             :                 }
    1764             :             }
    1765             :             /* If we recognized the profile type, start looking for the
    1766             :              * next payload list. */
    1767           0 :             if (profile_p->profile[prof+1] != SDP_TRANSPORT_UNSUPPORTED) {
    1768             :                 /* Now reset the payload counter for the next profile type. */
    1769           0 :                 payload = 0;
    1770           0 :                 prof++;
    1771           0 :                 profile_p->num_profiles++;
    1772           0 :                 if (prof < SDP_MAX_PROFILES) {
    1773           0 :                     profile_p->num_payloads[prof] = 0;
    1774             :                 }
    1775           0 :                 continue;
    1776             :             }
    1777             :         }
    1778             : 
    1779             :         /* This token must be a payload type. Make sure there aren't
    1780             :          * too many payload types. */
    1781           0 :         if (payload >= SDP_MAX_PAYLOAD_TYPES) {
    1782           0 :             sdp_parse_error(sdp_p,
    1783             :                 "%s Warning: Too many payload types "
    1784           0 :                 "found, truncating.", sdp_p->debug_str);
    1785           0 :             continue;
    1786             :         }
    1787             : 
    1788             :         /* See if the payload type is numeric. */
    1789           0 :         if (prof < SDP_MAX_PROFILES && payload < SDP_MAX_PAYLOAD_TYPES) {
    1790           0 :             profile_p->payload_type[prof][payload] = (uint16_t)sdp_getnextnumtok(tmp,
    1791             :                                                              (const char **)&tmp2,
    1792             :                                                              " \t", &result);
    1793           0 :             if (result == SDP_SUCCESS) {
    1794           0 :                 profile_p->payload_indicator[prof][payload] = SDP_PAYLOAD_NUMERIC;
    1795           0 :                 profile_p->num_payloads[prof]++;
    1796           0 :                 payload++;
    1797           0 :                 continue;
    1798             :             }
    1799             :         }
    1800             : 
    1801             :         /* No string payload types are currently valid for the AAL2
    1802             :          * transport types.  This support can be added when needed. */
    1803           0 :         sdp_parse_error(sdp_p,
    1804             :             "%s Warning: Unsupported payload type "
    1805           0 :             "found (%s).", sdp_p->debug_str, tmp);
    1806             :     }
    1807           0 :     for (i=0; i < profile_p->num_profiles; i++) {
    1808             :         /* Make sure we have payloads for each profile type. */
    1809           0 :         if (profile_p->num_payloads[i] == 0) {
    1810           0 :             sdp_parse_error(sdp_p,
    1811             :                 "%s Warning: No payload types specified "
    1812           0 :                 "for AAL2 profile %s.", sdp_p->debug_str,
    1813             :                 sdp_get_transport_name(profile_p->profile[i]));
    1814             :         }
    1815             :     }
    1816           0 :     return (SDP_SUCCESS);
    1817             : }

Generated by: LCOV version 1.13