static WTPInitMachine *init_machine_create(WAPAddrTuple *tuple, unsigned short tid, int tidnew) { WTPInitMachine *init_machine; init_machine = gw_malloc(sizeof(WTPInitMachine)); #define ENUM(name) init_machine->name = INITIATOR_NULL_STATE; #define INTEGER(name) init_machine->name = 0; #define EVENT(name) init_machine->name = NULL; #define TIMER(name) init_machine->name = gwtimer_create(queue); #define ADDRTUPLE(name) init_machine->name = NULL; #define MACHINE(field) field #include "wtp_init_machine.def" gwlist_append(init_machines, init_machine); init_machine->mid = counter_increase(init_machine_id_counter); init_machine->addr_tuple = wap_addr_tuple_duplicate(tuple); init_machine->tid = tid; init_machine->tidnew = tidnew; debug("wap.wtp", 0, "WTP: Created WTPInitMachine %p (%ld)", (void *) init_machine, init_machine->mid); return init_machine; }
static WTLSMachine *wtls_machine_create(WAPAddrTuple * tuple) { WTLSMachine *wtls_machine; wtls_machine = gw_malloc(sizeof(WTLSMachine)); #define MACHINE(field) field #define ENUM(name) wtls_machine->name = NULL_STATE; #define ADDRTUPLE(name) wtls_machine->name = NULL; #define INTEGER(name) wtls_machine->name = 0; #define OCTSTR(name) wtls_machine->name = NULL; #define PDULIST(name) wtls_machine->name = NULL; #include "wtls_machine-decl.h" gwlist_append(wtls_machines, wtls_machine); wtls_machine->mid = counter_increase(wtls_machine_id_counter); wtls_machine->addr_tuple = wap_addr_tuple_duplicate(tuple); wtls_machine->server_seq_num = wtls_machine->client_seq_num = -1; wtls_machine->last_refresh = -1; wtls_machine->handshake_data = octstr_create(""); debug("wap.wtls", 0, "WTLS: Created WTLSMachine %ld (0x%p)", wtls_machine->mid, (void *)wtls_machine); return wtls_machine; }
static WAPEvent *unpack_ack(WTP_PDU *pdu, WAPAddrTuple *addr_tuple) { WAPEvent *event; WTP_TPI *tpi; int i, num_tpis; event = wap_event_create(RcvAck); event->u.RcvAck.tid = pdu->u.Ack.tid; event->u.RcvAck.tid_ok = pdu->u.Ack.tidverify; event->u.RcvAck.rid = pdu->u.Ack.rid; event->u.RcvAck.addr_tuple = wap_addr_tuple_duplicate(addr_tuple); /* Set default to 0 because Ack on 1 piece message has no tpi */ event->u.RcvAck.psn = 0; num_tpis = gwlist_len(pdu->options); for (i = 0; i < num_tpis; i++) { tpi = gwlist_get(pdu->options, i); if (tpi->type == TPI_PSN) { event->u.RcvAck.psn = octstr_get_bits(tpi->data,0,8); break; } } return event; }
/* * Adds an item to the tid cache, one item per every initiator. Initiator is * identified by the address four-tuple, fetched from a wtp responder machine. */ static void add_tid(WTPRespMachine *resp_machine, long tid) { WTPCached_tid *new_item = NULL; new_item = cache_item_create_empty(); new_item->addr_tuple = wap_addr_tuple_duplicate(resp_machine->addr_tuple); new_item->tid = tid; list_append(tid_cache, new_item); }
static void fatalAlert(WAPEvent * event, int description) { WAPEvent *abort; abort = wap_event_create(SEC_Terminate_Req); abort->u.SEC_Terminate_Req.addr_tuple = wap_addr_tuple_duplicate (event->u.T_Unitdata_Ind.addr_tuple); abort->u.SEC_Terminate_Req.alert_level = fatal_alert; abort->u.SEC_Terminate_Req.alert_desc = description; wtls_dispatch_event(abort); }
int wtls_get_address_tuple(long mid, WAPAddrTuple ** tuple) { WTLSMachine *sm; sm = find_wtls_machine_using_mid(mid); if (sm == NULL) return -1; *tuple = wap_addr_tuple_duplicate(sm->addr_tuple); return 0; }
static WAPEvent *unpack_abort(WTP_PDU *pdu, WAPAddrTuple *addr_tuple) { WAPEvent *event; event = wap_event_create(RcvAbort); event->u.RcvAbort.tid = pdu->u.Abort.tid; event->u.RcvAbort.abort_type = pdu->u.Abort.abort_type; event->u.RcvAbort.abort_reason = pdu->u.Abort.abort_reason; event->u.RcvAbort.addr_tuple = wap_addr_tuple_duplicate(addr_tuple); return event; }
/* * Creates TR-Invoke.cnf event */ static WAPEvent *create_tr_invoke_cnf(WTPInitMachine *init_machine) { WAPEvent *event; gw_assert(init_machine != NULL); event = wap_event_create(TR_Invoke_Cnf); event->u.TR_Invoke_Cnf.handle = init_machine->mid; event->u.TR_Invoke_Cnf.addr_tuple = wap_addr_tuple_duplicate(init_machine->addr_tuple); return event; }
static void make_unit_push_request(WAPEvent *e) { WAPEvent *wsp_event; List *push_headers; Octstr *smsc_id; Octstr *dlr_url; Octstr *smsbox_id; Octstr *push_body; Octstr *service_name; gw_assert(e->type == Po_Unit_Push_Req); gw_assert(e->u.Po_Unit_Push_Req.addr_tuple); gw_assert(e->u.Po_Unit_Push_Req.service_name); smsc_id = octstr_duplicate(e->u.Po_Unit_Push_Req.smsc_id); dlr_url = octstr_duplicate(e->u.Po_Unit_Push_Req.dlr_url); smsbox_id = octstr_duplicate(e->u.Po_Unit_Push_Req.smsbox_id); push_body = octstr_duplicate(e->u.Po_Unit_Push_Req.push_body); service_name = octstr_duplicate(e->u.Po_Unit_Push_Req.service_name); push_headers = add_push_flag(e); wsp_event = wap_event_create(S_Unit_Push_Req); wsp_event->u.S_Unit_Push_Req.addr_tuple = wap_addr_tuple_duplicate(e->u.Po_Unit_Push_Req.addr_tuple); wsp_event->u.S_Unit_Push_Req.push_id = e->u.Po_Unit_Push_Req.push_id; wsp_event->u.S_Unit_Push_Req.push_headers = push_headers; wsp_event->u.S_Unit_Push_Req.address_type = e->u.Po_Unit_Push_Req.address_type; if (smsc_id != NULL) wsp_event->u.S_Unit_Push_Req.smsc_id = smsc_id; else wsp_event->u.S_Unit_Push_Req.smsc_id = NULL; if (dlr_url != NULL) wsp_event->u.S_Unit_Push_Req.dlr_url = dlr_url; else wsp_event->u.S_Unit_Push_Req.dlr_url = NULL; wsp_event->u.S_Unit_Push_Req.dlr_mask = e->u.Po_Unit_Push_Req.dlr_mask; if (smsbox_id != NULL) wsp_event->u.S_Unit_Push_Req.smsbox_id = smsbox_id; else wsp_event->u.S_Unit_Push_Req.smsbox_id = NULL; wsp_event->u.S_Unit_Push_Req.service_name = service_name; if (push_body != NULL) wsp_event->u.S_Unit_Push_Req.push_body = push_body; else wsp_event->u.S_Unit_Push_Req.push_body = NULL; dispatch_to_wsp_unit(wsp_event); debug("wap.push.ota", 0, "OTA: made connectionless session service" " request"); }
static WAPEvent *unpack_negative_ack(WTP_PDU *pdu, WAPAddrTuple *addr_tuple) { WAPEvent *event; event = wap_event_create(RcvNegativeAck); event->u.RcvNegativeAck.tid = pdu->u.Negative_ack.tid; event->u.RcvNegativeAck.rid = pdu->u.Negative_ack.rid; event->u.RcvNegativeAck.nmissing = pdu->u.Negative_ack.nmissing; event->u.RcvNegativeAck.missing = octstr_duplicate(pdu->u.Negative_ack.missing); event->u.RcvNegativeAck.addr_tuple = wap_addr_tuple_duplicate(addr_tuple); return event; }
static WAPEvent *pack_error(WAPEvent *datagram) { WAPEvent *event; gw_assert(datagram->type == T_DUnitdata_Ind); event = wap_event_create(RcvErrorPDU); event->u.RcvErrorPDU.tid = deduce_tid(datagram->u.T_DUnitdata_Ind.user_data); event->u.RcvErrorPDU.addr_tuple = wap_addr_tuple_duplicate(datagram->u.T_DUnitdata_Ind.addr_tuple); return event; }
/* * Creates TR-Abort.ind event from an initiator state machine. In addtion, set * the ir_flag on. */ static WAPEvent *create_tr_abort_ind(WTPInitMachine *sm, long abort_reason) { WAPEvent *event; event = wap_event_create(TR_Abort_Ind); event->u.TR_Abort_Ind.abort_code = abort_reason; event->u.TR_Abort_Ind.addr_tuple = wap_addr_tuple_duplicate(sm->addr_tuple); event->u.TR_Abort_Ind.handle = sm->mid; event->u.TR_Abort_Ind.ir_flag = INITIATOR_INDICATION; return event; }
static WAPEvent *unpack_result(WTP_PDU *pdu, WAPAddrTuple *addr_tuple) { WAPEvent *event; event = wap_event_create(RcvResult); event->u.RcvResult.user_data = octstr_duplicate(pdu->u.Result.user_data); event->u.RcvResult.tid = pdu->u.Result.tid; event->u.RcvResult.rid = pdu->u.Result.rid; event->u.RcvResult.gtr = pdu->u.Result.gtr; event->u.RcvResult.ttr = pdu->u.Result.ttr; event->u.RcvResult.addr_tuple = wap_addr_tuple_duplicate(addr_tuple); return event; }
static void make_session_request(WAPEvent *e) { WAPEvent *wsp_event; List *appid_headers, *push_headers; gw_assert(e->type == Pom_SessionRequest_Req); push_headers = e->u.Pom_SessionRequest_Req.push_headers; check_session_request_headers(push_headers); wsp_event = wap_event_create(S_Unit_Push_Req); wsp_event->u.S_Unit_Push_Req.address_type = e->u.Pom_SessionRequest_Req.address_type; if (e->u.Pom_SessionRequest_Req.smsc_id != NULL) wsp_event->u.S_Unit_Push_Req.smsc_id = octstr_duplicate(e->u.Pom_SessionRequest_Req.smsc_id); else wsp_event->u.S_Unit_Push_Req.smsc_id = NULL; if (e->u.Pom_SessionRequest_Req.dlr_url != NULL) wsp_event->u.S_Unit_Push_Req.dlr_url = octstr_duplicate(e->u.Pom_SessionRequest_Req.dlr_url); else wsp_event->u.S_Unit_Push_Req.dlr_url = NULL; wsp_event->u.S_Unit_Push_Req.dlr_mask = e->u.Pom_SessionRequest_Req.dlr_mask; if (e->u.Pom_SessionRequest_Req.smsbox_id != NULL) wsp_event->u.S_Unit_Push_Req.smsbox_id = octstr_duplicate(e->u.Pom_SessionRequest_Req.smsbox_id); else wsp_event->u.S_Unit_Push_Req.smsbox_id = NULL; wsp_event->u.S_Unit_Push_Req.service_name = octstr_duplicate(e->u.Pom_SessionRequest_Req.service_name); wsp_event->u.S_Unit_Push_Req.push_id = e->u.Pom_SessionRequest_Req.push_id; wsp_event->u.S_Unit_Push_Req.addr_tuple = wap_addr_tuple_duplicate(e->u.Pom_SessionRequest_Req.addr_tuple); wsp_event->u.S_Unit_Push_Req.push_headers = http_header_duplicate(push_headers); appid_headers = http_header_find_all(push_headers, "X-WAP-Application-Id"); wsp_event->u.S_Unit_Push_Req.push_body = pack_sia(appid_headers); debug("wap.push.ota", 0, "OTA: making a connectionless session request for" " creating a session"); dispatch_to_wsp_unit(wsp_event); }
static WAPEvent *unpack_segmented_invoke(WTP_PDU *pdu, WAPAddrTuple *addr_tuple) { WAPEvent *event; event = wap_event_create(RcvSegInvoke); event->u.RcvSegInvoke.user_data = octstr_duplicate(pdu->u.Segmented_invoke.user_data); event->u.RcvSegInvoke.tid = pdu->u.Segmented_invoke.tid; event->u.RcvSegInvoke.rid = pdu->u.Segmented_invoke.rid; event->u.RcvSegInvoke.no_cache_supported = 0; event->u.RcvSegInvoke.gtr = pdu->u.Segmented_invoke.gtr; event->u.RcvSegInvoke.ttr = pdu->u.Segmented_invoke.ttr; event->u.RcvSegInvoke.psn = pdu->u.Segmented_invoke.psn; event->u.RcvSegInvoke.addr_tuple = wap_addr_tuple_duplicate(addr_tuple); return event; }
static WAPEvent *unpack_invoke(WTP_PDU *pdu, WAPAddrTuple *addr_tuple) { WAPEvent *event; event = wap_event_create(RcvInvoke); event->u.RcvInvoke.user_data = octstr_duplicate(pdu->u.Invoke.user_data); event->u.RcvInvoke.tcl = pdu->u.Invoke.class; event->u.RcvInvoke.tid = pdu->u.Invoke.tid; event->u.RcvInvoke.tid_new = pdu->u.Invoke.tidnew; event->u.RcvInvoke.rid = pdu->u.Invoke.rid; event->u.RcvInvoke.up_flag = pdu->u.Invoke.uack; event->u.RcvInvoke.no_cache_supported = 0; event->u.RcvInvoke.version = pdu->u.Invoke.version; event->u.RcvInvoke.gtr = pdu->u.Invoke.gtr; event->u.RcvInvoke.ttr = pdu->u.Invoke.ttr; event->u.RcvInvoke.addr_tuple = wap_addr_tuple_duplicate(addr_tuple); return event; }
static WSPMethodMachine *method_machine_create(WSPMachine *sm, long wtp_handle) { WSPMethodMachine *msm; msm = gw_malloc(sizeof(*msm)); #define INTEGER(name) msm->name = 0; #define ADDRTUPLE(name) msm->name = NULL; #define EVENT(name) msm->name = NULL; #define MACHINE(fields) fields #include "wsp_server_method_machine.def" msm->transaction_id = wtp_handle; msm->state = NULL_METHOD; msm->addr_tuple = wap_addr_tuple_duplicate(sm->addr_tuple); msm->session_id = sm->session_id; gwlist_append(sm->methodmachines, msm); return msm; }
static WSPPushMachine *push_machine_create(WSPMachine *sm, long pid) { WSPPushMachine *m; m = gw_malloc(sizeof(WSPPushMachine)); #define INTEGER(name) m->name = 0; #define ADDRTUPLE(name) m->name = NULL; #define HTTPHEADER(name) m->name = http_create_empty_headers(); #define MACHINE(fields) fields #include "wsp_server_push_machine.def" m->server_push_id = pid; m->transaction_id = pid; m->state = SERVER_PUSH_NULL_STATE; m->addr_tuple = wap_addr_tuple_duplicate(sm->addr_tuple); m->session_id = sm->session_id; gwlist_append(sm->pushmachines, m); return m; }
static WSPMachine *find_session_machine(WAPEvent *event, WSP_PDU *pdu) { WSPMachine *sm; long session_id; WAPAddrTuple *tuple; tuple = NULL; session_id = -1; switch (event->type) { case TR_Invoke_Ind: tuple = wap_addr_tuple_duplicate( event->u.TR_Invoke_Ind.addr_tuple); break; case TR_Invoke_Cnf: tuple = wap_addr_tuple_duplicate( event->u.TR_Invoke_Cnf.addr_tuple); break; case TR_Result_Cnf: tuple = wap_addr_tuple_duplicate( event->u.TR_Result_Cnf.addr_tuple); break; case TR_Abort_Ind: tuple = wap_addr_tuple_duplicate( event->u.TR_Abort_Ind.addr_tuple); break; case S_Connect_Res: session_id = event->u.S_Connect_Res.session_id; break; case S_Resume_Res: session_id = event->u.S_Resume_Res.session_id; break; case Disconnect_Event: session_id = event->u.Disconnect_Event.session_handle; break; case Suspend_Event: session_id = event->u.Suspend_Event.session_handle; break; case S_MethodInvoke_Res: session_id = event->u.S_MethodInvoke_Res.session_id; break; case S_MethodResult_Req: session_id = event->u.S_MethodResult_Req.session_id; break; case S_ConfirmedPush_Req: session_id = event->u.S_ConfirmedPush_Req.session_id; break; case S_Push_Req: session_id = event->u.S_Push_Req.session_id; break; default: error(0, "WSP: Cannot find machine for %s event", wap_event_name(event->type)); } gw_assert(tuple != NULL || session_id != -1); /* Pre-state-machine tests, according to 7.1.5. After the tests, * caller will pass the event to sm if sm is not NULL. */ sm = NULL; /* First test is for MRUEXCEEDED, and we don't have a MRU */ /* Second test is for class 2 TR-Invoke.ind with Connect PDU */ if (event->type == TR_Invoke_Ind && event->u.TR_Invoke_Ind.tcl == 2 && pdu->type == Connect) { /* Create a new session, even if there is already * a session open for this address. The new session * will take care of killing the old ones. */ sm = machine_create(); gw_assert(tuple != NULL); sm->addr_tuple = wap_addr_tuple_duplicate(tuple); sm->connect_handle = event->u.TR_Invoke_Ind.handle; /* Third test is for class 2 TR-Invoke.ind with Resume PDU */ } else if (event->type == TR_Invoke_Ind && event->u.TR_Invoke_Ind.tcl == 2 && pdu->type == Resume) { /* Pass to session identified by session id, not * the address tuple. */ session_id = pdu->u.Resume.sessionid; sm = gwlist_search(session_machines, &session_id, find_by_session_id); if (sm == NULL) { /* No session; TR-Abort.req(DISCONNECT) */ send_abort(WSP_ABORT_DISCONNECT, event->u.TR_Invoke_Ind.handle); } /* Fourth test is for a class 1 or 2 TR-Invoke.Ind with no * session for that address tuple. We also handle class 0 * TR-Invoke.ind here by ignoring them; this seems to be * an omission in the spec table. */ } else if (event->type == TR_Invoke_Ind) { sm = gwlist_search(session_machines, tuple, transaction_belongs_to_session); if (sm == NULL && (event->u.TR_Invoke_Ind.tcl == 1 || event->u.TR_Invoke_Ind.tcl == 2)) { send_abort(WSP_ABORT_DISCONNECT, event->u.TR_Invoke_Ind.handle); } /* Other tests are for events not handled by the state tables; * do those later, after we've tried to handle them. */ } else { if (session_id != -1) { sm = gwlist_search(session_machines, &session_id, find_by_session_id); } else { sm = gwlist_search(session_machines, tuple, transaction_belongs_to_session); } /* The table doesn't really say what we should do with * non-Invoke events for which there is no session. But * such a situation means there is an error _somewhere_ * in the gateway. */ if (sm == NULL) { error(0, "WSP: Cannot find session machine for event."); wap_event_dump(event); } } wap_addr_tuple_destroy(tuple); return sm; }
wtp_event = make_abort(reason, handle); dispatch_to_wtp_init(wtp_event); } /* * The server sends invoke (to be exact, makes TR-Invoke.req) only when it is * pushing. (Only the client disconnects sessions.) */ static void send_invoke(WSPMachine *m, WSP_PDU *pdu, WAPEvent *e, long class) { WAPEvent *wtp_event; wtp_event = wap_event_create(TR_Invoke_Req); wtp_event->u.TR_Invoke_Req.addr_tuple = wap_addr_tuple_duplicate(m->addr_tuple); /* * There is no mention of acknowledgement type in the specs.�But because * confirmed push is confirmed after response from OTA, provider acknowledge- * ments seem redundant. */ wtp_event->u.TR_Invoke_Req.up_flag = USER_ACKNOWLEDGEMENT; wtp_event->u.TR_Invoke_Req.tcl = class; if (e->type == S_ConfirmedPush_Req) wtp_event->u.TR_Invoke_Req.handle = e->u.S_ConfirmedPush_Req.server_push_id; wtp_event->u.TR_Invoke_Req.user_data = wsp_pdu_pack(pdu); wsp_pdu_destroy(pdu); dispatch_to_wtp_init(wtp_event); }
static void clientHello(WAPEvent * event, WTLSMachine * wtls_machine) { /* The Wap event we have to dispatch */ WAPEvent *res; wtls_Payload *tempPayload; wtls_PDU *clientHelloPDU; CipherSuite *ciphersuite; int randomCounter, algo; tempPayload = (wtls_Payload *) gwlist_search(event->u.T_Unitdata_Ind.pdu_list, (void *)client_hello, match_handshake_type); if (!tempPayload) { error(0, "Illegal PDU while waiting for a ClientHello"); fatalAlert(event, unexpected_message); return; } clientHelloPDU = wtls_pdu_unpack(tempPayload, wtls_machine); /* Store the client's random value - use pack for simplicity */ wtls_machine->client_random = octstr_create(""); randomCounter = pack_int32(wtls_machine->client_random, 0, clientHelloPDU->u.handshake.client_hello-> random->gmt_unix_time); octstr_insert(wtls_machine->client_random, clientHelloPDU->u.handshake.client_hello->random-> random_bytes, randomCounter); /* Select the ciphersuite from the supplied list */ ciphersuite = wtls_choose_ciphersuite(clientHelloPDU->u.handshake.client_hello-> ciphersuites); if (!ciphersuite) { error(0, "Couldn't agree on encryption cipher. Aborting"); wtls_pdu_destroy(clientHelloPDU); fatalAlert(event, handshake_failure); return; } /* Set the relevant values in the wtls_machine and PDU structure */ wtls_machine->bulk_cipher_algorithm = ciphersuite->bulk_cipher_algo; wtls_machine->mac_algorithm = ciphersuite->mac_algo; /* Generate a SEC_Create_Res event, and pass it back into the queue */ res = wap_event_create(SEC_Create_Res); res->u.SEC_Create_Res.addr_tuple = wap_addr_tuple_duplicate(event->u.T_Unitdata_Ind.addr_tuple); res->u.SEC_Create_Res.bulk_cipher_algo = ciphersuite->bulk_cipher_algo; res->u.SEC_Create_Res.mac_algo = ciphersuite->mac_algo; res->u.SEC_Create_Res.client_key_id = wtls_choose_clientkeyid (clientHelloPDU->u.handshake.client_hello->client_key_ids, &algo); if (!res->u.SEC_Create_Res.client_key_id) { error(0, "Couldn't agree on key exchange protocol. Aborting"); wtls_pdu_destroy(clientHelloPDU); wap_event_destroy(res); fatalAlert(event, unknown_key_id); return; } wtls_machine->key_algorithm = algo; /* Set the sequence number mode in both the machine and the outgoing packet */ res->u.SEC_Create_Res.snmode = wtls_choose_snmode(clientHelloPDU->u.handshake.client_hello-> snmode); wtls_machine->sequence_number_mode = res->u.SEC_Create_Res.snmode; /* Set the key refresh mode in both the machine and the outgoing packet */ res->u.SEC_Create_Res.krefresh = clientHelloPDU->u.handshake.client_hello->krefresh; wtls_machine->key_refresh = res->u.SEC_Create_Res.krefresh; /* Global refresh variable */ debug("wtls", 0, "clientHello ~> Accepted refresh = %d, refresh_rate = " "%d", wtls_machine->key_refresh, 1 << wtls_machine->key_refresh); /* Keep the data so we can send it back in EXCHANGE * temporary - needs to delete old one if exists ! * wtls_machine->handshake_data = octstr_create(""); */ if (wtls_machine->handshake_data) octstr_destroy(wtls_machine->handshake_data); wtls_machine->handshake_data = octstr_create(""); octstr_append(wtls_machine->handshake_data, tempPayload->data); debug("wtls", 0, "clientHello ~> Dispatching SEC_Create_Res event"); wtls_pdu_destroy(clientHelloPDU); wtls_dispatch_event(res); }
static void serverHello(WAPEvent * event, WTLSMachine * wtls_machine) { WAPEvent *req; wtls_PDU *serverHelloPDU; // wtls_PDU* certificatePDU; Random *tempRandom; /* List *certList; Certificate *cert; */ int randomCounter = 0; /* Our serverHello */ serverHelloPDU = wtls_pdu_create(Handshake_PDU); serverHelloPDU->rlen = 1; serverHelloPDU->snMode = wtls_machine->sequence_number_mode ? 1 : 0; serverHelloPDU->u.handshake.msg_type = server_hello; serverHelloPDU->u.handshake.server_hello = (ServerHello *) gw_malloc(sizeof(ServerHello)); /* Set our server version */ serverHelloPDU->u.handshake.server_hello->serverversion = 1; /* Get a suitably random number - store it in both the machine structure and outgoing PDU */ tempRandom = wtls_get_random(); wtls_machine->server_random = octstr_create(""); randomCounter = pack_int32(wtls_machine->server_random, 0, tempRandom->gmt_unix_time); octstr_insert(wtls_machine->server_random, tempRandom->random_bytes, octstr_len(wtls_machine->server_random)); serverHelloPDU->u.handshake.server_hello->random = tempRandom; /* At the moment, we don't support session caching, so tell them to forget about caching us */ serverHelloPDU->u.handshake.server_hello->session_id = octstr_format("%llu", wtls_machine->mid); /* We need to select an appropriate mechanism here from the ones listed */ serverHelloPDU->u.handshake.server_hello->client_key_id = event->u.SEC_Create_Res.client_key_id; /* Get our ciphersuite details */ serverHelloPDU->u.handshake.server_hello->ciphersuite = (CipherSuite *) gw_malloc(sizeof(CipherSuite)); serverHelloPDU->u.handshake.server_hello->ciphersuite->bulk_cipher_algo = event->u.SEC_Create_Res.bulk_cipher_algo; serverHelloPDU->u.handshake.server_hello->ciphersuite->mac_algo = event->u.SEC_Create_Res.mac_algo; serverHelloPDU->u.handshake.server_hello->comp_method = null_comp; /* We need to confirm the client's choice, or if they haven't * specified one, select one ourselves */ serverHelloPDU->u.handshake.server_hello->snmode = event->u.SEC_Create_Res.snmode; /* We need to either confirm the client's choice of key refresh rate, or choose a lower rate */ serverHelloPDU->u.handshake.server_hello->krefresh = event->u.SEC_Create_Res.krefresh; /* Add the PDUsto the server's outgoing list */ add_pdu(wtls_machine, serverHelloPDU); wtls_pdu_destroy(serverHelloPDU); /* Generate and dispatch a SEC_Exchange_Req or maybe a SEC_Commit_Req */ req = wap_event_create(SEC_Exchange_Req); req->u.SEC_Exchange_Req.addr_tuple = wap_addr_tuple_duplicate(event->u.T_Unitdata_Ind.addr_tuple); wtls_dispatch_event(req); debug("wtls", 0, "serverHello ~> Dispatching SEC_Exchange_Req event"); }