modules/ims_qos: added patch for flow-description bug when request originates from...
[sip-router] / src / core / parser / digest / param_parser.c
1 /*
2  * 32-bit Digest parameter name parser
3  *
4  * Copyright (C) 2001-2003 FhG Fokus
5  *
6  * This file is part of ser, a free SIP server.
7  *
8  * ser 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  * For a license to use the ser software under conditions
14  * other than those described here, or to purchase support for this
15  * software, please contact iptel.org by e-mail at the following addresses:
16  *    info@iptel.org
17  *
18  * ser is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License 
24  * along with this program; if not, write to the Free Software 
25  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
26  */
27
28 #include "param_parser.h"
29 #include "digest_keys.h"
30 #include "../../trim.h"
31 #include "../../ut.h"
32
33 #define LOWER_BYTE(b) ((b) | 0x20)
34 #define LOWER_DWORD(d) ((d) | 0x20202020)
35
36 /*
37  * Parse short (less than 4 bytes) parameter names
38  */
39 #define PARSE_SHORT                                                   \
40         switch(LOWER_BYTE(*p)) {                                      \
41         case 'u':                                                     \
42                 if (LOWER_BYTE(*(p + 1)) == 'r') {                    \
43                         if (LOWER_BYTE(*(p + 2)) == 'i') {            \
44                                 *_type = PAR_URI;                     \
45                                 p += 3;                               \
46                                 goto end;                             \
47                         }                                             \
48                 }                                                     \
49                 break;                                                \
50                                                                       \
51         case 'q':                                                     \
52                 if (LOWER_BYTE(*(p + 1)) == 'o') {                    \
53                         if (LOWER_BYTE(*(p + 2)) == 'p') {            \
54                                 *_type = PAR_QOP;                     \
55                                 p += 3;                               \
56                                 goto end;                             \
57                         }                                             \
58                 }                                                     \
59                 break;                                                \
60                                                                       \
61         case 'n':                                                     \
62                 if (LOWER_BYTE(*(p + 1)) == 'c') {                    \
63                         *_type = PAR_NC;                              \
64                         p += 2;                                       \
65                         goto end;                                     \
66                 }                                                     \
67                 break;                                                \
68         }
69
70
71 /*
72  * Read 4-bytes from memory and store them in an integer variable
73  * Reading byte by byte ensures, that the code works also on HW which
74  * does not allow reading 4-bytes at once from unaligned memory position
75  * (Sparc for example)
76  */
77 #define READ(val) \
78 (*(val + 0) + (*(val + 1) << 8) + (*(val + 2) << 16) + (*(val + 3) << 24))
79
80
81 #define name_CASE                      \
82         switch(LOWER_DWORD(val)) {     \
83         case _name_:                   \
84                 *_type = PAR_USERNAME; \
85                 p += 4;                \
86                 goto end;              \
87         }
88
89
90 #define user_CASE         \
91         p += 4;           \
92         val = READ(p);    \
93         name_CASE;        \
94         goto other;
95
96
97 #define real_CASE                         \
98         p += 4;                           \
99         if (LOWER_BYTE(*p) == 'm') {      \
100                 *_type = PAR_REALM;       \
101                 p++;                      \
102                 goto end;                 \
103         }
104
105
106 #define nonc_CASE                         \
107         p += 4;                           \
108         if (LOWER_BYTE(*p) == 'e') {      \
109                 *_type = PAR_NONCE;       \
110                 p++;                      \
111                 goto end;                 \
112         }
113
114
115 #define onse_CASE                      \
116         switch(LOWER_DWORD(val)) {     \
117         case _onse_:                   \
118                 *_type = PAR_RESPONSE; \
119                 p += 4;                \
120                 goto end;              \
121         }
122
123
124 #define resp_CASE         \
125         p += 4;           \
126         val = READ(p);    \
127         onse_CASE;        \
128         goto other;
129
130
131 #define cnon_CASE                                 \
132         p += 4;                                   \
133         if (LOWER_BYTE(*p) == 'c') {              \
134                 p++;                              \
135                 if (LOWER_BYTE(*p) == 'e') {      \
136                         *_type = PAR_CNONCE;      \
137                         p++;                      \
138                         goto end;                 \
139                 }                                 \
140         }                                         \
141         goto other;
142
143
144 #define opaq_CASE                                 \
145         p += 4;                                   \
146         if (LOWER_BYTE(*p) == 'u') {              \
147                 p++;                              \
148                 if (LOWER_BYTE(*p) == 'e') {      \
149                         *_type = PAR_OPAQUE;      \
150                         p++;                      \
151                         goto end;                 \
152                 }                                 \
153         }                                         \
154         goto other;
155
156
157 #define rith_CASE                                 \
158         switch(LOWER_DWORD(val)) {                \
159         case _rith_:                              \
160                 p += 4;                           \
161                 if (LOWER_BYTE(*p) == 'm') {      \
162                         *_type = PAR_ALGORITHM;   \
163                         p++;                      \
164                         goto end;                 \
165                 }                                 \
166                 goto other;                       \
167         }
168
169
170 #define algo_CASE         \
171         p += 4;           \
172         val = READ(p);    \
173         rith_CASE;        \
174         goto other
175
176
177 #define FIRST_QUATERNIONS       \
178         case _user_: user_CASE; \
179         case _real_: real_CASE; \
180         case _nonc_: nonc_CASE; \
181         case _resp_: resp_CASE; \
182         case _cnon_: cnon_CASE; \
183         case _opaq_: opaq_CASE; \
184         case _algo_: algo_CASE;
185
186
187
188
189 int parse_param_name(str* _s, dig_par_t* _type)
190 {
191         register char* p;
192         register int val;
193         char* end;
194         
195         end = _s->s + _s->len;
196         
197         p = _s->s;
198         val = READ(p);
199         
200         if (_s->len < 4) {
201                 goto other;
202         }
203         
204         switch(LOWER_DWORD(val)) {
205         FIRST_QUATERNIONS;
206         default:
207                 PARSE_SHORT;
208                 goto other;
209         }
210
211  end:
212         _s->len -= p - _s->s;
213         _s->s = p;
214
215         trim_leading(_s);
216         if (_s->s[0] == '=') {
217                 return 0;
218         }
219         
220  other:
221         p = q_memchr(p, '=', end - p);
222         if (!p) {
223                 return -1; /* Parse error */
224         } else {
225                 *_type = PAR_OTHER;
226                 _s->len -= p - _s->s;
227                 _s->s = p;
228                 return 0;
229         }
230 }