parse_identityinfo.c

Go to the documentation of this file.
00001 /*
00002  * $Id$
00003  *
00004  * Copyright (c) 2007 iptelorg GmbH
00005  *
00006  * This file is part of ser, a free SIP server.
00007  *
00008  * ser is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version
00012  *
00013  * ser is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software
00020  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021  */
00022 
00029 #include <stdlib.h>
00030 #include <string.h>
00031 #include <ctype.h>
00032 #include "../mem/mem.h"
00033 #include "parse_def.h"
00034 #include "parse_identityinfo.h"
00035 #include "parser_f.h"  /* eat_space_end and so on */
00036 
00037 
00039 void parse_identityinfo(char *buffer, char *end, struct identityinfo_body *ii_b)
00040 {
00041         int status = II_START;
00042         int mainstatus = II_M_START;
00043         char *p;
00044 
00045 
00046         if (!buffer || !end || !ii_b) return ;
00047 
00048 
00049         ii_b->error = PARSE_ERROR;
00050 
00051         for(p = buffer; p < end; p++) {
00052                 switch(*p) {
00053                         case '<':
00054                                 if (status == II_START) {
00055                                         status=II_URI_BEGIN;
00056                                         mainstatus = II_M_URI_BEGIN;
00057                                         ii_b->uri.s = p + 1;
00058                                 } else
00059                                         goto parseerror;
00060                                         break;
00061                         case 'h':
00062                         case 'H': /* "http://" or "https://" part  */
00063                                 switch (status) {
00064                                         case II_URI_BEGIN:
00065                                                 if (end - p <= 8 || strncasecmp(p,"http",strlen("http")))
00066                                                         goto parseerror;
00067                                                 p+=4;
00068                                                 if (*p == 's' || *p == 'S') p++;
00069                                                 if (memcmp(p,"://",strlen("://")))
00070                                                         goto parseerror;
00071                                                 p+=2;
00072                                                 status = II_URI_DOMAIN;
00073                                                 break;
00074                                         case II_URI_DOMAIN:
00075                                                 status = II_URI_IPV4;
00076                                         case II_URI_IPV4:
00077                                         case II_URI_IPV6:
00078                                         case II_URI_PATH:
00079                                         case II_TOKEN:
00080                                         case II_TAG:
00081                                                 break;
00082                                         case II_EQUAL:
00083                                                 status = II_TOKEN;
00084                                                 mainstatus = II_M_TOKEN;
00085                                                 ii_b->alg.s = p;
00086                                                 break;
00087                                         case II_LWSCRLF:
00088                                                 ii_b->error=PARSE_OK;
00089                                                 return ;
00090                                         default:
00091                                                 goto parseerror;
00092                                 }
00093                                 break;
00094                         case '/':
00095                                 switch(status){
00096                                         case II_URI_IPV4:
00097                                                 ii_b->domain.len = p - ii_b->domain.s;
00098                                                 status = II_URI_PATH;
00099                                                 break;
00100                                         case II_URI_PATH:
00101                                                 break;
00102                                         case II_URI_IPV6:
00103                                         default:
00104                                                 goto parseerror;
00105                                 }
00106                                 break;
00107                         case '>':
00108                                 if (status == II_URI_PATH) {
00109                                         ii_b->uri.len = p - ii_b->uri.s;
00110                                         status = II_URI_END;
00111                                         mainstatus = II_M_URI_END;
00112                                 } else
00113                                         goto parseerror;
00114                                 break;
00115                         case ' ':
00116                         case '\t':
00117                                 switch (status) {
00118                                         case II_EQUAL:
00119                                         case II_TAG:
00120                                         case II_SEMIC:
00121                                         case II_URI_END:
00122                                                 status = II_LWS;
00123                                                 break;
00124                                         case II_LWS:
00125                                         case II_LWSCRLFSP:
00126                                                 break;
00127                                         case II_LWSCRLF:
00128                                                 status = II_LWSCRLFSP;
00129                                                 break;
00130                                         default:
00131                                                 goto parseerror;
00132                                 }
00133                                 break;
00134                         case '\r':
00135                                 switch (status) {
00136                                         case II_TOKEN:
00137                                                 ii_b->alg.len = p - ii_b->alg.s;
00138                                                 status = II_ENDHEADER;
00139                                                 break;
00140                                         case II_EQUAL:
00141                                         case II_TAG:
00142                                         case II_SEMIC:
00143                                         case II_URI_END:
00144                                         case II_LWS:
00145                                                 status = II_LWSCR;
00146                                                 break;
00147                                         case II_LWSCRLF:
00148                                                 ii_b->error=PARSE_OK;
00149                                                 return ;
00150                                         default:
00151                                                 goto parseerror;
00152                                 }
00153                                 break;
00154                         case '\n':
00155                                 switch (status) {
00156                                         case II_LWSCRLF:
00157                                                 ii_b->error=PARSE_OK;
00158                                                 return ;
00159                                         case II_EQUAL:
00160                                         case II_TAG:
00161                                         case II_SEMIC:
00162                                         case II_URI_END:
00163                                         case II_LWS:
00164                                         case II_LWSCR:
00165                                                 status = II_LWSCRLF;
00166                                                 break;
00167                                         case II_TOKEN: /* if there was not '\r' */
00168                                                 ii_b->alg.len = p - ii_b->alg.s;
00169                                         case II_ENDHEADER:
00170                                                 p=eat_lws_end(p, end);
00171                                                 /*check if the header ends here*/
00172                                                 if (p>=end) {
00173                                                         LOG(L_ERR, "ERROR: parse_identityinfo: strange EoHF\n");
00174                                                         goto parseerror;
00175                                                 }
00176                                                 ii_b->error=PARSE_OK;
00177                                                 return ;
00178                                         default:
00179                                                 goto parseerror;
00180                                 }
00181                                 break;
00182                         case ';':
00183                                 switch (status) {
00184                                         case II_URI_END:
00185                                         case II_LWS:
00186                                         case II_LWSCRLFSP:
00187                                                 if (mainstatus == II_M_URI_END) {
00188                                                         status = II_SEMIC;
00189                                                         mainstatus = II_M_SEMIC;
00190                                                 } else
00191                                                         goto parseerror;
00192                                                 break;
00193                                         default:
00194                                                 goto parseerror;
00195                                 }
00196                                 break;
00197                         case 'a': /* tag part of 'alg' parameter */
00198                         case 'A':
00199                                 switch (status) {
00200                                         case II_LWS:
00201                                         case II_LWSCRLFSP:
00202                                         case II_SEMIC:
00203                                                 if (mainstatus == II_M_SEMIC) {
00204                                                         mainstatus = II_M_TAG;
00205                                                         status = II_TAG;
00206                                                         if (end - p <= 3 || strncasecmp(p,"alg",strlen("alg")))
00207                                                                 goto parseerror;
00208                                                         p+=2;
00209                                                 } else
00210                                                         goto parseerror;
00211                                                 break;
00212                                         case II_URI_DOMAIN:
00213                                                 status = II_URI_IPV4;
00214                                         case II_URI_IPV4:
00215                                         case II_URI_IPV6:
00216                                         case II_URI_PATH:
00217                                         case II_TOKEN:
00218                                                 break;
00219                                         case II_EQUAL:
00220                                                 status = II_TOKEN;
00221                                                 mainstatus = II_M_TOKEN;
00222                                                 ii_b->alg.s = p;
00223                                                 break;
00224                                         case II_LWSCRLF:
00225                                                 ii_b->error=PARSE_OK;
00226                                                 return ;
00227                                         default:
00228                                                 goto parseerror;
00229                                 }
00230                                 break;
00231                         case '=':
00232                                 switch (status) {
00233                                         case II_TAG:
00234                                         case II_LWS:
00235                                         case II_LWSCRLFSP:
00236                                                 if (mainstatus == II_M_TAG) {
00237                                                         status = II_EQUAL;
00238                                                         mainstatus = II_M_EQUAL;
00239                                                 } else
00240                                                         goto parseerror;
00241                                                 break;
00242                                         case II_URI_PATH:
00243                                                 break;
00244                                         default:
00245                                                 goto parseerror;
00246                                 }
00247                                 break;
00248                         case '[':
00249                                 switch (status) {
00250                                         case II_URI_DOMAIN:
00251                                                 status = II_URI_IPV6;
00252                                                 ii_b->domain.s = p + 1;
00253                                                 break;
00254                                         default:
00255                                                 goto parseerror;
00256                                 }
00257                                 break;
00258                         case ']':
00259                                 switch (status) {
00260                                         case II_URI_IPV6:
00261                                                 ii_b->domain.len = p - ii_b->domain.s;
00262                                                 status = II_URI_PATH;
00263                                                 break;
00264                                         case II_URI_IPV4:
00265                                         case II_URI_PATH:
00266                                                 goto parseerror;
00267                                 }
00268                                 break;
00269                         case ':':
00270                                 if (status == II_URI_IPV4) {
00271                                         ii_b->domain.len = p - ii_b->domain.s;
00272                                         status = II_URI_PATH;
00273                                 }
00274                                 break;
00275                         default:
00276                                 switch (status) {
00277                                         case II_EQUAL:
00278                                         case II_LWS:
00279                                         case II_LWSCRLFSP:
00280                                                 if (mainstatus == II_M_EQUAL) {
00281                                                         status = II_TOKEN;
00282                                                         mainstatus = II_M_TOKEN;
00283                                                         ii_b->alg.s = p;
00284                                                 } else
00285                                                         goto parseerror;
00286                                                 break;
00287                                         case II_TOKEN:
00288                                                 break;
00289                                         case II_LWSCRLF:
00290                                                 ii_b->error=PARSE_OK;
00291                                                 return ;
00292                                         case II_URI_DOMAIN:
00293                                                 ii_b->domain.s = p;
00294                                                 status = II_URI_IPV4;
00295                                         case II_URI_IPV4:
00296                                         case II_URI_IPV6:
00297                                                 if (isalnum(*p)
00298                                                     || *p == '-'
00299                                                     || *p == '.'
00300                                                     || *p == ':' )
00301                                                 break;
00302                                         case II_START:
00303                                                 goto parseerror;
00304                                 }
00305                                 break;
00306                 }
00307         }
00308         /* we successfully parse the header */
00309         ii_b->error=PARSE_OK;
00310         return ;
00311 
00312 parseerror:
00313         LOG( L_ERR , "ERROR: parse_identityinfo: "
00314         "unexpected char [%c] in status %d: <<%.*s>> .\n",
00315         *p,status, (int)(p-buffer), ZSW(p));
00316         return ;
00317 }
00318 
00319 int parse_identityinfo_header(struct sip_msg *msg)
00320 {
00321         struct identityinfo_body* identityinfo_b;
00322 
00323 
00324         if ( !msg->identity_info
00325                  && (parse_headers(msg,HDR_IDENTITY_INFO_F,0)==-1
00326                          || !msg->identity_info) ) {
00327                 LOG(L_ERR,"ERROR:parse_identityinfo_header: bad msg or missing IDENTITY-INFO header\n");
00328                 goto error;
00329         }
00330 
00331         /* maybe the header is already parsed! */
00332         if (msg->identity_info->parsed)
00333                 return 0;
00334 
00335         identityinfo_b=pkg_malloc(sizeof(*identityinfo_b));
00336         if (identityinfo_b==0){
00337                 LOG(L_ERR, "ERROR:parse_identityinfo_header: out of memory\n");
00338                 goto error;
00339         }
00340         memset(identityinfo_b, 0, sizeof(*identityinfo_b));
00341 
00342         parse_identityinfo(msg->identity_info->body.s,
00343                                            msg->identity_info->body.s + msg->identity_info->body.len+1,
00344                                            identityinfo_b);
00345         if (identityinfo_b->error==PARSE_ERROR){
00346                 free_identityinfo(identityinfo_b);
00347                 goto error;
00348         }
00349         msg->identity_info->parsed=(void*)identityinfo_b;
00350 
00351         return 0;
00352 error:
00353         return -1;
00354 }
00355 
00356 void free_identityinfo(struct identityinfo_body *ii_b)
00357 {
00358         pkg_free(ii_b);
00359 }