parse_via.c

Go to the documentation of this file.
00001 /*
00002  * $Id$ 
00003  *
00004  * via parsing automaton
00005  * 
00006  *
00007  * Copyright (C) 2001-2003 FhG Fokus
00008  *
00009  * This file is part of ser, a free SIP server.
00010  *
00011  * ser is free software; you can redistribute it and/or modify
00012  * it under the terms of the GNU General Public License as published by
00013  * the Free Software Foundation; either version 2 of the License, or
00014  * (at your option) any later version
00015  *
00016  * For a license to use the ser software under conditions
00017  * other than those described here, or to purchase support for this
00018  * software, please contact iptel.org by e-mail at the following addresses:
00019  *    info@iptel.org
00020  *
00021  * ser is distributed in the hope that it will be useful,
00022  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00023  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00024  * GNU General Public License for more details.
00025  *
00026  * You should have received a copy of the GNU General Public License 
00027  * along with this program; if not, write to the Free Software 
00028  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00029  */
00030 
00037 /* 
00038  *  2003-01-21  added rport parsing code, contributed by
00039  *               Maxim Sobolev  <sobomax@FreeBSD.org>
00040  *  2003-01-23  added extra via param parsing code (i=...), used
00041  *               by tcp to identify the sending socket, by andrei
00042  *  2003-01-23  fixed rport parsing code to accept rport w/o any value,
00043  *               by andrei
00044  *  2003-01-27  modified parse_via to set new via_param->start member and
00045  *               via->params.s (andrei)
00046  *  2003-01-28  zero-terminations replaced with VIA_ZT (jiri)
00047  *  2003-02-28  scratchpad compatibility abandoned (jiri)
00048  *  2003-04-26  ZSW (jiri)
00049  *  2003-06-23  fixed  parse_via_param [op].* param. parsing bug (andrei)
00050  *  2003-07-02  added support for TLS parsing in via (andrei)
00051  *  2003-10-27  added support for alias via param parsing [see
00052  *               draft-ietf-sip-connect-reuse-00.txt.]  (andrei)
00053  *  2004-03-31  fixed rport set instead of i bug (andrei)
00054  *  2005-03-02  if via has multiple bodies, and one of them is bad set
00055  *               also the first one as bad (andrei)
00056  *  2006-02-24  added support for comp parameter parsing, see rfc3486 (andrei)
00057  *  2008-08-08  SCTP support (andrei)
00058  */
00059 
00060 
00061 
00062 #include "../comp_defs.h"
00063 #include <stdlib.h>
00064 #include <string.h>
00065 #include "../dprint.h"
00066 #include "../ut.h"
00067 #include "../mem/mem.h"
00068 #include "../ip_addr.h"
00069 #include "parse_via.h"
00070 #include "parse_def.h"
00071 #include "msg_parser.h"
00072 
00073 
00074 
00076 enum {           
00077         F_HOST, P_HOST,
00078         L_PORT, F_PORT, P_PORT,
00079         L_PARAM, F_PARAM, P_PARAM,
00080         L_VIA, F_VIA,
00081         F_COMMENT, P_COMMENT,
00082         F_IP6HOST, P_IP6HOST, 
00083         F_CRLF,
00084         F_LF,
00085         F_CR,
00086         END_OF_HEADER
00087 };
00088 
00089 
00091 enum {
00092         F_SIP = 100,
00093         SIP1, SIP2, FIN_SIP,
00094         L_VER, F_VER,
00095         VER1, VER2, FIN_VER,
00096         UDP1, UDP2, FIN_UDP,
00097         TCP_TLS1, TCP2, FIN_TCP,
00098                   TLS2, FIN_TLS,
00099         SCTP1, SCTP2, SCTP3, FIN_SCTP,
00100         OTHER_PROTO,
00101         L_PROTO, F_PROTO
00102 };
00103 
00104 
00108 enum {  
00109         L_VALUE = 200, F_VALUE, P_VALUE, P_STRING,
00110         HIDDEN1, HIDDEN2, HIDDEN3, HIDDEN4, HIDDEN5,
00111         TTL1, TTL2,
00112         BRANCH1, BRANCH2, BRANCH3, BRANCH4, BRANCH5,
00113         MADDR1, MADDR2, MADDR3, MADDR4,
00114         RECEIVED1, RECEIVED2, RECEIVED3, RECEIVED4, RECEIVED5, RECEIVED6,
00115         RECEIVED7,
00116         RPORT1, RPORT2, RPORT3,
00117         ALIAS1, ALIAS2, ALIAS3, ALIAS4,
00118 #ifdef USE_COMP
00119         COMP1, COMP2, COMP3, 
00120         /* values */
00121         L_COMP_VALUE, F_COMP_VALUE,
00122         V_COMP_S, V_SIGCOMP_I, V_SIGCOMP_G, V_SIGCOMP_C, V_SIGCOMP_O, V_SIGCOMP_M,
00123         FIN_V_SIGCOMP_P,
00124         V_SERGZ_E, V_SERGZ_R, V_SERGZ_G, FIN_V_SERGZ_Z,
00125 #endif
00126              /* fin states (227-...)*/
00127         FIN_HIDDEN = 230, FIN_TTL, FIN_BRANCH,
00128         FIN_MADDR, FIN_RECEIVED, FIN_RPORT, FIN_I, FIN_ALIAS
00129 #ifdef USE_COMP
00130         , FIN_COMP
00131 #endif
00132              /*GEN_PARAM,
00133                PARAM_ERROR*/ /* declared in msg_parser.h*/
00134 };
00135 
00136 
00137 /* entry state must be F_PARAM, or saved_state=F_PARAM and
00138  * state=F_{LF,CR,CRLF}!
00139  * output state = L_PARAM or F_PARAM or END_OF_HEADER
00140  * (and saved_state= last state); everything else => error 
00141  * WARNING: param->start must be filled before, it's used in param->size 
00142  * computation.
00143  */
00144 static /*inline*/ char* parse_via_param(char* p, char* end,
00145                                                                                 unsigned char* pstate, 
00146                                                                         unsigned char* psaved_state,
00147                                                                                 struct via_param* param,
00148                                                                                 struct via_body* vb)
00149 {
00150         char* tmp;
00151         register unsigned char state;
00152         unsigned char saved_state;
00153 
00154 #define value_case(c, C, oldstate, newstate, start_of_value) \
00155                         case (c): \
00156                         case (C): \
00157                                 switch(state){ \
00158                                         case (oldstate): \
00159                                                 state=(newstate); \
00160                                                 if ((start_of_value))  param->value.s=tmp; \
00161                                                 break; \
00162                                         default_value_cases \
00163                                 } \
00164                                 break
00165 
00166 #define value_case_double(c, C, oldstate1, newstate1, oldstate2, newstate2) \
00167                         case (c): \
00168                         case (C): \
00169                                 switch(state){ \
00170                                         case (oldstate1): \
00171                                                 state=(newstate1); \
00172                                                 break; \
00173                                         case (oldstate2): \
00174                                                 state=(newstate2); \
00175                                                 break; \
00176                                         default_value_cases \
00177                                 } \
00178                                 break
00179 
00180 #define default_value_cases \
00181                                         case F_VALUE: \
00182                                                 state=P_VALUE; \
00183                                                 param->value.s=tmp; \
00184                                                 break; \
00185                                         case P_VALUE: \
00186                                         case P_STRING: \
00187                                                 break; \
00188                                         case F_LF: \
00189                                         case F_CR:  \
00190                                         case F_CRLF: \
00191                                                 state=END_OF_HEADER; \
00192                                                 goto end_via; \
00193                                         default: \
00194                                                 switch(state){ \
00195                                                         case F_COMP_VALUE: \
00196                                                                 comp_unexpected_char; \
00197                                                                 state=P_VALUE; \
00198                                                                 param->value.s=tmp; \
00199                                                                 break; \
00200                                                         comp_states_cases \
00201                                                         comp_fin_states_cases \
00202                                                                 comp_unexpected_char; \
00203                                                                 state=P_VALUE; \
00204                                                                 break; \
00205                                                         default: \
00206                                                                 LOG(L_ERR, "ERROR: parse_via_param: invalid " \
00207                                                                         "char <%c> in state %d\n", *tmp, state); \
00208                                                                 goto error; \
00209                                                 }
00210 
00211 #define comp_states_cases \
00212                                         case V_COMP_S: \
00213                                         case V_SIGCOMP_I: \
00214                                         case V_SIGCOMP_G: \
00215                                         case V_SIGCOMP_C: \
00216                                         case V_SIGCOMP_O: \
00217                                         case V_SIGCOMP_M: \
00218                                         case V_SERGZ_E: \
00219                                         case V_SERGZ_R: \
00220                                         case V_SERGZ_G: 
00221 
00222 #define comp_fin_states_cases \
00223                                         case FIN_V_SIGCOMP_P: \
00224                                         case FIN_V_SERGZ_Z:
00225 
00226 
00227 /* if unrecognized/bad comp, don't return error, just ignore comp */
00228 #define comp_unexpected_char \
00229                                                         LOG(L_ERR, "parse_via_param: bad/unrecognized" \
00230                                                                         " comp method\n"); \
00231                                                         vb->comp_no=0
00232                                                                 
00233 
00234 
00235         state=*pstate;
00236         saved_state=*psaved_state;
00237         param->type=PARAM_ERROR;
00238 
00239         for (tmp=p;tmp<end;tmp++){
00240                 switch(*tmp){
00241                         case ' ':
00242                         case '\t':
00243                                 switch(state){
00244                                         case FIN_HIDDEN:
00245                                         case FIN_ALIAS:
00246                                                 param->type=state;
00247                                                 param->name.len=tmp-param->name.s;
00248                                                 state=L_PARAM;
00249                                                 goto endofparam;
00250                                         case FIN_BRANCH:
00251                                         case FIN_TTL:
00252                                         case FIN_MADDR:
00253                                         case FIN_RECEIVED:
00254                                         case FIN_RPORT:
00255                                         case FIN_I:
00256                                                 param->type=state;
00257                                                 param->name.len=tmp-param->name.s;
00258                                                 state=L_VALUE;
00259                                                 goto find_value;
00260 #ifdef USE_COMP
00261                                         case FIN_COMP:
00262                                                 param->type=state;
00263                                                 param->name.len=tmp-param->name.s;
00264                                                 state=L_COMP_VALUE;
00265                                                 goto find_value;
00266 #endif
00267                                         case F_PARAM:
00268                                                 break;
00269                                         case F_LF:
00270                                         case F_CR:
00271                                         case F_CRLF:
00272                                                 state=saved_state;
00273                                                 break;
00274                                         case GEN_PARAM:
00275                                         default:
00276                                                 param->type=GEN_PARAM;
00277                                                 param->name.len=tmp-param->name.s;
00278                                                 state=L_VALUE;
00279                                                 goto find_value;
00280                                 }
00281                                 break;
00282                         /* \n and \r*/
00283                         case '\n':
00284                                 switch(state){
00285                                         case FIN_HIDDEN:
00286                                         case FIN_ALIAS:
00287                                                 param->type=state;
00288                                                 param->name.len=tmp-param->name.s;
00289                                                 param->size=tmp-param->start; 
00290                                                 saved_state=L_PARAM;
00291                                                 state=F_LF;
00292                                                 goto endofparam;
00293                                         case FIN_BRANCH:
00294                                         case FIN_TTL:
00295                                         case FIN_MADDR:
00296                                         case FIN_RECEIVED:
00297                                         case FIN_I:
00298                                         case FIN_RPORT:
00299                                                 param->type=state;
00300                                                 param->name.len=tmp-param->name.s;
00301                                                 param->size=tmp-param->start; 
00302                                                 saved_state=L_VALUE;
00303                                                 state=F_LF;
00304                                                 goto find_value;
00305 #ifdef USE_COMP
00306                                         case FIN_COMP:
00307                                                 param->type=state;
00308                                                 param->name.len=tmp-param->name.s;
00309                                                 param->size=tmp-param->start; 
00310                                                 saved_state=L_COMP_VALUE;
00311                                                 state=F_LF;
00312                                                 goto find_value;
00313 #endif
00314                                         case F_PARAM:
00315                                                 saved_state=state;
00316                                                 state=F_LF;
00317                                                 break;
00318                                         case F_LF:
00319                                         case F_CRLF:
00320                                                 state=END_OF_HEADER;
00321                                                 goto end_via;
00322                                         case F_CR:
00323                                                 state=F_CRLF;
00324                                                 break;
00325                                         case GEN_PARAM:
00326                                         default:
00327                                                 param->type=GEN_PARAM;
00328                                                 saved_state=L_VALUE;
00329                                                 param->name.len=tmp-param->name.s;
00330                                                 param->size=tmp-param->start; 
00331                                                 state=F_LF;
00332                                                 goto find_value;
00333                                 }
00334                                 break;
00335                         case '\r':
00336                                 switch(state){
00337                                         case FIN_HIDDEN:
00338                                         case FIN_ALIAS:
00339                                                 param->type=state;
00340                                                 param->name.len=tmp-param->name.s;
00341                                                 param->size=tmp-param->start; 
00342                                                 saved_state=L_PARAM;
00343                                                 state=F_CR;
00344                                                 goto endofparam;
00345                                         case FIN_BRANCH:
00346                                         case FIN_TTL:
00347                                         case FIN_MADDR:
00348                                         case FIN_RECEIVED:
00349                                         case FIN_I:
00350                                         case FIN_RPORT:
00351                                                 param->type=state;
00352                                                 param->name.len=tmp-param->name.s;
00353                                                 param->size=tmp-param->start; 
00354                                                 saved_state=L_VALUE;
00355                                                 state=F_CR;
00356                                                 goto find_value;
00357 #ifdef USE_COMP
00358                                         case FIN_COMP:
00359                                                 param->type=state;
00360                                                 param->name.len=tmp-param->name.s;
00361                                                 param->size=tmp-param->start; 
00362                                                 saved_state=L_COMP_VALUE;
00363                                                 state=F_LF;
00364                                                 goto find_value;
00365 #endif
00366                                         case F_PARAM:
00367                                                 saved_state=state;
00368                                                 state=F_CR;
00369                                                 break;
00370                                         case F_CR:
00371                                         case F_CRLF:
00372                                                 state=END_OF_HEADER;
00373                                                 goto end_via;
00374                                         case GEN_PARAM:
00375                                         default:
00376                                                 param->type=GEN_PARAM;
00377                                                 param->name.len=tmp-param->name.s;
00378                                                 param->size=tmp-param->start; 
00379                                                 saved_state=L_VALUE;
00380                                                 state=F_CR;
00381                                                 goto find_value;
00382                                 }
00383                                 break;
00384 
00385                         case '=':
00386                                 switch(state){
00387                                         case FIN_BRANCH:
00388                                         case FIN_TTL:
00389                                         case FIN_MADDR:
00390                                         case FIN_RECEIVED:
00391                                         case FIN_RPORT:
00392                                         case FIN_I:
00393                                                 param->type=state;
00394                                                 param->name.len=tmp-param->name.s;
00395                                                 state=F_VALUE;
00396                                                 goto find_value;
00397 #ifdef USE_COMP
00398                                         case FIN_COMP:
00399                                                 param->type=state;
00400                                                 param->name.len=tmp-param->name.s;
00401                                                 state=F_COMP_VALUE;
00402                                                 goto find_value;
00403 #endif
00404                                         case F_PARAM:
00405                                         case FIN_HIDDEN:
00406                                         case FIN_ALIAS:
00407                                                 LOG(L_ERR, "ERROR: parse_via: invalid char <%c> in"
00408                                                                 " state %d\n", *tmp, state);
00409                                                 goto error;
00410                                         case F_CR:
00411                                         case F_LF:
00412                                         case F_CRLF:
00413                                                 state=END_OF_HEADER;
00414                                                 goto end_via;
00415                                         case GEN_PARAM:
00416                                         default:
00417                                                 param->type=GEN_PARAM;
00418                                                 param->name.len=tmp-param->name.s;
00419                                                 state=F_VALUE;
00420                                                 goto find_value;
00421                                 }
00422                                 break;
00423                         case ';':
00424                                 switch(state){
00425                                         case FIN_HIDDEN:
00426                                         case FIN_RPORT: /* rport can appear w/o a value */
00427                                         case FIN_ALIAS:
00428                                                 param->type=state;
00429                                                 param->name.len=tmp-param->name.s;
00430                                                 state=F_PARAM;
00431                                                 goto endofparam;
00432                                         case FIN_BRANCH:
00433                                         case FIN_MADDR:
00434                                         case FIN_TTL:
00435                                         case FIN_RECEIVED:
00436                                         case FIN_I:
00437 #ifdef USE_COMP
00438                                         case FIN_COMP:
00439 #endif
00440                                                 LOG(L_ERR, "ERROR: parse_via: invalid char <%c> in"
00441                                                                 " state %d\n", *tmp, state);
00442                                                 goto error;
00443                                         case F_CR:
00444                                         case F_LF:
00445                                         case F_CRLF:
00446                                                 state=END_OF_HEADER;
00447                                                 goto end_via;
00448                                         case GEN_PARAM:
00449                                         default:
00450                                                 param->type=GEN_PARAM;
00451                                                 param->name.len=tmp-param->name.s;
00452                                                 state=F_PARAM;
00453                                                 goto endofparam;
00454                                 }
00455                                 break;
00456                         case ',':
00457                                 switch(state){
00458                                         case FIN_HIDDEN:
00459                                         case FIN_RPORT:
00460                                         case FIN_ALIAS:
00461                                                 param->type=state;
00462                                                 param->name.len=tmp-param->name.s;
00463                                                 state=F_VIA;
00464                                                 goto endofvalue;
00465                                         case FIN_BRANCH:
00466                                         case FIN_MADDR:
00467                                         case FIN_TTL:
00468                                         case FIN_RECEIVED:
00469                                         case FIN_I:
00470 #ifdef USE_COMP
00471                                         case FIN_COMP:
00472 #endif
00473                                                 LOG(L_ERR, "ERROR: parse_via_param: new via found" 
00474                                                                 "(',') when '=' expected (state %d=)\n",
00475                                                                 state);
00476                                                 goto error; /* or we could ignore this bad param*/
00477                                         case F_CR:
00478                                         case F_LF:
00479                                         case F_CRLF:
00480                                                 state=END_OF_HEADER;
00481                                                 goto end_via;
00482                                         case GEN_PARAM:
00483                                         default:
00484                                                 param->type=GEN_PARAM;
00485                                                 param->name.len=tmp-param->name.s;
00486                                                 state=F_VIA;
00487                                                 goto endofvalue;
00488                                 }
00489                                 break; 
00490 
00491                                 /* param names */
00492                         case 'h':
00493                         case 'H':
00494                                 switch(state){
00495                                         case F_PARAM:
00496                                                 state=HIDDEN1;
00497                                                 param->name.s=tmp;
00498                                                 break;
00499                                         case BRANCH5:
00500                                                 state=FIN_BRANCH;
00501                                                 break;
00502                                         case GEN_PARAM:
00503                                                 break;
00504                                         case F_CR:
00505                                         case F_LF:
00506                                         case F_CRLF:
00507                                                 state=END_OF_HEADER;
00508                                                 goto end_via;
00509                                         default:
00510                                                 state=GEN_PARAM;
00511                                 }
00512                                 break;
00513                         case 'i':
00514                         case 'I':
00515                                 switch(state){
00516                                         case F_PARAM:
00517                                                 state=FIN_I;
00518                                                 param->name.s=tmp;
00519                                                 break;
00520                                         case HIDDEN1:
00521                                                 state=HIDDEN2;
00522                                                 break;
00523                                         case RECEIVED4:
00524                                                 state=RECEIVED5;
00525                                                 break;
00526                                         case ALIAS2:
00527                                                 state=ALIAS3;
00528                                                 break;
00529                                         case GEN_PARAM:
00530                                                 break;
00531                                         case F_CR:
00532                                         case F_LF:
00533                                         case F_CRLF:
00534                                                 state=END_OF_HEADER;
00535                                                 goto end_via;
00536                                         default:
00537                                                 state=GEN_PARAM;
00538                                 }
00539                                 break;
00540                         case 'd':
00541                         case 'D':
00542                                 switch(state){
00543                                         case F_PARAM:
00544                                                 state=GEN_PARAM;
00545                                                 param->name.s=tmp;
00546                                                 break;
00547                                         case HIDDEN2:
00548                                                 state=HIDDEN3;
00549                                                 break;
00550                                         case HIDDEN3:
00551                                                 state=HIDDEN4;
00552                                                 break;
00553                                         case MADDR2:
00554                                                 state=MADDR3;
00555                                                 break;
00556                                         case MADDR3:
00557                                                 state=MADDR4;
00558                                                 break;
00559                                         case RECEIVED7:
00560                                                 state=FIN_RECEIVED;
00561                                                 break;
00562                                         case GEN_PARAM:
00563                                                 break;
00564                                         case F_CR:
00565                                         case F_LF:
00566                                         case F_CRLF:
00567                                                 state=END_OF_HEADER;
00568                                                 goto end_via;
00569                                         default:
00570                                                 state=GEN_PARAM;
00571                                 }
00572                                 break;
00573                         case 'e':
00574                         case 'E':
00575                                 switch(state){
00576                                         case F_PARAM:
00577                                                 state=GEN_PARAM;
00578                                                 param->name.s=tmp;
00579                                                 break;
00580                                         case HIDDEN4:
00581                                                 state=HIDDEN5;
00582                                                 break;
00583                                         case RECEIVED1:
00584                                                 state=RECEIVED2;
00585                                                 break;
00586                                         case RECEIVED3:
00587                                                 state=RECEIVED4;
00588                                                 break;
00589                                         case RECEIVED6:
00590                                                 state=RECEIVED7;
00591                                                 break;
00592                                         case GEN_PARAM:
00593                                                 break;
00594                                         case F_CR:
00595                                         case F_LF:
00596                                         case F_CRLF:
00597                                                 state=END_OF_HEADER;
00598                                                 goto end_via;
00599                                         default:
00600                                                 state=GEN_PARAM;
00601                                 }
00602                                 break;
00603                         case 'n':
00604                         case 'N':
00605                                 switch(state){
00606                                         case F_PARAM:
00607                                                 state=GEN_PARAM;
00608                                                 param->name.s=tmp;
00609                                                 break;
00610                                         case HIDDEN5:
00611                                                 state=FIN_HIDDEN;
00612                                                 break;
00613                                         case BRANCH3:
00614                                                 state=BRANCH4;
00615                                                 break;
00616                                         case GEN_PARAM:
00617                                                 break;
00618                                         case F_CR:
00619                                         case F_LF:
00620                                         case F_CRLF:
00621                                                 state=END_OF_HEADER;
00622                                                 goto end_via;
00623                                         default:
00624                                                 state=GEN_PARAM;
00625                                 }
00626                                 break;
00627                         case 't':
00628                         case 'T':
00629                                 switch(state){
00630                                         case F_PARAM:
00631                                                 state=TTL1;
00632                                                 param->name.s=tmp;
00633                                                 break;
00634                                         case TTL1:
00635                                                 state=TTL2;
00636                                                 break;
00637                                         case RPORT3:
00638                                                 state=FIN_RPORT;
00639                                                 break;
00640                                         case GEN_PARAM:
00641                                                 break;
00642                                         case F_CR:
00643                                         case F_LF:
00644                                         case F_CRLF:
00645                                                 state=END_OF_HEADER;
00646                                                 goto end_via;
00647                                         default:
00648                                                 state=GEN_PARAM;
00649                                 }
00650                                 break;
00651                         case 'l':
00652                         case 'L':
00653                                 switch(state){
00654                                         case F_PARAM:
00655                                                 state=GEN_PARAM;
00656                                                 param->name.s=tmp;
00657                                                 break;
00658                                         case TTL2:
00659                                                 state=FIN_TTL;
00660                                                 break;
00661                                         case ALIAS1:
00662                                                 state=ALIAS2;
00663                                                 break;
00664                                         case GEN_PARAM:
00665                                                 break;
00666                                         case F_CR:
00667                                         case F_LF:
00668                                         case F_CRLF:
00669                                                 state=END_OF_HEADER;
00670                                                 goto end_via;
00671                                         default:
00672                                                 state=GEN_PARAM;
00673                                 }
00674                                 break;
00675                         case 'm':
00676                         case 'M':
00677                                 switch(state){
00678                                         case F_PARAM:
00679                                                 state=MADDR1;
00680                                                 param->name.s=tmp;
00681                                                 break;
00682 #ifdef USE_COMP
00683                                         case COMP2:
00684                                                 state=COMP3;
00685                                                 break;
00686 #endif
00687                                         case GEN_PARAM:
00688                                                 break;
00689                                         case F_CR:
00690                                         case F_LF:
00691                                         case F_CRLF:
00692                                                 state=END_OF_HEADER;
00693                                                 goto end_via;
00694                                         default:
00695                                                 state=GEN_PARAM;
00696                                 }
00697                                 break;
00698                         case 'a':
00699                         case 'A':
00700                                 switch(state){
00701                                         case F_PARAM:
00702                                                 state=ALIAS1;
00703                                                 param->name.s=tmp;
00704                                                 break;
00705                                         case MADDR1:
00706                                                 state=MADDR2;
00707                                                 break;
00708                                         case BRANCH2:
00709                                                 state=BRANCH3;
00710                                                 break;
00711                                         case ALIAS3:
00712                                                 state=ALIAS4;
00713                                                 break;
00714                                         case GEN_PARAM:
00715                                                 break;
00716                                         case F_CR:
00717                                         case F_LF:
00718                                         case F_CRLF:
00719                                                 state=END_OF_HEADER;
00720                                                 goto end_via;
00721                                         default:
00722                                                 state=GEN_PARAM;
00723                                 }
00724                                 break;
00725                         case 'r':
00726                         case 'R':
00727                                 switch(state){
00728                                         case MADDR4:
00729                                                 state=FIN_MADDR;
00730                                                 break;
00731                                         case F_PARAM:
00732                                                 state=RECEIVED1;
00733                                                 param->name.s=tmp;
00734                                                 break;
00735                                         case BRANCH1:
00736                                                 state=BRANCH2;
00737                                                 break;
00738                                         case RPORT2:
00739                                                 state=RPORT3;
00740                                                 break;
00741                                         case GEN_PARAM:
00742                                                 break;
00743                                         case F_CR:
00744                                         case F_LF:
00745                                         case F_CRLF:
00746                                                 state=END_OF_HEADER;
00747                                                 goto end_via;
00748                                         default:
00749                                                 state=GEN_PARAM;
00750                                 }
00751                                 break;
00752                         case 'c':
00753                         case 'C':
00754                                 switch(state){
00755                                         case F_PARAM:
00756 #ifdef USE_COMP
00757                                                 state=COMP1;
00758 #else
00759                                                 state=GEN_PARAM;
00760 #endif
00761                                                 param->name.s=tmp;
00762                                                 break;
00763                                         case RECEIVED2:
00764                                                 state=RECEIVED3;
00765                                                 break;
00766                                         case BRANCH4:
00767                                                 state=BRANCH5;
00768                                                 break;
00769                                         case GEN_PARAM:
00770                                                 break;
00771                                         case F_CR:
00772                                         case F_LF:
00773                                         case F_CRLF:
00774                                                 state=END_OF_HEADER;
00775                                                 goto end_via;
00776                                         default:
00777                                                 state=GEN_PARAM;
00778                                 }
00779                                 break;
00780                         case 'v':
00781                         case 'V':
00782                                 switch(state){
00783                                         case F_PARAM:
00784                                                 state=GEN_PARAM;
00785                                                 param->name.s=tmp;
00786                                                 break;
00787                                         case RECEIVED5:
00788                                                 state=RECEIVED6;
00789                                                 break;
00790                                         case GEN_PARAM:
00791                                                 break;
00792                                         case F_CR:
00793                                         case F_LF:
00794                                         case F_CRLF:
00795                                                 state=END_OF_HEADER;
00796                                                 goto end_via;
00797                                         default:
00798                                                 state=GEN_PARAM;
00799                                 }
00800                                 break;
00801                         case 'b':
00802                         case 'B':
00803                                 switch(state){
00804                                         case F_PARAM:
00805                                                 state=BRANCH1;
00806                                                 param->name.s=tmp;
00807                                                 break;
00808                                         case GEN_PARAM:
00809                                                 break;
00810                                         case F_CR:
00811                                         case F_LF:
00812                                         case F_CRLF:
00813                                                 state=END_OF_HEADER;
00814                                                 goto end_via;
00815                                         default:
00816                                                 state=GEN_PARAM;
00817                                 }
00818                                 break;
00819                         case 'p':
00820                         case 'P':
00821                                 switch(state){
00822                                         case F_PARAM:
00823                                                 state=GEN_PARAM;
00824                                                 param->name.s=tmp;
00825                                                 break;
00826                                         case RECEIVED1:
00827                                                 state=RPORT1;
00828                                                 break;
00829 #ifdef USE_COMP
00830                                         case COMP3:
00831                                                 state=FIN_COMP;
00832                                                 break;
00833 #endif
00834                                         case F_CR:
00835                                         case F_LF:
00836                                         case F_CRLF:
00837                                                 state=END_OF_HEADER;
00838                                                 goto end_via;
00839                                         default:
00840                                                 state=GEN_PARAM;
00841                                 }
00842                                 break;
00843                         case 'o':
00844                         case 'O':
00845                                 switch(state){
00846                                         case F_PARAM:
00847                                                 state=GEN_PARAM;
00848                                                 param->name.s=tmp;
00849                                                 break;
00850                                         case RPORT1:
00851                                                 state=RPORT2;
00852                                                 break;
00853 #ifdef USE_COMP
00854                                         case COMP1:
00855                                                 state=COMP2;
00856                                                 break;
00857 #endif
00858                                         case F_CR:
00859                                         case F_LF:
00860                                         case F_CRLF:
00861                                                 state=END_OF_HEADER;
00862                                                 goto end_via;
00863                                         default:
00864                                                 state=GEN_PARAM;
00865                                 }
00866                                 break;
00867                         case 's':
00868                         case 'S':
00869                                 switch(state){
00870                                         case F_PARAM:
00871                                                 state=GEN_PARAM;
00872                                                 param->name.s=tmp;
00873                                                 break;
00874                                         case ALIAS4:
00875                                                 state=FIN_ALIAS;
00876                                                 break;
00877                                         case F_CR:
00878                                         case F_LF:
00879                                         case F_CRLF:
00880                                                 state=END_OF_HEADER;
00881                                                 goto end_via;
00882                                         default:
00883                                                 state=GEN_PARAM;
00884                                 }
00885                                 break;
00886                         default:
00887                                 switch(state){
00888                                         case F_PARAM:
00889                                                 state=GEN_PARAM;
00890                                                 param->name.s=tmp;
00891                                                 break;
00892                                         case GEN_PARAM:
00893                                                 break;
00894                                         case F_CR:
00895                                         case F_LF:
00896                                         case F_CRLF:
00897                                                 state=END_OF_HEADER;
00898                                                 goto end_via;
00899                                         default:
00900                                                 state=GEN_PARAM;
00901                                 }
00902                 }
00903         }/* for tmp*/
00904 
00905         /* end of packet? => error, no cr/lf,',' found!!!*/
00906         saved_state=state;
00907         state=END_OF_HEADER;
00908         goto error;
00909         
00910  find_value:
00911         tmp++;
00912         for(;*tmp;tmp++){
00913                 switch(*tmp){
00914                         case ' ':
00915                         case '\t':
00916                                 switch(state){
00917                                         case L_VALUE:
00918                                         case F_VALUE: /*eat space*/
00919                                                 break; 
00920                                         case P_VALUE:
00921                                                 state=L_PARAM;
00922                                                 param->value.len=tmp-param->value.s;
00923                                                 goto endofvalue;
00924 #ifdef USE_COMP
00925                                         case L_COMP_VALUE:
00926                                         case F_COMP_VALUE:
00927                                                 break; /* eat space */
00928                                         case FIN_V_SIGCOMP_P:
00929                                                 state=L_PARAM;
00930                                                 param->value.len=tmp-param->value.s;
00931                                                 vb->comp_no=COMP_SIGCOMP;
00932                                                 goto endofvalue;
00933                                         case FIN_V_SERGZ_Z:
00934                                                 state=L_PARAM;
00935                                                 param->value.len=tmp-param->value.s;
00936                                                 vb->comp_no=COMP_SIGCOMP;
00937                                                 goto endofvalue;
00938                                         comp_states_cases
00939                                                 state=L_PARAM;
00940                                                 param->value.len=tmp-param->value.s;
00941                                                 comp_unexpected_char;
00942                                                 goto endofvalue;
00943 #endif
00944                                         case P_STRING:
00945                                                 break;
00946                                         case F_CR:
00947                                         case F_LF:
00948                                         case F_CRLF:
00949                                                 state=saved_state;
00950                                                 break;
00951                                         default:
00952                                                 LOG(L_ERR, "ERROR: parse_via: invalid char <%c>"
00953                                                                 " in state %d\n", *tmp, state);
00954                                                 goto error;
00955                                 }
00956                                 break;
00957                         case '\n':
00958                                 switch(state){
00959                                         case L_VALUE:
00960                                         case F_VALUE: /*eat space*/
00961 #ifdef USE_COMP
00962                                         case L_COMP_VALUE:
00963                                         case F_COMP_VALUE:
00964 #endif
00965                                         case P_STRING:
00966                                                 saved_state=state;
00967                                                 param->size=tmp-param->start;
00968                                                 state=F_LF;
00969                                                 break;
00970                                         case P_VALUE:
00971                                                 saved_state=L_PARAM;
00972                                                 state=F_LF;
00973                                                 param->value.len=tmp-param->value.s;
00974                                                 goto endofvalue;
00975 #ifdef USE_COMP
00976                                         case FIN_V_SIGCOMP_P:
00977                                                 saved_state=L_PARAM;
00978                                                 state=F_LF;
00979                                                 param->value.len=tmp-param->value.s;
00980                                                 vb->comp_no=COMP_SIGCOMP;
00981                                                 goto endofvalue;
00982                                         case FIN_V_SERGZ_Z:
00983                                                 saved_state=L_PARAM;
00984                                                 state=F_LF;
00985                                                 param->value.len=tmp-param->value.s;
00986                                                 vb->comp_no=COMP_SIGCOMP;
00987                                                 goto endofvalue;
00988                                         comp_states_cases
00989                                                 saved_state=L_PARAM;
00990                                                 state=F_LF;
00991                                                 param->value.len=tmp-param->value.s;
00992                                                 comp_unexpected_char;
00993                                                 goto endofvalue;
00994 #endif
00995                                         case F_LF:
00996                                         case F_CRLF:
00997                                                 state=END_OF_HEADER;
00998                                                 goto end_via;
00999                                         case F_CR:
01000                                                 state=F_CRLF;
01001                                                 break;
01002                                         default:
01003                                                 LOG(L_ERR, "ERROR: parse_via: invalid char <%c>"
01004                                                                 " in state %d\n", *tmp, state);
01005                                                 goto error;
01006                                 }
01007                                 break;
01008                         case '\r':
01009                                 switch(state){
01010                                         case L_VALUE:
01011                                         case F_VALUE: /*eat space*/
01012 #ifdef USE_COMP
01013                                         case L_COMP_VALUE:
01014                                         case F_COMP_VALUE:
01015 #endif
01016                                         case P_STRING:
01017                                                 saved_state=state;
01018                                                 param->size=tmp-param->start;
01019                                                 state=F_CR;
01020                                                 break;
01021                                         case P_VALUE:
01022                                                 param->value.len=tmp-param->value.s;
01023                                                 saved_state=L_PARAM;
01024                                                 state=F_CR;
01025                                                 goto endofvalue;
01026 #ifdef USE_COMP
01027                                         case FIN_V_SIGCOMP_P:
01028                                                 saved_state=L_PARAM;
01029                                                 state=F_CR;
01030                                                 param->value.len=tmp-param->value.s;
01031                                                 vb->comp_no=COMP_SIGCOMP;
01032                                                 goto endofvalue;
01033                                         case FIN_V_SERGZ_Z:
01034                                                 saved_state=L_PARAM;
01035                                                 state=F_CR;
01036                                                 param->value.len=tmp-param->value.s;
01037                                                 vb->comp_no=COMP_SIGCOMP;
01038                                                 goto endofvalue;
01039                                         comp_states_cases
01040                                                 saved_state=L_PARAM;
01041                                                 state=F_CR;
01042                                                 param->value.len=tmp-param->value.s;
01043                                                 comp_unexpected_char;
01044                                                 goto endofvalue;
01045 #endif
01046                                         case F_LF:
01047                                         case F_CR:
01048                                         case F_CRLF:
01049                                                 state=END_OF_HEADER;
01050                                                 goto end_via;
01051                                         default:
01052                                                 LOG(L_ERR, "ERROR: parse_via: invalid char <%c>"
01053                                                                 " in state %d\n", *tmp, state);
01054                                                 goto error;
01055                                 }
01056                                 break;
01057 
01058                         case '=':
01059                                 switch(state){
01060                                         case L_VALUE:
01061                                                 state=F_VALUE;
01062                                                 break;
01063 #ifdef USE_COMP
01064                                         case L_COMP_VALUE:
01065                                                 state=F_COMP_VALUE;
01066                                                 break;
01067                                         /* '=' in any other COMP value state is an error,
01068                                          * and it will be catched by the default branch */
01069 #endif
01070                                         case P_STRING:
01071                                                 break;
01072                                         case F_LF:
01073                                         case F_CR:
01074                                         case F_CRLF:
01075                                                 state=END_OF_HEADER;
01076                                                 goto end_via;
01077                                         default:
01078                                                 LOG(L_ERR, "ERROR: parse_via: invalid char <%c>"
01079                                                                 " in state %d\n", *tmp, state);
01080                                                 goto error;
01081                                 }
01082                                 break;
01083                         case ';':
01084                                 switch(state){
01085                                         case P_VALUE:
01086                                                 param->value.len=tmp-param->value.s;
01087                                                 state=F_PARAM;
01088                                                 goto endofvalue;
01089                                         case F_VALUE:
01090                                                 param->value.len=0;
01091                                                 state=F_PARAM;
01092                                                 goto endofvalue;
01093                                         case P_STRING:
01094                                                 break; /* what to do? */
01095                                         case F_LF:
01096                                         case F_CR:
01097                                         case F_CRLF:
01098                                                 state=END_OF_HEADER;
01099                                                 goto end_via;
01100 #ifdef USE_COMP
01101                                         case L_COMP_VALUE:
01102                                                 comp_unexpected_char;
01103                                                 /* we want to contine with no comp */
01104                                                 state=F_PARAM;
01105                                                 param->value.len=0;
01106                                                 param->value.s=0;
01107                                                 goto endofvalue;
01108                                         case F_COMP_VALUE:
01109                                                 comp_unexpected_char;
01110                                                 param->value.len=0;
01111                                                 state=F_PARAM;
01112                                                 goto endofvalue;
01113                                         comp_states_cases
01114                                                 comp_unexpected_char;
01115                                                 param->value.len=tmp-param->value.s;
01116                                                 state=F_PARAM;
01117                                                 goto endofvalue;
01118                                         case FIN_V_SIGCOMP_P:
01119                                                 vb->comp_no=COMP_SIGCOMP;
01120                                                 param->value.len=tmp-param->value.s;
01121                                                 state=F_PARAM;
01122                                                 goto endofvalue;
01123                                         case FIN_V_SERGZ_Z:
01124                                                 vb->comp_no=COMP_SIGCOMP;
01125                                                 param->value.len=tmp-param->value.s;
01126                                                 state=F_PARAM;
01127                                                 goto endofvalue;
01128 #endif
01129                                         case L_VALUE:
01130                                                 if (param->type==FIN_RPORT){
01131                                                         param->value.len=0;
01132                                                         param->value.s=0; /* null value */
01133                                                         state=F_PARAM;
01134                                                         goto endofvalue;
01135                                                 };
01136                                                 /* no break */
01137                                         default:
01138                                                 LOG(L_ERR, "ERROR: parse_via: invalid char <%c>"
01139                                                                 " in state %d\n", *tmp, state);
01140                                                 goto error;
01141                                 }
01142                                 break;
01143                         case ',':
01144                                 switch(state){
01145                                         case P_VALUE:
01146                                                 param->value.len=tmp-param->value.s;
01147                                                 state=F_VIA;
01148                                                 goto endofvalue;
01149                                         case P_STRING:
01150                                         case F_LF:
01151                                         case F_CR:
01152                                         case F_CRLF:
01153                                                 state=END_OF_HEADER;
01154                                                 goto end_via;
01155 #ifdef USE_COMP
01156                                         case L_COMP_VALUE:
01157                                                 comp_unexpected_char;
01158                                                 /* we want to contine with no comp */
01159                                                 state=F_VIA;
01160                                                 param->value.len=0;
01161                                                 param->value.s=0;
01162                                                 goto endofvalue;
01163                                         case F_COMP_VALUE:
01164                                                 comp_unexpected_char;
01165                                                 param->value.len=0;
01166                                                 state=F_VIA;
01167                                                 goto endofvalue;
01168                                         comp_states_cases
01169                                                 comp_unexpected_char;
01170                                                 param->value.len=tmp-param->value.s;
01171                                                 state=F_VIA;
01172                                                 goto endofvalue;
01173                                         case FIN_V_SIGCOMP_P:
01174                                                 vb->comp_no=COMP_SIGCOMP;
01175                                                 param->value.len=tmp-param->value.s;
01176                                                 state=F_VIA;
01177                                                 goto endofvalue;
01178                                         case FIN_V_SERGZ_Z:
01179                                                 vb->comp_no=COMP_SIGCOMP;
01180                                                 param->value.len=tmp-param->value.s;
01181                                                 state=F_VIA;
01182                                                 goto endofvalue;
01183 #endif
01184                                         case L_VALUE:
01185                                                 if (param->type==FIN_RPORT){
01186                                                         param->value.len=0;
01187                                                         param->value.s=0; /* null value */
01188                                                         state=F_VIA;
01189                                                         goto endofvalue;
01190                                                 };
01191                                                 /* no break */
01192                                         default:
01193                                                 LOG(L_ERR, "ERROR: parse_via: invalid char <%c>"
01194                                                                 " in state %d\n", *tmp, state);
01195                                                 goto error;
01196                                 }
01197                                 break; /* what to do? */
01198                         case '"':
01199                                 switch(state){
01200                                         case F_VALUE:
01201                                                 state=P_STRING;
01202                                                 param->value.s=tmp+1;
01203                                                 break;
01204                                         case P_STRING:
01205                                                 state=L_PARAM;
01206                                                 param->value.len=tmp-param->value.s;
01207                                                 goto endofvalue;
01208                                         case F_LF:
01209                                         case F_CR:
01210                                         case F_CRLF:
01211                                                 state=END_OF_HEADER;
01212                                                 goto end_via;
01213                                         default:
01214                                                 LOG(L_ERR, "ERROR: parse_via: invalid char <%c>"
01215                                                                 " in state %d\n", *tmp, state);
01216                                                 goto error;
01217                                 }
01218                                 break;
01219 #ifdef USE_COMP
01220                         value_case('s', 'S', F_COMP_VALUE, V_COMP_S, 1);
01221                         value_case('i', 'I', V_COMP_S, V_SIGCOMP_I, 0);
01222                         value_case_double('g', 'G', V_SIGCOMP_I, V_SIGCOMP_G,
01223                                                             V_SERGZ_R,   V_SERGZ_G);
01224                         value_case('c', 'C', V_SIGCOMP_G, V_SIGCOMP_C, 0);
01225                         value_case('o', 'O', V_SIGCOMP_C, V_SIGCOMP_O, 0);
01226                         value_case('m', 'M', V_SIGCOMP_O, V_SIGCOMP_M, 0);
01227                         value_case('p', 'P', V_SIGCOMP_M, FIN_V_SIGCOMP_P, 0);
01228                         
01229                         value_case('e', 'E', V_COMP_S, V_SERGZ_E, 0);
01230                         value_case('r', 'R', V_SERGZ_E, V_SERGZ_R, 0);
01231                         value_case('z', 'Z', V_SERGZ_G, FIN_V_SERGZ_Z, 0);
01232 #endif /* USE_COMP */
01233                                 
01234                         default:
01235                                 switch(state){
01236                                         case F_VALUE:
01237                                                 state=P_VALUE;
01238                                                 param->value.s=tmp;
01239                                                 break;
01240                                         case P_VALUE:
01241                                         case P_STRING:
01242                                                 break;
01243                                         case F_LF:
01244                                         case F_CR:
01245                                         case F_CRLF:
01246                                                 state=END_OF_HEADER;
01247                                                 goto end_via;
01248                                         default:
01249 #ifdef USE_COMP
01250                                                 switch(state){
01251                                                         case F_COMP_VALUE:
01252                                                                 comp_unexpected_char;
01253                                                                 state=P_VALUE;
01254                                                                 param->value.s=tmp;
01255                                                                 break;
01256                                                         comp_states_cases
01257                                                         comp_fin_states_cases
01258                                                                 comp_unexpected_char;
01259                                                                 state=P_VALUE;
01260                                                                 break;
01261                                                         default:
01262                                                                 LOG(L_ERR, "ERROR: parse_via_param: invalid "
01263                                                                         "char <%c> in state %d\n", *tmp, state);
01264                                                                 goto error;
01265                                                 }
01266 #else
01267                                                 LOG(L_ERR, "ERROR: parse_via: invalid char <%c>"
01268                                                                 " in state %d\n", *tmp, state);
01269                                                 goto error;
01270 #endif /* USE_COMP */
01271                                 }
01272                 }
01273         } /* for2 tmp*/
01274 
01275         /* end of buff and no CR/LF =>error*/
01276         saved_state=state;
01277         state=END_OF_HEADER;
01278         goto error;
01279         
01280  endofparam:
01281  endofvalue:
01282         param->size=tmp-param->start;
01283 normal_exit:
01284         *pstate=state;
01285         *psaved_state=saved_state;
01286         DBG("Found param type %d, <%.*s> = <%.*s>; state=%d\n", param->type,
01287                         param->name.len, ZSW(param->name.s), 
01288                         (param->value.len?param->value.len:3),
01289                         (param->value.len?param->value.s:"n/a"), state);
01290         return tmp;
01291         
01292  end_via:
01293              /* if we are here we found an "unexpected" end of via
01294               *  (cr/lf). This is valid only if the param type is GEN_PARAM or
01295                   *  RPORT (the only ones which can miss the value; HIDDEN is a 
01296                   *  special case )*/
01297         if ((param->type==GEN_PARAM)||(param->type==PARAM_RPORT)){
01298                 saved_state=L_PARAM; /* change the saved_state, we have an unknown
01299                                         param. w/o a value */
01300                 /* param->size should be computed before */
01301                 goto normal_exit;
01302         }
01303         *pstate=state;
01304         *psaved_state=saved_state;
01305         DBG("Error on  param type %d, <%.*s>, state=%d, saved_state=%d\n",
01306                 param->type, param->name.len, ZSW(param->name.s), state, saved_state);
01307 
01308  error:
01309         LOG(L_ERR, "error: parse_via_param\n");
01310         param->type=PARAM_ERROR;
01311         *pstate=PARAM_ERROR;
01312         *psaved_state=state;
01313         return tmp;
01314 }
01315 
01316 
01317 
01318 /*
01319  * call it with a vb initialized to 0
01320  * returns: pointer after the parsed parts and sets vb->error
01321  * WARNING: don't forget to cleanup on error with free_via_list(vb)!
01322  */
01323 char* parse_via(char* buffer, char* end, struct via_body *vbody)
01324 {
01325         char* tmp;
01326         char* param_start;
01327         unsigned char state;
01328         unsigned char saved_state;
01329         int c_nest;
01330         int err;
01331         struct via_body* vb;
01332         struct via_param* param;
01333 
01334         vb=vbody; /* keep orignal vbody value, needed to set the error member
01335                                  in case of multiple via bodies in the same header */
01336 parse_again:
01337         vb->error=PARSE_ERROR;
01338         /* parse start of via ( SIP/2.0/UDP    )*/
01339         state=F_SIP;
01340         saved_state=F_SIP; /* fixes gcc 4.0 warning */
01341         param_start=0;
01342         for(tmp=buffer;tmp<end;tmp++){
01343                 switch(*tmp){
01344                         case ' ':
01345                         case'\t':
01346                                 switch(state){
01347                                         case L_VER: /* eat space */
01348                                         case L_PROTO:
01349                                         case F_SIP:
01350                                         case F_VER:
01351                                         case F_PROTO:
01352                                                 break;
01353                                         case FIN_UDP:
01354                                                 vb->transport.len=tmp-vb->transport.s;
01355                                                 vb->proto=PROTO_UDP;
01356                                                 state=F_HOST; /* start looking for host*/
01357                                                 goto main_via;
01358                                         case FIN_TCP:
01359                                                 /* finished proto parsing */
01360                                                 vb->transport.len=tmp-vb->transport.s;
01361                                                 vb->proto=PROTO_TCP;
01362                                                 state=F_HOST; /* start looking for host*/
01363                                                 goto main_via;
01364                                         case FIN_TLS:
01365                                                 /* finished proto parsing */
01366                                                 vb->transport.len=tmp-vb->transport.s;
01367                                                 vb->proto=PROTO_TLS;
01368                                                 state=F_HOST; /* start looking for host*/
01369                                                 goto main_via;
01370                                         case FIN_SCTP:
01371                                                 /* finished proto parsing */
01372                                                 vb->transport.len=tmp-vb->transport.s;
01373                                                 vb->proto=PROTO_SCTP;
01374                                                 state=F_HOST; /* start looking for host*/
01375                                                 goto main_via;
01376                                         case OTHER_PROTO:
01377                                                 /* finished proto parsing */
01378                                                 vb->transport.len=tmp-vb->transport.s;
01379                                                 vb->proto=PROTO_OTHER;
01380                                                 state=F_HOST; /* start looking for host*/
01381                                                 goto main_via;
01382                                         case UDP1:
01383                                         case UDP2:
01384                                         case TCP_TLS1:
01385                                         case TCP2:
01386                                         case TLS2:
01387                                         case SCTP1:
01388                                         case SCTP2:
01389                                         case SCTP3:
01390                                                 /* finished proto parsing */
01391                                                 vb->transport.len=tmp-vb->transport.s;
01392                                                 vb->proto=PROTO_OTHER;
01393                                                 state=F_HOST; /* start looking for host*/
01394                                                 goto main_via;
01395                                         case FIN_SIP:
01396                                                 vb->name.len=tmp-vb->name.s;
01397                                                 state=L_VER;
01398                                                 break;
01399                                         case FIN_VER:
01400                                                 vb->version.len=tmp-vb->version.s;
01401                                                 state=L_PROTO;
01402                                                 break;
01403                                         case F_LF:
01404                                         case F_CRLF:
01405                                         case F_CR: /* header continues on this line */
01406                                                 state=saved_state;
01407                                                 break;
01408                                         default:
01409                                                 LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
01410                                                                 " state %d\n", *tmp, state);
01411                                                 goto error;
01412                                 }
01413                                 break;
01414                         case '\n':
01415                                 switch(state){
01416                                         case L_VER:
01417                                         case F_SIP:
01418                                         case F_VER:
01419                                         case F_PROTO:
01420                                         case L_PROTO:
01421                                                 saved_state=state;
01422                                                 state=F_LF;
01423                                                 break;
01424                                         case FIN_UDP:
01425                                                 vb->transport.len=tmp-vb->transport.s;
01426                                                 vb->proto=PROTO_UDP;
01427                                                 state=F_LF;
01428                                                 saved_state=F_HOST; /* start looking for host*/
01429                                                 goto main_via;
01430                                         case FIN_TCP:
01431                                                 vb->transport.len=tmp-vb->transport.s;
01432                                                 vb->proto=PROTO_TCP;
01433                                                 state=F_LF;
01434                                                 saved_state=F_HOST; /* start looking for host*/
01435                                                 goto main_via;
01436                                         case FIN_TLS:
01437                                                 vb->transport.len=tmp-vb->transport.s;
01438                                                 vb->proto=PROTO_TLS;
01439                                                 state=F_LF;
01440                                                 saved_state=F_HOST; /* start looking for host*/
01441                                                 goto main_via;
01442                                         case FIN_SCTP:
01443                                                 /* finished proto parsing */
01444                                                 vb->transport.len=tmp-vb->transport.s;
01445                                                 vb->proto=PROTO_SCTP;
01446                                                 state=F_LF;
01447                                                 saved_state=F_HOST; /* start looking for host*/
01448                                                 goto main_via;
01449                                         case OTHER_PROTO:
01450                                                 /* finished proto parsing */
01451                                                 vb->transport.len=tmp-vb->transport.s;
01452                                                 vb->proto=PROTO_OTHER;
01453                                                 state=F_LF;
01454                                                 saved_state=F_HOST; /* start looking for host*/
01455                                                 goto main_via;
01456                                         case UDP1:
01457                                         case UDP2:
01458                                         case TCP_TLS1:
01459                                         case TCP2:
01460                                         case TLS2:
01461                                         case SCTP1:
01462                                         case SCTP2:
01463                                         case SCTP3:
01464                                                 /* finished proto parsing */
01465                                                 vb->transport.len=tmp-vb->transport.s;
01466                                                 vb->proto=PROTO_OTHER;
01467                                                 state=F_LF;
01468                                                 saved_state=F_HOST; /* start looking for host*/
01469                                                 goto main_via;
01470                                         case FIN_SIP:
01471                                                 vb->name.len=tmp-vb->name.s;
01472                                                 state=F_LF;
01473                                                 saved_state=L_VER;
01474                                                 break;
01475                                         case FIN_VER:
01476                                                 vb->version.len=tmp-vb->version.s;
01477                                                 state=F_LF;
01478                                                 saved_state=L_PROTO;
01479                                                 break;
01480                                         case F_CR:
01481                                                 state=F_CRLF;
01482                                                 break;
01483                                         case F_LF:
01484                                         case F_CRLF:
01485                                                 state=saved_state;
01486                                                 goto endofheader;
01487                                         default:
01488                                                 LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
01489                                                                 " state %d\n", *tmp, state);
01490                                                 goto error;
01491                                 }
01492                                 break;
01493                         case '\r':
01494                                 switch(state){
01495                                         case L_VER:
01496                                         case F_SIP:
01497                                         case F_VER:
01498                                         case F_PROTO:
01499                                         case L_PROTO:
01500                                                 saved_state=state;
01501                                                 state=F_CR;
01502                                                 break;
01503                                         case FIN_UDP:
01504                                                 vb->transport.len=tmp-vb->transport.s;
01505                                                 vb->proto=PROTO_UDP;
01506                                                 state=F_CR;
01507                                                 saved_state=F_HOST;
01508                                                 goto main_via;
01509                                         case FIN_TCP:
01510                                                 vb->transport.len=tmp-vb->transport.s;
01511                                                 vb->proto=PROTO_TCP;
01512                                                 state=F_CR;
01513                                                 saved_state=F_HOST;
01514                                                 goto main_via;
01515                                         case FIN_TLS:
01516                                                 vb->transport.len=tmp-vb->transport.s;
01517                                                 vb->proto=PROTO_TLS;
01518                                                 state=F_CR;
01519                                                 saved_state=F_HOST;
01520                                                 goto main_via;
01521                                         case FIN_SCTP:
01522                                                 vb->transport.len=tmp-vb->transport.s;
01523                                                 vb->proto=PROTO_SCTP;
01524                                                 state=F_CR;
01525                                                 saved_state=F_HOST;
01526                                                 goto main_via;
01527                                         case OTHER_PROTO:
01528                                                 vb->transport.len=tmp-vb->transport.s;
01529                                                 vb->proto=PROTO_OTHER;
01530                                                 state=F_CR;
01531                                                 saved_state=F_HOST;
01532                                                 goto main_via;
01533                                         case UDP1:
01534                                         case UDP2:
01535                                         case TCP_TLS1:
01536                                         case TCP2:
01537                                         case TLS2:
01538                                         case SCTP1:
01539                                         case SCTP2:
01540                                         case SCTP3:
01541                                                 /* finished proto parsing */
01542                                                 vb->transport.len=tmp-vb->transport.s;
01543                                                 vb->proto=PROTO_OTHER;
01544                                                 state=F_CR;
01545                                                 saved_state=F_HOST;
01546                                                 goto main_via;
01547                                         case FIN_SIP:
01548                                                 vb->name.len=tmp-vb->name.s;
01549                                                 state=F_CR;
01550                                                 saved_state=L_VER;
01551                                                 break;
01552                                         case FIN_VER:
01553                                                 vb->version.len=tmp-vb->version.s;
01554                                                 state=F_CR;
01555                                                 saved_state=L_PROTO;
01556                                                 break;
01557                                         case F_LF: /*end of line ?next header?*/
01558                                         case F_CR:
01559                                         case F_CRLF:
01560                                                 state=saved_state;
01561                                                 goto endofheader;
01562                                         default:
01563                                                 LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
01564                                                                 " state %d\n", *tmp, state);
01565                                                 goto error;
01566                                 }
01567                                 break;
01568                         
01569                         case '/':
01570                                 switch(state){
01571                                         case FIN_SIP:
01572                                                 vb->name.len=tmp-vb->name.s;
01573                                                 state=F_VER;
01574                                                 break;
01575                                         case FIN_VER:
01576                                                 vb->version.len=tmp-vb->version.s;
01577                                                 state=F_PROTO;
01578                                                 break;
01579                                         case L_VER:
01580                                                 state=F_VER;
01581                                                 break;
01582                                         case L_PROTO:
01583                                                 state=F_PROTO;
01584                                                 break;
01585                                         default:
01586                                                 LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
01587                                                                 " state %d\n", *tmp, state);
01588                                                 goto error;
01589                                 }
01590                                 break;
01591                                 /* match SIP*/
01592                         case 'S':
01593                         case 's':
01594                                 switch(state){
01595                                         case F_SIP:
01596                                                 state=SIP1;
01597                                                 vb->name.s=tmp;
01598                                                 break;
01599                                         case TLS2:
01600                                                 state=FIN_TLS;
01601                                                 break;
01602                                         case F_PROTO:
01603                                                 state=SCTP1;
01604                                                 vb->transport.s=tmp;
01605                                                 break;
01606                                         case OTHER_PROTO:
01607                                                 break;
01608                                         case UDP1:
01609                                         case UDP2:
01610                                         case FIN_UDP:
01611                                         case TCP_TLS1:
01612                                         case TCP2:
01613                                         case FIN_TCP:
01614                                         case FIN_TLS:
01615                                         case SCTP1:
01616                                         case SCTP2:
01617                                         case SCTP3:
01618                                         case FIN_SCTP:
01619                                                 state=OTHER_PROTO;
01620                                                 break;
01621                                         default:
01622                                                 LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
01623                                                                 " state %d\n", *tmp, state);
01624                                                 goto error;
01625                                 }
01626                                 break;
01627                         case 'I':
01628                         case 'i':
01629                                 switch(state){
01630                                         case SIP1:
01631                                                 state=SIP2;
01632                                                 break;
01633                                         case OTHER_PROTO:
01634                                                 break;
01635                                         case UDP1:
01636                                         case UDP2:
01637                                         case FIN_UDP:
01638                                         case TCP_TLS1:
01639                                         case TCP2:
01640                                         case FIN_TCP:
01641                                         case TLS2:
01642                                         case FIN_TLS:
01643                                         case SCTP1:
01644                                         case SCTP2:
01645                                         case SCTP3:
01646                                         case FIN_SCTP:
01647                                                 state=OTHER_PROTO;
01648                                                 break;
01649                                         default:
01650                                                 LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
01651                                                                 " state %d\n", *tmp, state);
01652                                                 goto error;
01653                                 }
01654                                 break;
01655                         case 'p':
01656                         case 'P':
01657                                 switch(state){
01658                                         case SIP2:
01659                                                 state=FIN_SIP;
01660                                                 break;
01661                                         /* allow p in PROTO */
01662                                         case UDP2:
01663                                                 state=FIN_UDP;
01664                                                 break;
01665                                         case TCP2:
01666                                                 state=FIN_TCP;
01667                                                 break;
01668                                         case SCTP3:
01669                                                 state=FIN_SCTP;
01670                                                 break;
01671                                         case OTHER_PROTO:
01672                                                 break;
01673                                         case UDP1:
01674                                         case FIN_UDP:
01675                                         case TCP_TLS1:
01676                                         case FIN_TCP:
01677                                         case TLS2:
01678                                         case FIN_TLS:
01679                                         case SCTP1:
01680                                         case SCTP2:
01681                                         case FIN_SCTP:
01682                                                 state=OTHER_PROTO;
01683                                                 break;
01684                                         default:
01685                                                 LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
01686                                                                 " state %d\n", *tmp, state);
01687                                                 goto error;
01688                                 }
01689                                 break;
01690                         case 'U':
01691                         case 'u':
01692                                 switch(state){
01693                                         case F_PROTO:
01694                                                 state=UDP1;
01695                                                 vb->transport.s=tmp;
01696                                                 break;
01697                                         case OTHER_PROTO:
01698                                                 break;
01699                                         case UDP1:
01700                                         case UDP2:
01701                                         case FIN_UDP:
01702                                         case TCP_TLS1:
01703                                         case TCP2:
01704                                         case FIN_TCP:
01705                                         case TLS2:
01706                                         case FIN_TLS:
01707                                         case SCTP1:
01708                                         case SCTP2:
01709                                         case SCTP3:
01710                                         case FIN_SCTP:
01711                                                 state=OTHER_PROTO;
01712                                                 break;
01713                                         default:
01714                                                 LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
01715                                                                 " state %d\n", *tmp, state);
01716                                                 goto error;
01717                                 }
01718                                 break;
01719                         case 'D':
01720                         case 'd':
01721                                 switch(state){
01722                                         case UDP1:
01723                                                 state=UDP2;
01724                                                 break;
01725                                         case OTHER_PROTO:
01726                                                 break;
01727                                         case UDP2:
01728                                         case FIN_UDP:
01729                                         case TCP_TLS1:
01730                                         case TCP2:
01731                                         case FIN_TCP:
01732                                         case TLS2:
01733                                         case FIN_TLS:
01734                                         case SCTP1:
01735                                         case SCTP2:
01736                                         case SCTP3:
01737                                         case FIN_SCTP:
01738                                                 state=OTHER_PROTO;
01739                                                 break;
01740                                         default:
01741                                                 LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
01742                                                                 " state %d\n", *tmp, state);
01743                                                 goto error;
01744                                 }
01745                                 break;
01746                         case 'T':
01747                         case 't':
01748                                 switch(state){
01749                                         case F_PROTO:
01750                                                 state=TCP_TLS1;
01751                                                 vb->transport.s=tmp;
01752                                                 break;
01753                                         case SCTP2:
01754                                                 state=SCTP3;
01755                                                 break;
01756                                         case OTHER_PROTO:
01757                                                 break;
01758                                         case UDP1:
01759                                         case UDP2:
01760                                         case FIN_UDP:
01761                                         case TCP_TLS1:
01762                                         case TCP2:
01763                                         case FIN_TCP:
01764                                         case TLS2:
01765                                         case FIN_TLS:
01766                                         case SCTP1:
01767                                         case SCTP3:
01768                                         case FIN_SCTP:
01769                                                 state=OTHER_PROTO;
01770                                                 break;
01771                                         default:
01772                                                 LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
01773                                                                 " state %d\n", *tmp, state);
01774                                                 goto error;
01775                                 }
01776                                 break;
01777                         case 'C':
01778                         case 'c':
01779                                 switch(state){
01780                                         case TCP_TLS1:
01781                                                 state=TCP2;
01782                                                 break;
01783                                         case SCTP1:
01784                                                 state=SCTP2;
01785                                                 break;
01786                                         case OTHER_PROTO:
01787                                                 break;
01788                                         case UDP1:
01789                                         case UDP2:
01790                                         case FIN_UDP:
01791                                         case TCP2:
01792                                         case FIN_TCP:
01793                                         case TLS2:
01794                                         case FIN_TLS:
01795                                         case SCTP2:
01796                                         case SCTP3:
01797                                         case FIN_SCTP:
01798                                                 state=OTHER_PROTO;
01799                                                 break;
01800                                         default:
01801                                                 LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
01802                                                                 " state %d\n", *tmp, state);
01803                                                 goto error;
01804                                 }
01805                                 break;
01806                         case 'L':
01807                         case 'l':
01808                                 switch(state){
01809                                         case TCP_TLS1:
01810                                                 state=TLS2;
01811                                                 break;
01812                                         case OTHER_PROTO:
01813                                                 break;
01814                                         case UDP1:
01815                                         case UDP2:
01816                                         case FIN_UDP:
01817                                         case TCP2:
01818                                         case FIN_TCP:
01819                                         case TLS2:
01820                                         case FIN_TLS:
01821                                         case SCTP1:
01822                                         case SCTP2:
01823                                         case SCTP3:
01824                                         case FIN_SCTP:
01825                                                 state=OTHER_PROTO;
01826                                                 break;
01827                                         default:
01828                                                 LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
01829                                                                 " state %d\n", *tmp, state);
01830                                                 goto error;
01831                                 }
01832                                 break;
01833                         /*match 2.0*/
01834                         case '2':
01835                                 switch(state){
01836                                         case F_VER:
01837                                                 state=VER1;
01838                                                 vb->version.s=tmp;
01839                                                 break;
01840                                         case OTHER_PROTO:
01841                                                 break;
01842                                         case UDP1:
01843                                         case UDP2:
01844                                         case FIN_UDP:
01845                                         case TCP_TLS1:
01846                                         case TCP2:
01847                                         case FIN_TCP:
01848                                         case TLS2:
01849                                         case FIN_TLS:
01850                                         case SCTP1:
01851                                         case SCTP2:
01852                                         case SCTP3:
01853                                         case FIN_SCTP:
01854                                                 state=OTHER_PROTO;
01855                                                 break;
01856                                         default:
01857                                                 LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
01858                                                                 " state %d\n", *tmp, state);
01859                                                 goto error;
01860                                 }
01861                                 break;
01862                         case '.':
01863                                 switch(state){
01864                                         case VER1:
01865                                                 state=VER2;
01866                                                 break;
01867                                         case OTHER_PROTO:
01868                                                 break;
01869                                         case UDP1:
01870                                         case UDP2:
01871                                         case FIN_UDP:
01872                                         case TCP_TLS1:
01873                                         case TCP2:
01874                                         case FIN_TCP:
01875                                         case TLS2:
01876                                         case FIN_TLS:
01877                                         case SCTP1:
01878                                         case SCTP2:
01879                                         case SCTP3:
01880                                         case FIN_SCTP:
01881                                                 state=OTHER_PROTO;
01882                                                 break;
01883                                         default:
01884                                                 LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
01885                                                                 " state %d\n", *tmp, state);
01886                                                 goto error;
01887                                 }
01888                                  break;
01889                         case '0':
01890                                 switch(state){
01891                                         case VER2:
01892                                                 state=FIN_VER;
01893                                                 break;
01894                                         case OTHER_PROTO:
01895                                                 break;
01896                                         case UDP1:
01897                                         case UDP2:
01898                                         case FIN_UDP:
01899                                         case TCP_TLS1:
01900                                         case TCP2:
01901                                         case FIN_TCP:
01902                                         case TLS2:
01903                                         case FIN_TLS:
01904                                         case SCTP1:
01905                                         case SCTP2:
01906                                         case SCTP3:
01907                                         case FIN_SCTP:
01908                                                 state=OTHER_PROTO;
01909                                                 break;
01910                                         default:
01911                                                 LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
01912                                                                 " state %d\n", *tmp, state);
01913                                                 goto error;
01914                                 }
01915                                 break;
01916                         default:
01917                                 switch(state){
01918                                         case F_PROTO:
01919                                                 state=OTHER_PROTO;
01920                                                 vb->transport.s=tmp;
01921                                                 break;
01922                                         case OTHER_PROTO:
01923                                                 break;
01924                                         case UDP1:
01925                                         case UDP2:
01926                                         case FIN_UDP:
01927                                         case TCP_TLS1:
01928                                         case TCP2:
01929                                         case FIN_TCP:
01930                                         case TLS2:
01931                                         case FIN_TLS:
01932                                         case SCTP1:
01933                                         case SCTP2:
01934                                         case SCTP3:
01935                                         case FIN_SCTP:
01936                                                 state=OTHER_PROTO;
01937                                                 break;
01938                                         default:
01939                                                 LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
01940                                                 " state %d\n", *tmp, state);
01941                                                 goto error;
01942                                 }
01943                                 break;
01944                 }
01945         } /* for tmp*/
01946 
01947         /* we should not be here! if everything is ok > main_via*/
01948         LOG(L_ERR, "ERROR: parse_via: bad via: end of packet on state=%d\n",
01949                         state);
01950         goto error;
01951 
01952  main_via:
01953         /* inc tmp to point to the next char*/
01954         tmp++;
01955         c_nest=0;
01956         /*state should always be F_HOST here*/;
01957         for(;*tmp;tmp++){
01958                 switch(*tmp){
01959                 case ' ':
01960                 case '\t':
01961                         switch(state){
01962                                         case F_HOST:/*eat the spaces*/
01963                                                 break;
01964                                         case P_HOST:
01965                                                  /*mark end of host*/
01966                                                  vb->host.len=tmp-vb->host.s;
01967                                                  state=L_PORT;
01968                                                  break;
01969                                         case L_PORT: /*eat the spaces*/
01970                                         case F_PORT:
01971                                                 break;
01972                                         case P_PORT:
01973                                                 /*end of port */
01974                                                 vb->port_str.len=tmp-vb->port_str.s;
01975                                                 state=L_PARAM;
01976                                                 break;
01977                                         case L_PARAM: /* eat the space */
01978                                         case F_PARAM:
01979                                                 break;
01980                                         case P_PARAM:
01981                                         /*      *tmp=0;*/ 
01982                                                 state=L_PARAM;
01983                                                 break;
01984                                         case L_VIA:
01985                                         case F_VIA: /* eat the space */
01986                                                 break;
01987                                         case F_COMMENT:
01988                                         case P_COMMENT:
01989                                                 break;
01990                                         case F_IP6HOST: /*no spaces allowed*/
01991                                         case P_IP6HOST:
01992                                                 LOG(L_ERR, "ERROR:parse_via: bad ipv6 reference\n");
01993                                                 goto error;
01994                                         case F_CRLF:
01995                                         case F_LF:
01996                                         case F_CR:
01997                                                 /*previous=crlf and now =' '*/
01998                                                 state=saved_state;
01999                                                 break;
02000                                         default:
02001                                                 LOG(L_CRIT,"BUG: parse_via"
02002                                                         " on <%c>, state=%d\n",*tmp, state);
02003                                                 goto  error;
02004                                 }
02005                         break;
02006                         case '\n':
02007                                 switch(state){
02008                                         case F_HOST:/*eat the spaces*/
02009                                         case L_PORT: /*eat the spaces*/
02010                                         case F_PORT:
02011                                         case L_PARAM: /* eat the space */
02012                                         case F_PARAM:
02013                                         case F_VIA: /* eat the space */
02014                                         case L_VIA:
02015                                         case F_COMMENT:
02016                                         case P_COMMENT:
02017                                         case F_IP6HOST:
02018                                         case P_IP6HOST:
02019                                                 saved_state=state;
02020                                                 state=F_LF;
02021                                                 break;
02022                                         case P_HOST:
02023                                                  /*mark end of host*/
02024                                                  vb->host.len=tmp-vb->host.s;
02025                                                  saved_state=L_PORT;
02026                                                  state=F_LF;
02027                                                  break;
02028                                         case P_PORT:
02029                                                 /*end of port */
02030                                                 vb->port_str.len=tmp-vb->port_str.s;
02031                                                 saved_state=L_PARAM;
02032                                                 state=F_LF;
02033                                                 break;
02034                                         case P_PARAM:
02035                                         /*      *tmp=0;*/ 
02036                                                 saved_state=L_PARAM;
02037                                                 state=F_LF;
02038                                                 break;
02039                                         case F_CR:
02040                                                 state=F_CRLF;
02041                                                 break;
02042                                         case F_CRLF:
02043                                         case F_LF:
02044                                                 state=saved_state;
02045                                                 goto endofheader;
02046                                         default:
02047                                                 LOG(L_CRIT,"BUG: parse_via"
02048                                                         " on <%c>\n",*tmp);
02049                                                 goto  error;
02050                                 }
02051                         break;
02052                 case '\r':
02053                                 switch(state){
02054                                         case F_HOST:/*eat the spaces*/
02055                                         case L_PORT: /*eat the spaces*/
02056                                         case F_PORT:
02057                                         case L_PARAM: /* eat the space */
02058                                         case F_PARAM:
02059                                         case F_VIA: /* eat the space */
02060                                         case L_VIA:
02061                                         case F_COMMENT:
02062                                         case P_COMMENT:
02063                                         case F_IP6HOST:
02064                                         case P_IP6HOST:
02065                                                 saved_state=state;
02066                                                 state=F_CR;
02067                                                 break;
02068                                         case P_HOST:
02069                                                  /*mark end of host*/
02070                                                  vb->host.len=tmp-vb->host.s;
02071                                                  saved_state=L_PORT;
02072                                                  state=F_CR;
02073                                                  break;
02074                                         case P_PORT:
02075                                                 /*end of port */
02076                                                 vb->port_str.len=tmp-vb->port_str.s;
02077                                                 saved_state=L_PARAM;
02078                                                 state=F_CR;
02079                                                 break;
02080                                         case P_PARAM:
02081                                         /*      *tmp=0;*/ 
02082                                                 saved_state=L_PARAM;
02083                                                 state=F_CR;
02084                                                 break;
02085                                         case F_CRLF:
02086                                         case F_CR:
02087                                         case F_LF:
02088                                                 state=saved_state;
02089                                                 goto endofheader;
02090                                         default:
02091                                                 LOG(L_CRIT,"BUG: parse_via"
02092                                                         " on <%c>\n",*tmp);
02093                                                 goto  error;
02094                                 }
02095                         break;
02096                         
02097                         case ':':
02098                                 switch(state){
02099                                         case F_HOST:
02100                                         case F_IP6HOST:
02101                                                 state=P_IP6HOST;
02102                                                 break;
02103                                         case P_IP6HOST:
02104                                                 break;
02105                                         case P_HOST:
02106                                                 /*mark  end of host*/
02107                                                 vb->host.len=tmp-vb->host.s;
02108                                                 state=F_PORT;
02109                                                 break;
02110                                         case L_PORT:
02111                                                 state=F_PORT;
02112                                                 break;
02113                                         case P_PORT:
02114                                                 LOG(L_ERR, "ERROR:parse_via:"
02115                                                         " bad port\n");
02116                                                 goto error;
02117                                         case L_PARAM:
02118                                         case F_PARAM:
02119                                         case F_PORT:
02120                                         case P_PARAM:
02121                                                 LOG(L_ERR, "ERROR:parse_via:"
02122                                                 " bad char <%c> in state %d\n",
02123                                                         *tmp,state);
02124                                                 goto error;
02125                                         case L_VIA:
02126                                         case F_VIA:
02127                                                 LOG(L_ERR, "ERROR:parse_via:"
02128                                                 " bad char in compact via\n");
02129                                                 goto error;
02130                                         case F_CRLF:
02131                                         case F_LF:
02132                                         case F_CR:
02133                                                 /*previous=crlf and now !=' '*/
02134                                                 goto endofheader;
02135                                         case F_COMMENT:/*everything is allowed in a comment*/
02136                                                 vb->comment.s=tmp;
02137                                                 state=P_COMMENT;
02138                                                 break;
02139                                         case P_COMMENT: /*everything is allowed in a comment*/
02140                                                 break;
02141                                         default:
02142                                                 LOG(L_CRIT,"BUG: parse_via"
02143                                                         " on <%c> state %d\n",
02144                                                         *tmp, state);
02145                                                 goto error;
02146                                 }
02147                                 break;
02148                         case ';':
02149                                 switch(state){
02150                                         case F_HOST:
02151                                         case F_IP6HOST:
02152                                                 LOG(L_ERR,"ERROR:parse_via:"
02153                                                         " no host found\n");
02154                                                 goto error;
02155                                         case P_IP6HOST:
02156                                                 LOG(L_ERR, "ERROR:parse_via: bad ipv6 reference\n");
02157                                                 goto error;
02158                                         case P_HOST:
02159                                                 vb->host.len=tmp-vb->host.s;
02160                                                 state=F_PARAM;
02161                                                 param_start=tmp+1;
02162                                                 break;
02163                                         case P_PORT:
02164                                                 /*mark the end*/
02165                                                 vb->port_str.len=tmp-vb->port_str.s;
02166                                         case L_PORT:
02167                                         case L_PARAM:
02168                                                 state=F_PARAM;
02169                                                 param_start=tmp+1;
02170                                                 break;
02171                                         case F_PORT:
02172                                                 LOG(L_ERR, "ERROR:parse_via:"
02173                                                 " bad char <%c> in state %d\n",
02174                                                         *tmp,state);
02175                                                 goto error;
02176                                         case F_PARAM:
02177                                                 LOG(L_ERR,  "ERROR:parse_via:"
02178                                                         " null param?\n");
02179                                                 goto error;
02180                                         case P_PARAM:
02181                                                 /*hmm next, param?*/
02182                                                 state=F_PARAM;
02183                                                 param_start=tmp+1;
02184                                                 break;
02185                                         case L_VIA:
02186                                         case F_VIA:
02187                                                 LOG(L_ERR, "ERROR:parse_via:"
02188                                                 " bad char <%c> in next via\n",
02189                                                         *tmp);
02190                                                 goto error;
02191                                         case F_CRLF:
02192                                         case F_LF:
02193                                         case F_CR:
02194                                                 /*previous=crlf and now !=' '*/
02195                                                 goto endofheader;
02196                                         case F_COMMENT:/*everything is allowed in a comment*/
02197                                                 vb->comment.s=tmp;
02198                                                 state=P_COMMENT;
02199                                                 break;
02200                                         case P_COMMENT: /*everything is allowed in a comment*/
02201                                                 break;
02202                                         
02203                                         default:
02204                                                 LOG(L_CRIT,"BUG: parse_via"
02205                                                         " on <%c> state %d\n",
02206                                                         *tmp, state);
02207                                                 goto  error;
02208                                 }
02209                         break;
02210                         case ',':
02211                                 switch(state){
02212                                         case F_HOST:
02213                                         case F_IP6HOST:
02214                                                 LOG(L_ERR,"ERROR:parse_via:"
02215                                                         " no host found\n");
02216                                                 goto error;
02217                                         case P_IP6HOST:
02218                                                 LOG(L_ERR, "ERROR:parse_via: bad ipv6 reference\n");
02219                                                 goto error;
02220                                         case P_HOST:
02221                                                 /*mark the end*/
02222                                                 vb->host.len=tmp-vb->host.s;
02223                                                 state=F_VIA;
02224                                                 break;
02225                                         case P_PORT:
02226                                                 /*mark the end*/
02227                                                 vb->port_str.len=tmp-vb->port_str.s;
02228                                                 state=F_VIA;
02229                                                 break;
02230                                         case L_PORT:
02231                                         case L_PARAM:
02232                                         case P_PARAM:
02233                                         case L_VIA:
02234                                                 state=F_VIA;
02235                                                 break;
02236                                         case F_PORT:
02237                                         case F_PARAM:
02238                                                 LOG(L_ERR, "ERROR:parse_via:"
02239                                                 " invalid char <%c> in state"
02240                                                 " %d\n", *tmp,state);
02241                                                 goto error;
02242                                         case F_VIA:
02243                                                 /* do  nothing,  eat ","*/
02244                                                 break;  
02245                                         case F_CRLF:
02246                                         case F_LF:
02247                                         case F_CR:
02248                                                 /*previous=crlf and now !=' '*/
02249                                                 goto endofheader;
02250                                         case F_COMMENT:/*everything is allowed in a comment*/
02251                                                 vb->comment.s=tmp;
02252                                                 state=P_COMMENT;
02253                                                 break;
02254                                         case P_COMMENT: /*everything is allowed in a comment*/
02255                                                 break;
02256                                         default:
02257                                                 LOG(L_CRIT,"BUG: parse_via"
02258                                                         " on <%c> state %d\n",
02259                                                         *tmp, state);
02260                                                 goto  error;
02261                                 }
02262                         break;
02263                         case '(':
02264                                 switch(state){
02265                                         case F_HOST:
02266                                         case F_PORT:
02267                                         case F_PARAM:
02268                                         case F_VIA:
02269                                         case F_IP6HOST:
02270                                         case P_IP6HOST: /*must be terminated in ']'*/
02271                                                 LOG(L_ERR,"ERROR:parse_via"
02272                                                         " on <%c> state %d\n",
02273                                                         *tmp, state);
02274                                                 goto  error;
02275                                         case P_HOST:
02276                                                 /*mark the end*/
02277                                                 vb->host.len=tmp-vb->host.s;
02278                                                 state=F_COMMENT;
02279                                                 c_nest++;
02280                                                 break;
02281                                         case P_PORT:
02282                                                 /*mark the end*/
02283                                                 vb->port_str.len=tmp-vb->port_str.s;
02284                                                 state=F_COMMENT;
02285                                                 c_nest++;
02286                                                 break;
02287                                         case P_PARAM:
02288                                                 /*mark the end*/
02289                                                 vb->params.len=tmp-vb->params.s;
02290                                                 state=F_COMMENT;
02291                                                 c_nest++;
02292                                                 break;
02293                                         case L_PORT:
02294                                         case L_PARAM:
02295                                         case L_VIA:
02296                                                 state=F_COMMENT;
02297                                                 vb->params.len=tmp-vb->params.s;
02298                                                 c_nest++;
02299                                                 break;
02300                                         case P_COMMENT:
02301                                         case F_COMMENT:
02302                                                 c_nest++;
02303                                                 break;
02304                                         case F_CRLF:
02305                                         case F_LF:
02306                                         case F_CR:
02307                                                 /*previous=crlf and now !=' '*/
02308                                                 goto endofheader;
02309                                         default:
02310                                                 LOG(L_CRIT,"BUG: parse_via"
02311                                                         " on <%c> state %d\n",
02312                                                         *tmp, state);
02313                                                 goto  error;
02314                                 }
02315                         break;
02316                         case ')':
02317                                 switch(state){
02318                                         case F_COMMENT:
02319                                         case P_COMMENT:
02320                                                 if (c_nest){
02321                                                         c_nest--;
02322                                                         if(c_nest==0){
02323                                                                 state=L_VIA;
02324                                                                 vb->comment.len=tmp-vb->comment.s;
02325                                                                 break;
02326                                                         }
02327                                                 }else{
02328                                                         LOG(L_ERR,"ERROR:"
02329                                                             "parse_via: "
02330                                                             "missing '(' - "
02331                                                             "nesting = %d\n",
02332                                                             c_nest);
02333                                                          goto error;
02334                                                 }
02335                                                 break;
02336                                         case F_HOST:
02337                                         case F_PORT:
02338                                         case F_PARAM:
02339                                         case F_VIA:
02340                                         case P_HOST:
02341                                         case P_PORT:
02342                                         case P_PARAM:
02343                                         case L_PORT:
02344                                         case L_PARAM:
02345                                         case L_VIA:
02346                                         case F_IP6HOST:
02347                                         case P_IP6HOST:
02348                                                 LOG(L_ERR,"ERROR:parse_via"
02349                                                         " on <%c> state %d\n",
02350                                                         *tmp, state);
02351                                                 goto  error;
02352                                         case F_CRLF:
02353                                         case F_LF:
02354                                         case F_CR:
02355                                                 /*previous=crlf and now !=' '*/
02356                                                 goto endofheader;
02357                                         default:
02358                                                 LOG(L_CRIT,"BUG: parse_via"
02359                                                         " on <%c> state %d\n",
02360                                                         *tmp, state);
02361                                                 goto  error;
02362                                 }
02363                                 break;
02364                         case '[':
02365                                 switch(state){
02366                                         case F_HOST:
02367                                                 vb->host.s=tmp; /* mark start here (include [])*/
02368                                                 state=F_IP6HOST;
02369                                                 break;
02370                                         case F_COMMENT:/*everything is allowed in a comment*/
02371                                                 vb->comment.s=tmp;
02372                                                 state=P_COMMENT;
02373                                                 break;
02374                                         case P_COMMENT:
02375                                                 break;
02376                                         case F_CRLF:
02377                                         case F_LF:
02378                                         case F_CR:
02379                                                 /*previous=crlf and now !=' '*/
02380                                                 goto endofheader;
02381                                         default:
02382                                                 LOG(L_ERR,"ERROR:parse_via"
02383                                                         " on <%c> state %d\n",
02384                                                         *tmp, state);
02385                                                 goto  error;
02386                                 }
02387                                 break;
02388                         case ']':
02389                                 switch(state){
02390                                         case P_IP6HOST:
02391                                                 /*mark the end*/
02392                                                 vb->host.len=(tmp-vb->host.s)+1; /* include "]" */
02393                                                 state=L_PORT;
02394                                                 break;
02395                                         case F_CRLF:
02396                                         case F_LF:
02397                                         case F_CR:
02398                                                 /*previous=crlf and now !=' '*/
02399                                                 goto endofheader;
02400                                         case F_COMMENT:/*everything is allowed in a comment*/
02401                                                 vb->comment.s=tmp;
02402                                                 state=P_COMMENT;
02403                                                 break;
02404                                         case P_COMMENT:
02405                                                 break;
02406                                         default:
02407                                                 LOG(L_ERR,"ERROR:parse_via"
02408                                                         " on <%c> state %d\n",
02409                                                         *tmp, state);
02410                                                 goto  error;
02411                                 }
02412                                 break;
02413                                                 
02414                         default:
02415                                 switch(state){
02416                                         case F_HOST:
02417                                                 state=P_HOST;
02418                                                 vb->host.s=tmp;
02419                                                 break;
02420                                         case P_HOST:
02421                                                 break;
02422                                         case F_PORT:
02423                                                 state=P_PORT;
02424                                                 vb->port_str.s=tmp;
02425                                                 break;
02426                                         case P_PORT:
02427                                                 /*check if number?*/
02428                                                 break;
02429                                         case F_PARAM:
02430                                                 /*state=P_PARAM*/;
02431                                                 if(vb->params.s==0) vb->params.s=param_start;
02432                                                 param=pkg_malloc(sizeof(struct via_param));
02433                                                 if (param==0){
02434                                                         LOG(L_ERR, "ERROR:parse_via: mem. allocation"
02435                                                                         " error\n");
02436                                                         goto error;
02437                                                 }
02438                                                 memset(param,0, sizeof(struct via_param));
02439                                                 param->start=param_start;
02440                                                 tmp=parse_via_param(tmp, end, &state, &saved_state,
02441                                                                                         param, vb);
02442 
02443                                                 switch(state){
02444                                                         case F_PARAM:
02445                                                                 param_start=tmp+1;
02446                                                         case L_PARAM:
02447                                                         case F_LF:
02448                                                         case F_CR:
02449                                                                 break;
02450                                                         case F_VIA:
02451                                                                 vb->params.len=param->start+param->size
02452                                                                                                 -vb->params.s;
02453                                                                 break;
02454                                                         case END_OF_HEADER:
02455                                                                 vb->params.len=param->start+param->size
02456                                                                                                 -vb->params.s;
02457                                                                 break;
02458                                                         case PARAM_ERROR:
02459                                                                 pkg_free(param);
02460                                                                 goto error;
02461                                                         default:
02462                                                                 pkg_free(param);
02463                                                                 LOG(L_ERR, "ERROR: parse_via after"
02464                                                                                 " parse_via_param: invalid"
02465                                                                                 " char <%c> on state %d\n",
02466                                                                                 *tmp, state);
02467                                                                 goto error;
02468                                                 }
02469                                                 /*add param to the list*/
02470                                                 if (vb->last_param)     vb->last_param->next=param;
02471                                                 else                            vb->param_lst=param;
02472                                                 vb->last_param=param;
02473                                                 /* update param. shortcuts */
02474                                                 switch(param->type){
02475                                                         case PARAM_BRANCH:
02476                                                                 vb->branch=param;
02477                                                                 break;
02478                                                         case PARAM_RECEIVED:
02479                                                                 vb->received=param;
02480                                                                 break;
02481                                                         case PARAM_RPORT:
02482                                                                 vb->rport=param;
02483                                                                 break;
02484                                                         case PARAM_I:
02485                                                                 vb->i=param;
02486                                                                 break;
02487                                                         case PARAM_ALIAS:
02488                                                                 vb->alias=param;
02489                                                                 break;
02490 #ifdef USE_COMP
02491                                                         case PARAM_COMP:
02492                                                                 vb->comp=param;
02493                                                                 /*  moved comp value parsing in via_param */
02494                                                                 /*
02495                                                                 if  ((param->value.len==SIGCOMP_NAME_LEN) &&
02496                                                                         (strncasecmp(param->value.s, SIGCOMP_NAME,
02497                                                                                                 SIGCOMP_NAME_LEN)==0)){
02498                                                                         vb->comp_no=COMP_SIGCOMP;
02499                                                                 }else if ((param->value.len==SERGZ_NAME_LEN) &&
02500                                                                                 (strncasecmp(param->value.s,
02501                                                                                                         SERGZ_NAME,
02502                                                                                                         SERGZ_NAME_LEN)==0)){
02503                                                                         vb->comp_no=COMP_SERGZ;
02504                                                                 }else{
02505                                                                         LOG(L_ERR, "ERROR: parse_via: unrecognized"
02506                                                                                 " compression method in comp=%.*s\n",
02507                                                                                 param->value.len, param->value.s);
02508                                                                 }
02509                                                                 */
02510                                                                 break;
02511 #endif
02512                                                 }
02513                                                 
02514                                                 if (state==END_OF_HEADER){
02515                                                         state=saved_state;
02516                                                         goto endofheader;
02517                                                 }
02518                                                 break;
02519                                         case P_PARAM:
02520                                                 break;
02521                                         case F_VIA:
02522                                                 /*vb->next=tmp;*/ /*???*/
02523                                                 goto nextvia;
02524                                         case L_PORT:
02525                                         case L_PARAM:
02526                                         case L_VIA:
02527                                                 LOG(L_ERR,"ERROR:parse_via"
02528                                                         " on <%c> state %d (default)\n",
02529                                                         *tmp, state);
02530                                                 goto  error;
02531                                         case F_COMMENT:
02532                                                 state=P_COMMENT;
02533                                                 vb->comment.s=tmp;
02534                                                 break;
02535                                         case P_COMMENT:
02536                                                 break;
02537                                         case F_IP6HOST:
02538                                                 state=P_IP6HOST;
02539                                                 break;
02540                                         case P_IP6HOST:
02541                                                 break;
02542                                         case F_CRLF:
02543                                         case F_LF:
02544                                         case F_CR:
02545                                                 /*previous=crlf and now !=' '*/
02546                                                 goto endofheader;
02547                                         default:
02548                                                 LOG(L_ERR, "BUG:parse_via:"
02549                                                         " invalid char <%c>"
02550                                                         " in state %d\n",
02551                                                         *tmp, state);
02552                                                 goto error;
02553                                 }
02554 
02555 
02556                 }
02557         }
02558 
02559         DBG("end of packet reached, state=%d\n", state);
02560         goto endofpacket; /*end of packet, probably should be goto error*/
02561         
02562 endofheader:
02563         state=saved_state;
02564         DBG("end of header reached, state=%d\n", state);
02565 endofpacket:
02566         /* check if error*/
02567         switch(state){
02568                 case P_HOST:
02569                 case L_PORT:
02570                 case P_PORT:
02571                 case L_PARAM:
02572                 case P_PARAM:
02573                 case P_VALUE:
02574                 case GEN_PARAM:
02575                 case FIN_HIDDEN:
02576                 case L_VIA:
02577                         break;
02578                 default:
02579                         LOG(L_ERR, "ERROR: parse_via: invalid via - end of header in"
02580                                         " state %d\n", state);
02581                         goto error;
02582         }
02583 
02584 
02585         /*
02586         if (proto) printf("<SIP/2.0/%s>\n", proto);
02587         if (host) printf("host= <%s>\n", host);
02588         if (port_str) printf("port= <%s>\n", port_str);
02589         if (param) printf("params= <%s>\n", param);
02590         if (comment) printf("comment= <%s>\n", comment);
02591         if(next_via) printf("next_via= <%s>\n", next_via);
02592         */
02593         /*DBG("parse_via: rest=<%s>\n", tmp);*/
02594 
02595         vb->error=PARSE_OK;
02596         vb->bsize=tmp-buffer;
02597         if (vb->port_str.s){
02598                 vb->port=str2s(vb->port_str.s, vb->port_str.len, &err);
02599                 if (err){
02600                                         LOG(L_ERR, "ERROR: parse_via: invalid port number <%.*s>\n",
02601                                                 vb->port_str.len, ZSW(vb->port_str.s));
02602                                         goto error;
02603                 }
02604         }
02605         return tmp;
02606 nextvia:
02607         DBG("parse_via: next_via\n");
02608         vb->error=PARSE_OK;
02609         vb->bsize=tmp-buffer;
02610         if (vb->port_str.s){
02611                 vb->port=str2s(vb->port_str.s, vb->port_str.len, &err);
02612                 if (err){
02613                                         LOG(L_ERR, "ERROR: parse_via: invalid port number <%.*s>\n",
02614                                                 vb->port_str.len, ZSW(vb->port_str.s));
02615                                         goto error;
02616                 }
02617         }
02618         vb->next=pkg_malloc(sizeof(struct via_body));
02619         if (vb->next==0){
02620                 LOG(L_ERR, "ERROR: parse_via: out of memory\n");
02621                 goto error;
02622         }
02623         vb=vb->next;
02624         memset(vb, 0, sizeof(struct via_body));
02625         buffer=tmp;
02626         goto parse_again;
02627 
02628 error:
02629         if (end>buffer){
02630                 LOG(L_ERR, "ERROR: parse_via on: <%.*s>\n", (int)(end-buffer), ZSW(buffer));
02631         }
02632         if ((tmp>buffer)&&(tmp<end)){
02633                 LOG(L_ERR, "ERROR: parse_via parse error, parsed so far:<%.*s>\n",
02634                                 (int)(tmp-buffer), ZSW(buffer) );
02635         }else{
02636                 LOG(L_ERR, "ERROR: parse_via: via parse error\n");
02637         }
02638         vb->error=PARSE_ERROR;
02639         vbody->error=PARSE_ERROR; /* make sure the first via body is marked
02640                                                                  as bad also */
02641         return tmp;
02642 }
02643 
02644 
02645 static inline void free_via_param_list(struct via_param* vp)
02646 {
02647         struct via_param* foo;
02648         while(vp){
02649                 foo=vp;
02650                 vp=vp->next;
02651                 pkg_free(foo);
02652         }
02653 }
02654 
02655 
02656 void free_via_list(struct via_body* vb)
02657 {
02658         struct via_body* foo;
02659         while(vb){
02660                 foo=vb;
02661                 vb=vb->next;
02662                 if (foo->param_lst) free_via_param_list(foo->param_lst);
02663                 pkg_free(foo);
02664         }
02665 }
02666 
02667 int parse_via_header( struct sip_msg *msg, int n, struct via_body** q)
02668 {
02669         struct hdr_field *p;
02670         struct via_body *pp = NULL;
02671         int i;
02672         
02673         switch (n) {
02674         case 1:
02675         case 2:
02676                 if (!msg->h_via1 && (parse_headers(msg,HDR_VIA_F,0)==-1 || !msg->h_via1)) {
02677                         DBG("bad msg or missing VIA1 header \n");
02678                         return -1;
02679                 }
02680                 pp = msg->h_via1->parsed;
02681                 if (n==1) break;
02682                 pp = pp->next;
02683                 if (pp) break;
02684                 
02685                 if (!msg->h_via2 && (parse_headers(msg,HDR_VIA2_F,0)==-1 || !msg->h_via2)) {
02686                         DBG("bad msg or missing VIA2 header \n");
02687                         return -1;
02688                 }
02689                 pp = msg->h_via2->parsed;
02690                 break;
02691         default:        
02692                 if (!msg->eoh && (parse_headers(msg,HDR_EOH_F,0)==-1 || !msg->eoh)) {
02693                         ERR("bad msg while parsing to EOH \n");
02694                         return -1;
02695                 }
02696                 p = msg->h_via1;
02697                 i = n;
02698                 while (i && p) {
02699                         if (p->type == HDR_VIA_T) {
02700                                 i--;
02701                                 pp = p->parsed;
02702                                 while (i && (pp->next)) {
02703                                         i--;
02704                                         pp = pp->next;
02705                                 }
02706                         }
02707                         p = p->next;
02708                 }
02709                 if (i > 0) {
02710                         DBG("missing VIA[%d] header\n", n);
02711                         return -1;
02712                 }
02713         }
02714         if (pp) {
02715                 *q = pp;
02716                 return 0;
02717         } else
02718                 return -1;
02719 }
02720