parse_via.c

Go to the documentation of this file.
00001 /*
00002  * $Id: parse_via.c 4720 2008-08-23 10:56:15Z henningw $ 
00003  *
00004  * Copyright (C) 2001-2003 FhG Fokus
00005  *
00006  * This file is part of Kamailio, a free SIP server.
00007  *
00008  * Kamailio 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  * Kamailio 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 
00023 /*
00024  *  2003-01-21  added rport parsing code, contributed by
00025  *               Maxim Sobolev  <sobomax@FreeBSD.org>
00026  *  2003-01-23  added extra via param parsing code (i=...), used
00027  *               by tcp to identify the sending socket, by andrei
00028  *  2003-01-23  fixed rport parsing code to accept rport w/o any value,
00029  *               by andrei
00030  *  2003-01-27  modified parse_via to set new via_param->start member and
00031  *               via->params.s (andrei)
00032  *  2003-01-28  zero-terminations replaced with VIA_ZT (jiri)
00033  *  2003-02-28  scratchpad compatibility abandoned (jiri)
00034  *  2003-04-26  ZSW (jiri)
00035  *  2003-06-23  fixed  parse_via_param [op].* param. parsing bug (andrei)
00036  *  2003-07-02  added support for TLS parsing in via (andrei)
00037  *  2003-10-27  added support for alias via param parsing [see
00038  *               draft-ietf-sip-connect-reuse-00.txt.]  (andrei)
00039  *  2004-03-31  fixed rport set instead of i bug (andrei)
00040  *  2005-03-02  if via has multiple bodies, and one of them is bad set
00041  *               also the first one as bad (andrei)
00042  */
00043 
00044 /*!
00045  * \file
00046  * \brief VIA parsing automaton
00047  * \ingroup parser
00048  */
00049 
00050 #include <stdlib.h>
00051 #include <string.h>
00052 #include "../dprint.h"
00053 #include "../ut.h"
00054 #include "../mem/mem.h"
00055 #include "../ip_addr.h"
00056 #include "parse_via.h"
00057 #include "parse_def.h"
00058 
00059 
00060 
00061 /*! main via states (uri:port ...) */
00062 enum {            
00063    F_HOST, P_HOST,
00064    L_PORT, F_PORT, P_PORT,
00065    L_PARAM, F_PARAM, P_PARAM,
00066    L_VIA, F_VIA,
00067    F_COMMENT, P_COMMENT,
00068    F_IP6HOST, P_IP6HOST, 
00069    F_CRLF,
00070    F_LF,
00071    F_CR,
00072    END_OF_HEADER
00073 };
00074 
00075 
00076 /*! first via part state */
00077 enum {
00078    F_SIP = 100,
00079    SIP1, SIP2, FIN_SIP,
00080    L_VER, F_VER,
00081    VER1, VER2, FIN_VER,
00082    UDP1, UDP2, FIN_UDP,
00083    TCP_TLS1, TCP2, FIN_TCP,
00084              TLS2, FIN_TLS,
00085    SCTP1, SCTP2, SCTP3, FIN_SCTP,
00086    L_PROTO, F_PROTO
00087 };
00088 
00089 
00090 /*! param related states
00091  * \warning keep in sync with parse_via.h, PARAM_HIDDEN..
00092  */
00093 enum {   
00094    L_VALUE = 200, F_VALUE, P_VALUE, P_STRING,
00095    HIDDEN1, HIDDEN2, HIDDEN3, HIDDEN4, HIDDEN5,
00096    TTL1, TTL2,
00097    BRANCH1, BRANCH2, BRANCH3, BRANCH4, BRANCH5,
00098    MADDR1, MADDR2, MADDR3, MADDR4,
00099    RECEIVED1, RECEIVED2, RECEIVED3, RECEIVED4, RECEIVED5, RECEIVED6,
00100    RECEIVED7,
00101    RPORT1, RPORT2, RPORT3,
00102    ALIAS1, ALIAS2, ALIAS3, ALIAS4,
00103         /* fin states (227-...)*/
00104    FIN_HIDDEN = 230, FIN_TTL, FIN_BRANCH,
00105    FIN_MADDR, FIN_RECEIVED, FIN_RPORT, FIN_I, FIN_ALIAS
00106         /*GEN_PARAM,
00107           PARAM_ERROR*/ /* declared in msg_parser.h*/
00108 };
00109 
00110 
00111 /*! entry state must be F_PARAM, or saved_state=F_PARAM and
00112  * state=F_{LF,CR,CRLF}!
00113  * output state = L_PARAM or F_PARAM or END_OF_HEADER
00114  * (and saved_state= last state); everything else => error 
00115  * \warning param->start must be filled before, it's used in param->size computation.
00116  */
00117 static /*inline*/ char* parse_via_param(char* p, char* end,
00118                               unsigned char* pstate, 
00119                               unsigned char* psaved_state,
00120                               struct via_param* param)
00121 {
00122    char* tmp;
00123    register unsigned char state;
00124    unsigned char saved_state;
00125 
00126    state=*pstate;
00127 
00128    saved_state=*psaved_state;
00129    param->type=PARAM_ERROR;
00130 
00131    for (tmp=p;tmp<end;tmp++){
00132       switch(*tmp){
00133          case ' ':
00134          case '\t':
00135             switch(state){
00136                case FIN_HIDDEN:
00137                case FIN_ALIAS:
00138                   param->type=state;
00139                   param->name.len=tmp-param->name.s;
00140                   state=L_PARAM;
00141                   goto endofparam;
00142                case FIN_BRANCH:
00143                case FIN_TTL:
00144                case FIN_MADDR:
00145                case FIN_RECEIVED:
00146                case FIN_RPORT:
00147                case FIN_I:
00148                   param->type=state;
00149                   param->name.len=tmp-param->name.s;
00150                   state=L_VALUE;
00151                   goto find_value;
00152                case F_PARAM:
00153                   break;
00154                case F_LF:
00155                case F_CR:
00156                case F_CRLF:
00157                   state=saved_state;
00158                   break;
00159                case GEN_PARAM:
00160                default:
00161                   param->type=GEN_PARAM;
00162                   param->name.len=tmp-param->name.s;
00163                   state=L_VALUE;
00164                   goto find_value;
00165             }
00166             break;
00167          /* \n and \r*/
00168          case '\n':
00169             switch(state){
00170                case FIN_HIDDEN:
00171                case FIN_ALIAS:
00172                   param->type=state;
00173                   param->name.len=tmp-param->name.s;
00174                   param->size=tmp-param->start; 
00175                   saved_state=L_PARAM;
00176                   state=F_LF;
00177                   goto endofparam;
00178                case FIN_BRANCH:
00179                case FIN_TTL:
00180                case FIN_MADDR:
00181                case FIN_RECEIVED:
00182                case FIN_I:
00183                case FIN_RPORT:
00184                   param->type=state;
00185                   param->name.len=tmp-param->name.s;
00186                   param->size=tmp-param->start; 
00187                   saved_state=L_VALUE;
00188                   state=F_LF;
00189                   goto find_value;
00190                case F_PARAM:
00191                   saved_state=state;
00192                   state=F_LF;
00193                   break;
00194                case F_LF:
00195                case F_CRLF:
00196                   state=END_OF_HEADER;
00197                   goto end_via;
00198                case F_CR:
00199                   state=F_CRLF;
00200                   break;
00201                case GEN_PARAM:
00202                default:
00203                   param->type=GEN_PARAM;
00204                   saved_state=L_VALUE;
00205                   param->name.len=tmp-param->name.s;
00206                   param->size=tmp-param->start; 
00207                   state=F_LF;
00208                   goto find_value;
00209             }
00210             break;
00211          case '\r':
00212             switch(state){
00213                case FIN_HIDDEN:
00214                case FIN_ALIAS:
00215                   param->type=state;
00216                   param->name.len=tmp-param->name.s;
00217                   param->size=tmp-param->start; 
00218                   saved_state=L_PARAM;
00219                   state=F_CR;
00220                   goto endofparam;
00221                case FIN_BRANCH:
00222                case FIN_TTL:
00223                case FIN_MADDR:
00224                case FIN_RECEIVED:
00225                case FIN_I:
00226                case FIN_RPORT:
00227                   param->type=state;
00228                   param->name.len=tmp-param->name.s;
00229                   param->size=tmp-param->start; 
00230                   saved_state=L_VALUE;
00231                   state=F_CR;
00232                   goto find_value;
00233                case F_PARAM:
00234                   saved_state=state;
00235                   state=F_CR;
00236                   break;
00237                case F_CR:
00238                case F_CRLF:
00239                   state=END_OF_HEADER;
00240                   goto end_via;
00241                case GEN_PARAM:
00242                default:
00243                   param->type=GEN_PARAM;
00244                   param->name.len=tmp-param->name.s;
00245                   param->size=tmp-param->start; 
00246                   saved_state=L_VALUE;
00247                   state=F_CR;
00248                   goto find_value;
00249             }
00250             break;
00251 
00252          case '=':
00253             switch(state){
00254                case FIN_BRANCH:
00255                case FIN_TTL:
00256                case FIN_MADDR:
00257                case FIN_RECEIVED:
00258                case FIN_RPORT:
00259                case FIN_I:
00260                   param->type=state;
00261                   param->name.len=tmp-param->name.s;
00262                   state=F_VALUE;
00263                   goto find_value;
00264                case F_PARAM:
00265                case FIN_HIDDEN:
00266                case FIN_ALIAS:
00267                   LM_ERR("invalid char <%c> in state %d\n", *tmp, state);
00268                   goto error;
00269                case F_CR:
00270                case F_LF:
00271                case F_CRLF:
00272                   state=END_OF_HEADER;
00273                   goto end_via;
00274                case GEN_PARAM:
00275                default:
00276                   param->type=GEN_PARAM;
00277                   param->name.len=tmp-param->name.s;
00278                   state=F_VALUE;
00279                   goto find_value;
00280             }
00281             break;
00282          case ';':
00283             switch(state){
00284                case FIN_HIDDEN:
00285                case FIN_RPORT: /* rport can appear w/o a value */
00286                case FIN_ALIAS:
00287                   param->type=state;
00288                   param->name.len=tmp-param->name.s;
00289                   state=F_PARAM;
00290                   goto endofparam;
00291                case FIN_BRANCH:
00292                case FIN_MADDR:
00293                case FIN_TTL:
00294                case FIN_RECEIVED:
00295                case FIN_I:
00296                   LM_ERR("invalid char <%c> in state %d\n", *tmp, state);
00297                   goto error;
00298                case F_CR:
00299                case F_LF:
00300                case F_CRLF:
00301                   state=END_OF_HEADER;
00302                   goto end_via;
00303                case GEN_PARAM:
00304                default:
00305                   param->type=GEN_PARAM;
00306                   param->name.len=tmp-param->name.s;
00307                   state=F_PARAM;
00308                   goto endofparam;
00309             }
00310             break;
00311          case ',':
00312             switch(state){
00313                case FIN_HIDDEN:
00314                case FIN_RPORT:
00315                case FIN_ALIAS:
00316                   param->type=state;
00317                   param->name.len=tmp-param->name.s;
00318                   state=F_VIA;
00319                   goto endofvalue;
00320                case FIN_BRANCH:
00321                case FIN_MADDR:
00322                case FIN_TTL:
00323                case FIN_RECEIVED:
00324                case FIN_I:
00325                   LM_ERR("new via found (',') when '=' expected"
00326                         "(state %d=)\n", state);
00327                   goto error; /* or we could ignore this bad param*/
00328                case F_CR:
00329                case F_LF:
00330                case F_CRLF:
00331                   state=END_OF_HEADER;
00332                   goto end_via;
00333                case GEN_PARAM:
00334                default:
00335                   param->type=GEN_PARAM;
00336                   param->name.len=tmp-param->name.s;
00337                   state=F_VIA;
00338                   goto endofvalue;
00339             }
00340             break; 
00341 
00342             /* param names */
00343          case 'h':
00344          case 'H':
00345             switch(state){
00346                case F_PARAM:
00347                   state=HIDDEN1;
00348                   param->name.s=tmp;
00349                   break;
00350                case BRANCH5:
00351                   state=FIN_BRANCH;
00352                   break;
00353                case GEN_PARAM:
00354                   break;
00355                case F_CR:
00356                case F_LF:
00357                case F_CRLF:
00358                   state=END_OF_HEADER;
00359                   goto end_via;
00360                default:
00361                   state=GEN_PARAM;
00362             }
00363             break;
00364          case 'i':
00365          case 'I':
00366             switch(state){
00367                case F_PARAM:
00368                   state=FIN_I;
00369                   param->name.s=tmp;
00370                   break;
00371                case HIDDEN1:
00372                   state=HIDDEN2;
00373                   break;
00374                case RECEIVED4:
00375                   state=RECEIVED5;
00376                   break;
00377                case ALIAS2:
00378                   state=ALIAS3;
00379                   break;
00380                case GEN_PARAM:
00381                   break;
00382                case F_CR:
00383                case F_LF:
00384                case F_CRLF:
00385                   state=END_OF_HEADER;
00386                   goto end_via;
00387                default:
00388                   state=GEN_PARAM;
00389             }
00390             break;
00391          case 'd':
00392          case 'D':
00393             switch(state){
00394                case F_PARAM:
00395                   state=GEN_PARAM;
00396                   param->name.s=tmp;
00397                   break;
00398                case HIDDEN2:
00399                   state=HIDDEN3;
00400                   break;
00401                case HIDDEN3:
00402                   state=HIDDEN4;
00403                   break;
00404                case MADDR2:
00405                   state=MADDR3;
00406                   break;
00407                case MADDR3:
00408                   state=MADDR4;
00409                   break;
00410                case RECEIVED7:
00411                   state=FIN_RECEIVED;
00412                   break;
00413                case GEN_PARAM:
00414                   break;
00415                case F_CR:
00416                case F_LF:
00417                case F_CRLF:
00418                   state=END_OF_HEADER;
00419                   goto end_via;
00420                default:
00421                   state=GEN_PARAM;
00422             }
00423             break;
00424          case 'e':
00425          case 'E':
00426             switch(state){
00427                case F_PARAM:
00428                   state=GEN_PARAM;
00429                   param->name.s=tmp;
00430                   break;
00431                case HIDDEN4:
00432                   state=HIDDEN5;
00433                   break;
00434                case RECEIVED1:
00435                   state=RECEIVED2;
00436                   break;
00437                case RECEIVED3:
00438                   state=RECEIVED4;
00439                   break;
00440                case RECEIVED6:
00441                   state=RECEIVED7;
00442                   break;
00443                case GEN_PARAM:
00444                   break;
00445                case F_CR:
00446                case F_LF:
00447                case F_CRLF:
00448                   state=END_OF_HEADER;
00449                   goto end_via;
00450                default:
00451                   state=GEN_PARAM;
00452             }
00453             break;
00454          case 'n':
00455          case 'N':
00456             switch(state){
00457                case F_PARAM:
00458                   state=GEN_PARAM;
00459                   param->name.s=tmp;
00460                   break;
00461                case HIDDEN5:
00462                   state=FIN_HIDDEN;
00463                   break;
00464                case BRANCH3:
00465                   state=BRANCH4;
00466                   break;
00467                case GEN_PARAM:
00468                   break;
00469                case F_CR:
00470                case F_LF:
00471                case F_CRLF:
00472                   state=END_OF_HEADER;
00473                   goto end_via;
00474                default:
00475                   state=GEN_PARAM;
00476             }
00477             break;
00478          case 't':
00479          case 'T':
00480             switch(state){
00481                case F_PARAM:
00482                   state=TTL1;
00483                   param->name.s=tmp;
00484                   break;
00485                case TTL1:
00486                   state=TTL2;
00487                   break;
00488                case RPORT3:
00489                   state=FIN_RPORT;
00490                   break;
00491                case GEN_PARAM:
00492                   break;
00493                case F_CR:
00494                case F_LF:
00495                case F_CRLF:
00496                   state=END_OF_HEADER;
00497                   goto end_via;
00498                default:
00499                   state=GEN_PARAM;
00500             }
00501             break;
00502          case 'l':
00503          case 'L':
00504             switch(state){
00505                case F_PARAM:
00506                   state=GEN_PARAM;
00507                   param->name.s=tmp;
00508                   break;
00509                case TTL2:
00510                   state=FIN_TTL;
00511                   break;
00512                case ALIAS1:
00513                   state=ALIAS2;
00514                   break;
00515                case GEN_PARAM:
00516                   break;
00517                case F_CR:
00518                case F_LF:
00519                case F_CRLF:
00520                   state=END_OF_HEADER;
00521                   goto end_via;
00522                default:
00523                   state=GEN_PARAM;
00524             }
00525             break;
00526          case 'm':
00527          case 'M':
00528             switch(state){
00529                case F_PARAM:
00530                   state=MADDR1;
00531                   param->name.s=tmp;
00532                   break;
00533                case GEN_PARAM:
00534                   break;
00535                case F_CR:
00536                case F_LF:
00537                case F_CRLF:
00538                   state=END_OF_HEADER;
00539                   goto end_via;
00540                default:
00541                   state=GEN_PARAM;
00542             }
00543             break;
00544          case 'a':
00545          case 'A':
00546             switch(state){
00547                case F_PARAM:
00548                   state=ALIAS1;
00549                   param->name.s=tmp;
00550                   break;
00551                case MADDR1:
00552                   state=MADDR2;
00553                   break;
00554                case BRANCH2:
00555                   state=BRANCH3;
00556                   break;
00557                case ALIAS3:
00558                   state=ALIAS4;
00559                   break;
00560                case GEN_PARAM:
00561                   break;
00562                case F_CR:
00563                case F_LF:
00564                case F_CRLF:
00565                   state=END_OF_HEADER;
00566                   goto end_via;
00567                default:
00568                   state=GEN_PARAM;
00569             }
00570             break;
00571          case 'r':
00572          case 'R':
00573             switch(state){
00574                case MADDR4:
00575                   state=FIN_MADDR;
00576                   break;
00577                case F_PARAM:
00578                   state=RECEIVED1;
00579                   param->name.s=tmp;
00580                   break;
00581                case BRANCH1:
00582                   state=BRANCH2;
00583                   break;
00584                case RPORT2:
00585                   state=RPORT3;
00586                   break;
00587                case GEN_PARAM:
00588                   break;
00589                case F_CR:
00590                case F_LF:
00591                case F_CRLF:
00592                   state=END_OF_HEADER;
00593                   goto end_via;
00594                default:
00595                   state=GEN_PARAM;
00596             }
00597             break;
00598          case 'c':
00599          case 'C':
00600             switch(state){
00601                case F_PARAM:
00602                   state=GEN_PARAM;
00603                   param->name.s=tmp;
00604                   break;
00605                case RECEIVED2:
00606                   state=RECEIVED3;
00607                   break;
00608                case BRANCH4:
00609                   state=BRANCH5;
00610                   break;
00611                case GEN_PARAM:
00612                   break;
00613                case F_CR:
00614                case F_LF:
00615                case F_CRLF:
00616                   state=END_OF_HEADER;
00617                   goto end_via;
00618                default:
00619                   state=GEN_PARAM;
00620             }
00621             break;
00622          case 'v':
00623          case 'V':
00624             switch(state){
00625                case F_PARAM:
00626                   state=GEN_PARAM;
00627                   param->name.s=tmp;
00628                   break;
00629                case RECEIVED5:
00630                   state=RECEIVED6;
00631                   break;
00632                case GEN_PARAM:
00633                   break;
00634                case F_CR:
00635                case F_LF:
00636                case F_CRLF:
00637                   state=END_OF_HEADER;
00638                   goto end_via;
00639                default:
00640                   state=GEN_PARAM;
00641             }
00642             break;
00643          case 'b':
00644          case 'B':
00645             switch(state){
00646                case F_PARAM:
00647                   state=BRANCH1;
00648                   param->name.s=tmp;
00649                   break;
00650                case GEN_PARAM:
00651                   break;
00652                case F_CR:
00653                case F_LF:
00654                case F_CRLF:
00655                   state=END_OF_HEADER;
00656                   goto end_via;
00657                default:
00658                   state=GEN_PARAM;
00659             }
00660             break;
00661          case 'p':
00662          case 'P':
00663             switch(state){
00664                case F_PARAM:
00665                   state=GEN_PARAM;
00666                   param->name.s=tmp;
00667                   break;
00668                case RECEIVED1:
00669                   state=RPORT1;
00670                   break;
00671                case F_CR:
00672                case F_LF:
00673                case F_CRLF:
00674                   state=END_OF_HEADER;
00675                   goto end_via;
00676                default:
00677                   state=GEN_PARAM;
00678             }
00679             break;
00680          case 'o':
00681          case 'O':
00682             switch(state){
00683                case F_PARAM:
00684                   state=GEN_PARAM;
00685                   param->name.s=tmp;
00686                   break;
00687                case RPORT1:
00688                   state=RPORT2;
00689                   break;
00690                case F_CR:
00691                case F_LF:
00692                case F_CRLF:
00693                   state=END_OF_HEADER;
00694                   goto end_via;
00695                default:
00696                   state=GEN_PARAM;
00697             }
00698             break;
00699          case 's':
00700          case 'S':
00701             switch(state){
00702                case F_PARAM:
00703                   state=GEN_PARAM;
00704                   param->name.s=tmp;
00705                   break;
00706                case ALIAS4:
00707                   state=FIN_ALIAS;
00708                   break;
00709                case F_CR:
00710                case F_LF:
00711                case F_CRLF:
00712                   state=END_OF_HEADER;
00713                   goto end_via;
00714                default:
00715                   state=GEN_PARAM;
00716             }
00717             break;
00718          default:
00719             switch(state){
00720                case F_PARAM:
00721                   state=GEN_PARAM;
00722                   param->name.s=tmp;
00723                   break;
00724                case GEN_PARAM:
00725                   break;
00726                case F_CR:
00727                case F_LF:
00728                case F_CRLF:
00729                   state=END_OF_HEADER;
00730                   goto end_via;
00731                default:
00732                   state=GEN_PARAM;
00733             }
00734       }
00735    }/* for tmp*/
00736 
00737    /* end of packet? => error, no cr/lf,',' found!!!*/
00738    saved_state=state;
00739    state=END_OF_HEADER;
00740    goto error;
00741    
00742  find_value:
00743    tmp++;
00744    for(;*tmp;tmp++){
00745       switch(*tmp){
00746          case ' ':
00747          case '\t':
00748             switch(state){
00749                case L_VALUE:
00750                case F_VALUE: /*eat space*/
00751                   break; 
00752                case P_VALUE:
00753                   state=L_PARAM;
00754                   param->value.len=tmp-param->value.s;
00755                   goto endofvalue;
00756                case P_STRING:
00757                   break;
00758                case F_CR:
00759                case F_LF:
00760                case F_CRLF:
00761                   state=saved_state;
00762                   break;
00763                default:
00764                   LM_ERR("invalid char <%c> in state %d\n", *tmp, state);
00765                   goto error;
00766             }
00767             break;
00768          case '\n':
00769             switch(state){
00770                case L_VALUE:
00771                case F_VALUE: /*eat space*/
00772                case P_STRING:
00773                   saved_state=state;
00774                   param->size=tmp-param->start;
00775                   state=F_LF;
00776                   break;
00777                case P_VALUE:
00778                   saved_state=L_PARAM;
00779                   state=F_LF;
00780                   param->value.len=tmp-param->value.s;
00781                   goto endofvalue;
00782                case F_LF:
00783                case F_CRLF:
00784                   state=END_OF_HEADER;
00785                   goto end_via;
00786                case F_CR:
00787                   state=F_CRLF;
00788                   break;
00789                default:
00790                   LM_ERR("invalid char <%c> in state %d\n", *tmp, state);
00791                   goto error;
00792             }
00793             break;
00794          case '\r':
00795             switch(state){
00796                case L_VALUE:
00797                case F_VALUE: /*eat space*/
00798                case P_STRING:
00799                   saved_state=state;
00800                   param->size=tmp-param->start;
00801                   state=F_CR;
00802                   break;
00803                case P_VALUE:
00804                   param->value.len=tmp-param->value.s;
00805                   saved_state=L_PARAM;
00806                   state=F_CR;
00807                   goto endofvalue;
00808                case F_LF:
00809                case F_CR:
00810                case F_CRLF:
00811                   state=END_OF_HEADER;
00812                   goto end_via;
00813                default:
00814                   LM_ERR("invalid char <%c> in state %d\n", *tmp, state);
00815                   goto error;
00816             }
00817             break;
00818 
00819          case '=':
00820             switch(state){
00821                case L_VALUE:
00822                   state=F_VALUE;
00823                   break;
00824                case P_STRING:
00825                   break;
00826                case F_LF:
00827                case F_CR:
00828                case F_CRLF:
00829                   state=END_OF_HEADER;
00830                   goto end_via;
00831                default:
00832                   LM_ERR("invalid char <%c> in state %d\n", *tmp, state);
00833                   goto error;
00834             }
00835             break;
00836          case ';':
00837             switch(state){
00838                case P_VALUE:
00839                   param->value.len=tmp-param->value.s;
00840                   state=F_PARAM;
00841                   goto endofvalue;
00842                case F_VALUE:
00843                   param->value.len=0;
00844                   state=F_PARAM;
00845                   goto endofvalue;
00846                case P_STRING:
00847                   break; /* what to do? */
00848                case F_LF:
00849                case F_CR:
00850                case F_CRLF:
00851                   state=END_OF_HEADER;
00852                   goto end_via;
00853                case L_VALUE:
00854                   if (param->type==FIN_RPORT){
00855                      param->value.len=0;
00856                      param->value.s=0; /* null value */
00857                      state=F_PARAM;
00858                      goto endofvalue;
00859                   };
00860                   /* no break */
00861                default:
00862                   LM_ERR("invalid char <%c> in state %d\n", *tmp, state);
00863                   goto error;
00864             }
00865             break;
00866          case ',':
00867             switch(state){
00868                case P_VALUE:
00869                   param->value.len=tmp-param->value.s;
00870                   state=F_VIA;
00871                   goto endofvalue;
00872                case P_STRING:
00873                case F_LF:
00874                case F_CR:
00875                case F_CRLF:
00876                   state=END_OF_HEADER;
00877                   goto end_via;
00878                case L_VALUE:
00879                   if (param->type==FIN_RPORT){
00880                      param->value.len=0;
00881                      param->value.s=0; /* null value */
00882                      state=F_VIA;
00883                      goto endofvalue;
00884                   };
00885                   /* no break */
00886                default:
00887                   LM_ERR("invalid char <%c> in state %d\n", *tmp, state);
00888                   goto error;
00889             }
00890             break; /* what to do? */
00891          case '"':
00892             switch(state){
00893                case F_VALUE:
00894                   state=P_STRING;
00895                   param->value.s=tmp+1;
00896                   break;
00897                case P_STRING:
00898                   state=L_PARAM;
00899                   param->value.len=tmp-param->value.s;
00900                   goto endofvalue;
00901                case F_LF:
00902                case F_CR:
00903                case F_CRLF:
00904                   state=END_OF_HEADER;
00905                   goto end_via;
00906                default:
00907                   LM_ERR("invalid char <%c> in state %d\n", *tmp, state);
00908                   goto error;
00909             }
00910             break;
00911          default:
00912             switch(state){
00913                case F_VALUE:
00914                   state=P_VALUE;
00915                   param->value.s=tmp;
00916                   break;
00917                case P_VALUE:
00918                case P_STRING:
00919                   break;
00920                case F_LF:
00921                case F_CR:
00922                case F_CRLF:
00923                   state=END_OF_HEADER;
00924                   goto end_via;
00925                default:
00926                   LM_ERR("invalid char <%c> in state %d\n", *tmp, state);
00927                   goto error;
00928             }
00929       }
00930    } /* for2 tmp*/
00931 
00932    /* end of buff and no CR/LF =>error*/
00933    saved_state=state;
00934    state=END_OF_HEADER;
00935    goto error;
00936    
00937  endofparam:
00938  endofvalue:
00939    param->size=tmp-param->start;
00940 normal_exit:
00941    *pstate=state;
00942    *psaved_state=saved_state;
00943    LM_DBG("found param type %d, <%.*s> = <%.*s>; state=%d\n", param->type,
00944          param->name.len, ZSW(param->name.s), 
00945          (param->value.len?param->value.len:3),
00946          (param->value.len?param->value.s:"n/a"), state);
00947    return tmp;
00948    
00949  end_via:
00950         /* if we are here we found an "unexpected" end of via
00951          *  (cr/lf). This is valid only if the param type is GEN_PARAM or
00952         *  RPORT (the only ones which can miss the value; HIDDEN is a 
00953         *  special case )*/
00954    if ((param->type==GEN_PARAM)||(param->type==PARAM_RPORT)){
00955       saved_state=L_PARAM; /* change the saved_state, we have an unknown
00956                               param. w/o a value */
00957       /* param->size should be computed before */
00958       goto normal_exit;
00959    }
00960    *pstate=state;
00961    *psaved_state=saved_state;
00962    LM_DBG("error on  param type %d, <%.*s>, state=%d, saved_state=%d\n",
00963       param->type, param->name.len, ZSW(param->name.s), state, saved_state);
00964 
00965  error:
00966    LM_ERR("parse_via_param\n");
00967    param->type=PARAM_ERROR;
00968    *pstate=PARAM_ERROR;
00969    *psaved_state=state;
00970    return tmp;
00971 }
00972 
00973 
00974 
00975 /*!
00976  * call it with a vb initialized to 0
00977  * \return pointer after the parsed parts and sets vb->error
00978  * \warning don't forget to cleanup on error with free_via_list(vb)!
00979  */
00980 char* parse_via(char* buffer, char* end, struct via_body *vbody)
00981 {
00982    char* tmp;
00983    char* param_start;
00984    unsigned char state;
00985    unsigned char saved_state;
00986    int c_nest;
00987    int err;
00988    struct via_body* vb;
00989    struct via_param* param;
00990 
00991    vb=vbody; /* keep orignal vbody value, needed to set the error member
00992              in case of multiple via bodies in the same header */
00993 parse_again:
00994    vb->error=PARSE_ERROR;
00995    /* parse start of via ( SIP/2.0/UDP    )*/
00996    state=F_SIP;
00997    saved_state=0; /*it should generate error if it's used without set*/
00998    param_start=0;
00999    for(tmp=buffer;tmp<end;tmp++){
01000       switch(*tmp){
01001          case ' ':
01002          case'\t':
01003             switch(state){
01004                case L_VER: /* eat space */
01005                case L_PROTO:
01006                case F_SIP:
01007                case F_VER:
01008                case F_PROTO:
01009                   break;
01010                case FIN_UDP:
01011                   vb->transport.len=tmp-vb->transport.s;
01012                   vb->proto=PROTO_UDP;
01013                   state=F_HOST; /* start looking for host*/
01014                   goto main_via;
01015                case FIN_TCP:
01016                   /* finished proto parsing */
01017                   vb->transport.len=tmp-vb->transport.s;
01018                   vb->proto=PROTO_TCP;
01019                   state=F_HOST; /* start looking for host*/
01020                   goto main_via;
01021                case FIN_TLS:
01022                   /* finished proto parsing */
01023                   vb->transport.len=tmp-vb->transport.s;
01024                   vb->proto=PROTO_TLS;
01025                   state=F_HOST; /* start looking for host*/
01026                   goto main_via;
01027                case FIN_SCTP:
01028                   /* finished proto parsing */
01029                   vb->transport.len=tmp-vb->transport.s;
01030                   vb->proto=PROTO_SCTP;
01031                   state=F_HOST; /* start looking for host*/
01032                   goto main_via;
01033                case FIN_SIP:
01034                   vb->name.len=tmp-vb->name.s;
01035                   state=L_VER;
01036                   break;
01037                case FIN_VER:
01038                   vb->version.len=tmp-vb->version.s;
01039                   state=L_PROTO;
01040                   break;
01041                case F_LF:
01042                case F_CRLF:
01043                case F_CR: /* header continues on this line */
01044                   state=saved_state;
01045                   break;
01046                default:
01047                   LM_ERR("bad char <%c> on state %d\n", *tmp, state);
01048                   goto error;
01049             }
01050             break;
01051          case '\n':
01052             switch(state){
01053                case L_VER:
01054                case F_SIP:
01055                case F_VER:
01056                case F_PROTO:
01057                case L_PROTO:
01058                   saved_state=state;
01059                   state=F_LF;
01060                   break;
01061                case FIN_UDP:
01062                   vb->transport.len=tmp-vb->transport.s;
01063                   vb->proto=PROTO_UDP;
01064                   state=F_LF;
01065                   saved_state=F_HOST; /* start looking for host*/
01066                   goto main_via;
01067                case FIN_TCP:
01068                   vb->transport.len=tmp-vb->transport.s;
01069                   vb->proto=PROTO_TCP;
01070                   state=F_LF;
01071                   saved_state=F_HOST; /* start looking for host*/
01072                   goto main_via;
01073                case FIN_TLS:
01074                   vb->transport.len=tmp-vb->transport.s;
01075                   vb->proto=PROTO_TLS;
01076                   state=F_LF;
01077                   saved_state=F_HOST; /* start looking for host*/
01078                   goto main_via;
01079                case FIN_SIP:
01080                   vb->name.len=tmp-vb->name.s;
01081                   state=F_LF;
01082                   saved_state=L_VER;
01083                   break;
01084                case FIN_VER:
01085                   vb->version.len=tmp-vb->version.s;
01086                   state=F_LF;
01087                   saved_state=L_PROTO;
01088                   break;
01089                case F_CR:
01090                   state=F_CRLF;
01091                   break;
01092                case F_LF:
01093                case F_CRLF:
01094                   state=saved_state;
01095                   goto endofheader;
01096                default:
01097                   LM_ERR("bad char <%c> on state %d\n", *tmp, state);
01098                   goto error;
01099             }
01100             break;
01101          case '\r':
01102             switch(state){
01103                case L_VER:
01104                case F_SIP:
01105                case F_VER:
01106                case F_PROTO:
01107                case L_PROTO:
01108                   saved_state=state;
01109                   state=F_CR;
01110                   break;
01111                case FIN_UDP:
01112                   vb->transport.len=tmp-vb->transport.s;
01113                   vb->proto=PROTO_UDP;
01114                   state=F_CR;
01115                   saved_state=F_HOST;
01116                   goto main_via;
01117                case FIN_TCP:
01118                   vb->transport.len=tmp-vb->transport.s;
01119                   vb->proto=PROTO_TCP;
01120                   state=F_CR;
01121                   saved_state=F_HOST;
01122                   goto main_via;
01123                case FIN_TLS:
01124                   vb->transport.len=tmp-vb->transport.s;
01125                   vb->proto=PROTO_TLS;
01126                   state=F_CR;
01127                   saved_state=F_HOST;
01128                   goto main_via;
01129                case FIN_SIP:
01130                   vb->name.len=tmp-vb->name.s;
01131                   state=F_CR;
01132                   saved_state=L_VER;
01133                   break;
01134                case FIN_VER:
01135                   vb->version.len=tmp-vb->version.s;
01136                   state=F_CR;
01137                   saved_state=L_PROTO;
01138                   break;
01139                case F_LF: /*end of line ?next header?*/
01140                case F_CR:
01141                case F_CRLF:
01142                   state=saved_state;
01143                   goto endofheader;
01144                default:
01145                   LM_ERR("bad char <%c> on state %d\n", *tmp, state);
01146                   goto error;
01147             }
01148             break;
01149          
01150          case '/':
01151             switch(state){
01152                case FIN_SIP:
01153                   vb->name.len=tmp-vb->name.s;
01154                   state=F_VER;
01155                   break;
01156                case FIN_VER:
01157                   vb->version.len=tmp-vb->version.s;
01158                   state=F_PROTO;
01159                   break;
01160                case L_VER:
01161                   state=F_VER;
01162                   break;
01163                case L_PROTO:
01164                   state=F_PROTO;
01165                   break;
01166                default:
01167                   LM_ERR("bad char <%c> on state %d\n", *tmp, state);
01168                   goto error;
01169             }
01170             break;
01171             /* match SIP*/
01172          case 'S':
01173          case 's':
01174             switch(state){
01175                case F_SIP:
01176                   state=SIP1;
01177                   vb->name.s=tmp;
01178                   break;
01179                case TLS2:
01180                   state=FIN_TLS;
01181                   break;
01182                case F_PROTO:
01183                   state=SCTP1;
01184                   vb->transport.s=tmp;
01185                   break;
01186                default:
01187                   LM_ERR("bad char <%c> on state %d\n", *tmp, state);
01188                   goto error;
01189             }
01190             break;
01191          case 'I':
01192          case 'i':
01193             switch(state){
01194                case SIP1:
01195                   state=SIP2;
01196                   break;
01197                default:
01198                   LM_ERR("bad char <%c> on state %d\n", *tmp, state);
01199                   goto error;
01200             }
01201             break;
01202          case 'p':
01203          case 'P':
01204             switch(state){
01205                case SIP2:
01206                   state=FIN_SIP;
01207                   break;
01208                /* allow p in PROTO */
01209                case UDP2:
01210                   state=FIN_UDP;
01211                   break;
01212                case TCP2:
01213                   state=FIN_TCP;
01214                   break;
01215                case SCTP3:
01216                   state=FIN_SCTP;
01217                   break;
01218                default:
01219                   LM_ERR("bad char <%c> on state %d\n", *tmp, state);
01220                   goto error;
01221             }
01222             break;
01223          case 'U':
01224          case 'u':
01225             switch(state){
01226                case F_PROTO:
01227                   state=UDP1;
01228                   vb->transport.s=tmp;
01229                   break;
01230                default:
01231                   LM_ERR("bad char <%c> on state %d\n", *tmp, state);
01232                   goto error;
01233             }
01234             break;
01235          case 'D':
01236          case 'd':
01237             switch(state){
01238                case UDP1:
01239                   state=UDP2;
01240                   break;
01241                default:
01242                   LM_ERR("bad char <%c> on state %d\n", *tmp, state);
01243                   goto error;
01244             }
01245             break;
01246          case 'T':
01247          case 't':
01248             switch(state){
01249                case F_PROTO:
01250                   state=TCP_TLS1;
01251                   vb->transport.s=tmp;
01252                   break;
01253                case SCTP2:
01254                   state=SCTP3;
01255                   break;
01256                default:
01257                   LM_ERR("bad char <%c> on state %d\n", *tmp, state);
01258                   goto error;
01259             }
01260             break;
01261          case 'C':
01262          case 'c':
01263             switch(state){
01264                case TCP_TLS1:
01265                   state=TCP2;
01266                   break;
01267                case SCTP1:
01268                   state=SCTP2;
01269                   break;
01270                default:
01271                   LM_ERR("bad char <%c> on state %d\n", *tmp, state);
01272                   goto error;
01273             }
01274             break;
01275          case 'L':
01276          case 'l':
01277             switch(state){
01278                case TCP_TLS1:
01279                   state=TLS2;
01280                   break;
01281                default:
01282                   LM_ERR("bad char <%c> on state %d\n", *tmp, state);
01283                   goto error;
01284             }
01285             break;
01286          /*match 2.0*/
01287          case '2':
01288             switch(state){
01289                case F_VER:
01290                   state=VER1;
01291                   vb->version.s=tmp;
01292                   break;
01293                default:
01294                   LM_ERR("bad char <%c> on state %d\n", *tmp, state);
01295                   goto error;
01296             }
01297             break;
01298          case '.':
01299             switch(state){
01300                case VER1:
01301                   state=VER2;
01302                   break;
01303                default:
01304                   LM_ERR("bad char <%c> on state %d\n", *tmp, state);
01305                   goto error;
01306             }
01307              break;
01308          case '0':
01309             switch(state){
01310                case VER2:
01311                   state=FIN_VER;
01312                   break;
01313                default:
01314                   LM_ERR("bad char <%c> on state %d\n", *tmp, state);
01315                   goto error;
01316             }
01317             break;
01318          
01319          default:
01320                   LM_ERR("bad char <%c> on state %d\n", *tmp, state);
01321                   goto error;
01322             break;
01323       }
01324    } /* for tmp*/
01325 
01326    /* we should not be here! if everything is ok > main_via*/
01327    LM_ERR("bad via: end of packet on state=%d\n", state);
01328    goto error;
01329 
01330  main_via:
01331    /* inc tmp to point to the next char*/
01332    tmp++;
01333    c_nest=0;
01334    /*state should always be F_HOST here*/;
01335    for(;*tmp;tmp++){
01336       switch(*tmp){
01337       case ' ':
01338       case '\t':
01339          switch(state){
01340                case F_HOST:/*eat the spaces*/
01341                   break;
01342                case P_HOST:
01343                    /*mark end of host*/
01344                    vb->host.len=tmp-vb->host.s;
01345                    state=L_PORT;
01346                    break;
01347                case L_PORT: /*eat the spaces*/
01348                case F_PORT:
01349                   break;
01350                case P_PORT:
01351                   /*end of port */
01352                   vb->port_str.len=tmp-vb->port_str.s;
01353                   state=L_PARAM;
01354                   break;
01355                case L_PARAM: /* eat the space */
01356                case F_PARAM:
01357                   break;
01358                case P_PARAM:
01359                /* *tmp=0;*/ /*!?end of param*/
01360                   state=L_PARAM;
01361                   break;
01362                case L_VIA:
01363                case F_VIA: /* eat the space */
01364                   break;
01365                case F_COMMENT:
01366                case P_COMMENT:
01367                   break;
01368                case F_IP6HOST: /*no spaces allowed*/
01369                case P_IP6HOST:
01370                   LM_ERR("bad ipv6 reference\n");
01371                   goto error;
01372                case F_CRLF:
01373                case F_LF:
01374                case F_CR:
01375                   /*previous=crlf and now =' '*/
01376                   state=saved_state;
01377                   break;
01378                default:
01379                   LM_CRIT("on <%c>, state=%d\n",*tmp, state);
01380                   goto  error;
01381             }
01382          break;
01383          case '\n':
01384             switch(state){
01385                case F_HOST:/*eat the spaces*/
01386                case L_PORT: /*eat the spaces*/
01387                case F_PORT:
01388                case L_PARAM: /* eat the space */
01389                case F_PARAM:
01390                case F_VIA: /* eat the space */
01391                case L_VIA:
01392                case F_COMMENT:
01393                case P_COMMENT:
01394                case F_IP6HOST:
01395                case P_IP6HOST:
01396                   saved_state=state;
01397                   state=F_LF;
01398                   break;
01399                case P_HOST:
01400                    /*mark end of host*/
01401                    vb->host.len=tmp-vb->host.s;
01402                    saved_state=L_PORT;
01403                    state=F_LF;
01404                    break;
01405                case P_PORT:
01406                   /*end of port */
01407                   vb->port_str.len=tmp-vb->port_str.s;
01408                   saved_state=L_PARAM;
01409                   state=F_LF;
01410                   break;
01411                case P_PARAM:
01412                /* *tmp=0;*/ /*!?end of param*/
01413                   saved_state=L_PARAM;
01414                   state=F_LF;
01415                   break;
01416                case F_CR:
01417                   state=F_CRLF;
01418                   break;
01419                case F_CRLF:
01420                case F_LF:
01421                   state=saved_state;
01422                   goto endofheader;
01423                default:
01424                   LM_CRIT("BUG on <%c>\n",*tmp);
01425                   goto  error;
01426             }
01427          break;
01428       case '\r':
01429             switch(state){
01430                case F_HOST:/*eat the spaces*/
01431                case L_PORT: /*eat the spaces*/
01432                case F_PORT:
01433                case L_PARAM: /* eat the space */
01434                case F_PARAM:
01435                case F_VIA: /* eat the space */
01436                case L_VIA:
01437                case F_COMMENT:
01438                case P_COMMENT:
01439                case F_IP6HOST:
01440                case P_IP6HOST:
01441                   saved_state=state;
01442                   state=F_CR;
01443                   break;
01444                case P_HOST:
01445                    /*mark end of host*/
01446                    vb->host.len=tmp-vb->host.s;
01447                    saved_state=L_PORT;
01448                    state=F_CR;
01449                    break;
01450                case P_PORT:
01451                   /*end of port */
01452                   vb->port_str.len=tmp-vb->port_str.s;
01453                   saved_state=L_PARAM;
01454                   state=F_CR;
01455                   break;
01456                case P_PARAM:
01457                /* *tmp=0;*/ /*!?end of param*/
01458                   saved_state=L_PARAM;
01459                   state=F_CR;
01460                   break;
01461                case F_CRLF:
01462                case F_CR:
01463                case F_LF:
01464                   state=saved_state;
01465                   goto endofheader;
01466                default:
01467                   LM_CRIT("on <%c>\n",*tmp);
01468                   goto  error;
01469             }
01470          break;
01471          
01472          case ':':
01473             switch(state){
01474                case F_HOST:
01475                case F_IP6HOST:
01476                   state=P_IP6HOST;
01477                   break;
01478                case P_IP6HOST:
01479                   break;
01480                case P_HOST:
01481                   /*mark  end of host*/
01482                   vb->host.len=tmp-vb->host.s;
01483                   state=F_PORT;
01484                   break;
01485                case L_PORT:
01486                   state=F_PORT;
01487                   break;
01488                case P_PORT:
01489                   LM_ERR("bad port\n");
01490                   goto error;
01491                case L_PARAM:
01492                case F_PARAM:
01493                case P_PARAM:
01494                   LM_ERR("bad char <%c> in state %d\n",
01495                      *tmp,state);
01496                   goto error;
01497                case L_VIA:
01498                case F_VIA:
01499                   LM_ERR("bad char in compact via\n");
01500                   goto error;
01501                case F_CRLF:
01502                case F_LF:
01503                case F_CR:
01504                   /*previous=crlf and now !=' '*/
01505                   goto endofheader;
01506                case F_COMMENT:/*everything is allowed in a comment*/
01507                   vb->comment.s=tmp;
01508                   state=P_COMMENT;
01509                   break;
01510                case P_COMMENT: /*everything is allowed in a comment*/
01511                   break;
01512                default:
01513                   LM_CRIT("on <%c> state %d\n", *tmp, state);
01514                   goto error;
01515             }
01516             break;
01517          case ';':
01518             switch(state){
01519                case F_HOST:
01520                case F_IP6HOST:
01521                   LM_ERR(" no host found\n");
01522                   goto error;
01523                case P_IP6HOST:
01524                   LM_ERR(" bad ipv6 reference\n");
01525                   goto error;
01526                case P_HOST:
01527                   vb->host.len=tmp-vb->host.s;
01528                   state=F_PARAM;
01529                   param_start=tmp+1;
01530                   break;
01531                case P_PORT:
01532                   /*mark the end*/
01533                   vb->port_str.len=tmp-vb->port_str.s;
01534                case L_PORT:
01535                case L_PARAM:
01536                   state=F_PARAM;
01537                   param_start=tmp+1;
01538                   break;
01539                case F_PORT:
01540                   LM_ERR(" bad char <%c> in state %d\n",
01541                      *tmp,state);
01542                   goto error;
01543                case F_PARAM:
01544                   LM_ERR("null param?\n");
01545                   goto error;
01546                case P_PARAM:
01547                   /*hmm next, param?*/
01548                   state=F_PARAM;
01549                   param_start=tmp+1;
01550                   break;
01551                case L_VIA:
01552                case F_VIA:
01553                   LM_ERR("bad char <%c> in next via\n", *tmp);
01554                   goto error;
01555                case F_CRLF:
01556                case F_LF:
01557                case F_CR:
01558                   /*previous=crlf and now !=' '*/
01559                   goto endofheader;
01560                case F_COMMENT:/*everything is allowed in a comment*/
01561                   vb->comment.s=tmp;
01562                   state=P_COMMENT;
01563                   break;
01564                case P_COMMENT: /*everything is allowed in a comment*/
01565                   break;
01566                
01567                default:
01568                   LM_CRIT("on <%c> state %d\n", *tmp, state);
01569                   goto  error;
01570             }
01571          break;
01572          case ',':
01573             switch(state){
01574                case F_HOST:
01575                case F_IP6HOST:
01576                   LM_ERR("no host found\n");
01577                   goto error;
01578                case P_IP6HOST:
01579                   LM_ERR(" bad ipv6 reference\n");
01580                   goto error;
01581                case P_HOST:
01582                   /*mark the end*/
01583                   vb->host.len=tmp-vb->host.s;
01584                   state=F_VIA;
01585                   break;
01586                case P_PORT:
01587                   /*mark the end*/
01588                   vb->port_str.len=tmp-vb->port_str.s;
01589                   state=F_VIA;
01590                   break;
01591                case L_PORT:
01592                case L_PARAM:
01593                case P_PARAM:
01594                case L_VIA:
01595                   state=F_VIA;
01596                   break;
01597                case F_PORT:
01598                case F_PARAM:
01599                   LM_ERR("invalid char <%c> in state %d\n", *tmp,state);
01600                   goto error;
01601                case F_VIA:
01602                   /* do  nothing,  eat ","*/
01603                   break;   
01604                case F_CRLF:
01605                case F_LF:
01606                case F_CR:
01607                   /*previous=crlf and now !=' '*/
01608                   goto endofheader;
01609                case F_COMMENT:/*everything is allowed in a comment*/
01610                   vb->comment.s=tmp;
01611                   state=P_COMMENT;
01612                   break;
01613                case P_COMMENT: /*everything is allowed in a comment*/
01614                   break;
01615                default:
01616                   LM_CRIT("on <%c> state %d\n",*tmp, state);
01617                   goto  error;
01618             }
01619          break;
01620          case '(':
01621             switch(state){
01622                case F_HOST:
01623                case F_PORT:
01624                case F_PARAM:
01625                case F_VIA:
01626                case F_IP6HOST:
01627                case P_IP6HOST: /*must be terminated in ']'*/
01628                   LM_ERR(" on <%c> state %d\n", *tmp, state);
01629                   goto  error;
01630                case P_HOST:
01631                   /*mark the end*/
01632                   vb->host.len=tmp-vb->host.s;
01633                   state=F_COMMENT;
01634                   c_nest++;
01635                   break;
01636                case P_PORT:
01637                   /*mark the end*/
01638                   vb->port_str.len=tmp-vb->port_str.s;
01639                   state=F_COMMENT;
01640                   c_nest++;
01641                   break;
01642                case P_PARAM:
01643                   /*mark the end*/
01644                   vb->params.len=tmp-vb->params.s;
01645                   state=F_COMMENT;
01646                   c_nest++;
01647                   break;
01648                case L_PORT:
01649                case L_PARAM:
01650                case L_VIA:
01651                   state=F_COMMENT;
01652                   vb->params.len=tmp-vb->params.s;
01653                   c_nest++;
01654                   break;
01655                case P_COMMENT:
01656                case F_COMMENT:
01657                   c_nest++;
01658                   break;
01659                case F_CRLF:
01660                case F_LF:
01661                case F_CR:
01662                   /*previous=crlf and now !=' '*/
01663                   goto endofheader;
01664                default:
01665                   LM_CRIT("on <%c> state %d\n", *tmp, state);
01666                   goto  error;
01667             }
01668          break;
01669          case ')':
01670             switch(state){
01671                case F_COMMENT:
01672                case P_COMMENT:
01673                   if (c_nest){
01674                      c_nest--;
01675                      if(c_nest==0){
01676                         state=L_VIA;
01677                         vb->comment.len=tmp-vb->comment.s;
01678                         break;
01679                      }
01680                   }else{
01681                      LM_ERR(" missing '(' - nesting= %d\n", c_nest);
01682                       goto error;
01683                   }
01684                   break;
01685                case F_HOST:
01686                case F_PORT:
01687                case F_PARAM:
01688                case F_VIA:
01689                case P_HOST:
01690                case P_PORT:
01691                case P_PARAM:
01692                case L_PORT:
01693                case L_PARAM:
01694                case L_VIA:
01695                case F_IP6HOST:
01696                case P_IP6HOST:
01697                   LM_ERR(" on <%c> state %d\n",*tmp, state);
01698                   goto  error;
01699                case F_CRLF:
01700                case F_LF:
01701                case F_CR:
01702                   /*previous=crlf and now !=' '*/
01703                   goto endofheader;
01704                default:
01705                   LM_CRIT("on <%c> state %d\n", *tmp, state);
01706                   goto  error;
01707             }
01708             break;
01709          case '[':
01710             switch(state){
01711                case F_HOST:
01712                   vb->host.s=tmp; /* mark start here (include [])*/
01713                   state=F_IP6HOST;
01714                   break;
01715                case F_COMMENT:/*everything is allowed in a comment*/
01716                   vb->comment.s=tmp;
01717                   state=P_COMMENT;
01718                   break;
01719                case P_COMMENT:
01720                   break;
01721                case F_CRLF:
01722                case F_LF:
01723                case F_CR:
01724                   /*previous=crlf and now !=' '*/
01725                   goto endofheader;
01726                default:
01727                   LM_ERR("on <%c> state %d\n",*tmp, state);
01728                   goto  error;
01729             }
01730             break;
01731          case ']':
01732             switch(state){
01733                case P_IP6HOST:
01734                   /*mark the end*/
01735                   vb->host.len=(tmp-vb->host.s)+1; /* include "]" */
01736                   state=L_PORT;
01737                   break;
01738                case F_CRLF:
01739                case F_LF:
01740                case F_CR:
01741                   /*previous=crlf and now !=' '*/
01742                   goto endofheader;
01743                case F_COMMENT:/*everything is allowed in a comment*/
01744                   vb->comment.s=tmp;
01745                   state=P_COMMENT;
01746                   break;
01747                case P_COMMENT:
01748                   break;
01749                default:
01750                   LM_ERR("on <%c> state %d\n",*tmp, state);
01751                   goto  error;
01752             }
01753             break;
01754                   
01755          default:
01756             switch(state){
01757                case F_HOST:
01758                   state=P_HOST;
01759                   vb->host.s=tmp;
01760                   break;
01761                case P_HOST:
01762                   break;
01763                case F_PORT:
01764                   state=P_PORT;
01765                   vb->port_str.s=tmp;
01766                   break;
01767                case P_PORT:
01768                   /*check if number?*/
01769                   break;
01770                case F_PARAM:
01771                   /*state=P_PARAM*/;
01772                   if(vb->params.s==0) vb->params.s=param_start;
01773                   param=pkg_malloc(sizeof(struct via_param));
01774                   if (param==0){
01775                      LM_ERR("no pkg memory left\n");
01776                      goto error;
01777                   }
01778                   memset(param,0, sizeof(struct via_param));
01779                   param->start=param_start;
01780                   tmp=parse_via_param(tmp, end, &state, &saved_state,
01781                                  param);
01782 
01783                   switch(state){
01784                      case F_PARAM:
01785                         param_start=tmp+1;
01786                      case L_PARAM:
01787                      case F_LF:
01788                      case F_CR:
01789                         break;
01790                      case F_VIA:
01791                         vb->params.len=param->start+param->size
01792                                     -vb->params.s;
01793                         break;
01794                      case END_OF_HEADER:
01795                         vb->params.len=param->start+param->size
01796                                     -vb->params.s;
01797                         break;
01798                      case PARAM_ERROR:
01799                         pkg_free(param);
01800                         goto error;
01801                      default:
01802                         pkg_free(param);
01803                         LM_ERR(" after parse_via_param: invalid"
01804                               " char <%c> on state %d\n",*tmp, state);
01805                         goto error;
01806                   }
01807                   /*add param to the list*/
01808                   if (vb->last_param)  vb->last_param->next=param;
01809                   else           vb->param_lst=param;
01810                   vb->last_param=param;
01811                   /* update param. shortcuts */
01812                   switch(param->type){
01813                      case PARAM_BRANCH:
01814                         vb->branch=param;
01815                         break;
01816                      case PARAM_RECEIVED:
01817                         vb->received=param;
01818                         break;
01819                      case PARAM_RPORT:
01820                         vb->rport=param;
01821                         break;
01822                      case PARAM_I:
01823                         vb->i=param;
01824                         break;
01825                      case PARAM_ALIAS:
01826                         vb->alias=param;
01827                         break;
01828                      case PARAM_MADDR:
01829                         vb->maddr=param;
01830                         break;
01831                   }
01832                   
01833                   if (state==END_OF_HEADER){
01834                      state=saved_state;
01835                      goto endofheader;
01836                   }
01837                   break;
01838                case P_PARAM:
01839                   break;
01840                case F_VIA:
01841                   /*vb->next=tmp;*/ /*???*/
01842                   goto nextvia;
01843                case L_PORT:
01844                case L_PARAM:
01845                case L_VIA:
01846                   LM_ERR("on <%c> state %d (default)\n",*tmp, state);
01847                   goto  error;
01848                case F_COMMENT:
01849                   state=P_COMMENT;
01850                   vb->comment.s=tmp;
01851                   break;
01852                case P_COMMENT:
01853                   break;
01854                case F_IP6HOST:
01855                   state=P_IP6HOST;
01856                   break;
01857                case P_IP6HOST:
01858                   break;
01859                case F_CRLF:
01860                case F_LF:
01861                case F_CR:
01862                   /*previous=crlf and now !=' '*/
01863                   goto endofheader;
01864                default:
01865                   LM_CRIT("invalid char <%c> in state %d\n",*tmp, state);
01866                   goto error;
01867             }
01868 
01869 
01870       }
01871    }
01872 
01873    LM_DBG("end of packet reached, state=%d\n", state);
01874    goto endofpacket; /*end of packet, probably should be goto error*/
01875    
01876 endofheader:
01877    state=saved_state;
01878    LM_DBG("end of header reached, state=%d\n", state);
01879 endofpacket:
01880    /* check if error*/
01881    switch(state){
01882       case P_HOST:
01883       case L_PORT:
01884       case P_PORT:
01885       case L_PARAM:
01886       case P_PARAM:
01887       case P_VALUE:
01888       case GEN_PARAM:
01889       case FIN_HIDDEN:
01890       case L_VIA:
01891          break;
01892       default:
01893          LM_ERR(" invalid via - end of header in state %d\n", state);
01894          goto error;
01895    }
01896 
01897 
01898    /*
01899    if (proto) printf("<SIP/2.0/%s>\n", proto);
01900    if (host) printf("host= <%s>\n", host);
01901    if (port_str) printf("port= <%s>\n", port_str);
01902    if (param) printf("params= <%s>\n", param);
01903    if (comment) printf("comment= <%s>\n", comment);
01904    if(next_via) printf("next_via= <%s>\n", next_via);
01905    */
01906    /*LM_DBG("rest=<%s>\n", tmp);*/
01907 
01908    vb->error=PARSE_OK;
01909    vb->bsize=tmp-buffer;
01910    if (vb->port_str.s){
01911       vb->port=str2s(vb->port_str.s, vb->port_str.len, &err);
01912       if (err){
01913                LM_ERR(" invalid port number <%.*s>\n",
01914                   vb->port_str.len, ZSW(vb->port_str.s));
01915                goto error;
01916       }
01917    }
01918    return tmp;
01919 nextvia:
01920    LM_DBG("next_via\n");
01921    vb->error=PARSE_OK;
01922    vb->bsize=tmp-buffer;
01923    if (vb->port_str.s){
01924       vb->port=str2s(vb->port_str.s, vb->port_str.len, &err);
01925       if (err){
01926                LM_ERR(" invalid port number <%.*s>\n",
01927                   vb->port_str.len, ZSW(vb->port_str.s));
01928                goto error;
01929       }
01930    }
01931    vb->next=pkg_malloc(sizeof(struct via_body));
01932    if (vb->next==0){
01933       LM_ERR(" out of pkg memory\n");
01934       goto error;
01935    }
01936    vb=vb->next;
01937    memset(vb, 0, sizeof(struct via_body));
01938    buffer=tmp;
01939    goto parse_again;
01940 
01941 error:
01942    if (end>buffer){
01943       LM_ERR(" <%.*s>\n", (int)(end-buffer), ZSW(buffer));
01944    }
01945    if ((tmp>buffer)&&(tmp<end)){
01946       LM_ERR("parsed so far:<%.*s>\n",
01947             (int)(tmp-buffer), ZSW(buffer) );
01948    }else{
01949       LM_ERR("via parse failed\n");
01950    }
01951    vb->error=PARSE_ERROR;
01952    vbody->error=PARSE_ERROR; /* make sure the first via body is marked
01953                          as bad also */
01954    return tmp;
01955 }
01956 
01957 
01958 static inline void free_via_param_list(struct via_param* vp)
01959 {
01960    struct via_param* foo;
01961    while(vp){
01962       foo=vp;
01963       vp=vp->next;
01964       pkg_free(foo);
01965    }
01966 }
01967 
01968 
01969 void free_via_list(struct via_body* vb)
01970 {
01971    struct via_body* foo;
01972    while(vb){
01973       foo=vb;
01974       vb=vb->next;
01975       if (foo->param_lst) free_via_param_list(foo->param_lst);
01976       pkg_free(foo);
01977    }
01978 }

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