int get_sip_header_info(struct sip_msg * req, struct sip_msg * reply, int interim, int32_t * acc_record_type, str * sip_method, str * event, uint32_t * expires, str * callid, str * from_uri, str * to_uri){ LOG(L_DBG, "retrieving sip info\n"); sip_method->s = req->first_line.u.request.method.s; sip_method->len = req->first_line.u.request.method.len; if(!interim && sip_method->len == 6 && strncmp(sip_method->s, "INVITE",6) == 0) *acc_record_type = AAA_ACCT_START; else if (sip_method->len == 3 && strncmp(sip_method->s, "BYE",3) == 0) *acc_record_type = AAA_ACCT_STOP; else if (sip_method->len == 7 && strncmp(sip_method->s, "MESSAGE", 7) == 0) *acc_record_type = AAA_ACCT_EVENT; else if(interim && sip_method->len == 6 && (strncmp(sip_method->s, "INVITE", 6) == 0 || strncmp(sip_method->s, "UPDATE", 6) ==0)) *acc_record_type = AAA_ACCT_INTERIM; else *acc_record_type = AAA_ACCT_EVENT; *event = cscf_get_event(req); *expires = cscf_get_expires_hdr(req, 0); *callid = cscf_get_call_id(req, NULL); if(!cscf_get_from_uri(req, from_uri)) goto error; if(!cscf_get_to_uri(req, to_uri)) goto error; LOG(L_DBG, "retrieved sip info : sip_method %.*s acc_record_type %i, event %.*s expires %u " "call_id %.*s from_uri %.*s to_uri %.*s\n", sip_method->len, sip_method->s, *acc_record_type, event->len, event->s, *expires, callid->len, callid->s, from_uri->len, from_uri->s, to_uri->len, to_uri->s); return 1; error: return 0; }
int get_sip_header_info(struct sip_msg * req, struct sip_msg * reply, int32_t * acc_record_type, str * sip_method, str * event, uint32_t * expires, str * callid, str * asserted_id_uri, str * to_uri) { sip_method->s = req->first_line.u.request.method.s; sip_method->len = req->first_line.u.request.method.len; if (strncmp(sip_method->s, "INVITE", 6) == 0) *acc_record_type = AAA_ACCT_START; else if (strncmp(sip_method->s, "BYE", 3) == 0) *acc_record_type = AAA_ACCT_STOP; else *acc_record_type = AAA_ACCT_EVENT; *event = cscf_get_event(req); *expires = cscf_get_expires_hdr(req, 0); *callid = cscf_get_call_id(req, NULL); if ((*asserted_id_uri = cscf_get_asserted_identity(req, 0)).len == 0) { LM_DBG("No P-Asserted-Identity hdr found. Using From hdr"); if (!cscf_get_from_uri(req, asserted_id_uri)) { LM_ERR("Error assigning P-Asserted-Identity using From hdr"); goto error; } } *to_uri = req->first_line.u.request.uri; LM_DBG("retrieved sip info : sip_method %.*s acc_record_type %i, event %.*s expires %u " "call_id %.*s from_uri %.*s to_uri %.*s\n", sip_method->len, sip_method->s, *acc_record_type, event->len, event->s, *expires, callid->len, callid->s, asserted_id_uri->len, asserted_id_uri->s, to_uri->len, to_uri->s); return 1; error: return 0; }
/** * Save this subscription. * @param msg - the SIP SUBSCRIBE message * @param str1 - not used * @param str2 - not used * @returns #CSCF_RETURN_TRUE if allowed, #CSCF_RETURN_FALSE if not, #CSCF_RETURN_ERROR on error */ int S_subscribe(struct sip_msg *msg,char *str1,char *str2) { int ret=CSCF_RETURN_FALSE; struct sip_uri puri; str uri={0,0}; str event; int event_i=IMS_EVENT_NONE; int expires=0,expires_time=0; str subscriber; r_public *p=0; r_subscriber *s=0,*new_s=0; dlg_t *dialog=0; LOG(L_DBG,"DBG:"M_NAME":S_subscribe: Saving SUBSCRIBE\n"); /* First check the parameters */ if (msg->first_line.type!=SIP_REQUEST) { LOG(L_ERR,"ERR:"M_NAME":S_subscribe: This message is not a request\n"); goto error; } if (msg->first_line.u.request.method.len != 9 || memcmp(msg->first_line.u.request.method.s,"SUBSCRIBE",9)!=0) { LOG(L_ERR,"ERR:"M_NAME":S_subscribe: This message is not a SUBSCRIBE\n"); goto error; } /* 1. Get the event */ event = cscf_get_event(msg); if (event.len!=3||strncasecmp(event.s,"reg",3)!=0){ LOG(L_ERR,"ERR:"M_NAME":S_subscribe: Accepting only <Event: reg>. Found: <%.*s>\n", event.len,event.s); ret = CSCF_RETURN_FALSE; goto done; } if (event.len==0 && strncasecmp(event.s,"reg",3)==0) event_i = IMS_EVENT_REG; /* 2. Get the target of the SUBSCRIBE from RequestURI */ if (msg->new_uri.s) uri = msg->new_uri; else uri = msg->first_line.u.request.uri; if (parse_uri(uri.s, uri.len, &puri) < 0) { LOG(L_ERR,"ERR:"M_NAME":S_subscribe: Error parsing uri <%.*s>\n", uri.len,uri.s); goto error; } uri.len = lookup_sip.len+puri.user.len+1+puri.host.len; uri.s = pkg_malloc(uri.len); if (!uri.s){ LOG(L_ERR,"ERR:"M_NAME":S_subscribe: Error allocating %d bytes\n",uri.len); goto error; } uri.len=0; memcpy(uri.s,lookup_sip.s,lookup_sip.len); uri.len+=lookup_sip.len; memcpy(uri.s+uri.len,puri.user.s,puri.user.len); uri.len+=puri.user.len; uri.s[uri.len++]='@'; memcpy(uri.s+uri.len,puri.host.s,puri.host.len); uri.len+=puri.host.len; /* 3. Get the Subscriber's Identity */ subscriber = cscf_get_contact(msg); if (!subscriber.len){ LOG(L_ERR,"ERR:"M_NAME":S_subscribe: Contact empty.\n"); ret = CSCF_RETURN_FALSE; goto done; } LOG(L_DBG,"DBG:"M_NAME":S_subscribe: Contact <%.*s>.\n", subscriber.len,subscriber.s); p = get_r_public(uri); /* Registration is possible even if the user is not registered... so just create one */ if (!p){ p = add_r_public(uri,0,0); } if (!p){ LOG(L_ERR,"ERR:"M_NAME":S_subscribe: Identity not found and error on creation <%.*s>\n", uri.len,uri.s); ret = CSCF_RETURN_FALSE; goto done; } expires = cscf_get_expires_hdr(msg,0); if (expires == -1) expires = subscription_default_expires; if (expires > 0) { if (expires < subscription_min_expires) expires = subscription_min_expires; if (expires > subscription_max_expires) expires = subscription_max_expires; r_act_time(); expires_time = expires + time_now; /* get the old subscriber - if any */ s = get_r_subscriber(p,subscriber,event_i); if (!s){ /* create a new dialog */ if (tmb.new_dlg_uas(msg, 200, &dialog) < 0) { LOG(L_ERR,"ERR:"M_NAME":S_subscribe: Error while creating dialog state\n"); ret = CSCF_RETURN_FALSE; goto error; } }else dialog = s->dialog; /* update the subscriber */ if ((new_s=update_r_subscriber(p,subscriber,event_i,&expires_time,dialog))!=0){ //if (!s) /* Only on first subscription, not on refreshes, send a notify */ S_event_reg(p,0,new_s,IMS_REGISTRAR_SUBSCRIBE,0); ret = CSCF_RETURN_TRUE; } else ret = CSCF_RETURN_FALSE; }else{ /* Unsubscribe */ /* get the old subscriber - if any */ r_act_time(); s = get_r_subscriber(p,subscriber,event_i); if (s) { s->expires = time_now; S_event_reg(p,0,s,IMS_REGISTRAR_UNSUBSCRIBE,1); del_r_subscriber(p,s); } ret = CSCF_RETURN_TRUE; } done: r_unlock(p->hash); if (expires ==0 )S_SUBSCRIBE_reply(msg,200,MSG_REG_UNSUBSCRIBE_OK,&expires,&uri); else S_SUBSCRIBE_reply(msg,200,MSG_REG_SUBSCRIBE_OK,&expires,&uri); if (uri.s) pkg_free(uri.s); return ret; error: if (p) r_unlock(p->hash); if (uri.s) pkg_free(uri.s); ret=CSCF_RETURN_FALSE; return ret; }
/** * Check if this message quallifies for a subscription. * Only 3 entities can subscribe: * - the user agent to its own state * - the P-CSCF specified in a Path header for that user * - AS (not implemented yet * \todo Allow also the AS listed in iFC and not belonging to a 3rd party * @param msg - the SIP SUBSCRIBE message * @param str1 - not used * @param str2 - not used * @returns #CSCF_RETURN_TRUE if allowed, #CSCF_RETURN_FALSE if not, #CSCF_RETURN_ERROR on error */ int S_can_subscribe(struct sip_msg *msg,char *str1,char *str2) { int ret=CSCF_RETURN_FALSE; struct sip_uri puri; str uri={0,0}; str event; str asserted_id; r_public *p=0; r_contact *c=0; ims_public_identity *pi=0; int i,j; LOG(L_DBG,"DBG:"M_NAME":S_can_subscribe: Checking if allowed to SUBSCRIBE\n"); /* First check the parameters */ if (msg->first_line.type!=SIP_REQUEST) { LOG(L_ERR,"ERR:"M_NAME":S_can_subscribe: This message is not a request\n"); goto error; } if (msg->first_line.u.request.method.len != 9 || memcmp(msg->first_line.u.request.method.s,"SUBSCRIBE",9)!=0) { LOG(L_ERR,"ERR:"M_NAME":S_can_subscribe: This message is not a SUBSCRIBE\n"); goto error; } /* 1. Get the event */ event = cscf_get_event(msg); if (event.len!=3||strncasecmp(event.s,"reg",3)!=0){ LOG(L_ERR,"ERR:"M_NAME":S_can_subscribe: Accepting only <Event: reg>. Found: <%.*s>\n", event.len,event.s); ret = CSCF_RETURN_FALSE; goto done; } /* 2. Get the target of the SUBSCRIBE from RequestURI */ if (msg->new_uri.s) uri = msg->new_uri; else uri = msg->first_line.u.request.uri; if (parse_uri(uri.s, uri.len, &puri) < 0) { LOG(L_ERR,"ERR:"M_NAME":S_can_subscribe: Error parsing uri <%.*s>\n", uri.len,uri.s); goto error; } uri.len = lookup_sip.len+puri.user.len+1+puri.host.len; uri.s = pkg_malloc(uri.len); if (!uri.s){ LOG(L_ERR,"ERR:"M_NAME":S_can_subscribe: Error allocating %d bytes\n",uri.len); goto error; } uri.len=0; memcpy(uri.s,lookup_sip.s,lookup_sip.len); uri.len+=lookup_sip.len; memcpy(uri.s+uri.len,puri.user.s,puri.user.len); uri.len+=puri.user.len; uri.s[uri.len++]='@'; memcpy(uri.s+uri.len,puri.host.s,puri.host.len); uri.len+=puri.host.len; /* 3. Check if the asserted identity is in the same group with the ReqURI */ asserted_id = cscf_get_asserted_identity(msg); if (!asserted_id.len){ LOG(L_ERR,"ERR:"M_NAME":S_can_subscribe: P-Asserted-Identity empty.\n"); ret = CSCF_RETURN_FALSE; goto done; } LOG(L_DBG,"DBG:"M_NAME":S_can_subscribe: P-Asserted-Identity <%.*s>.\n", asserted_id.len,asserted_id.s); p = get_r_public(uri); if (!p){ LOG(L_ERR,"ERR:"M_NAME":S_can_subscribe: Identity not found <%.*s>\n", uri.len,uri.s); ret = CSCF_RETURN_FALSE; goto done; } if (p->aor.len == asserted_id.len && strncasecmp(p->aor.s,asserted_id.s,asserted_id.len)==0) { LOG(L_DBG,"DBG:"M_NAME":S_can_subscribe: Identity found as AOR <%.*s>\n", uri.len,uri.s); ret = CSCF_RETURN_TRUE; goto done; } if (p->s){ for(i=0;i<p->s->service_profiles_cnt;i++) for(j=0;j<p->s->service_profiles[i].public_identities_cnt;j++) { pi = &(p->s->service_profiles[i].public_identities[j]); if (!pi->barring && pi->public_identity.len == asserted_id.len && strncasecmp(pi->public_identity.s,asserted_id.s,asserted_id.len)==0) { LOG(L_DBG,"DBG:"M_NAME":S_can_subscribe: Identity found in SP[%d][%d]\n", i,j); ret = CSCF_RETURN_TRUE; goto done; } } } /* 4. Check if it present in any of the Path headers */ c=p->head; while(c){ if (c->path.len){ for(i=0;i<c->path.len-asserted_id.len;i++) if (strncasecmp(c->path.s+i,asserted_id.s,asserted_id.len)==0){ LOG(L_DBG,"DBG:"M_NAME":S_can_subscribe: Identity found in Path <%.*s>\n", c->path.len,c->path.s); ret = CSCF_RETURN_TRUE; goto done; } } c = c->next; } done: if (p) r_unlock(p->hash); if (uri.s) pkg_free(uri.s); return ret; error: if (p) r_unlock(p->hash); if (uri.s) pkg_free(uri.s); ret=CSCF_RETURN_ERROR; return ret; }
/** * Saves a dialog. * @param msg - the initial request * @param str1 - direction - "orig" or "term" * @param str2 - not used * @returns #CSCF_RETURN_TRUE if ok, #CSCF_RETURN_FALSE if not or #CSCF_RETURN_BREAK on error */ int S_save_dialog(struct sip_msg* msg, char* str1, char* str2) { str call_id; s_dialog *d; str aor; char buf1[256],buf2[256]; str uri,tag,ruri,x; time_t t_time; str ses_exp = {0,0}; str refresher = {0,0}; str event = {0,0}; struct hdr_field *h; unsigned int hash; enum s_dialog_direction dir = get_dialog_direction(str1); if (!find_dialog_aor(msg,dir,&aor)){ LOG(L_ERR,"ERR:"M_NAME":S_save_dialog(): Error retrieving %s contact\n",str1); return CSCF_RETURN_BREAK; } call_id = cscf_get_call_id(msg,0); if (!call_id.len) return CSCF_RETURN_FALSE; LOG(L_INFO,"DBG:"M_NAME":S_save_dialog(%s): Call-ID <%.*s>\n",str1,call_id.len,call_id.s); if (is_s_dialog(call_id,aor,dir)){ LOG(L_ERR,"ERR:"M_NAME":S_save_dialog: dialog already exists!\n"); return CSCF_RETURN_TRUE; } d = add_s_dialog(call_id,aor,dir); if (!d) return CSCF_RETURN_FALSE; d->method = get_dialog_method(msg->first_line.u.request.method); STR_SHM_DUP(d->method_str,msg->first_line.u.request.method,"shm"); d->first_cseq = cscf_get_cseq(msg,0); d->last_cseq = d->first_cseq; d->state = DLG_STATE_INITIAL; d->uac_supp_timer = supports_extension(msg, &str_ext_timer); ses_exp = cscf_get_session_expires_body(msg, &h); t_time = cscf_get_session_expires(ses_exp, &refresher); if (!t_time) { d->expires = d_act_time() + 60; d->lr_session_expires = 0; } else { d->expires = d_act_time() + t_time; d->lr_session_expires = t_time; if (refresher.len) STR_SHM_DUP(d->refresher, refresher, "DIALOG_REFRESHER"); } cscf_get_from_tag(msg,&tag); cscf_get_from_uri(msg,&x); uri.len = snprintf(buf1,256,"<%.*s>",x.len,x.s); uri.s = buf1; cscf_get_to_uri(msg,&x); ruri.len = snprintf(buf2,256,"<%.*s>",x.len,x.s); ruri.s = buf2; tmb.new_dlg_uac(&call_id, &tag, d->first_cseq,&uri, &ruri, &d->dialog_c); tmb.new_dlg_uas(msg,99,&d->dialog_s); event = cscf_get_event(msg); if (event.len){ STR_SHM_DUP(d->event,event,"shm"); } else d->event = event; d_unlock(d->hash); print_s_dialogs(L_INFO); return CSCF_RETURN_TRUE; out_of_memory: if (d){ hash = d->hash; del_s_dialog(d); d_unlock(hash); } return CSCF_RETURN_ERROR; }