int run_timer_check(void *e_data, void *data, void *r_data) { unsigned int i=hash_index; reg_record_t *rec = (reg_record_t*)e_data; struct timer_check_data *t_check_data = (struct timer_check_data*)data; time_t now = t_check_data->now; str *s_now = t_check_data->s_now; switch(rec->state){ case REGISTERING_STATE: case AUTHENTICATING_STATE: break; case WRONG_CREDENTIALS_STATE: case REGISTER_TIMEOUT_STATE: case INTERNAL_ERROR_STATE: case REGISTRAR_ERROR_STATE: reg_print_record(rec); new_call_id_ftag_4_record(rec, s_now); if(send_register(i, rec, NULL)==1) { rec->last_register_sent = now; rec->state = REGISTERING_STATE; } else { rec->registration_timeout = now + rec->expires - timer_interval; rec->state = INTERNAL_ERROR_STATE; } break; case REGISTERED_STATE: /* check if we need to re-register */ if (now < rec->registration_timeout) { break; } case NOT_REGISTERED_STATE: if(send_register(i, rec, NULL)==1) { rec->last_register_sent = now; rec->state = REGISTERING_STATE; } else { rec->registration_timeout = now + rec->expires - timer_interval; rec->state = INTERNAL_ERROR_STATE; } break; default: LM_ERR("Unexpected state [%d] for rec [%p]\n", rec->state, rec); } return 0; /* continue list traversal */ }
int add_record(uac_reg_map_t *uac, str *now) { reg_record_t *rec, *prev_rec, *record; unsigned int size, expires; dlg_t *td; str call_id_ftag; char *p; if (uac->expires.s && uac->expires.len) { if (str2int(&uac->expires, &expires)<0) { LM_ERR("unable to get expiry from [%.*s]\n", uac->expires.len, uac->expires.s); return -1; } } else { expires = default_expires; } /* Reserve space for record */ size = sizeof(reg_record_t) + MD5_LEN + uac->to_uri.len + uac->from_uri.len + uac->registrar_uri.len + uac->auth_user.len + uac->auth_password.len + uac->contact_uri.len + uac->contact_params.len + uac->proxy_uri.len; record = (reg_record_t *)shm_malloc(size); if(!record) { LM_ERR("oom\n"); return -1; } memset(record, 0, size); record->expires = expires; td = &(record->td); p = (char *)(record + 1); /* Setting the td->id */ gen_call_id_ftag(&uac->to_uri, now, &call_id_ftag); memcpy(p, call_id_ftag.s, call_id_ftag.len); td->id.call_id.s = p; td->id.call_id.len = MD5_LEN - 5; td->id.loc_tag.s = p + MD5_LEN - 5; td->id.loc_tag.len = 5; p += MD5_LEN; //td->id.rem_tag.s = NULL; //td->id.rem_tag.len = 0; /* Setting the CSeq */ td->loc_seq.value = 0; td->loc_seq.is_set = 1; //td->loc_seq.rem_tag.s = NULL; //td->loc_seq.rem_tag.len = 0; /* Setting the remote URI */ td->rem_uri.s = p; td->rem_uri.len = uac->to_uri.len; memcpy(p, uac->to_uri.s, uac->to_uri.len); p += uac->to_uri.len; /* Setting the outbound proxy */ if (uac->proxy_uri.s && uac->proxy_uri.len) { td->obp.s = p; td->obp.len = uac->proxy_uri.len; memcpy(p, uac->proxy_uri.s, uac->proxy_uri.len); p += uac->proxy_uri.len; } /* Setting the local URI */ if(uac->from_uri.s && uac->from_uri.len) { LM_DBG("got from [%.*s]\n", uac->from_uri.len, uac->from_uri.s); td->loc_uri.s = p; td->loc_uri.len = uac->from_uri.len; memcpy(p, uac->from_uri.s, uac->from_uri.len); p += uac->from_uri.len; } else { td->loc_uri.s = td->rem_uri.s; td->loc_uri.len = td->rem_uri.len; } /* Setting the Remote target URI */ td->rem_target.s = p; td->rem_target.len = uac->registrar_uri.len; memcpy(p, uac->registrar_uri.s, uac->registrar_uri.len); p += uac->registrar_uri.len; /* Setting the Local/Remote Display Name */ //td->loc_dname.s = td->rem_dname.s = NULL; //td->loc_dname.len = td->rem_dname.len = 0; //td->T_flags = 0; td->state = DLG_CONFIRMED; /* Setting the Route set */ //td->route_set = NULL; /* Setting the hooks */ //td->hooks <- no hooks for REGISTER /* Setting the socket */ td->send_sock = uac->send_sock; /* Done with td */ if (uac->auth_user.s && uac->auth_user.len) { record->auth_user.s = p; record->auth_user.len = uac->auth_user.len; memcpy(p, uac->auth_user.s, uac->auth_user.len); p += uac->auth_user.len; } if (uac->auth_password.s && uac->auth_password.len) { record->auth_password.s = p; record->auth_password.len = uac->auth_password.len; memcpy(p, uac->auth_password.s, uac->auth_password.len); p += uac->auth_password.len; } record->contact_uri.s = p; record->contact_uri.len = uac->contact_uri.len; memcpy(p, uac->contact_uri.s, uac->contact_uri.len); p += uac->contact_uri.len; if (uac->contact_params.s && uac->contact_params.len) { record->contact_params.s = p; record->contact_params.len = uac->contact_params.len; memcpy(p, uac->contact_params.s, uac->contact_params.len); p += uac->contact_params.len; } reg_print_record(record); rec = reg_htable[uac->hash_code].first; if (rec) { while(rec) { prev_rec = rec; rec = rec->next; } prev_rec->next = record; record->prev = prev_rec; } else { reg_htable[uac->hash_code].first = record; record->prev = record->next = NULL; } return 0; }
void timer_check(unsigned int ticks, void* param) { unsigned int i=hash_index; reg_record_t *rec; char *p; int len; time_t now; str str_now = {NULL, 0}; now = time(0); p = int2str((unsigned long)(time(0)), &len); if (p && len>0) { str_now.s = (char *)pkg_malloc(len); if (str_now.s) { memcpy(str_now.s, p, len); str_now.len = len; } else { LM_ERR("oom\n"); return; } } lock_get(®_htable[i].lock); //LM_DBG("checking ... [%d] on htable[%d]\n", (unsigned int)now, i); rec = reg_htable[i].first; while (rec) { switch(rec->state){ case REGISTERING_STATE: case AUTHENTICATING_STATE: case WRONG_CREDENTIALS_STATE: break; case REGISTER_TIMEOUT_STATE: case INTERNAL_ERROR_STATE: case REGISTRAR_ERROR_STATE: reg_print_record(rec); new_call_id_ftag_4_record(rec, &str_now); if(send_register(i, rec, NULL)==1) { rec->last_register_sent = now; rec->state = REGISTERING_STATE; } else { rec->registration_timeout = now + rec->expires - timer_interval; rec->state = INTERNAL_ERROR_STATE; } break; case REGISTERED_STATE: /* check if we need to re-register */ if (now < rec->registration_timeout) { break; } case NOT_REGISTERED_STATE: if(send_register(i, rec, NULL)==1) { rec->last_register_sent = now; rec->state = REGISTERING_STATE; } else { rec->registration_timeout = now + rec->expires - timer_interval; rec->state = INTERNAL_ERROR_STATE; } break; default: LM_ERR("Unexpected state [%d] for rec [%p]\n", rec->state, rec); } rec = rec->next; } lock_release(®_htable[i].lock); if (str_now.s) {pkg_free(str_now.s);} hash_index = (++i)%reg_hsize; return; }
void reg_tm_cback(struct cell *t, int type, struct tmcb_params *ps) { struct sip_msg *msg; reg_tm_cb_t *cb_param; int statuscode = 0; unsigned int exp = 0; reg_record_t *rec; struct hdr_field *c_ptr, *head_contact; struct uac_credential crd; contact_t *contact; struct authenticate_body *auth = NULL; static struct authenticate_nc_cnonce auth_nc_cnonce; HASHHEX response; str *new_hdr; time_t now; if(ps==NULL || ps->rpl==NULL) { LM_ERR("wrong ps parameter\n"); return; } if(ps->param==NULL || *ps->param==NULL) { LM_ERR("null callback parameter\n"); return; } cb_param = (reg_tm_cb_t *)*ps->param; if(cb_param->uac == NULL) { LM_ERR("null record\n"); return; } statuscode = ps->code; now = time(0); LM_DBG("tm [%p] notification cb for %s [%d] reply at [%d]\n", t, (ps->rpl==FAKED_REPLY)?"FAKED_REPLY":"", statuscode, (unsigned int)now); if(statuscode<200) return; lock_get(®_htable[cb_param->hash_index].lock); rec = reg_htable[cb_param->hash_index].first; while(rec) { if (rec==cb_param->uac) { break; } rec = rec->next; } if(!rec) { LM_ERR("record [%p] not found on hash index [%d]\n", cb_param->uac, cb_param->hash_index); lock_release(®_htable[cb_param->hash_index].lock); return; } reg_print_record(rec); switch(statuscode) { case 200: msg = ps->rpl; if(msg==FAKED_REPLY) { LM_ERR("FAKED_REPLY\n"); goto done; } if (parse_headers(msg, HDR_EOH_F, 0) == -1) { LM_ERR("failed to parse headers\n"); goto done; } if (msg->contact) { c_ptr = msg->contact; while(c_ptr) { if (c_ptr->type == HDR_CONTACT_T) { if (!c_ptr->parsed && (parse_contact(c_ptr)<0)) { LM_ERR("failed to parse Contact body\n"); goto done; } } c_ptr = c_ptr->next; } } else { LM_ERR("No contact header in received 200ok\n"); goto done; } head_contact = msg->contact; contact = ((contact_body_t*)msg->contact->parsed)->contacts; while (contact) { /* Check for binding */ if (contact->uri.len==rec->contact_uri.len && strncmp(contact->uri.s,rec->contact_uri.s,contact->uri.len)==0){ if (contact->expires && contact->expires->body.len) { if (str2int(&contact->expires->body, &exp)<0) { LM_ERR("Unable to extract expires from [%.*s]" " for binding [%.*s]\n", contact->expires->body.len, contact->expires->body.s, contact->uri.len, contact->uri.s); } else { rec->expires = exp; } } break; } /* get the next contact */ if (contact->next == NULL) { contact = NULL; c_ptr = head_contact->next; while(c_ptr) { if (c_ptr->type == HDR_CONTACT_T) { head_contact = c_ptr; contact = ((contact_body_t*)c_ptr->parsed)->contacts; break; } c_ptr = c_ptr->next; } } else { contact = contact->next; } } rec->state = REGISTERED_STATE; rec->registration_timeout = now + rec->expires - timer_interval; break; case WWW_AUTH_CODE: case PROXY_AUTH_CODE: msg = ps->rpl; if(msg==FAKED_REPLY) { LM_ERR("FAKED_REPLY\n"); goto done; } if (rec->auth_user.s==NULL || rec->auth_user.len==0 || rec->auth_password.s==NULL || rec->auth_password.len==0) { LM_ERR("Credentials not provisioned\n"); rec->state = WRONG_CREDENTIALS_STATE; rec->registration_timeout = 0; lock_release(®_htable[cb_param->hash_index].lock); return; } if (statuscode==WWW_AUTH_CODE) { if (0 == parse_www_authenticate_header(msg)) auth = get_www_authenticate(msg); } else if (statuscode==PROXY_AUTH_CODE) { if (0 == parse_proxy_authenticate_header(msg)) auth = get_proxy_authenticate(msg); } if (auth == NULL) { LM_ERR("Unable to extract authentication info\n"); goto done; } LM_DBG("flags=[%d] realm=[%.*s] domain=[%.*s] nonce=[%.*s]" " opaque=[%.*s] qop=[%.*s]\n", auth->flags, auth->realm.len, auth->realm.s, auth->domain.len, auth->domain.s, auth->nonce.len, auth->nonce.s, auth->opaque.len, auth->opaque.s, auth->qop.len, auth->qop.s); switch(rec->state) { case REGISTERING_STATE: break; case AUTHENTICATING_STATE: /* We already sent an authenticated REGISTER and we are still challanged! */ LM_ERR("Wrong credentials for \n"); rec->state = WRONG_CREDENTIALS_STATE; rec->registration_timeout = 0; lock_release(®_htable[cb_param->hash_index].lock); return; default: LM_ERR("Unexpected [%d] notification cb in state [%d]\n", statuscode, rec->state); goto done; } /* perform authentication */ if (auth->realm.s && auth->realm.len) { crd.realm.s = auth->realm.s; crd.realm.len = auth->realm.len; } else { LM_ERR("No realm found\n"); goto done; } crd.user.s = rec->auth_user.s; crd.user.len = rec->auth_user.len; crd.passwd.s = rec->auth_password.s; crd.passwd.len = rec->auth_password.len; memset(&auth_nc_cnonce, 0, sizeof(struct authenticate_nc_cnonce)); uac_auth_api._do_uac_auth(®ister_method, &rec->td.rem_target, &crd, auth, &auth_nc_cnonce, response); new_hdr = uac_auth_api._build_authorization_hdr(statuscode, &rec->td.rem_target, &crd, auth, &auth_nc_cnonce, response); if (!new_hdr) { LM_ERR("failed to build authorization hdr\n"); goto done; } if(send_register(cb_param->hash_index, rec, new_hdr)==1) { rec->state = AUTHENTICATING_STATE; } else { rec->state = INTERNAL_ERROR_STATE; } break; default: if(statuscode<400 && statuscode>=300) { LM_ERR("Redirection not implemented yet\n"); rec->state = INTERNAL_ERROR_STATE; } else { /* we got an error from the server */ rec->state = REGISTRAR_ERROR_STATE; rec->registration_timeout = now + rec->expires - timer_interval; } } lock_release(®_htable[cb_param->hash_index].lock); return; done: rec->state = INTERNAL_ERROR_STATE; rec->registration_timeout = now + rec->expires; lock_release(®_htable[cb_param->hash_index].lock); return; }
int run_reg_tm_cback(void *e_data, void *data, void *r_data) { struct sip_msg *msg; int statuscode = 0; unsigned int exp = 0; reg_record_t *rec = (reg_record_t*)e_data; struct hdr_field *c_ptr, *head_contact; struct uac_credential crd; contact_t *contact; struct authenticate_body *auth = NULL; static struct authenticate_nc_cnonce auth_nc_cnonce; HASHHEX response; str *new_hdr; struct reg_tm_cback_data *tm_cback_data = (struct reg_tm_cback_data*)data; struct cell *t; struct tmcb_params *ps; time_t now; reg_tm_cb_t *cb_param; cb_param = tm_cback_data->cb_param; if (rec!=cb_param->uac) { /* no action on current list elemnt */ return 0; /* continue list traversal */ } t = tm_cback_data->t; ps = tm_cback_data->ps; now = tm_cback_data->now; reg_print_record(rec); if (ps->rpl==FAKED_REPLY) memset(&rec->td.forced_to_su, 0, sizeof(union sockaddr_union)); else if (rec->td.forced_to_su.s.sa_family == AF_UNSPEC) rec->td.forced_to_su = t->uac[0].request.dst.to; statuscode = ps->code; switch(statuscode) { case 200: msg = ps->rpl; if(msg==FAKED_REPLY) { LM_ERR("FAKED_REPLY\n"); goto done; } if (parse_headers(msg, HDR_EOH_F, 0) == -1) { LM_ERR("failed to parse headers\n"); goto done; } if (msg->contact) { c_ptr = msg->contact; while(c_ptr) { if (c_ptr->type == HDR_CONTACT_T) { if (!c_ptr->parsed && (parse_contact(c_ptr)<0)) { LM_ERR("failed to parse Contact body\n"); goto done; } } c_ptr = c_ptr->next; } } else { LM_ERR("No contact header in received 200ok\n"); goto done; } head_contact = msg->contact; contact = ((contact_body_t*)msg->contact->parsed)->contacts; while (contact) { /* Check for binding */ if (contact->uri.len==rec->contact_uri.len && strncmp(contact->uri.s,rec->contact_uri.s,contact->uri.len)==0){ if (contact->expires && contact->expires->body.len) { if (str2int(&contact->expires->body, &exp)<0) { LM_ERR("Unable to extract expires from [%.*s]" " for binding [%.*s]\n", contact->expires->body.len, contact->expires->body.s, contact->uri.len, contact->uri.s); } } break; } /* get the next contact */ if (contact->next == NULL) { contact = NULL; c_ptr = head_contact->next; while(c_ptr) { if (c_ptr->type == HDR_CONTACT_T) { head_contact = c_ptr; contact = ((contact_body_t*)c_ptr->parsed)->contacts; break; } c_ptr = c_ptr->next; } } else { contact = contact->next; } } rec->state = REGISTERED_STATE; if (exp) rec->expires = exp; rec->registration_timeout = now + rec->expires - timer_interval; break; case WWW_AUTH_CODE: case PROXY_AUTH_CODE: msg = ps->rpl; if(msg==FAKED_REPLY) { LM_ERR("FAKED_REPLY\n"); goto done; } if (rec->auth_user.s==NULL || rec->auth_user.len==0 || rec->auth_password.s==NULL || rec->auth_password.len==0) { LM_ERR("Credentials not provisioned\n"); rec->state = WRONG_CREDENTIALS_STATE; rec->registration_timeout = 0; /* action successfuly completed on current list element */ return 1; /* exit list traversal */ } if (statuscode==WWW_AUTH_CODE) { if (0 == parse_www_authenticate_header(msg)) auth = get_www_authenticate(msg); } else if (statuscode==PROXY_AUTH_CODE) { if (0 == parse_proxy_authenticate_header(msg)) auth = get_proxy_authenticate(msg); } if (auth == NULL) { LM_ERR("Unable to extract authentication info\n"); goto done; } LM_DBG("flags=[%d] realm=[%.*s] domain=[%.*s] nonce=[%.*s]" " opaque=[%.*s] qop=[%.*s]\n", auth->flags, auth->realm.len, auth->realm.s, auth->domain.len, auth->domain.s, auth->nonce.len, auth->nonce.s, auth->opaque.len, auth->opaque.s, auth->qop.len, auth->qop.s); switch(rec->state) { case REGISTERING_STATE: break; case AUTHENTICATING_STATE: /* We already sent an authenticated REGISTER and we are still challanged! */ LM_WARN("Wrong credentials for [%.*s]\n", rec->td.rem_uri.len, rec->td.rem_uri.s); rec->state = WRONG_CREDENTIALS_STATE; rec->registration_timeout = 0; /* action successfuly completed on current list element */ return 1; /* exit list traversal */ default: LM_ERR("Unexpected [%d] notification cb in state [%d]\n", statuscode, rec->state); goto done; } /* perform authentication */ if (auth->realm.s && auth->realm.len) { crd.realm.s = auth->realm.s; crd.realm.len = auth->realm.len; } else { LM_ERR("No realm found\n"); goto done; } crd.user.s = rec->auth_user.s; crd.user.len = rec->auth_user.len; crd.passwd.s = rec->auth_password.s; crd.passwd.len = rec->auth_password.len; memset(&auth_nc_cnonce, 0, sizeof(struct authenticate_nc_cnonce)); uac_auth_api._do_uac_auth(®ister_method, &rec->td.rem_target, &crd, auth, &auth_nc_cnonce, response); new_hdr = uac_auth_api._build_authorization_hdr(statuscode, &rec->td.rem_target, &crd, auth, &auth_nc_cnonce, response); if (!new_hdr) { LM_ERR("failed to build authorization hdr\n"); goto done; } if(send_register(cb_param->hash_index, rec, new_hdr)==1) { rec->state = AUTHENTICATING_STATE; } else { rec->state = INTERNAL_ERROR_STATE; } pkg_free(new_hdr->s); new_hdr->s = NULL; new_hdr->len = 0; break; case 423: /* Interval Too Brief */ msg = ps->rpl; if(msg==FAKED_REPLY) { LM_ERR("FAKED_REPLY\n"); goto done; } if (0 == parse_min_expires(msg)) { rec->expires = (unsigned int)(long)msg->min_expires->parsed; if(send_register(cb_param->hash_index, rec, NULL)==1) rec->state = REGISTERING_STATE; else rec->state = INTERNAL_ERROR_STATE; } else { rec->state = REGISTRAR_ERROR_STATE; rec->registration_timeout = now + rec->expires - timer_interval; } break; case 408: /* Interval Too Brief */ rec->state = REGISTER_TIMEOUT_STATE; rec->registration_timeout = now + rec->expires - timer_interval; break; default: if(statuscode<400 && statuscode>=300) { LM_ERR("Redirection not implemented yet\n"); rec->state = INTERNAL_ERROR_STATE; } else { /* we got an error from the server */ rec->state = REGISTRAR_ERROR_STATE; rec->registration_timeout = now + rec->expires - timer_interval; } } /* action successfuly completed on current list element */ return 1; /* exit list traversal */ done: rec->state = INTERNAL_ERROR_STATE; rec->registration_timeout = now + rec->expires; return -1; /* exit list traversal */ }