modules/ims_qos: added patch for flow-description bug when request originates from...
[sip-router] / src / modules / acc / diam_message.c
1 /*
2  * $Id$
3  *
4  * Copyright (C) 2002-2003 FhG Fokus
5  *
6  * This file is part of disc, a free diameter server/client.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License 
19  * along with this program; if not, write to the Free Software 
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21  *
22  * History:
23  * ---------
24  *
25  *   2003-04-07 created by bogdan
26  */
27
28 /*! \file
29  * \ingroup acc
30  * \brief Acc:: Diameter messages
31  *
32  * - Module: \ref acc
33  */
34
35 #ifdef DIAM_ACC
36
37 #include <stdlib.h>
38 #include <string.h>
39 #include <netinet/in.h>
40
41 #include "../../mem/shm_mem.h"
42 #include "../../dprint.h"
43 #include "diam_message.h"
44
45 #define get_3bytes(_b) \
46         ((((unsigned int)(_b)[0])<<16)|(((unsigned int)(_b)[1])<<8)|\
47         (((unsigned int)(_b)[2])))
48
49 #define get_4bytes(_b) \
50         ((((unsigned int)(_b)[0])<<24)|(((unsigned int)(_b)[1])<<16)|\
51         (((unsigned int)(_b)[2])<<8)|(((unsigned int)(_b)[3])))
52
53 #define set_3bytes(_b,_v) \
54         {(_b)[0]=((_v)&0x00ff0000)>>16;(_b)[1]=((_v)&0x0000ff00)>>8;\
55         (_b)[2]=((_v)&0x000000ff);}
56
57 #define set_4bytes(_b,_v) \
58         {(_b)[0]=((_v)&0xff000000)>>24;(_b)[1]=((_v)&0x00ff0000)>>16;\
59         (_b)[2]=((_v)&0x0000ff00)>>8;(_b)[3]=((_v)&0x000000ff);}
60
61 #define to_32x_len( _len_ ) \
62         ( (_len_)+(((_len_)&3)?4-((_len_)&3):0) )
63
64
65 /*! \brief from a AAAMessage structure, a buffer to be send is build
66  */
67 AAAReturnCode AAABuildMsgBuffer( AAAMessage *msg )
68 {
69         char *p;
70         AAA_AVP       *avp;
71
72         /* first let's compute the length of the buffer */
73         msg->buf.len = AAA_MSG_HDR_SIZE; /* AAA message header size */
74         /* count and add the avps */
75         for(avp=msg->avpList.head;avp;avp=avp->next) {
76                 msg->buf.len += AVP_HDR_SIZE(avp->flags)+ to_32x_len( avp->data.len );
77         }
78
79         /* allocate some memory */
80         msg->buf.s = (char*)ad_malloc( msg->buf.len );
81         if (!msg->buf.s) {
82                 LM_ERR("no more pkg free memory!\n");
83                 goto error;
84         }
85         memset(msg->buf.s, 0, msg->buf.len);
86
87         /* fill in the buffer */
88         p = msg->buf.s;
89         /* DIAMETER HEADER */
90         /* message length */
91         ((unsigned int*)p)[0] =htonl(msg->buf.len);
92         /* Diameter Version */
93         *p = 1;
94         p += VER_SIZE + MESSAGE_LENGTH_SIZE;
95         /* command code */
96         ((unsigned int*)p)[0] = htonl(msg->commandCode);
97         /* flags */
98         *p = (unsigned char)msg->flags;
99         p += FLAGS_SIZE + COMMAND_CODE_SIZE;
100         /* application-ID */
101         ((unsigned int*)p)[0] = htonl(msg->applicationId);
102         p += APPLICATION_ID_SIZE;
103         /* hop by hop id */
104         ((unsigned int*)p)[0] = msg->hopbyhopId;
105         p += HOP_BY_HOP_IDENTIFIER_SIZE;
106         /* end to end id */
107         ((unsigned int*)p)[0] = msg->endtoendId;
108         p += END_TO_END_IDENTIFIER_SIZE;
109
110         /* AVPS */
111         for(avp=msg->avpList.head;avp;avp=avp->next) {
112                 /* AVP HEADER */
113                 /* avp code */
114                 set_4bytes(p,avp->code);
115                 p +=4;
116                 /* flags */
117                 (*p++) = (unsigned char)avp->flags;
118                 /* avp length */
119                 set_3bytes(p, (AVP_HDR_SIZE(avp->flags)+avp->data.len) );
120                 p += 3;
121                 /* vendor id */
122                 if ((avp->flags&0x80)!=0) {
123                         set_4bytes(p,avp->vendorId);
124                         p +=4;
125                 }
126                 /* data */
127                 memcpy( p, avp->data.s, avp->data.len);
128                 p += to_32x_len( avp->data.len );
129         }
130
131         if ((char*)p-msg->buf.s!=msg->buf.len) {
132                 LM_ERR("mismatch between len and buf!\n");
133                 ad_free( msg->buf.s );
134                 msg->buf.s = 0;
135                 msg->buf.len = 0;
136                 goto error;
137         }
138         LM_DBG("Message: %.*s\n", msg->buf.len, msg->buf.s);
139         return AAA_ERR_SUCCESS;
140 error:
141         return -1;
142 }
143
144
145
146 /*! \brief frees a message allocated through AAANewMessage()
147  */
148 AAAReturnCode  AAAFreeMessage(AAAMessage **msg)
149 {
150         AAA_AVP *avp_t;
151         AAA_AVP *avp;
152
153         /* param check */
154         if (!msg || !(*msg))
155                 goto done;
156
157         /* free the avp list */
158         avp = (*msg)->avpList.head;
159         while (avp) {
160                 avp_t = avp;
161                 avp = avp->next;
162                 /*free the avp*/
163                 AAAFreeAVP(&avp_t);
164         }
165
166         /* free the buffer (if any) */
167         if ( (*msg)->buf.s )
168                 ad_free( (*msg)->buf.s );
169
170         /* free the AAA msg */
171         ad_free(*msg);
172         msg = 0;
173
174 done:
175         return AAA_ERR_SUCCESS;
176 }
177
178
179
180 /*! \brief Sets the proper result_code into the Result-Code AVP; thus avp must already
181  * exists into the reply message */
182 AAAResultCode  AAASetMessageResultCode(
183         AAAMessage *message,
184         AAAResultCode resultCode)
185 {
186         if ( !is_req(message) && message->res_code) {
187                 *((unsigned int*)(message->res_code->data.s)) = htonl(resultCode);
188                 return AAA_ERR_SUCCESS;
189         }
190         return AAA_ERR_FAILURE;
191 }
192
193
194
195 /*! \brief This function convert message to message structure */
196 AAAMessage* AAATranslateMessage( unsigned char* source, unsigned int sourceLen,
197                                                                                                                         int attach_buf)
198 {
199         unsigned char *ptr;
200         AAAMessage    *msg;
201         unsigned char version;
202         unsigned int  msg_len;
203         AAA_AVP       *avp;
204         unsigned int  avp_code;
205         unsigned char avp_flags;
206         unsigned int  avp_len;
207         unsigned int  avp_vendorID;
208         unsigned int  avp_data_len;
209
210         /* check the params */
211         if( !source || !sourceLen || sourceLen<AAA_MSG_HDR_SIZE) {
212                 LM_ERR("invalid buffered received!\n");
213                 goto error;
214         }
215
216         /* inits */
217         msg = 0;
218         avp = 0;
219         ptr = source;
220
221         /* alloc a new message structure */
222         msg = (AAAMessage*)ad_malloc(sizeof(AAAMessage));
223         if (!msg) {
224                 LM_ERR("no more pkg free memory!!\n");
225                 goto error;
226         }
227         memset(msg,0,sizeof(AAAMessage));
228
229         /* get the version */
230         version = (unsigned char)*ptr;
231         ptr += VER_SIZE;
232         if (version!=1) {
233                 LM_ERR("invalid version [%d]in AAA msg\n",version);
234                 goto error;
235         }
236
237         /* message length */
238         msg_len = get_3bytes( ptr );
239         ptr += MESSAGE_LENGTH_SIZE;
240         if (msg_len>sourceLen) {
241                 LM_ERR("AAA message len [%d] bigger then buffer len [%d]\n",
242                                 msg_len,sourceLen);
243                 goto error;
244         }
245
246         /* command flags */
247         msg->flags = *ptr;
248         ptr += FLAGS_SIZE;
249
250         /* command code */
251         msg->commandCode = get_3bytes( ptr );
252         ptr += COMMAND_CODE_SIZE;
253
254         /* application-Id */
255         msg->applicationId = get_4bytes( ptr );
256         ptr += APPLICATION_ID_SIZE;
257
258         /* Hop-by-Hop-Id */
259         msg->hopbyhopId = *((unsigned int*)ptr);
260         ptr += HOP_BY_HOP_IDENTIFIER_SIZE;
261
262         /* End-to-End-Id */
263         msg->endtoendId = *((unsigned int*)ptr);
264         ptr += END_TO_END_IDENTIFIER_SIZE;
265
266         /* start decoding the AVPS */
267         while (ptr < source+msg_len) {
268                 if (ptr+AVP_HDR_SIZE(0x80)>source+msg_len){
269                         LM_ERR("source buffer to short!! "
270                                 "Cannot read the whole AVP header!\n");
271                         goto error;
272                 }
273                 /* avp code */
274                 avp_code = get_4bytes( ptr );
275                 ptr += AVP_CODE_SIZE;
276                 /* avp flags */
277                 avp_flags = (unsigned char)*ptr;
278                 ptr += AVP_FLAGS_SIZE;
279                 /* avp length */
280                 avp_len = get_3bytes( ptr );
281                 ptr += AVP_LENGTH_SIZE;
282                 if (avp_len<1) {
283                         LM_ERR("invalid AVP len [%d]\n", avp_len);
284                         goto error;
285                 }
286                 /* avp vendor-ID */
287                 avp_vendorID = 0;
288                 if (avp_flags&AAA_AVP_FLAG_VENDOR_SPECIFIC) {
289                         avp_vendorID = get_4bytes( ptr );
290                         ptr += AVP_VENDOR_ID_SIZE;
291                 }
292                 /* data length */
293                 avp_data_len = avp_len-AVP_HDR_SIZE(avp_flags);
294                 /*check the data length */
295                 if ( source+msg_len<ptr+avp_data_len) {
296                         LM_ERR("source buffer to short!! "
297                                 "Cannot read a whole data for AVP!\n");
298                         goto error;
299                 }
300
301                 /* create the AVP */
302                 avp = AAACreateAVP( avp_code, avp_flags, avp_vendorID, (char*)ptr,
303                         avp_data_len, AVP_DONT_FREE_DATA);
304                 if (!avp)
305                         goto error;
306
307                 /* link the avp into aaa message to the end */
308                 AAAAddAVPToMessage( msg, avp, msg->avpList.tail);
309
310                 ptr += to_32x_len( avp_data_len );
311         }
312
313         /* link the buffer to the message */
314         if (attach_buf) {
315                 msg->buf.s = (char*)source;
316                 msg->buf.len = msg_len;
317         }
318
319         //AAAPrintMessage( msg );
320         return  msg;
321 error:
322         LM_ERR("message conversion droped!!\n");
323         AAAFreeMessage(&msg);
324         return 0;
325 }
326
327
328
329 /*! \brief print as debug all info contained by an aaa message + AVPs
330  */
331 void AAAPrintMessage( AAAMessage *msg)
332 {
333         char    buf[1024];
334         AAA_AVP *avp;
335
336         /* print msg info */
337         LM_DBG("AAA_MESSAGE - %p\n",msg);
338         LM_DBG("\tCode = %u\n",msg->commandCode);
339         LM_DBG("\tFlags = %x\n",msg->flags);
340
341         /*print the AVPs */
342         avp = msg->avpList.head;
343         while (avp) {
344                 AAAConvertAVPToString(avp,buf,1024);
345                 LM_DBG("\n%s\n",buf);
346                 avp=avp->next;
347         }
348 }
349
350 AAAMessage* AAAInMessage(AAACommandCode cmdCode, 
351                                 AAAApplicationId appID)
352 {
353         AAAMessage *msg;
354
355         /* allocated a new AAAMessage structure a set it to 0 */
356         msg = (AAAMessage*)ad_malloc(sizeof(AAAMessage));
357         if (!msg) {
358                 LM_ERR("no more pkg free memory!\n");
359                 return NULL;
360         }
361         memset(msg, 0, sizeof(AAAMessage));
362
363         /* command code */
364         msg->commandCode = cmdCode;
365
366         /* application ID */
367         msg->applicationId = appID;
368
369         /* it's a new request -> set the flag */
370         msg->flags = 0x80;
371
372         return msg;
373 }
374
375 #endif