static void address_list_foreach (InternetAddressList *addrlist, MuMsgContactType ctype, MuMsgContactForeachFunc func, gpointer user_data) { int i, len; if (!addrlist) return; len = internet_address_list_length(addrlist); for (i = 0; i != len; ++i) { MuMsgContact contact; if (!fill_contact(&contact, internet_address_list_get_address (addrlist, i), ctype)) continue; if (!(func)(&contact, user_data)) break; } }
int ipsec_forward(struct sip_msg* m, udomain_t* d) { struct pcontact_info ci; pcontact_t* pcontact = NULL; int ret = IPSEC_CMD_FAIL; // FAIL by default // // Find the contact // if(fill_contact(&ci, m) != 0) { LM_ERR("Error filling in contact data\n"); return ret; } ul.lock_udomain(d, &ci.via_host, ci.via_port, ci.via_prot); if (ul.get_pcontact(d, &ci, &pcontact) != 0) { LM_ERR("Contact doesn't exist\n"); goto cleanup; } if(pcontact->security_temp == NULL) { LM_ERR("No security parameters found in contact\n"); goto cleanup; } //get security parameters if(pcontact->security_temp->type != SECURITY_IPSEC ) { LM_ERR("Unsupported security type: %d\n", pcontact->security_temp->type); goto cleanup; } ipsec_t* s = pcontact->security_temp->data.ipsec; // Update the destination // // from sec-agree // v // sip:host:port // ^ // from URI //int uri_len = 4 /* strlen("sip:") */ + ci.via_host.len + 5 /* max len of port number */ ; if(m->dst_uri.s) { pkg_free(m->dst_uri.s); m->dst_uri.s = NULL; m->dst_uri.len = 0; } char buf[1024]; int buf_len = snprintf(buf, sizeof(buf) - 1, "sip:%.*s:%d", ci.via_host.len, ci.via_host.s, s->port_us); if((m->dst_uri.s = pkg_malloc(buf_len)) == NULL) { LM_ERR("Error allocating memory for dst_uri\n"); goto cleanup; } memcpy(m->dst_uri.s, buf, buf_len); m->dst_uri.len = buf_len; // Set send socket struct socket_info * client_sock = grep_sock_info(&ipsec_listen_addr, ipsec_client_port, PROTO_UDP); if(!client_sock) { LM_ERR("Error calling grep_sock_info() for ipsec client port in ipsec_forward\n"); return -1; } m->force_send_socket = client_sock; // Set destination info struct dest_info dst_info; dst_info.send_sock = client_sock; #ifdef USE_DNS_FAILOVER if (!uri2dst(NULL, &dst_info, m, &m->dst_uri, PROTO_UDP)) { #else if (!uri2dst(&dst_info, m, &m->dst_uri, PROTO_UDP)) { #endif LM_ERR("Error converting dst_uri (%.*s) to struct dst_info\n", m->dst_uri.len, m->dst_uri.s); goto cleanup; } // Update dst_info in message if(m->first_line.type == SIP_REPLY) { struct cell *t = tmb.t_gett(); if (!t) { LM_ERR("Error getting transaction\n"); goto cleanup; } t->uas.response.dst = dst_info; } LM_DBG("Destination changed to %.*s\n", m->dst_uri.len, m->dst_uri.s); ret = IPSEC_CMD_SUCCESS; // all good, return SUCCESS if(add_supported_secagree_header(m) != 0) { goto cleanup; } if(add_security_server_header(m, s) != 0) { goto cleanup; } ret = IPSEC_CMD_SUCCESS; // all good, set ret to SUCCESS, and exit cleanup: ul.unlock_udomain(d, &ci.via_host, ci.via_port, ci.via_prot); pkg_free(ci.received_host.s); return ret; } int ipsec_destroy(struct sip_msg* m, udomain_t* d) { struct pcontact_info ci; pcontact_t* pcontact = NULL; int ret = IPSEC_CMD_FAIL; // FAIL by default // // Find the contact // if(fill_contact(&ci, m) != 0) { LM_ERR("Error filling in contact data\n"); return ret; } ul.lock_udomain(d, &ci.via_host, ci.via_port, ci.via_prot); if (ul.get_pcontact(d, &ci, &pcontact) != 0) { LM_ERR("Contact doesn't exist\n"); goto cleanup; } if(pcontact->security_temp == NULL) { LM_ERR("No security parameters found in contact\n"); goto cleanup; } //get security parameters if(pcontact->security_temp->type != SECURITY_IPSEC ) { LM_ERR("Unsupported security type: %d\n", pcontact->security_temp->type); goto cleanup; } destroy_ipsec_tunnel(ci.received_host, pcontact->security_temp->data.ipsec); ret = IPSEC_CMD_SUCCESS; // all good, set ret to SUCCESS, and exit cleanup: ul.unlock_udomain(d, &ci.via_host, ci.via_port, ci.via_prot); pkg_free(ci.received_host.s); return ret; } int ipsec_cleanall() { struct mnl_socket* nlsock = init_mnl_socket(); if(!nlsock) { return -1; } if(clean_sa(nlsock) != 0) { LM_WARN("Error cleaning IPSec Security associations during startup.\n"); } if(clean_policy(nlsock) != 0) { LM_WARN("Error cleaning IPSec Policies during startup.\n"); } close_mnl_socket(nlsock); return 0; }
int ipsec_create(struct sip_msg* m, udomain_t* d) { pcontact_t* pcontact = NULL; struct pcontact_info ci; int ret = IPSEC_CMD_FAIL; // FAIL by default // Find the contact if(fill_contact(&ci, m) != 0) { LM_ERR("Error filling in contact data\n"); return ret; } ul.lock_udomain(d, &ci.via_host, ci.via_port, ci.via_prot); if (ul.get_pcontact(d, &ci, &pcontact) != 0) { LM_ERR("Contact doesn't exist\n"); goto cleanup; } // Get security parameters if(pcontact->security_temp == NULL) { LM_ERR("No security parameters found in contact\n"); goto cleanup; } if(pcontact->security_temp->type != SECURITY_IPSEC ) { LM_ERR("Unsupported security type: %d\n", pcontact->security_temp->type); goto cleanup; } ipsec_t* s = pcontact->security_temp->data.ipsec; if(update_contact_ipsec_params(s, m) != 0) { goto cleanup; } if(create_ipsec_tunnel(ci.received_host, s) != 0) { goto cleanup; } // TODO: Save security_tmp to security!!!!! if (ul.update_pcontact(d, &ci, pcontact) != 0) { LM_ERR("Error updating contact\n"); goto cleanup; } // Destroy the tunnel, if the contact expires if(ul.register_ulcb(pcontact, PCSCF_CONTACT_EXPIRE|PCSCF_CONTACT_DELETE, on_expire, NULL) != 1) { LM_ERR("Error subscribing for contact\n"); goto cleanup; } if(add_supported_secagree_header(m) != 0) { goto cleanup; } if(add_security_server_header(m, s) != 0) { goto cleanup; } ret = IPSEC_CMD_SUCCESS; // all good, set ret to SUCCESS, and exit cleanup: // Do not free str* sec_header! It will be freed in data_lump.c -> free_lump() ul.unlock_udomain(d, &ci.via_host, ci.via_port, ci.via_prot); pkg_free(ci.received_host.s); return ret; }