Kannel: Open Source WAP and SMS gateway  $Revision: 5037 $
wtp_tid.c
Go to the documentation of this file.
1 /* ====================================================================
2  * The Kannel Software License, Version 1.0
3  *
4  * Copyright (c) 2001-2016 Kannel Group
5  * Copyright (c) 1998-2001 WapIT Ltd.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Kannel Group (http://www.kannel.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Kannel" and "Kannel Group" must not be used to
28  * endorse or promote products derived from this software without
29  * prior written permission. For written permission, please
30  * contact org@kannel.org.
31  *
32  * 5. Products derived from this software may not be called "Kannel",
33  * nor may "Kannel" appear in their name, without prior written
34  * permission of the Kannel Group.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS
40  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
41  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
42  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
43  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
44  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
45  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
46  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many
50  * individuals on behalf of the Kannel Group. For more information on
51  * the Kannel Group, please see <http://www.kannel.org/>.
52  *
53  * Portions of this software are based upon software originally written at
54  * WapIT Ltd., Helsinki, Finland for the Kannel project.
55  */
56 
57 /*
58  * wtp_tid.c - Implementation of WTP tid validation tests. Note that only
59  * WTP responder uses tid validation.
60  *
61  * By Aarno Syvšnen for Wapit Ltd.
62  */
63 
64 #include "gwlib/gwlib.h"
65 #include "wtp_tid.h"
66 
67 /*
68  * Constants used for defining the tid cache status
69  */
70 enum {
71  no_cache = -1,
74  cached = 0
75 };
76 
77 /*
78  * Global data structure:
79  *
80  * Tid cache is implemented by using a library object List
81  */
82  static List *tid_cache = NULL;
83 
84 /*****************************************************************************
85  * Prototypes of internal functions
86  */
88 static void cache_item_destroy(void *item);
89 /*
90 static void cache_item_dump(WTPCached_tid *item);
91 */
92 static void add_tid(WTPRespMachine *resp_machine, long tid);
93 static void set_tid_by_item(WTPCached_tid *item, long tid);
94 static int tid_in_window(long rcv_tid, long last_tid);
95 static WTPCached_tid *tid_cached(WTPRespMachine *resp_machine);
96 
97 /******************************************************************************
98  *
99  * External functions:
100  */
101 
103 {
104  tid_cache = gwlist_create();
105 }
106 
108 {
109  debug("wap.wtp_tid", 0, "%ld items left in the tid cache",
110  gwlist_len(tid_cache));
112 }
113 
114 /*
115  * Tid verification is invoked, when tid_new flag of the incoming message is
116  * on. It is not, if the initiator is not yet cached. If initiator is cached,
117  * the received tid is stored.
118  */
119 int wtp_tid_is_valid(WAPEvent *event, WTPRespMachine *resp_machine)
120 {
121  long rcv_tid = -1,
122  last_tid = -1;
123 
124  WTPCached_tid *item = NULL;
125 
126 #if 0
127  debug("wap.wtp.tid", 0, "starting validation");
128 #endif
129  rcv_tid = resp_machine->tid;
130 
131  if (!event->u.RcvInvoke.tid_new) {
132 /*
133  * First we check whether the current initiator has a cache item for it.
134  */
135  if ((item = tid_cached(resp_machine)) == NULL) {
136  if (event->u.RcvInvoke.no_cache_supported)
137  return no_cached_tid;
138  else {
139 #if 0
140  debug("wap.wtp.tid", 0, "empty cache");
141 #endif
142  add_tid(resp_machine, rcv_tid);
143  return ok;
144  }
145  }
146 /*
147  * If it has, we check if the message is a duplicate or has tid wrapped up
148  * confusingly.
149  */
150  last_tid = item->tid;
151 
152  if (tid_in_window(rcv_tid, last_tid) == 0){
153  info(0, "WTP_TID: tid out of the window");
154  return fail;
155  } else {
156 #if 0
157  debug("wap.wtp.tid", 0, "tid in the window");
158 #endif
159  set_tid_by_item(item, rcv_tid);
160  return ok;
161  }
162 
163  } else {
164  info(0, "WTP_TID: tid_new flag on");
165  rcv_tid = 0;
166 
167  if (item == NULL) {
168  add_tid(resp_machine, rcv_tid);
169  } else {
170  set_tid_by_item(item, rcv_tid);
171  }
172 
173  return fail;
174  }
175 /*
176  * This return is unnecessary but the compiler demands it
177  */
178  return fail;
179 }
180 
181 /*
182  * Changes tid value used by an existing initiator. Input responder machine
183  * and the new tid.
184  */
185 void wtp_tid_set_by_machine(WTPRespMachine *resp_machine, long tid)
186 {
187  WTPCached_tid *item = NULL;
188 
189  item = tid_cached(resp_machine);
190  set_tid_by_item(item, tid);
191 }
192 
193 /*****************************************************************************
194  *
195  * Internal functions:
196  *
197  * Checks whether the received tid is inside the window of acceptable ones.
198  * The size of the window is set by the constant WTP_TID_WINDOW_SIZE (half of
199  * the tid space is the recommended value).
200  *
201  * Inputs: stored tid, received tid. Output 0, if received tid is outside the
202  * window, 1, if it is inside.
203  */
204 static int tid_in_window(long rcv_tid, long last_tid)
205 {
206 #if 0
207  debug("wap.wtp.tid", 0, "tids were rcv_tid, %ld and last_tid, %ld"
208  " and test window %ld", rcv_tid, last_tid, WTP_TID_WINDOW_SIZE);
209 #endif
210  if (last_tid == rcv_tid) {
211  return 0;
212  }
213 
214  if (rcv_tid > last_tid) {
215  if (abs(rcv_tid - last_tid) <= WTP_TID_WINDOW_SIZE) {
216  return 1;
217  } else {
218  return 0;
219  }
220  }
221 
222  if (rcv_tid < last_tid) {
223  if (abs(rcv_tid - last_tid) >= WTP_TID_WINDOW_SIZE){
224  return 1;
225  } else {
226  return 0;
227  }
228  }
229 
230 /*
231  * Following return is unnecessary but our compiler demands it
232  */
233  return 0;
234 }
235 
237 {
238  WTPCached_tid *item = NULL;
239 
240  item = gw_malloc(sizeof(*item));
241  item->addr_tuple = NULL;
242  item->tid = 0;
243 
244  return item;
245 }
246 
247 static void cache_item_destroy(void *p)
248 {
249  WTPCached_tid *item;
250 
251  item = p;
253  gw_free(item);
254 }
255 
256 /*
257  * Checking whether there is an item stored for a specific initiator. Receives
258  * address quadruplet - the identifier it uses - from object WTPRespMachine.
259  * Ditto tid. Returns the item or NULL, if there is not one. Initiator is
260  * identified by the address four-tuple.
261  */
262 
263 static int tid_is_cached(void *a, void *b)
264 {
265  WAPAddrTuple *initiator_profile;
266  WTPCached_tid *item;
267 
268  item = a;
269  initiator_profile = b;
270 
271  return wap_addr_tuple_same(item->addr_tuple, initiator_profile);
272 }
273 
275 {
276  WTPCached_tid *item = NULL;
277 
278  item = gwlist_search(tid_cache, resp_machine->addr_tuple, tid_is_cached);
279 
280  return item;
281 }
282 
283 /*
284  * Adds an item to the tid cache, one item per every initiator. Initiator is
285  * identified by the address four-tuple, fetched from a wtp responder machine.
286  */
287 static void add_tid(WTPRespMachine *resp_machine, long tid)
288 {
289  WTPCached_tid *new_item = NULL;
290 
291  new_item = cache_item_create_empty();
292  new_item->addr_tuple = wap_addr_tuple_duplicate(resp_machine->addr_tuple);
293  new_item->tid = tid;
294 
295  gwlist_append(tid_cache, new_item);
296 }
297 
298 /*
299  * Set tid for an existing initiator. Input a cache item and the new tid.
300  */
301 static void set_tid_by_item(WTPCached_tid *item, long tid)
302 {
303  gwlist_lock(tid_cache);
304  item->tid = tid;
305  gwlist_unlock(tid_cache);
306 }
void info(int err, const char *fmt,...)
Definition: log.c:636
void * gwlist_search(List *list, void *pattern, int(*cmp)(void *, void *))
Definition: list.c:486
#define WTP_TID_WINDOW_SIZE
Definition: wtp_tid.h:75
void gwlist_append(List *list, void *item)
Definition: list.c:179
static unsigned short rcv_tid(unsigned short tid)
Definition: wtp_init.c:541
long gwlist_len(List *list)
Definition: list.c:166
static Item * new_item(long producer, long num, long index)
Definition: check_list.c:88
void wtp_tid_set_by_machine(WTPRespMachine *resp_machine, long tid)
Definition: wtp_tid.c:185
WAPAddrTuple * wap_addr_tuple_duplicate(WAPAddrTuple *tuple)
Definition: wap_addr.c:125
void wtp_tid_cache_init(void)
Definition: wtp_tid.c:102
WAPAddrTuple * addr_tuple
Definition: wtp_tid.h:90
Definition: wtp_tid.c:74
void gwlist_unlock(List *list)
Definition: list.c:354
static WTPCached_tid * tid_cached(WTPRespMachine *resp_machine)
Definition: wtp_tid.c:274
static WTPCached_tid * cache_item_create_empty(void)
Definition: wtp_tid.c:236
static int tid_in_window(long rcv_tid, long last_tid)
Definition: wtp_tid.c:204
static List * tid_cache
Definition: wtp_tid.c:82
static void add_tid(WTPRespMachine *resp_machine, long tid)
Definition: wtp_tid.c:287
int wtp_tid_is_valid(WAPEvent *event, WTPRespMachine *resp_machine)
Definition: wtp_tid.c:119
void wap_addr_tuple_destroy(WAPAddrTuple *tuple)
Definition: wap_addr.c:108
void wtp_tid_cache_shutdown(void)
Definition: wtp_tid.c:107
long tid
Definition: wtp_tid.h:91
void gwlist_lock(List *list)
Definition: list.c:347
T DUnitdata TR Invoke TR Invoke TR Result TR Abort S Connect S Suspend S Resume S Suspend S Resume S Disconnect S MethodInvoke S MethodInvoke S MethodResult S MethodInvoke S MethodResult S MethodAbort S Push S ConfirmedPush S ConfirmedPush S PushAbort RcvInvoke
Definition: wap_events.h:491
int wap_addr_tuple_same(WAPAddrTuple *a, WAPAddrTuple *b)
Definition: wap_addr.c:118
static int tid_is_cached(void *a, void *b)
Definition: wtp_tid.c:263
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:690
Definition: wtp_tid.h:82
static void set_tid_by_item(WTPCached_tid *item, long tid)
Definition: wtp_tid.c:301
#define gwlist_create()
Definition: list.h:136
union WAPEvent::@87 u
Definition: wtp_tid.h:83
Definition: list.c:102
static void cache_item_destroy(void *item)
Definition: wtp_tid.c:247
void gwlist_destroy(List *list, gwlist_item_destructor_t *destructor)
Definition: list.c:145
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.