/** * Sends a pending aggregate message for a given group and message */ void send_pending(int listidx, int pendidx) { switch (group_list[listidx].pending[pendidx].msg) { case REGISTER: send_register(listidx, pendidx); break; case INFO_ACK: send_info_ack(listidx, pendidx, FILEINFO); break; case STATUS: send_status(listidx, pendidx); break; case COMPLETE: send_complete(listidx, pendidx); break; default: log(group_list[listidx].group_id, 0, "Tried to send pending on " "invalid type %s", func_name(group_list[listidx].pending[pendidx].msg)); return; } if (group_list[listidx].pending[pendidx].count <= 0) { // Finish the cleanup we started in load_pending free(group_list[listidx].pending[pendidx].naklist); memset(&group_list[listidx].pending[pendidx], 0, sizeof(struct pr_pending_info_t)); } }
/** * Sends a pending aggregate message for a given group and message */ void send_pending(struct pr_group_list_t *group, int pendidx) { switch (group->pending[pendidx].msg) { case REGISTER: send_register(group, pendidx); break; case FILEINFO_ACK: send_fileinfo_ack(group, pendidx); break; case STATUS: send_status(group, pendidx); break; case COMPLETE: send_complete(group, pendidx); break; default: glog1(group, "Tried to send pending on invalid type %s", func_name(group->pending[pendidx].msg)); return; } if ((group->pending[pendidx].count <= 0) || (group->pending[pendidx].msg == STATUS)) { // Finish the cleanup we started in load_pending // Always do this for a STATUS, since we don't have a pending list free(group->pending[pendidx].naklist); memset(&group->pending[pendidx], 0, sizeof(struct pr_pending_info_t)); } }
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 */ }
static void register_lm_open_cb(LmConnection *connection, gboolean success, gpointer user_data) { struct register_data *rd; rd = user_data; if (!success) goto err; rd->handler = lm_message_handler_new(handle_register, rd, NULL); send_register(rd); return; err: signal_emit("xmpp registration failed", 3, rd->username, rd->domain, REGISTRATION_ERROR_CONNECTION); rd_cleanup(rd); }
/** * Gets the current timeout value to use for the main loop * * First check to see if any active groups have an expired timeout, and * handle that timeout. Once all expired timeouts have been handled, find * the active group with the earliest timeout and return the time until that * timeout. If there are no active groups, return NULL. */ struct timeval *getrecenttimeout(void) { static struct timeval tv = {0,0}; struct timeval current_timestamp, min_timestamp; int i, found_timeout, done, sent_naks; struct group_list_t *group; unsigned int section, nak_count; unsigned char *naks; gettimeofday(¤t_timestamp, NULL); done = 0; while (!done) { found_timeout = 0; done = 1; for (i = 0; i < MAXLIST; i++) { group = &group_list[i]; if (group->group_id != 0) { if (cmptimestamp(current_timestamp, group->timeout_time) >= 0) { switch (group->phase) { case PHASE_REGISTERED: send_register(group); break; case PHASE_RECEIVING: case PHASE_MIDGROUP: glog1(group, "Transfer timed out"); send_abort(group, "Transfer timed out"); break; case PHASE_COMPLETE: send_complete(group, 0); break; } done = 0; } else if ((!found_timeout) || (cmptimestamp(group->timeout_time, min_timestamp) < 0)) { glog5(group, "found min timeout time: %d:%06d", group->timeout_time.tv_sec, group->timeout_time.tv_usec); min_timestamp = group->timeout_time; found_timeout = 1; } // Check for a NAK timeout for sending a STATUS or COMPLETE if ((group->fileinfo.nak_time.tv_sec != 0) && cmptimestamp(current_timestamp, group->fileinfo.nak_time) >= 0) { group->fileinfo.nak_time.tv_sec = 0; group->fileinfo.nak_time.tv_usec = 0; // Send NAKs sent_naks = 0; retry_naks: for (section = group->fileinfo.nak_section_first; section < group->fileinfo.nak_section_last; section++) { naks = NULL; nak_count = get_naks(group, section, &naks); glog3(group, "read %d NAKs for section %d", nak_count, section); if (nak_count > 0) { send_status(group, section, naks, nak_count); sent_naks = 1; } free(naks); naks = NULL; } if (file_done(group, 1)) { glog2(group, "File transfer complete"); send_complete(group, 0); file_cleanup(group, 0); } else if (group->fileinfo.got_done && !sent_naks) { // We didn't send any NAKs since the last time // but the server is asking for some, // so check all prior sections group->fileinfo.nak_section_last = group->fileinfo.nak_section_first; group->fileinfo.nak_section_first = 0; group->fileinfo.got_done = 0; goto retry_naks; } } else if ((group->fileinfo.nak_time.tv_sec != 0) && ((!found_timeout) || (cmptimestamp(group->fileinfo.nak_time, min_timestamp) < 0))) { glog5(group, "found min nak time: %d:%06d", group->fileinfo.nak_time.tv_sec, group->fileinfo.nak_time.tv_usec); min_timestamp = group->fileinfo.nak_time; found_timeout = 1; } // Check congestion control feedback timer if (!group->isclr) { if ((group->cc_time.tv_sec != 0) && (cmptimestamp(current_timestamp, group->cc_time) >= 0)) { send_cc_ack(group); } else if ((group->cc_time.tv_sec != 0) && ((!found_timeout) || (cmptimestamp(group->cc_time, min_timestamp) < 0))) { glog5(group, "found min CC time: %d:%06d", group->cc_time.tv_sec, group->cc_time.tv_usec); min_timestamp = group->cc_time; found_timeout = 1; } } } } // Check timeout for proxy key request if (has_proxy && (proxy_pubkey.key == 0)) { if (cmptimestamp(current_timestamp, next_keyreq_time) >= 0) { send_key_req(); done = 0; } else if ((!found_timeout) || (cmptimestamp(next_keyreq_time, min_timestamp) < 0)) { min_timestamp = next_keyreq_time; found_timeout = 1; } } // Check timeout for sending heartbeat if (hbhost_count) { if (cmptimestamp(current_timestamp, next_hb_time) >= 0) { send_hb_request(listener, hb_hosts, hbhost_count, &next_hb_time, hb_interval, uid); done = 0; } else if ((!found_timeout) || (cmptimestamp(next_hb_time, min_timestamp) < 0)) { min_timestamp = next_hb_time; found_timeout = 1; } } } if (found_timeout) { tv = diff_timeval(min_timestamp, current_timestamp); return &tv; } else { return NULL; } }
/** * Gets the current timeout value to use for the main loop * * First check to see if any active groups have an expired timeout, and * handle that timeout. Once all expired timeouts have been handled, find * the active group with the earliest timeout and return the time until that * timeout. If there are no active groups, return NULL. */ struct timeval *getrecenttimeout() { static struct timeval tv = {0,0}; struct timeval current_timestamp, min_timestamp; int i, found_timeout, done; int32_t usecs; gettimeofday(¤t_timestamp, NULL); done = 0; while (!done) { found_timeout = 0; done = 1; for (i = 0; i < MAXLIST; i++) { if (group_list[i].group_id != 0) { if (cmptimestamp(current_timestamp, group_list[i].timeout_time) >= 0) { switch (group_list[i].phase) { case PHASE_REGISTERED: send_register(i); break; case PHASE_RECEIVING: case PHASE_MIDGROUP: log1(group_list[i].group_id, group_list[i].file_id, "Transfer timed out"); send_abort(i, "Transfer timed out"); break; case PHASE_COMPLETE: send_complete(i); break; } done = 0; } else if (!found_timeout) { min_timestamp = group_list[i].timeout_time; found_timeout = 1; } else if (cmptimestamp(group_list[i].timeout_time, min_timestamp) < 0) { min_timestamp = group_list[i].timeout_time; } } } // Check timeout for proxy key request if (has_proxy && (proxy_key == (RSA_key_t)NULL)) { if (cmptimestamp(current_timestamp, next_keyreq_time) >= 0) { send_key_req(); done = 0; } else if ((!found_timeout) || (cmptimestamp(next_keyreq_time, min_timestamp) < 0)) { min_timestamp = next_keyreq_time; found_timeout = 1; } } // Check timeout for sending heartbeat if (hbhost_count) { if (cmptimestamp(current_timestamp, next_hb_time) >= 0) { send_hb_request(listener, hb_hosts, hbhost_count, &next_hb_time, hb_interval); done = 0; } else if ((!found_timeout) || (cmptimestamp(next_hb_time, min_timestamp) < 0)) { min_timestamp = next_hb_time; found_timeout = 1; } } } if (found_timeout) { usecs = (int32_t)diff_usec(min_timestamp, current_timestamp); tv.tv_sec = usecs / 1000000; tv.tv_usec = usecs % 1000000; return &tv; } else { return NULL; } }
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 */ }
/** * Processes a new incoming ANNOUNCE */ void handle_announce(union sockaddr_u *src, unsigned char *packet, unsigned packetlen, struct timeval rxtime) { struct uftp_h *header; struct announce_h *announce; uint32_t *addrlist; int addrlen, rval; struct group_list_t *group; time_t t; struct tm *start_time; char privname[INET6_ADDRSTRLEN], srcname[INET6_ADDRSTRLEN]; char srcfqdn[DESTNAME_LEN]; header = (struct uftp_h *)packet; announce = (struct announce_h *)(packet + sizeof(struct uftp_h)); addrlist = (uint32_t *)((unsigned char *)announce + (announce->hlen * 4)); addrlen = (packetlen - sizeof(struct uftp_h) - (announce->hlen * 4)) / 4; if ((packetlen < sizeof(struct uftp_h) + (announce->hlen * 4U)) || ((announce->hlen * 4U) < sizeof(struct announce_h))) { log1(ntohl(header->group_id), header->group_inst, 0, "Rejecting ANNOUNCE from %08X: invalid message size", ntohl(header->src_id)); return; } if ((addrlen != 0) && (!uid_in_list(addrlist, addrlen))) { log1(ntohl(header->group_id), header->group_inst, 0, "Name not in host list"); return; } if ((group = find_open_slot()) == NULL ) { log0(ntohl(header->group_id), header->group_inst, 0, "Error: maximum number of incoming files exceeded: %d\n", MAXLIST); return; } t = time(NULL); start_time = localtime(&t); snprintf(group->start_date, sizeof(group->start_date), "%04d%02d%02d", start_time->tm_year + 1900, start_time->tm_mon + 1, start_time->tm_mday); snprintf(group->start_time, sizeof(group->start_time), "%02d%02d%02d", start_time->tm_hour, start_time->tm_min, start_time->tm_sec); if (!read_announce(group, packet, src, rxtime, packetlen)) { return; } if ((rval = getnameinfo((struct sockaddr *)src, family_len(*src), srcname, sizeof(srcname), NULL, 0, NI_NUMERICHOST)) != 0) { glog1(group, "getnameinfo failed: %s", gai_strerror(rval)); } if (!noname) { if ((rval = getnameinfo((struct sockaddr *)src, family_len(*src), srcfqdn, sizeof(srcfqdn), NULL, 0, 0)) != 0) { glog1(group, "getnameinfo failed: %s", gai_strerror(rval)); } } else { strncpy(srcfqdn, srcname, sizeof(srcfqdn) - 1); } if ((rval = getnameinfo((struct sockaddr *)&group->multi, family_len(group->multi), privname, sizeof(privname), NULL, 0, NI_NUMERICHOST)) != 0) { glog1(group, "getnameinfo failed: %s", gai_strerror(rval)); } glog2(group, "Received request from %08X at %s (%s)", ntohl(group->src_id), srcfqdn, srcname); glog2(group, "Using private multicast address %s", privname); glog3(group, "grtt = %.6f", group->grtt); glog3(group, "send time: %d.%06d", group->last_server_ts.tv_sec, group->last_server_ts.tv_usec); glog3(group, "receive time: %d.%06d", group->last_server_rx_ts.tv_sec, group->last_server_rx_ts.tv_usec); if (status_file) { fprintf(status_file, "CONNECT;%04d/%02d/%02d-%02d:%02d:%02d;%08X;%08X;%s;%s\n", start_time->tm_year + 1900, start_time->tm_mon + 1, start_time->tm_mday, start_time->tm_hour, start_time->tm_min, start_time->tm_sec, ntohl(group->src_id), group->group_id, srcname, srcfqdn); fflush(status_file); } if (group->restart) { if (group->sync_mode) { glog1(group, "Sync mode and restart mode incompatible"); send_abort(group, "Sync mode and restart mode incompatible"); return; } } if (!addr_blank(&group->multi)) { if (server_count > 0) { if (!is_multicast(&group->multi, 1)) { glog1(group, "Invalid source specific multicast address: %s", privname); send_abort(group, "Invalid source specific multicast address"); return; } if (!other_mcast_users(group)) { if (!multicast_join(listener, group->group_id, &group->multi, m_interface, interface_count, server_keys, server_count)) { send_abort(group, "Error joining multicast group"); return; } if (has_proxy) { if (!multicast_join(listener,group->group_id, &group->multi, m_interface, interface_count, &proxy_info, 1)) { send_abort(group, "Error joining multicast group"); return; } } } } else { if (!is_multicast(&group->multi, 0)) { glog1(group, "Invalid multicast address: %s", privname); send_abort(group, "Invalid multicast address"); return; } if (!other_mcast_users(group)) { if (!multicast_join(listener, group->group_id, &group->multi, m_interface, interface_count, NULL, 0)) { send_abort(group, "Error joining multicast group"); return; } } } group->multi_join = 1; } send_register(group); }