param_parser.c

Go to the documentation of this file.
00001 /*
00002  * $Id: param_parser.c 4892 2008-09-11 17:44:28Z henningw $
00003  *
00004  * 32-bit Digest parameter name parser
00005  *
00006  * Copyright (C) 2001-2003 FhG Fokus
00007  *
00008  * This file is part of Kamailio, a free SIP server.
00009  *
00010  * Kamailio is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version
00014  *
00015  * Kamailio is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License 
00021  * along with this program; if not, write to the Free Software 
00022  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00023  */
00024 
00025 #include "param_parser.h"
00026 #include "digest_keys.h"
00027 #include "../../trim.h"
00028 #include "../../ut.h"
00029 
00030 #define LOWER_BYTE(b) ((b) | 0x20)
00031 #define LOWER_DWORD(d) ((d) | 0x20202020)
00032 
00033 /*
00034  * Parse short (less than 4 bytes) parameter names
00035  */
00036 #define PARSE_SHORT                                                   \
00037    switch(LOWER_BYTE(*p)) {                                      \
00038    case 'u':                                                     \
00039       if (LOWER_BYTE(*(p + 1)) == 'r') {                    \
00040          if (LOWER_BYTE(*(p + 2)) == 'i') {            \
00041             *_type = PAR_URI;                     \
00042                                 p += 3;                               \
00043             goto end;                             \
00044          }                                             \
00045       }                                                     \
00046       break;                                                \
00047                                                                       \
00048    case 'q':                                                     \
00049       if (LOWER_BYTE(*(p + 1)) == 'o') {                    \
00050          if (LOWER_BYTE(*(p + 2)) == 'p') {            \
00051             *_type = PAR_QOP;                     \
00052                                 p += 3;                               \
00053             goto end;                             \
00054          }                                             \
00055       }                                                     \
00056       break;                                                \
00057                                                                       \
00058    case 'n':                                                     \
00059       if (LOWER_BYTE(*(p + 1)) == 'c') {                    \
00060          *_type = PAR_NC;                              \
00061                         p += 2;                                       \
00062          goto end;                                     \
00063       }                                                     \
00064       break;                                                \
00065    }
00066 
00067 
00068 /*
00069  * Read 4-bytes from memory and store them in an integer variable
00070  * Reading byte by byte ensures, that the code works also on HW which
00071  * does not allow reading 4-bytes at once from unaligned memory position
00072  * (Sparc for example)
00073  */
00074 #define READ(val) \
00075 (*(val + 0) + (*(val + 1) << 8) + (*(val + 2) << 16) + (*(val + 3) << 24))
00076 
00077 
00078 #define name_CASE                      \
00079         switch(LOWER_DWORD(val)) {     \
00080         case _name_:                   \
00081       *_type = PAR_USERNAME; \
00082                 p += 4;                \
00083       goto end;              \
00084         }
00085 
00086 
00087 #define user_CASE         \
00088         p += 4;           \
00089         val = READ(p);    \
00090         name_CASE;        \
00091         goto other;
00092 
00093 
00094 #define real_CASE                         \
00095         p += 4;                           \
00096         if (LOWER_BYTE(*p) == 'm') {      \
00097       *_type = PAR_REALM;       \
00098                 p++;                      \
00099       goto end;                 \
00100    }
00101 
00102 
00103 #define nonc_CASE                         \
00104         p += 4;                           \
00105         if (LOWER_BYTE(*p) == 'e') {      \
00106            *_type = PAR_NONCE;       \
00107                 p++;                      \
00108       goto end;                 \
00109    }
00110 
00111 
00112 #define onse_CASE                      \
00113         switch(LOWER_DWORD(val)) {     \
00114         case _onse_:                   \
00115       *_type = PAR_RESPONSE; \
00116                 p += 4;                \
00117       goto end;              \
00118         }
00119 
00120 
00121 #define resp_CASE         \
00122         p += 4;           \
00123         val = READ(p);    \
00124         onse_CASE;        \
00125         goto other;
00126 
00127 
00128 #define cnon_CASE                                 \
00129         p += 4;                                   \
00130         if (LOWER_BYTE(*p) == 'c') {              \
00131       p++;                              \
00132       if (LOWER_BYTE(*p) == 'e') {      \
00133          *_type = PAR_CNONCE;      \
00134                         p++;                      \
00135          goto end;                 \
00136       }                                 \
00137    }                                         \
00138         goto other;
00139 
00140 
00141 #define opaq_CASE                                 \
00142         p += 4;                                   \
00143         if (LOWER_BYTE(*p) == 'u') {              \
00144       p++;                              \
00145       if (LOWER_BYTE(*p) == 'e') {      \
00146          *_type = PAR_OPAQUE;      \
00147                         p++;                      \
00148          goto end;                 \
00149       }                                 \
00150    }                                         \
00151         goto other;
00152 
00153 
00154 #define rith_CASE                                 \
00155         switch(LOWER_DWORD(val)) {                \
00156    case _rith_:                              \
00157       p += 4;                           \
00158       if (LOWER_BYTE(*p) == 'm') {      \
00159          *_type = PAR_ALGORITHM;   \
00160                         p++;                      \
00161          goto end;                 \
00162       }                                 \
00163       goto other;                       \
00164    }
00165 
00166 
00167 #define algo_CASE         \
00168         p += 4;           \
00169         val = READ(p);    \
00170         rith_CASE;        \
00171         goto other
00172 
00173 
00174 #define FIRST_QUATERNIONS       \
00175         case _user_: user_CASE; \
00176         case _real_: real_CASE; \
00177         case _nonc_: nonc_CASE; \
00178         case _resp_: resp_CASE; \
00179         case _cnon_: cnon_CASE; \
00180         case _opaq_: opaq_CASE; \
00181         case _algo_: algo_CASE;
00182 
00183 
00184 
00185 
00186 int parse_param_name(str* _s, dig_par_t* _type)
00187 {
00188         register char* p;
00189         register int val;
00190    char* end;
00191    
00192    end = _s->s + _s->len;
00193    
00194    p = _s->s;
00195    val = READ(p);
00196    
00197    if (_s->len < 4) {
00198       goto other;
00199    }
00200    
00201         switch(LOWER_DWORD(val)) {
00202    FIRST_QUATERNIONS;
00203    default:
00204       PARSE_SHORT;
00205       goto other;
00206         }
00207 
00208  end:
00209    _s->len -= p - _s->s;
00210    _s->s = p;
00211 
00212    trim_leading(_s);
00213    if (_s->s[0] == '=') {
00214       return 0;
00215    }
00216    
00217  other:
00218    p = memchr(p, '=', end - p);
00219    if (!p) {
00220       return -1; /* Parse error */
00221    } else {
00222       *_type = PAR_OTHER;
00223       _s->len -= p - _s->s;
00224       _s->s = p;
00225       return 0;
00226    }
00227 }

Generated on Thu May 24 00:00:28 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6