static long unpack_tpis(Octstr *data, long bitpos, WTP_PDU *pdu) { long length; int type; Octstr *tpidata; int another; do { another = octstr_get_bits(data, bitpos, 1); type = octstr_get_bits(data, bitpos + 1, 4); if (octstr_get_bits(data, bitpos + 5, 1)) { /* Long TPI */ length = octstr_get_bits(data, bitpos + 8, 8); bitpos += 16; } else { /* Short TPI */ length = octstr_get_bits(data, bitpos + 6, 2); bitpos += 8; } gw_assert(bitpos % 8 == 0); tpidata = octstr_copy(data, bitpos / 8, length); bitpos += 8 * length; wtp_pdu_append_tpi(pdu, type, tpidata); } while (another); return bitpos; }
int wtls_payload_guess_length(Octstr* data) { int type = 0, lengthFlag = 0, lengthSize = 0, pdu_length = 0; long lengthOffset = 1; /* Is the fragment length indicator on? */ lengthFlag = octstr_get_bits(data, 0, 1); if (lengthFlag) { lengthSize = 2; } /* Is the sequence number indicator on? */ if (octstr_get_bits(data, 1, 1)) { /* Yes, so hop over two extra bytes when reading the length */ lengthOffset += 2; } /* the message type */ type = octstr_get_bits(data, 4, 4); /* If fragment length is turned on, jump to the necessary spot */ if (lengthFlag == 1) { /* After this, lengthOffset + pdu_length == the total length of the PDU */ pdu_length = unpack_int16(data, &lengthOffset); } /* Oh great, so it's not switched on. How considerate. We'll have to make a reasonable guess as to what it might be. */ else { switch (type) { case ChangeCipher_PDU: /* They're really short */ pdu_length = 1; break; case Alert_PDU: /* They're a bit longer */ pdu_length = 6; break; default: /* Otherwise just give up and play dead */ pdu_length = -1; break; } } /* And that's the length of the contents, now just add the other doodads on */ if (pdu_length == -1) { return -1; } else { /* The pdu length, plus the sequence number, plus the length of the length value, plus the actual header byte */ return (pdu_length + lengthOffset); } }
/****************************************************************************** * * EXTERNAL FUNCTIONS: * * Handles a possible concatenated message. Creates a list of wap events. */ List *wtp_unpack_wdp_datagram(WAPEvent *datagram) { List *events = NULL; WAPEvent *event = NULL; WAPEvent *subdgram = NULL; Octstr *data = NULL; long pdu_len; gw_assert(datagram->type == T_DUnitdata_Ind); events = gwlist_create(); if (concatenated_message(datagram->u.T_DUnitdata_Ind.user_data)) { data = octstr_duplicate(datagram->u.T_DUnitdata_Ind.user_data); octstr_delete(data, 0, 1); while (octstr_len(data) != 0) { if (octstr_get_bits(data, 0, 1) == 0) { pdu_len = octstr_get_char(data, 0); octstr_delete(data, 0, 1); } else { pdu_len = octstr_get_bits(data, 1, 15); octstr_delete(data, 0, 2); } subdgram = wap_event_duplicate(datagram); octstr_destroy(subdgram->u.T_DUnitdata_Ind.user_data); subdgram->u.T_DUnitdata_Ind.user_data = octstr_copy(data, 0, pdu_len); wap_event_assert(subdgram); if ((event = unpack_wdp_datagram_real(subdgram)) != NULL) { wap_event_assert(event); gwlist_append(events, event); } octstr_delete(data, 0, pdu_len); wap_event_destroy(subdgram); } octstr_destroy(data); } else if ((event = unpack_wdp_datagram_real(datagram)) != NULL) { wap_event_assert(event); gwlist_append(events, event); } else { warning(0, "WTP: Dropping unhandled datagram data:"); octstr_dump(datagram->u.T_DUnitdata_Ind.user_data, 0, GW_WARNING); } return events; }
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; }
wtls_Payload *wtls_payload_unpack(Octstr *data) { wtls_Payload *payload = NULL; Octstr *buffer; long bitpos = 0, charpos = 0; int msg_length; gw_assert(data != NULL); payload = gw_malloc(sizeof(wtls_Payload)); /* the record field length flag */ payload->rlen = octstr_get_bits(data, bitpos, 1); bitpos += 1; /* the sequence number flag */ payload->seqnum = octstr_get_bits(data, bitpos, 1); bitpos += 1; /* the cipher usage flag */ payload->cipher = octstr_get_bits(data, bitpos, 1); bitpos += 1; /* the reserved bit */ payload->reserved = octstr_get_bits(data, bitpos, 1); bitpos += 1; /* the message type */ payload->type = octstr_get_bits(data, bitpos, 4); bitpos += 4; charpos += 1; /* get the sequence number if present */ if(payload->seqnum) { seqnum = unpack_int16(data, &charpos); } /* get the WTLS plaintext length if present */ if(payload->rlen) { msg_length = unpack_int16(data, &charpos); } /* the part of data that has just been processed is not needed anymore. We delete it. What is left of data is the payload. */ octstr_delete(data, 0, charpos); payload->data = data; return payload; }
static int deduce_tid(Octstr *user_data) { return octstr_get_bits(user_data, 8, 16); }