/*! \brief * This method is used to parse DIVERSION header. * * params: msg : sip msg * returns 0 on success, * -1 on failure. */ int parse_diversion_header(struct sip_msg *msg) { struct to_body* diversion_b; if (!msg->diversion && (parse_headers(msg, HDR_DIVERSION_F, 0) == -1 || !msg->diversion)) { goto error; } /* maybe the header is already parsed! */ if (msg->diversion->parsed) return 0; /* bad luck! :-( - we have to parse it */ /* first, get some memory */ diversion_b = pkg_malloc(sizeof(struct to_body)); if (diversion_b == 0) { LOG(L_ERR, "ERROR:parse_diversion_header: out of pkg_memory\n"); goto error; } /* now parse it!! */ memset(diversion_b, 0, sizeof(struct to_body)); parse_to(msg->diversion->body.s, msg->diversion->body.s + msg->diversion->body.len + 1, diversion_b); if (diversion_b->error == PARSE_ERROR) { LOG(L_ERR, "ERROR:parse_diversion_header: bad diversion header\n"); free_to(diversion_b); goto error; } msg->diversion->parsed = diversion_b; return 0; error: return -1; }
/*! \brief * This method is used to parse RPID header. * * params: msg : sip msg * returns 0 on success, * -1 on failure. */ int parse_rpid_header( struct sip_msg *msg ) { struct to_body* rpid_b; if ( !msg->rpid && (parse_headers(msg, HDR_RPID_F, 0)==-1 || !msg->rpid)) { goto error; } /* maybe the header is already parsed! */ if (msg->rpid->parsed) return 0; /* bad luck! :-( - we have to parse it */ /* first, get some memory */ rpid_b = pkg_malloc(sizeof(struct to_body)); if (rpid_b == 0) { LOG(L_ERR, "ERROR:parse_rpid_header: out of pkg_memory\n"); goto error; } /* now parse it!! */ memset(rpid_b, 0, sizeof(struct to_body)); parse_to(msg->rpid->body.s,msg->rpid->body.s+msg->rpid->body.len+1,rpid_b); if (rpid_b->error == PARSE_ERROR) { LOG(L_ERR, "ERROR:parse_rpid_header: bad rpid header\n"); free_to(rpid_b); goto error; } msg->rpid->parsed = rpid_b; return 0; error: return -1; }
/*! \brief * This method is used to parse the from header. * * \note It was decided not to parse * anything in core that is not *needed* so this method gets called by * rad_acc module and any other modules that needs the FROM header. * * params: msg : sip msg * returns 0 on success, * -1 on failure. */ int parse_from_header( struct sip_msg *msg) { struct to_body* from_b; if ( !msg->from && ( parse_headers(msg,HDR_FROM_F,0)==-1 || !msg->from)) { LOG(L_ERR,"ERROR:parse_from_header: bad msg or missing FROM header\n"); goto error; } /* maybe the header is already parsed! */ if (msg->from->parsed) return 0; /* bad luck! :-( - we have to parse it */ /* first, get some memory */ from_b = pkg_malloc(sizeof(struct to_body)); if (from_b == 0) { LOG(L_ERR, "ERROR:parse_from_header: out of pkg_memory\n"); goto error; } /* now parse it!! */ memset(from_b, 0, sizeof(struct to_body)); parse_to(msg->from->body.s,msg->from->body.s+msg->from->body.len+1,from_b); if (from_b->error == PARSE_ERROR) { LOG(L_ERR, "ERROR:parse_from_header: bad from header [%.*s]\n", msg->from->body.len, msg->from->body.s); free_to(from_b); goto error; } msg->from->parsed = from_b; return 0; error: return -1; }
/* returns pointer to next header line, and fill hdr_f ; * if at end of header returns pointer to the last crlf (always buf)*/ char* get_hdr_field(char* const buf, char* const end, struct hdr_field* const hdr) { char *tmp = 0; char *match; struct via_body *vb; struct cseq_body* cseq_b; struct to_body* to_b; int integer, err; unsigned uval; if(!buf) { DBG("null buffer pointer\n"); goto error; } if ((*buf)=='\n' || (*buf)=='\r') { /* double crlf or lflf or crcr */ DBG("found end of header\n"); hdr->type=HDR_EOH_T; return buf; } tmp=parse_hname(buf, end, hdr); if (hdr->type==HDR_ERROR_T) { LOG(L_ERR, "ERROR: get_hdr_field: bad header\n"); goto error; } /* eliminate leading whitespace */ tmp=eat_lws_end(tmp, end); if (tmp>=end) { LOG(L_ERR, "ERROR: get_hdr_field: HF empty\n"); goto error; } /* if header-field well-known, parse it, find its end otherwise ; * after leaving the hdr->type switch, tmp should be set to the * next header field */ switch(hdr->type) { case HDR_VIA_T: /* keep number of vias parsed -- we want to report it in replies for diagnostic purposes */ via_cnt++; vb=pkg_malloc(sizeof(struct via_body)); if (vb==0) { LOG(L_ERR, "get_hdr_field: out of memory\n"); goto error; } memset(vb,0,sizeof(struct via_body)); hdr->body.s=tmp; tmp=parse_via(tmp, end, vb); if (vb->error==PARSE_ERROR) { LOG(L_ERR, "ERROR: get_hdr_field: bad via\n"); free_via_list(vb); goto error; } hdr->parsed=vb; vb->hdr.s=hdr->name.s; vb->hdr.len=hdr->name.len; hdr->body.len=tmp-hdr->body.s; break; case HDR_CSEQ_T: cseq_b=pkg_malloc(sizeof(struct cseq_body)); if (cseq_b==0) { LOG(L_ERR, "get_hdr_field: out of memory\n"); goto error; } memset(cseq_b, 0, sizeof(struct cseq_body)); hdr->body.s=tmp; tmp=parse_cseq(tmp, end, cseq_b); if (cseq_b->error==PARSE_ERROR) { LOG(L_ERR, "ERROR: get_hdr_field: bad cseq\n"); free_cseq(cseq_b); goto error; } hdr->parsed=cseq_b; hdr->body.len=tmp-hdr->body.s; DBG("get_hdr_field: cseq <%.*s>: <%.*s> <%.*s>\n", hdr->name.len, ZSW(hdr->name.s), cseq_b->number.len, ZSW(cseq_b->number.s), cseq_b->method.len, cseq_b->method.s); break; case HDR_TO_T: to_b=pkg_malloc(sizeof(struct to_body)); if (to_b==0) { LOG(L_ERR, "get_hdr_field: out of memory\n"); goto error; } memset(to_b, 0, sizeof(struct to_body)); hdr->body.s=tmp; tmp=parse_to(tmp, end,to_b); if (to_b->error==PARSE_ERROR) { LOG(L_ERR, "ERROR: get_hdr_field: bad to header\n"); free_to(to_b); goto error; } hdr->parsed=to_b; hdr->body.len=tmp-hdr->body.s; DBG("DEBUG: get_hdr_field: <%.*s> [%d]; uri=[%.*s] \n", hdr->name.len, ZSW(hdr->name.s), hdr->body.len, to_b->uri.len,ZSW(to_b->uri.s)); DBG("DEBUG: to body [%.*s]\n",to_b->body.len, ZSW(to_b->body.s)); break; case HDR_CONTENTLENGTH_T: hdr->body.s=tmp; tmp=parse_content_length(tmp,end, &integer); if (tmp==0) { LOG(L_ERR, "ERROR:get_hdr_field: bad content_length header\n"); goto error; } hdr->parsed=(void*)(long)integer; hdr->body.len=tmp-hdr->body.s; DBG("DEBUG: get_hdr_body : content_length=%d\n", (int)(long)hdr->parsed); break; case HDR_RETRY_AFTER_T: hdr->body.s=tmp; tmp=parse_retry_after(tmp,end, &uval, &err); if (err) { LOG(L_ERR, "ERROR:get_hdr_field: bad retry_after header\n"); goto error; } hdr->parsed=(void*)(unsigned long)uval; hdr->body.len=tmp-hdr->body.s; DBG("DEBUG: get_hdr_body : retry_after=%d\n", (unsigned)(long)hdr->parsed); break; case HDR_IDENTITY_T: case HDR_DATE_T: case HDR_IDENTITY_INFO_T: case HDR_SUPPORTED_T: case HDR_REQUIRE_T: case HDR_CONTENTTYPE_T: case HDR_FROM_T: case HDR_CALLID_T: case HDR_CONTACT_T: case HDR_ROUTE_T: case HDR_RECORDROUTE_T: case HDR_MAXFORWARDS_T: case HDR_AUTHORIZATION_T: case HDR_EXPIRES_T: case HDR_PROXYAUTH_T: case HDR_PROXYREQUIRE_T: case HDR_UNSUPPORTED_T: case HDR_ALLOW_T: case HDR_EVENT_T: case HDR_ACCEPT_T: case HDR_ACCEPTLANGUAGE_T: case HDR_ORGANIZATION_T: case HDR_PRIORITY_T: case HDR_SUBJECT_T: case HDR_USERAGENT_T: case HDR_SERVER_T: case HDR_CONTENTDISPOSITION_T: case HDR_DIVERSION_T: case HDR_RPID_T: case HDR_SIPIFMATCH_T: case HDR_REFER_TO_T: case HDR_SESSIONEXPIRES_T: case HDR_MIN_SE_T: case HDR_SUBSCRIPTION_STATE_T: case HDR_ACCEPTCONTACT_T: case HDR_ALLOWEVENTS_T: case HDR_CONTENTENCODING_T: case HDR_REFERREDBY_T: case HDR_REJECTCONTACT_T: case HDR_REQUESTDISPOSITION_T: case HDR_WWW_AUTHENTICATE_T: case HDR_PROXY_AUTHENTICATE_T: case HDR_PATH_T: case HDR_PRIVACY_T: case HDR_PAI_T: case HDR_PPI_T: case HDR_REASON_T: case HDR_OTHER_T: /* just skip over it */ hdr->body.s=tmp; /* find end of header */ /* find lf */ do { match=q_memchr(tmp, '\n', end-tmp); if (match) { match++; } else { LOG(L_ERR, "ERROR: get_hdr_field: bad body for <%s>(%d)\n", hdr->name.s, hdr->type); /* abort(); */ tmp=end; goto error; } tmp=match; } while( match<end &&( (*match==' ')||(*match=='\t') ) ); tmp=match; hdr->body.len=match-hdr->body.s; break; default: LOG(L_CRIT, "BUG: get_hdr_field: unknown header type %d\n", hdr->type); goto error; } /* jku: if \r covered by current length, shrink it */ trim_r( hdr->body ); hdr->len=tmp-hdr->name.s; return tmp; error: DBG("get_hdr_field: error exit\n"); STATS_BAD_MSG_HDR(); hdr->type=HDR_ERROR_T; hdr->len=tmp-hdr->name.s; return tmp; }
/** Frees a hdr_field structure. * WARNING: it frees only parsed (and not name.s, body.s) */ void clean_hdr_field(struct hdr_field* const hf) { void** h_parsed; if (hf->parsed){ h_parsed=&hf->parsed; /* strict aliasing warnings workarround */ switch(hf->type){ /* headers with pkg alloc for parsed structure (alphabetic order) */ case HDR_ACCEPT_T: pkg_free(hf->parsed); break; case HDR_ALLOW_T: free_allow_header(hf); break; case HDR_AUTHORIZATION_T: free_credentials((auth_body_t**)h_parsed); break; case HDR_CONTACT_T: free_contact((contact_body_t**)h_parsed); break; case HDR_CONTENTDISPOSITION_T: free_disposition( ((struct disposition**)h_parsed)); break; case HDR_CSEQ_T: free_cseq(hf->parsed); break; case HDR_DATE_T: free_date(hf->parsed); break; case HDR_DIVERSION_T: free_to(hf->parsed); break; case HDR_EVENT_T: free_event((event_t**)h_parsed); break; case HDR_EXPIRES_T: free_expires((exp_body_t**)h_parsed); break; case HDR_FROM_T: free_to(hf->parsed); break; case HDR_IDENTITY_INFO_T: free_identityinfo(hf->parsed); break; case HDR_IDENTITY_T: free_identity(hf->parsed); break; case HDR_PAI_T: free_pai_ppi_body(hf->parsed); break; case HDR_PPI_T: free_pai_ppi_body(hf->parsed); break; case HDR_PROXYAUTH_T: free_credentials((auth_body_t**)h_parsed); break; case HDR_RECORDROUTE_T: free_rr((rr_t**)h_parsed); break; case HDR_REFER_TO_T: free_to(hf->parsed); break; case HDR_ROUTE_T: free_rr((rr_t**)h_parsed); break; case HDR_RPID_T: free_to(hf->parsed); break; case HDR_SESSIONEXPIRES_T: hdr_free_parsed(h_parsed); break; case HDR_SIPIFMATCH_T: free_sipifmatch((str **)h_parsed); break; case HDR_SUBSCRIPTION_STATE_T: free_subscription_state((subscription_state_t**)h_parsed); break; case HDR_SUPPORTED_T: hdr_free_parsed(h_parsed); break; case HDR_TO_T: free_to(hf->parsed); break; case HDR_VIA_T: free_via_list(hf->parsed); break; /* headers with no alloc for parsed structure */ case HDR_CALLID_T: case HDR_MAXFORWARDS_T: case HDR_CONTENTTYPE_T: case HDR_CONTENTLENGTH_T: case HDR_RETRY_AFTER_T: case HDR_REQUIRE_T: case HDR_PROXYREQUIRE_T: case HDR_UNSUPPORTED_T: case HDR_ACCEPTLANGUAGE_T: case HDR_ORGANIZATION_T: case HDR_PRIORITY_T: case HDR_SUBJECT_T: case HDR_USERAGENT_T: case HDR_SERVER_T: case HDR_MIN_SE_T: case HDR_ACCEPTCONTACT_T: case HDR_ALLOWEVENTS_T: case HDR_CONTENTENCODING_T: case HDR_REFERREDBY_T: case HDR_REJECTCONTACT_T: case HDR_REQUESTDISPOSITION_T: case HDR_WWW_AUTHENTICATE_T: case HDR_PROXY_AUTHENTICATE_T: case HDR_PATH_T: case HDR_PRIVACY_T: case HDR_REASON_T: break; default: LOG(L_CRIT, "BUG: clean_hdr_field: unknown header type %d\n", hf->type); break; } } }
/* * Frees a hdr_field structure, * WARNING: it frees only parsed (and not name.s, body.s) */ void clean_hdr_field(struct hdr_field* hf) { if (hf->parsed){ switch(hf->type){ case HDR_VIA_T: free_via_list(hf->parsed); hf->parsed = NULL; break; case HDR_TO_T: free_to(hf->parsed); hf->parsed = NULL; break; case HDR_FROM_T: free_to(hf->parsed); hf->parsed = NULL; break; case HDR_CSEQ_T: free_cseq(hf->parsed); hf->parsed = NULL; break; case HDR_CALLID_T: break; case HDR_CONTACT_T: free_contact((contact_body_t**)(void*)(&(hf->parsed))); break; case HDR_MAXFORWARDS_T: break; case HDR_ROUTE_T: free_rr((rr_t**)(void*)(&hf->parsed)); break; case HDR_RECORDROUTE_T: free_rr((rr_t**)(void*)(&hf->parsed)); break; case HDR_PATH_T: free_rr((rr_t**)(void*)(&hf->parsed)); break; case HDR_CONTENTTYPE_T: free_contenttype((content_t**)(void*)(&hf->parsed)); break; case HDR_CONTENTLENGTH_T: break; case HDR_AUTHORIZATION_T: free_credentials((auth_body_t**)(void*)(&(hf->parsed))); break; case HDR_EXPIRES_T: free_expires((exp_body_t**)(void*)(&(hf->parsed))); break; case HDR_PROXYAUTH_T: free_credentials((auth_body_t**)(void*)(&(hf->parsed))); break; case HDR_SUPPORTED_T: free_supported((struct supported_body**)(void*)(&(hf->parsed))); break; case HDR_PROXYREQUIRE_T: break; case HDR_UNSUPPORTED_T: break; case HDR_ALLOW_T: free_allow((struct allow_body**)(void*)(&(hf->parsed))); break; case HDR_EVENT_T: free_event((event_t**)(void*)(&(hf->parsed))); break; case HDR_ACCEPT_T: pkg_free(hf->parsed); hf->parsed = NULL; break; case HDR_ACCEPTLANGUAGE_T: break; case HDR_ORGANIZATION_T: break; case HDR_PRIORITY_T: break; case HDR_SUBJECT_T: break; case HDR_USERAGENT_T: break; case HDR_ACCEPTDISPOSITION_T: break; case HDR_CONTENTDISPOSITION_T: free_disposition( ((struct disposition**)(void*)(&hf->parsed)) ); break; case HDR_DIVERSION_T: free_to(hf->parsed); hf->parsed = NULL; break; case HDR_RPID_T: free_to(hf->parsed); hf->parsed = NULL; break; case HDR_REFER_TO_T: free_to(hf->parsed); hf->parsed = NULL; break; case HDR_SESSION_EXPIRES_T: free_session_expires((struct session_expires*)hf->parsed ); hf->parsed = NULL; break; case HDR_MIN_SE_T: break; case HDR_MIN_EXPIRES_T: break; case HDR_PPI_T: free_to(hf->parsed); hf->parsed = NULL; break; case HDR_PAI_T: free_to(hf->parsed); hf->parsed = NULL; break; case HDR_PRIVACY_T: break; case HDR_RETRY_AFTER_T: break; case HDR_CALL_INFO_T: free_call_info(hf->parsed); hf->parsed = NULL; break; case HDR_WWW_AUTHENTICATE_T: case HDR_PROXY_AUTHENTICATE_T: free_authenticate((struct authenticate_body *)hf->parsed); hf->parsed = NULL; break; default: LM_CRIT("unknown header type %d\n", hf->type); break; } } }
/* * Frees a hdr_field structure, * WARNING: it frees only parsed (and not name.s, body.s) */ void clean_hdr_field(struct hdr_field* hf) { if (hf->parsed){ switch(hf->type){ case HDR_VIA: free_via_list(hf->parsed); break; case HDR_TO: free_to(hf->parsed); break; case HDR_FROM: free_to(hf->parsed); break; case HDR_CSEQ: free_cseq(hf->parsed); break; case HDR_CALLID: break; case HDR_CONTACT: free_contact((contact_body_t**)(&(hf->parsed))); break; case HDR_MAXFORWARDS: break; case HDR_ROUTE: free_rr((rr_t**)(&hf->parsed)); break; case HDR_RECORDROUTE: free_rr((rr_t**)(&hf->parsed)); break; case HDR_CONTENTTYPE: break; case HDR_CONTENTLENGTH: break; case HDR_AUTHORIZATION: free_credentials((auth_body_t**)(&(hf->parsed))); break; case HDR_EXPIRES: free_expires((exp_body_t**)(&(hf->parsed))); break; case HDR_PROXYAUTH: free_credentials((auth_body_t**)(&(hf->parsed))); break; case HDR_SUPPORTED: break; case HDR_PROXYREQUIRE: break; case HDR_UNSUPPORTED: break; case HDR_ALLOW: break; case HDR_EVENT: free_event((event_t**)(&(hf->parsed))); break; case HDR_ACCEPT: pkg_free(hf->parsed); break; case HDR_ACCEPTLANGUAGE: break; case HDR_ORGANIZATION: break; case HDR_PRIORITY: break; case HDR_SUBJECT: break; case HDR_USERAGENT: break; case HDR_ACCEPTDISPOSITION: break; case HDR_CONTENTDISPOSITION: free_disposition( ((struct disposition**)(&hf->parsed)) ); break; default: LOG(L_CRIT, "BUG: clean_hdr_field: unknown header type %d\n", hf->type); break; } } }