00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064 #include "wtp.h"
00065 #include "wap_events.h"
00066 #include "wtp_pdu.h"
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079 static WAPEvent *unpack_wdp_datagram_real(WAPEvent *datagram);
00080
00081 static int deduce_tid(Octstr *user_data);
00082 static int concatenated_message(Octstr *user_data);
00083 static int truncated_datagram(WAPEvent *event);
00084 static WAPEvent *unpack_invoke(WTP_PDU *pdu, WAPAddrTuple *addr_tuple);
00085 static WAPEvent *unpack_segmented_invoke(WTP_PDU *pdu, WAPAddrTuple *addr_tuple);
00086 static WAPEvent *unpack_result(WTP_PDU *pdu, WAPAddrTuple *addr_tuple);
00087 static WAPEvent *unpack_ack(WTP_PDU *pdu, WAPAddrTuple *addr_tuple);
00088 static WAPEvent *unpack_negative_ack(WTP_PDU *pdu, WAPAddrTuple *addr_tuple);
00089 static WAPEvent *unpack_abort(WTP_PDU *pdu, WAPAddrTuple *addr_tuple);
00090 static WAPEvent *pack_error(WAPEvent *datagram);
00091
00092
00093
00094
00095
00096
00097
00098 List *wtp_unpack_wdp_datagram(WAPEvent *datagram)
00099 {
00100 List *events = NULL;
00101 WAPEvent *event = NULL;
00102 WAPEvent *subdgram = NULL;
00103 Octstr *data = NULL;
00104 long pdu_len;
00105
00106 gw_assert(datagram->type == T_DUnitdata_Ind);
00107
00108 events = gwlist_create();
00109
00110 if (concatenated_message(datagram->u.T_DUnitdata_Ind.user_data)) {
00111 data = octstr_duplicate(datagram->u.T_DUnitdata_Ind.user_data);
00112 octstr_delete(data, 0, 1);
00113
00114 while (octstr_len(data) != 0) {
00115
00116 if (octstr_get_bits(data, 0, 1) == 0) {
00117 pdu_len = octstr_get_char(data, 0);
00118 octstr_delete(data, 0, 1);
00119 } else {
00120 pdu_len = octstr_get_bits(data, 1, 15);
00121 octstr_delete(data, 0, 2);
00122 }
00123
00124 subdgram = wap_event_duplicate(datagram);
00125 octstr_destroy(subdgram->u.T_DUnitdata_Ind.user_data);
00126 subdgram->u.T_DUnitdata_Ind.user_data = octstr_copy(data, 0, pdu_len);
00127 wap_event_assert(subdgram);
00128 if ((event = unpack_wdp_datagram_real(subdgram)) != NULL) {
00129 wap_event_assert(event);
00130 gwlist_append(events, event);
00131 }
00132 octstr_delete(data, 0, pdu_len);
00133 wap_event_destroy(subdgram);
00134 }
00135
00136 octstr_destroy(data);
00137
00138 } else if ((event = unpack_wdp_datagram_real(datagram)) != NULL) {
00139 wap_event_assert(event);
00140 gwlist_append(events, event);
00141 } else {
00142 warning(0, "WTP: Dropping unhandled datagram data:");
00143 octstr_dump(datagram->u.T_DUnitdata_Ind.user_data, 0, GW_WARNING);
00144 }
00145
00146 return events;
00147 }
00148
00149
00150
00151
00152
00153
00154
00155
00156 int wtp_event_is_for_responder(WAPEvent *event)
00157 {
00158
00159 switch(event->type){
00160
00161 case RcvInvoke:
00162 return event->u.RcvInvoke.tid < INITIATOR_TID_LIMIT;
00163
00164 case RcvSegInvoke:
00165 return event->u.RcvSegInvoke.tid < INITIATOR_TID_LIMIT;
00166
00167 case RcvResult:
00168 return event->u.RcvResult.tid < INITIATOR_TID_LIMIT;
00169
00170 case RcvAck:
00171 return event->u.RcvAck.tid < INITIATOR_TID_LIMIT;
00172
00173 case RcvNegativeAck:
00174 return event->u.RcvNegativeAck.tid < INITIATOR_TID_LIMIT;
00175
00176 case RcvAbort:
00177 return event->u.RcvAbort.tid < INITIATOR_TID_LIMIT;
00178
00179 case RcvErrorPDU:
00180 return event->u.RcvErrorPDU.tid < INITIATOR_TID_LIMIT;
00181
00182 default:
00183 error(1, "Received an erroneous PDU corresponding an event");
00184 wap_event_dump(event);
00185 return -1;
00186 }
00187 }
00188
00189
00190
00191
00192
00193
00194
00195 static int truncated_datagram(WAPEvent *dgram)
00196 {
00197 gw_assert(dgram->type == T_DUnitdata_Ind);
00198
00199 if (octstr_len(dgram->u.T_DUnitdata_Ind.user_data) < 3) {
00200 debug("wap.wtp", 0, "A too short PDU received");
00201 wap_event_dump(dgram);
00202 return 1;
00203 } else
00204 return 0;
00205 }
00206
00207 static WAPEvent *unpack_invoke(WTP_PDU *pdu, WAPAddrTuple *addr_tuple)
00208 {
00209 WAPEvent *event;
00210
00211 event = wap_event_create(RcvInvoke);
00212 event->u.RcvInvoke.user_data =
00213 octstr_duplicate(pdu->u.Invoke.user_data);
00214 event->u.RcvInvoke.tcl = pdu->u.Invoke.class;
00215 event->u.RcvInvoke.tid = pdu->u.Invoke.tid;
00216 event->u.RcvInvoke.tid_new = pdu->u.Invoke.tidnew;
00217 event->u.RcvInvoke.rid = pdu->u.Invoke.rid;
00218 event->u.RcvInvoke.up_flag = pdu->u.Invoke.uack;
00219 event->u.RcvInvoke.no_cache_supported = 0;
00220 event->u.RcvInvoke.version = pdu->u.Invoke.version;
00221 event->u.RcvInvoke.gtr = pdu->u.Invoke.gtr;
00222 event->u.RcvInvoke.ttr = pdu->u.Invoke.ttr;
00223 event->u.RcvInvoke.addr_tuple = wap_addr_tuple_duplicate(addr_tuple);
00224
00225 return event;
00226 }
00227
00228 static WAPEvent *unpack_segmented_invoke(WTP_PDU *pdu, WAPAddrTuple *addr_tuple)
00229 {
00230 WAPEvent *event;
00231
00232 event = wap_event_create(RcvSegInvoke);
00233 event->u.RcvSegInvoke.user_data =
00234 octstr_duplicate(pdu->u.Segmented_invoke.user_data);
00235 event->u.RcvSegInvoke.tid = pdu->u.Segmented_invoke.tid;
00236 event->u.RcvSegInvoke.rid = pdu->u.Segmented_invoke.rid;
00237 event->u.RcvSegInvoke.no_cache_supported = 0;
00238 event->u.RcvSegInvoke.gtr = pdu->u.Segmented_invoke.gtr;
00239 event->u.RcvSegInvoke.ttr = pdu->u.Segmented_invoke.ttr;
00240 event->u.RcvSegInvoke.psn = pdu->u.Segmented_invoke.psn;
00241 event->u.RcvSegInvoke.addr_tuple = wap_addr_tuple_duplicate(addr_tuple);
00242
00243 return event;
00244 }
00245
00246 static WAPEvent *unpack_result(WTP_PDU *pdu, WAPAddrTuple *addr_tuple)
00247 {
00248 WAPEvent *event;
00249
00250 event = wap_event_create(RcvResult);
00251 event->u.RcvResult.user_data =
00252 octstr_duplicate(pdu->u.Result.user_data);
00253 event->u.RcvResult.tid = pdu->u.Result.tid;
00254 event->u.RcvResult.rid = pdu->u.Result.rid;
00255 event->u.RcvResult.gtr = pdu->u.Result.gtr;
00256 event->u.RcvResult.ttr = pdu->u.Result.ttr;
00257 event->u.RcvResult.addr_tuple = wap_addr_tuple_duplicate(addr_tuple);
00258
00259 return event;
00260 }
00261
00262 static WAPEvent *unpack_ack(WTP_PDU *pdu, WAPAddrTuple *addr_tuple)
00263 {
00264 WAPEvent *event;
00265 WTP_TPI *tpi;
00266 int i, num_tpis;
00267
00268 event = wap_event_create(RcvAck);
00269 event->u.RcvAck.tid = pdu->u.Ack.tid;
00270 event->u.RcvAck.tid_ok = pdu->u.Ack.tidverify;
00271 event->u.RcvAck.rid = pdu->u.Ack.rid;
00272 event->u.RcvAck.addr_tuple = wap_addr_tuple_duplicate(addr_tuple);
00273
00274
00275 event->u.RcvAck.psn = 0;
00276 num_tpis = gwlist_len(pdu->options);
00277
00278 for (i = 0; i < num_tpis; i++) {
00279 tpi = gwlist_get(pdu->options, i);
00280 if (tpi->type == TPI_PSN) {
00281 event->u.RcvAck.psn = octstr_get_bits(tpi->data,0,8);
00282 break;
00283 }
00284 }
00285
00286 return event;
00287 }
00288
00289 static WAPEvent *unpack_negative_ack(WTP_PDU *pdu, WAPAddrTuple *addr_tuple)
00290 {
00291 WAPEvent *event;
00292
00293 event = wap_event_create(RcvNegativeAck);
00294 event->u.RcvNegativeAck.tid = pdu->u.Negative_ack.tid;
00295 event->u.RcvNegativeAck.rid = pdu->u.Negative_ack.rid;
00296 event->u.RcvNegativeAck.nmissing = pdu->u.Negative_ack.nmissing;
00297 event->u.RcvNegativeAck.missing = octstr_duplicate(pdu->u.Negative_ack.missing);
00298 event->u.RcvNegativeAck.addr_tuple = wap_addr_tuple_duplicate(addr_tuple);
00299
00300 return event;
00301 }
00302
00303 static WAPEvent *unpack_abort(WTP_PDU *pdu, WAPAddrTuple *addr_tuple)
00304 {
00305 WAPEvent *event;
00306
00307 event = wap_event_create(RcvAbort);
00308 event->u.RcvAbort.tid = pdu->u.Abort.tid;
00309 event->u.RcvAbort.abort_type = pdu->u.Abort.abort_type;
00310 event->u.RcvAbort.abort_reason = pdu->u.Abort.abort_reason;
00311 event->u.RcvAbort.addr_tuple = wap_addr_tuple_duplicate(addr_tuple);
00312
00313 return event;
00314 }
00315
00316 static WAPEvent *pack_error(WAPEvent *datagram)
00317 {
00318 WAPEvent *event;
00319
00320 gw_assert(datagram->type == T_DUnitdata_Ind);
00321
00322 event = wap_event_create(RcvErrorPDU);
00323 event->u.RcvErrorPDU.tid = deduce_tid(datagram->u.T_DUnitdata_Ind.user_data);
00324 event->u.RcvErrorPDU.addr_tuple =
00325 wap_addr_tuple_duplicate(datagram->u.T_DUnitdata_Ind.addr_tuple);
00326
00327 return event;
00328 }
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342 WAPEvent *unpack_wdp_datagram_real(WAPEvent *datagram)
00343 {
00344 WTP_PDU *pdu;
00345 WAPEvent *event;
00346 Octstr *data;
00347
00348 gw_assert(datagram->type == T_DUnitdata_Ind);
00349
00350 data = datagram->u.T_DUnitdata_Ind.user_data;
00351
00352 if (truncated_datagram(datagram)) {
00353 warning(0, "WTP: got a truncated datagram, ignoring");
00354 return NULL;
00355 }
00356
00357 pdu = wtp_pdu_unpack(data);
00358
00359
00360
00361
00362
00363
00364
00365 if (pdu == NULL) {
00366 error(0, "WTP: cannot unpack pdu, dropping packet.");
00367 return NULL;
00368 }
00369
00370 event = NULL;
00371
00372 switch (pdu->type) {
00373
00374 case Invoke:
00375 event = unpack_invoke(pdu, datagram->u.T_DUnitdata_Ind.addr_tuple);
00376
00377 if (!wtp_event_is_for_responder(event)){
00378 debug("wap.wtp", 0, "WTP: Invoke when initiator. Message was");
00379 wap_event_destroy(event);
00380 event = pack_error(datagram);
00381 }
00382 break;
00383
00384 case Segmented_invoke:
00385 event = unpack_segmented_invoke(pdu, datagram->u.T_DUnitdata_Ind.addr_tuple);
00386 break;
00387
00388 case Result:
00389 event = unpack_result(pdu, datagram->u.T_DUnitdata_Ind.addr_tuple);
00390
00391 if (wtp_event_is_for_responder(event)){
00392 debug("wap.wtp", 0, "WTP: Result when responder. Message was");
00393 wap_event_destroy(event);
00394 event = pack_error(datagram);
00395 }
00396 break;
00397
00398 case Ack:
00399 event = unpack_ack(pdu, datagram->u.T_DUnitdata_Ind.addr_tuple);
00400 break;
00401
00402 case Negative_ack:
00403 event = unpack_negative_ack(pdu, datagram->u.T_DUnitdata_Ind.addr_tuple);
00404 break;
00405
00406 case Abort:
00407 event = unpack_abort(pdu, datagram->u.T_DUnitdata_Ind.addr_tuple);
00408 break;
00409
00410 default:
00411 event = pack_error(datagram);
00412 debug("wap.wtp", 0, "WTP: Unhandled PDU type. Message was");
00413 wap_event_dump(datagram);
00414 return event;
00415 }
00416
00417 wtp_pdu_destroy(pdu);
00418
00419 wap_event_assert(event);
00420 return event;
00421 }
00422
00423
00424
00425
00426
00427
00428
00429 static int deduce_tid(Octstr *user_data)
00430 {
00431 return octstr_get_bits(user_data, 8, 16);
00432 }
00433
00434 static int concatenated_message(Octstr *user_data)
00435 {
00436 return octstr_get_char(user_data, 0) == 0x00;
00437 }
00438
00439
00440
See file LICENSE for details about the license agreement for using,
modifying, copying or deriving work from this software.