static int l_siplua_pseudoVar(lua_State *L) { struct sipapi_object *o; const char *name; str s; pv_elem_t *model; int buf_size = 4096; char *out; o = luaL_checkudata(L, 1, "siplua.api"); name = luaL_checkstring(L, 2); s.s = (char *)name; s.len = strlen(name); if (pv_parse_format(&s, &model) < 0) { lua_pushnil(L); return 1; } out = pkg_malloc(buf_size); if (!out) { pv_elem_free_all(model); return luaL_error(L, "Not enough memory"); } if (pv_printf(o->msg, model, out, &buf_size) < 0) lua_pushnil(L); else lua_pushstring(L, out); pkg_free(out); pv_elem_free_all(model); return 1; }
/** * Compile a string with pseudo variables substituted by their values. * A string buffer is allocated. Deallocate afterwards! */ char *pv_sprintf(struct sip_msg *m, char *fmt) { int buf_size = 4096; pv_elem_t *model; str s; char *out = (char *)pkg_malloc(buf_size); char *ret = NULL; if (!out) { LM_ERR("pv_sprintf: Memory exhausted!\n"); return NULL; } s.s = fmt; s.len = strlen(s.s); if(pv_parse_format(&s, &model) < 0) { LM_ERR("pv_sprintf: ERROR: wrong format[%s]!\n", fmt); return NULL; } if(pv_printf(m, model, out, &buf_size) < 0) { ret = NULL; } else { ret = strdup(out); } pv_elem_free_all(model); pkg_free(out); return ret; }
static void destroy(void) { if (auth_db_handle) { auth_dbf.close(auth_db_handle); auth_db_handle = 0; } if (credentials) { pv_elem_free_all(credentials); credentials = 0; credentials_n = 0; } }
/** fparam_t free function. * Frees the "content" of a fparam, but not the fparam itself. * Note: it doesn't free fp->orig! * Assumes pkg_malloc'ed content. * @param fp - fparam to be freed * */ void fparam_free_contents(fparam_t* fp) { if (fp==0) return; switch(fp->type) { case FPARAM_UNSPEC: case FPARAM_STRING: /* asciiz string, not str */ case FPARAM_INT: case FPARAM_STR: /* nothing to do */ break; case FPARAM_REGEX: if (fp->v.regex){ regfree(fp->v.regex); pkg_free(fp->v.regex); fp->v.regex=0; } break; case FPARAM_AVP: free_avp_name(&fp->v.avp.flags, &fp->v.avp.name); break; case FPARAM_SELECT: if (fp->v.select){ free_select(fp->v.select); fp->v.select=0; } break; case FPARAM_SUBST: if (fp->v.subst){ subst_expr_free(fp->v.subst); fp->v.subst=0; } break; case FPARAM_PVS: if (fp->v.pvs){ pv_spec_free(fp->v.pvs); fp->v.pvs=0; } break; case FPARAM_PVE: if (fp->v.pve){ pv_elem_free_all(fp->v.pve); fp->v.pve=0; } break; } }
/* * Parse extra credentials list */ int parse_aaa_pvs(char *definition, pv_elem_t **pv_def, int *cnt) { pv_elem_t *pve; str pv; char *p; char *end; char *sep; p = definition; if (p==0 || *p==0) return 0; *pv_def = 0; *cnt = 0; /* get element by element */ while ( (end=strchr(p,';'))!=0 || (end=p+strlen(p))!=p ) { /* new pv_elem_t */ if ( (pve=(pv_elem_t*)pkg_malloc(sizeof(pv_elem_t)))==0 ) { LM_ERR("no more pkg mem\n"); goto error; } memset( pve, 0, sizeof(pv_elem_t)); /* definition is between p and e */ /* search backwards because PV definition may contain '=' characters */ for (sep = end; sep >= p && *sep != '='; sep--); if (sep > p) { /* pv=column style */ /* set column name */ pve->text.s = sep + 1; pve->text.len = end - pve->text.s; trim(&pve->text); if (pve->text.len == 0) { goto parse_error; } /* set pv spec */ pv.s = p; pv.len = sep - p; trim(&pv); if (pv.len == 0) { goto parse_error; } } else { /* no pv, only column name */ pve->text.s = p; pve->text.len = end - pve->text.s; trim(&pve->text); if (pve->text.len == 0) { goto parse_error; } /* create an avp definition for the spec parser */ pv.s = (char*)pkg_malloc(pve->text.len + 7); if (pv.s == NULL) { LM_ERR("no more pkg mem\n"); goto parse_error; } pv.len = snprintf(pv.s, pve->text.len + 7, "$avp(%.*s)", pve->text.len, pve->text.s); } /* create a pv spec */ LM_DBG("column: %.*s pv: %.*s\n", pve->text.len, pve->text.s, pv.len, pv.s); pve->spec = pv_spec_lookup(&pv, NULL); if(pve->spec==NULL || pve->spec->setf == NULL) { LM_ERR("PV is not writeable: %.*s\n", pv.len, pv.s); goto parse_error; } /* link the element */ pve->next = *pv_def; *pv_def = pve; (*cnt)++; pve = 0; /* go to the end */ p = end; if (*p==';') { p++; } if (*p==0) { break; } } return 0; parse_error: LM_ERR("parse failed in \"%s\" at pos %d(%s)\n", definition, (int)(long)(p-definition),p); error: pkg_free( pve ); pv_elem_free_all( *pv_def ); *pv_def = 0; *cnt = 0; return -1; }
int process_body(struct sip_msg* msg, str notify_body, udomain_t * domain) { xmlDocPtr doc = NULL; xmlNodePtr doc_root = NULL, registrations = NULL, contacts = NULL, uris = NULL; str aor = {0, 0}; str callid = {0, 0}; str contact_uri = {0, 0}; str received = {0, 0}; str path = {0, 0}; str user_agent = {0, 0}; int reg_state, contact_state, event, expires, result, final_result = RESULT_ERROR; char * expires_char=0, * cseq_char=0, *registration_state=0, *contact_state_s=0, *event_s=0; int cseq = 0; pv_elem_t *presentity_uri_pv; doc = xmlParseMemory(notify_body.s, notify_body.len); if (doc == NULL) { LM_ERR("Error while parsing the xml body message, Body is:\n%.*s\n", notify_body.len, notify_body.s); return -1; } doc_root = xmlGetNodeByName(doc->children, "reginfo"); if (doc_root == NULL) { LM_ERR("while extracting the reginfo node\n"); goto error; } registrations = doc_root->children; while (registrations) { /* Only process registration sub-items */ if (xmlStrcasecmp(registrations->name, BAD_CAST "registration") != 0) goto next_registration; registration_state = xmlGetAttrContentByName(registrations, "state"); reg_state = reginfo_parse_state(registration_state); if (reg_state == STATE_UNKNOWN) { LM_ERR("No state for this registration!\n"); goto next_registration; } aor.s = xmlGetAttrContentByName(registrations, "aor"); if (aor.s == NULL) { LM_ERR("No AOR for this registration!\n"); goto next_registration; } aor.len = strlen(aor.s); LM_DBG("AOR %.*s has reg_state \"%d\"\n", aor.len, aor.s, reg_state); if (reg_state == STATE_TERMINATED) { //TODO we if there is a IMPU record state here we should delete all contacts associated to it //Right now we do it go through all the contacts LM_DBG("AOR %.*s is in state terminated so unsubscribing from reginfo\n", aor.len, aor.s); //we return a successful result here even if no contacts final_result = RESULT_TERMINATED_SUCCESS; if (pv_parse_format(&aor, &presentity_uri_pv) < 0) { LM_ERR("wrong format[%.*s] - failed unsubscribing to reginfo\n", aor.len, aor.s); } reginfo_subscribe_real(msg, presentity_uri_pv, 0, 0); pv_elem_free_all(presentity_uri_pv); } /* Now lets process the Contact's from this Registration: */ contacts = registrations->children; while (contacts) { if (xmlStrcasecmp(contacts->name, BAD_CAST "contact") != 0) goto next_contact; callid.s = xmlGetAttrContentByName(contacts, "callid"); if (callid.s == NULL) { LM_DBG("No Call-ID for this contact!\n"); callid.len = 0; } else { callid.len = strlen(callid.s); LM_DBG("contact has callid <%.*s>\n", callid.len, callid.s); } received.s = xmlGetAttrContentByName(contacts, "received"); if (received.s == NULL) { LM_DBG("No received for this contact!\n"); received.len = 0; } else { received.len = strlen(received.s); LM_DBG("contact has received <%.*s>\n", received.len, received.s); } path.s = xmlGetAttrContentByName(contacts, "path"); if (path.s == NULL) { LM_DBG("No path for this contact!\n"); path.len = 0; } else { path.len = strlen(path.s); LM_DBG("contact has path <%.*s>\n", path.len, path.s); } user_agent.s = xmlGetAttrContentByName(contacts, "user_agent"); if (user_agent.s == NULL) { LM_DBG("No user_agent for this contact!\n"); user_agent.len = 0; } else { user_agent.len = strlen(user_agent.s); LM_DBG("contact has user_agent <%.*s>\n", user_agent.len, user_agent.s); } event_s = xmlGetAttrContentByName(contacts, "event"); event = reginfo_parse_event(event_s); if (event == EVENT_UNKNOWN) { LM_ERR("No event for this contact - going to next contact!\n"); goto next_contact; } expires_char = xmlGetAttrContentByName(contacts, "expires"); if (expires_char == NULL) { LM_ERR("No expires for this contact - going to next contact!\n"); goto next_contact; } expires = atoi(expires_char); if (expires < 0) { LM_ERR("No valid expires for this contact - going to next contact!\n"); goto next_contact; } contact_state_s = xmlGetAttrContentByName(contacts, "state"); contact_state = reginfo_parse_state(contact_state_s); if (contact_state == STATE_UNKNOWN) { LM_ERR("No state for this contact - going to next contact!\n"); goto next_contact; } LM_DBG("Contact state %d: Event \"%d\", expires %d\n", contact_state, event, expires); cseq_char = xmlGetAttrContentByName(contacts, "cseq"); if (cseq_char == NULL) { LM_DBG("No cseq for this contact!\n"); } else { cseq = atoi(cseq_char); if (cseq < 0) { LM_DBG("No valid cseq for this contact!\n"); } } /* Now lets process the URI's from this Contact: */ uris = contacts->children; while (uris) { if (xmlStrcasecmp(uris->name, BAD_CAST "uri") != 0) goto next_uri; contact_uri.s = (char*) xmlNodeGetContent(uris); if (contact_uri.s == NULL) { LM_ERR("No URI for this contact - going to next registration!\n"); goto next_registration; } contact_uri.len = strlen(contact_uri.s); LM_DBG("Contact: %.*s\n", contact_uri.len, contact_uri.s); /* Add to Usrloc: */ result = process_contact(domain, expires, contact_uri, contact_state); if (contact_uri.s && (strlen(contact_uri.s)>0)) { xmlFree(contact_uri.s); contact_uri.s = NULL; } /* Process the result */ if (final_result != RESULT_CONTACTS_FOUND) final_result = result; next_uri: uris = uris->next; } next_contact: if (cseq_char && (strlen(cseq_char)>0)) { xmlFree(cseq_char); cseq_char=NULL; } if (expires_char && (strlen(expires_char)>0)) { xmlFree(expires_char); expires_char = NULL; } if (user_agent.s && (strlen(user_agent.s)>0)) { xmlFree(user_agent.s); user_agent.s = NULL; } if (path.s && (strlen(path.s)>0)) { xmlFree(path.s); path.s = NULL; } if (received.s && (strlen(received.s)>0)) { xmlFree(received.s); received.s = NULL; } if (callid.s && (strlen(callid.s)>0)) { xmlFree(callid.s); callid.s = NULL; } if (contact_state_s && (strlen(contact_state_s)>0)) { xmlFree(contact_state_s); contact_state_s = NULL; } if (event_s && (strlen(event_s)>0)) { xmlFree(event_s); event_s = NULL; } contacts = contacts->next; } next_registration: // if (ul_record) ul.release_urecord(ul_record); /* Unlock the domain for this AOR: */ //if (aor_key.len > 0) // ul.unlock_udomain(domain, &aor_key); if (registration_state && (strlen(registration_state)>0)) { xmlFree(registration_state); registration_state = NULL; } if (aor.len > 0 && aor.s) { xmlFree(aor.s); aor.s = NULL; aor.len = 0; } registrations = registrations->next; } error: /* Free the XML-Document */ if (doc) xmlFreeDoc(doc); return final_result; }
int pv_parse_format(str *in, pv_elem_p *el) { char *p, *p0; int n = 0; pv_elem_p e, e0; str s; int len; if(in==NULL || in->s==NULL || el==NULL) return -1; /*LM_DBG("parsing [%.*s]\n", in->len, in->s);*/ if(in->len == 0) { *el = pkg_malloc(sizeof(pv_elem_t)); if(*el == NULL) goto error; memset(*el, 0, sizeof(pv_elem_t)); (*el)->text = *in; return 0; } p = in->s; *el = NULL; e = e0 = NULL; while(is_in_str(p,in)) { e0 = e; e = pkg_malloc(sizeof(pv_elem_t)); if(!e) goto error; memset(e, 0, sizeof(pv_elem_t)); n++; if(*el == NULL) *el = e; if(e0) e0->next = e; e->text.s = p; while(is_in_str(p,in) && *p!=PV_MARKER) p++; e->text.len = p - e->text.s; if(*p == '\0' || !is_in_str(p,in)) break; s.s = p; s.len = in->s+in->len-p; e->spec = pv_spec_lookup(&s, &len); if(e->spec==NULL) goto error; p0 = p + len; if(*p0 == '\0') break; p = p0; } /*LM_DBG("format parsed OK: [%d] items\n", n);*/ if(*el == NULL) return -1; return 0; error: pv_elem_free_all(*el); *el = NULL; return -1; }
/** * Save the contacts and their associated public ids. * @param rpl - the SIP Register 200 OK response that contains the Expire and Contact and P-associated-uri headers * @param _d - domain * @param _cflags - flags * @returns #CSCF_RETURN_TRUE if OK, #CSCF_RETURN_ERROR on error */ int save(struct sip_msg* _m, udomain_t* _d, int _cflags) { struct sip_msg* req; int expires_hdr = 0; contact_body_t* cb = 0; str *public_ids=0; int num_public_ids = 0; str *service_routes=0; int num_service_routes = 0; pv_elem_t *presentity_uri_pv; //get request from reply req = get_request_from_reply(_m); if (!req) { LM_ERR("Unable to get request from reply for REGISTER. No transaction\n"); goto error; } expires_hdr = cscf_get_expires_hdr(_m, 0); cb = cscf_parse_contacts(_m); if (!cb || (!cb->contacts && !cb->star)) { LM_DBG("No contact headers and not *\n"); goto error; } cscf_get_p_associated_uri(_m, &public_ids, &num_public_ids, 1); service_routes = cscf_get_service_route(_m, &num_service_routes, 1); //update contacts if (!update_contacts(req, _m, _d, cb->star, expires_hdr, public_ids, num_public_ids, service_routes, num_service_routes, 0)) { LM_ERR("failed to update pcontact\n"); goto error; } if(subscribe_to_reginfo == 1){ //use the first p_associated_uri - i.e. the default IMPU LM_DBG("Subscribe to reg event for primary p_associated_uri"); if(num_public_ids > 0){ //find the first routable (not a tel: URI and use that that presentity) //if you can not find one then exit int i = 0; int found_presentity_uri=0; while (i < num_public_ids && found_presentity_uri == 0) { //check if public_id[i] is NOT a tel URI - if it isn't then concert to pv format and set found presentity_uri to 1 if (strncasecmp(public_ids[i].s,"tel:",4)==0) { LM_DBG("This is a tel URI - it is not routable so we don't use it to subscribe"); i++; } else { //convert primary p_associated_uri to pv_elem_t if(pv_parse_format(&public_ids[i], &presentity_uri_pv)<0) { LM_ERR("wrong format[%.*s]\n",public_ids[i].len, public_ids[i].s); goto error; } found_presentity_uri=1; } } if(found_presentity_uri!=1){ LM_ERR("Could not find routable URI in p_assoiated_uri list - failed to subscribe"); goto error; } }else{ //Now some how check if there is a pua record and what the presentity uri is from there - if nothing there LM_DBG("No p_associated_uri in 200 OK this must be a de-register - we ignore this - will unsubscribe when the notify is received"); goto done; } reginfo_subscribe_real(_m, presentity_uri_pv, service_routes, subscription_expires); pv_elem_free_all(presentity_uri_pv); } done: if (public_ids && public_ids->s) pkg_free(public_ids); if (service_routes && service_routes->s) pkg_free(service_routes); return 1; error: if (public_ids && public_ids->s) pkg_free(public_ids); if (service_routes && service_routes->s) pkg_free(service_routes); return -1; }
int do_acc_fixup(void** param, int param_no) { str s; pv_elem_p el; unsigned long long ival; unsigned long long* ival_p; acc_type_param_t* acc_param; do_acc_parser parser; if (param_no < 1 || param_no > 3) { LM_ERR("invalid param_no <%d>!\n", param_no); return -1; } switch (param_no) { case 1: parser=do_acc_type_parser; s.s = *param; s.len = strlen(s.s); if (pv_parse_format(&s, &el) < 0) { LM_ERR("invalid format <%.*s>!\n", s.len, s.s); return -1; } acc_param=pkg_malloc(sizeof(acc_type_param_t)); if (acc_param == NULL) { LM_ERR("no more pkg mem!\n"); return -1; } memset(acc_param, 0, sizeof(acc_type_param_t)); if (el->next == 0 && el->spec.getf == 0) { pv_elem_free_all(el); if ( (ival=do_acc_parse(&el->text, parser)) < 0) { LM_ERR("Invalid value <%.*s>!\n", el->text.len, el->text.s); return -1; } acc_param->t = DO_ACC_PARAM_TYPE_VALUE; acc_param->u.ival = ival; } else { acc_param->t = DO_ACC_PARAM_TYPE_PV; acc_param->u.pval = el; } *param = acc_param; break; case 2: parser=do_acc_flags_parser; s.s = *param; s.len = strlen(s.s); if ( (ival=do_acc_parse(&s, parser)) < 0) { LM_ERR("Invalid value <%.*s>!\n", s.len, s.s); return -1; } if ((ival_p=pkg_malloc(sizeof(unsigned long long))) == NULL) { LM_ERR("no more pkg mem!\n"); return -1; } *ival_p = ival; *param = ival_p; break; case 3: return fixup_sgp(param); } return 0; }