b3addd9ec3fe99b930008b124178453fe268d3e8
[sip-router] / parser / parse_via.c
1 /*
2  * $Id$ 
3  *
4  * via parsing automaton
5  * 
6  *
7  * Copyright (C) 2001-2003 Fhg Fokus
8  *
9  * This file is part of ser, a free SIP server.
10  *
11  * ser is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version
15  *
16  * For a license to use the ser software under conditions
17  * other than those described here, or to purchase support for this
18  * software, please contact iptel.org by e-mail at the following addresses:
19  *    info@iptel.org
20  *
21  * ser is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License 
27  * along with this program; if not, write to the Free Software 
28  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
29  */
30
31
32
33 /* 
34  *  2003-01-21  added rport parsing code, contributed by
35  *               Maxim Sobolev  <sobomax@FreeBSD.org>
36  *  2003-01-23  added extra via param parsing code (i=...), used
37  *               by tcp to identify the sending socket, by andrei
38  *  2003-01-23  fixed rport parsing code to accept rport w/o any value,
39  *               by andrei
40  *  2003-01-27  modified parse_via to set new via_param->start member and
41  *               via->params.s (andrei)
42  */
43
44
45
46 #include <stdlib.h>
47 #include <string.h>
48 #include "../dprint.h"
49 #include "../ut.h"
50 #include "../mem/mem.h"
51 #include "../ip_addr.h"
52 #include "parse_via.h"
53 #include "parse_def.h"
54
55
56
57 /* main via states (uri:port ...) */
58 enum {           
59         F_HOST, P_HOST,
60         L_PORT, F_PORT, P_PORT,
61         L_PARAM, F_PARAM, P_PARAM,
62         L_VIA, F_VIA,
63         F_COMMENT, P_COMMENT,
64         F_IP6HOST, P_IP6HOST,
65         F_CRLF,
66         F_LF,
67         F_CR,
68         END_OF_HEADER
69 };
70
71
72 /* first via part state */
73 enum {
74         F_SIP = 100,
75         SIP1, SIP2, FIN_SIP,
76         L_VER, F_VER,
77         VER1, VER2, FIN_VER,
78         UDP1, UDP2, FIN_UDP,
79         TCP1, TCP2, FIN_TCP,
80         L_PROTO, F_PROTO
81 };
82
83
84 /* param related states
85  * WARNING: keep in sync with parse_via.h, PARAM_HIDDEN, ...
86  */
87 enum {  
88         L_VALUE = 200, F_VALUE, P_VALUE, P_STRING,
89         HIDDEN1, HIDDEN2, HIDDEN3, HIDDEN4, HIDDEN5,
90         TTL1, TTL2,
91         BRANCH1, BRANCH2, BRANCH3, BRANCH4, BRANCH5,
92         MADDR1, MADDR2, MADDR3, MADDR4,
93         RECEIVED1, RECEIVED2, RECEIVED3, RECEIVED4, RECEIVED5, RECEIVED6,
94         RECEIVED7,
95         RPORT1, RPORT2, RPORT3,
96              /* fin states (227-...)*/
97         FIN_HIDDEN = 230, FIN_TTL, FIN_BRANCH, FIN_MADDR, FIN_RECEIVED,
98         FIN_RPORT, FIN_I
99              /*GEN_PARAM,
100                PARAM_ERROR*/ /* declared in msg_parser.h*/
101 };
102
103
104 /* entry state must be F_PARAM, or saved_state=F_PARAM and
105  * state=F_{LF,CR,CRLF}!
106  * output state = L_PARAM or F_PARAM or END_OF_HEADER
107  * (and saved_state= last state); everything else => error 
108  * WARNING: param->start must be filled before, it's used in param->size 
109  * computation.
110  */
111 static /*inline*/ char* parse_via_param(char* p, char* end,
112                                                                                 unsigned char* pstate, 
113                                                                         unsigned char* psaved_state,
114                                                                                 struct via_param* param)
115 {
116         char* tmp;
117         register unsigned char state;
118         unsigned char saved_state;
119
120         state=*pstate;
121         saved_state=*psaved_state;
122         param->type=PARAM_ERROR;
123
124         for (tmp=p;tmp<end;tmp++){
125                 switch(*tmp){
126                         case ' ':
127                         case '\t':
128                                 switch(state){
129                                         case FIN_HIDDEN:
130                                                 *tmp=0;
131                                                 param->type=state;
132                                                 param->name.len=tmp-param->name.s;
133                                                 state=L_PARAM;
134                                                 goto endofparam;
135                                         case FIN_BRANCH:
136                                         case FIN_TTL:
137                                         case FIN_MADDR:
138                                         case FIN_RECEIVED:
139                                         case FIN_RPORT:
140                                         case FIN_I:
141                                                 *tmp=0;
142                                                 param->type=state;
143                                                 param->name.len=tmp-param->name.s;
144                                                 state=L_VALUE;
145                                                 goto find_value;
146                                         case F_PARAM:
147                                                 break;
148                                         case F_LF:
149                                         case F_CR:
150                                         case F_CRLF:
151                                                 state=saved_state;
152                                                 break;
153                                         case GEN_PARAM:
154                                         default:
155                                                 *tmp=0;
156                                                 param->type=GEN_PARAM;
157                                                 param->name.len=tmp-param->name.s;
158                                                 state=L_VALUE;
159                                                 goto find_value;
160                                 }
161                                 break;
162                         /* \n and \r*/
163                         case '\n':
164                                 switch(state){
165                                         case FIN_HIDDEN:
166                                                 *tmp=0;
167                                                 param->type=state;
168                                                 param->name.len=tmp-param->name.s;
169                                                 param->size=tmp-param->start; 
170                                                 saved_state=L_PARAM;
171                                                 state=F_LF;
172                                                 goto endofparam;
173                                         case FIN_BRANCH:
174                                         case FIN_TTL:
175                                         case FIN_MADDR:
176                                         case FIN_RECEIVED:
177                                         case FIN_I:
178                                         case FIN_RPORT:
179                                                 *tmp=0;
180                                                 param->type=state;
181                                                 param->name.len=tmp-param->name.s;
182                                                 param->size=tmp-param->start; 
183                                                 saved_state=L_VALUE;
184                                                 state=F_LF;
185                                                 goto find_value;
186                                         case F_PARAM:
187                                                 saved_state=state;
188                                                 state=F_LF;
189                                                 break;
190                                         case F_LF:
191                                         case F_CRLF:
192                                                 state=END_OF_HEADER;
193                                                 goto end_via;
194                                         case F_CR:
195                                                 state=F_CRLF;
196                                                 break;
197                                         case GEN_PARAM:
198                                         default:
199                                                 *tmp=0;
200                                                 param->type=GEN_PARAM;
201                                                 saved_state=L_VALUE;
202                                                 param->name.len=tmp-param->name.s;
203                                                 param->size=tmp-param->start; 
204                                                 state=F_LF;
205                                                 goto find_value;
206                                 }
207                                 break;
208                         case '\r':
209                                 switch(state){
210                                         case FIN_HIDDEN:
211                                                 *tmp=0;
212                                                 param->type=state;
213                                                 param->name.len=tmp-param->name.s;
214                                                 param->size=tmp-param->start; 
215                                                 saved_state=L_PARAM;
216                                                 state=F_CR;
217                                                 goto endofparam;
218                                         case FIN_BRANCH:
219                                         case FIN_TTL:
220                                         case FIN_MADDR:
221                                         case FIN_RECEIVED:
222                                         case FIN_I:
223                                         case FIN_RPORT:
224                                                 *tmp=0;
225                                                 param->type=state;
226                                                 param->name.len=tmp-param->name.s;
227                                                 param->size=tmp-param->start; 
228                                                 saved_state=L_VALUE;
229                                                 state=F_CR;
230                                                 goto find_value;
231                                         case F_PARAM:
232                                                 saved_state=state;
233                                                 state=F_CR;
234                                                 break;
235                                         case F_CR:
236                                         case F_CRLF:
237                                                 state=END_OF_HEADER;
238                                                 goto end_via;
239                                         case GEN_PARAM:
240                                         default:
241                                                 *tmp=0;
242                                                 param->type=GEN_PARAM;
243                                                 param->name.len=tmp-param->name.s;
244                                                 param->size=tmp-param->start; 
245                                                 saved_state=L_VALUE;
246                                                 state=F_CR;
247                                                 goto find_value;
248                                 }
249                                 break;
250
251                         case '=':
252                                 switch(state){
253                                         case FIN_BRANCH:
254                                         case FIN_TTL:
255                                         case FIN_MADDR:
256                                         case FIN_RECEIVED:
257                                         case FIN_RPORT:
258                                         case FIN_I:
259                                                 *tmp=0;
260                                                 param->type=state;
261                                                 param->name.len=tmp-param->name.s;
262                                                 state=F_VALUE;
263                                                 goto find_value;
264                                         case F_PARAM:
265                                         case FIN_HIDDEN:
266                                                 LOG(L_ERR, "ERROR: parse_via: invalid char <%c> in"
267                                                                 " state %d\n", *tmp, state);
268                                                 goto error;
269                                         case F_CR:
270                                         case F_LF:
271                                         case F_CRLF:
272                                                 state=END_OF_HEADER;
273                                                 goto end_via;
274                                         case GEN_PARAM:
275                                         default:
276                                                 *tmp=0;
277                                                 param->type=GEN_PARAM;
278                                                 param->name.len=tmp-param->name.s;
279                                                 state=F_VALUE;
280                                                 goto find_value;
281                                 }
282                                 break;
283                         case ';':
284                                 switch(state){
285                                         case FIN_HIDDEN:
286                                         case FIN_RPORT: /* rport can appear w/o a value */
287                                                 *tmp=0;
288                                                 param->type=state;
289                                                 param->name.len=tmp-param->name.s;
290                                                 state=F_PARAM;
291                                                 goto endofparam;
292                                         case FIN_BRANCH:
293                                         case FIN_MADDR:
294                                         case FIN_TTL:
295                                         case FIN_RECEIVED:
296                                         case FIN_I:
297                                                 LOG(L_ERR, "ERROR: parse_via: invalid char <%c> in"
298                                                                 " state %d\n", *tmp, state);
299                                                 goto error;
300                                         case F_CR:
301                                         case F_LF:
302                                         case F_CRLF:
303                                                 state=END_OF_HEADER;
304                                                 goto end_via;
305                                         case GEN_PARAM:
306                                         default:
307                                                 *tmp=0;
308                                                 param->type=GEN_PARAM;
309                                                 param->name.len=tmp-param->name.s;
310                                                 state=F_PARAM;
311                                                 goto endofparam;
312                                 }
313                                 break;
314                         case ',':
315                                 switch(state){
316                                         case FIN_HIDDEN:
317                                         case FIN_RPORT:
318                                                 *tmp=0;
319                                                 param->type=state;
320                                                 param->name.len=tmp-param->name.s;
321                                                 state=F_VIA;
322                                                 goto endofvalue;
323                                         case FIN_BRANCH:
324                                         case FIN_MADDR:
325                                         case FIN_TTL:
326                                         case FIN_RECEIVED:
327                                         case FIN_I:
328                                                 LOG(L_ERR, "ERROR: parse_via_param: new via found" 
329                                                                 "(',') when '=' expected (state %d=)\n",
330                                                                 state);
331                                                 goto error; /* or we could ignore this bad param*/
332                                         case F_CR:
333                                         case F_LF:
334                                         case F_CRLF:
335                                                 state=END_OF_HEADER;
336                                                 goto end_via;
337                                         case GEN_PARAM:
338                                         default:
339                                                 *tmp=0;
340                                                 param->type=GEN_PARAM;
341                                                 param->name.len=tmp-param->name.s;
342                                                 state=F_VIA;
343                                                 goto endofvalue;
344                                 }
345                                 break; 
346
347                                 /* param names */
348                         case 'h':
349                         case 'H':
350                                 switch(state){
351                                         case F_PARAM:
352                                                 state=HIDDEN1;
353                                                 param->name.s=tmp;
354                                                 break;
355                                         case BRANCH5:
356                                                 state=FIN_BRANCH;
357                                                 break;
358                                         case GEN_PARAM:
359                                                 break;
360                                         case F_CR:
361                                         case F_LF:
362                                         case F_CRLF:
363                                                 state=END_OF_HEADER;
364                                                 goto end_via;
365                                         default:
366                                                 state=GEN_PARAM;
367                                 }
368                                 break;
369                         case 'i':
370                         case 'I':
371                                 switch(state){
372                                         case F_PARAM:
373                                                 state=FIN_I;
374                                                 param->name.s=tmp;
375                                                 break;
376                                         case HIDDEN1:
377                                                 state=HIDDEN2;
378                                                 break;
379                                         case RECEIVED4:
380                                                 state=RECEIVED5;
381                                                 break;
382                                         case GEN_PARAM:
383                                                 break;
384                                         case F_CR:
385                                         case F_LF:
386                                         case F_CRLF:
387                                                 state=END_OF_HEADER;
388                                                 goto end_via;
389                                         default:
390                                                 state=GEN_PARAM;
391                                 }
392                                 break;
393                         case 'd':
394                         case 'D':
395                                 switch(state){
396                                         case F_PARAM:
397                                                 state=GEN_PARAM;
398                                                 param->name.s=tmp;
399                                                 break;
400                                         case HIDDEN2:
401                                                 state=HIDDEN3;
402                                                 break;
403                                         case HIDDEN3:
404                                                 state=HIDDEN4;
405                                                 break;
406                                         case MADDR2:
407                                                 state=MADDR3;
408                                                 break;
409                                         case MADDR3:
410                                                 state=MADDR4;
411                                                 break;
412                                         case RECEIVED7:
413                                                 state=FIN_RECEIVED;
414                                                 break;
415                                         case GEN_PARAM:
416                                                 break;
417                                         case F_CR:
418                                         case F_LF:
419                                         case F_CRLF:
420                                                 state=END_OF_HEADER;
421                                                 goto end_via;
422                                         default:
423                                                 state=GEN_PARAM;
424                                 }
425                                 break;
426                         case 'e':
427                         case 'E':
428                                 switch(state){
429                                         case F_PARAM:
430                                                 state=GEN_PARAM;
431                                                 param->name.s=tmp;
432                                                 break;
433                                         case HIDDEN4:
434                                                 state=HIDDEN5;
435                                                 break;
436                                         case RECEIVED1:
437                                                 state=RECEIVED2;
438                                                 break;
439                                         case RECEIVED3:
440                                                 state=RECEIVED4;
441                                                 break;
442                                         case RECEIVED6:
443                                                 state=RECEIVED7;
444                                                 break;
445                                         case GEN_PARAM:
446                                                 break;
447                                         case F_CR:
448                                         case F_LF:
449                                         case F_CRLF:
450                                                 state=END_OF_HEADER;
451                                                 goto end_via;
452                                         default:
453                                                 state=GEN_PARAM;
454                                 }
455                                 break;
456                         case 'n':
457                         case 'N':
458                                 switch(state){
459                                         case F_PARAM:
460                                                 state=GEN_PARAM;
461                                                 param->name.s=tmp;
462                                                 break;
463                                         case HIDDEN5:
464                                                 state=FIN_HIDDEN;
465                                                 break;
466                                         case BRANCH3:
467                                                 state=BRANCH4;
468                                                 break;
469                                         case GEN_PARAM:
470                                                 break;
471                                         case F_CR:
472                                         case F_LF:
473                                         case F_CRLF:
474                                                 state=END_OF_HEADER;
475                                                 goto end_via;
476                                         default:
477                                                 state=GEN_PARAM;
478                                 }
479                                 break;
480                         case 't':
481                         case 'T':
482                                 switch(state){
483                                         case F_PARAM:
484                                                 state=TTL1;
485                                                 param->name.s=tmp;
486                                                 break;
487                                         case TTL1:
488                                                 state=TTL2;
489                                                 break;
490                                         case RPORT3:
491                                                 state=FIN_RPORT;
492                                                 break;
493                                         case GEN_PARAM:
494                                                 break;
495                                         case F_CR:
496                                         case F_LF:
497                                         case F_CRLF:
498                                                 state=END_OF_HEADER;
499                                                 goto end_via;
500                                         default:
501                                                 state=GEN_PARAM;
502                                 }
503                                 break;
504                         case 'l':
505                         case 'L':
506                                 switch(state){
507                                         case F_PARAM:
508                                                 state=GEN_PARAM;
509                                                 param->name.s=tmp;
510                                                 break;
511                                         case TTL2:
512                                                 state=FIN_TTL;
513                                                 break;
514                                         case GEN_PARAM:
515                                                 break;
516                                         case F_CR:
517                                         case F_LF:
518                                         case F_CRLF:
519                                                 state=END_OF_HEADER;
520                                                 goto end_via;
521                                         default:
522                                                 state=GEN_PARAM;
523                                 }
524                                 break;
525                         case 'm':
526                         case 'M':
527                                 switch(state){
528                                         case F_PARAM:
529                                                 state=MADDR1;
530                                                 param->name.s=tmp;
531                                                 break;
532                                         case GEN_PARAM:
533                                                 break;
534                                         case F_CR:
535                                         case F_LF:
536                                         case F_CRLF:
537                                                 state=END_OF_HEADER;
538                                                 goto end_via;
539                                         default:
540                                                 state=GEN_PARAM;
541                                 }
542                                 break;
543                         case 'a':
544                         case 'A':
545                                 switch(state){
546                                         case F_PARAM:
547                                                 state=GEN_PARAM;
548                                                 param->name.s=tmp;
549                                                 break;
550                                         case MADDR1:
551                                                 state=MADDR2;
552                                                 break;
553                                         case BRANCH2:
554                                                 state=BRANCH3;
555                                                 break;
556                                         case GEN_PARAM:
557                                                 break;
558                                         case F_CR:
559                                         case F_LF:
560                                         case F_CRLF:
561                                                 state=END_OF_HEADER;
562                                                 goto end_via;
563                                         default:
564                                                 state=GEN_PARAM;
565                                 }
566                                 break;
567                         case 'r':
568                         case 'R':
569                                 switch(state){
570                                         case MADDR4:
571                                                 state=FIN_MADDR;
572                                                 break;
573                                         case F_PARAM:
574                                                 state=RECEIVED1;
575                                                 param->name.s=tmp;
576                                                 break;
577                                         case BRANCH1:
578                                                 state=BRANCH2;
579                                                 break;
580                                         case RPORT2:
581                                                 state=RPORT3;
582                                                 break;
583                                         case GEN_PARAM:
584                                                 break;
585                                         case F_CR:
586                                         case F_LF:
587                                         case F_CRLF:
588                                                 state=END_OF_HEADER;
589                                                 goto end_via;
590                                         default:
591                                                 state=GEN_PARAM;
592                                 }
593                                 break;
594                         case 'c':
595                         case 'C':
596                                 switch(state){
597                                         case F_PARAM:
598                                                 state=GEN_PARAM;
599                                                 param->name.s=tmp;
600                                                 break;
601                                         case RECEIVED2:
602                                                 state=RECEIVED3;
603                                                 break;
604                                         case BRANCH4:
605                                                 state=BRANCH5;
606                                                 break;
607                                         case GEN_PARAM:
608                                                 break;
609                                         case F_CR:
610                                         case F_LF:
611                                         case F_CRLF:
612                                                 state=END_OF_HEADER;
613                                                 goto end_via;
614                                         default:
615                                                 state=GEN_PARAM;
616                                 }
617                                 break;
618                         case 'v':
619                         case 'V':
620                                 switch(state){
621                                         case F_PARAM:
622                                                 state=GEN_PARAM;
623                                                 param->name.s=tmp;
624                                                 break;
625                                         case RECEIVED5:
626                                                 state=RECEIVED6;
627                                                 break;
628                                         case GEN_PARAM:
629                                                 break;
630                                         case F_CR:
631                                         case F_LF:
632                                         case F_CRLF:
633                                                 state=END_OF_HEADER;
634                                                 goto end_via;
635                                         default:
636                                                 state=GEN_PARAM;
637                                 }
638                                 break;
639                         case 'b':
640                         case 'B':
641                                 switch(state){
642                                         case F_PARAM:
643                                                 state=BRANCH1;
644                                                 param->name.s=tmp;
645                                                 break;
646                                         case GEN_PARAM:
647                                                 break;
648                                         case F_CR:
649                                         case F_LF:
650                                         case F_CRLF:
651                                                 state=END_OF_HEADER;
652                                                 goto end_via;
653                                         default:
654                                                 state=GEN_PARAM;
655                                 }
656                                 break;
657                         case 'p':
658                         case 'P':
659                                 switch(state){
660                                         case RECEIVED1:
661                                                 state=RPORT1;
662                                                 break;
663                                         case F_CR:
664                                         case F_LF:
665                                         case F_CRLF:
666                                                 state=END_OF_HEADER;
667                                                 goto end_via;
668                                         default:
669                                                 state=GEN_PARAM;
670                                 }
671                                 break;
672                         case 'o':
673                         case 'O':
674                                 switch(state){
675                                         case RPORT1:
676                                                 state=RPORT2;
677                                                 break;
678                                         case F_CR:
679                                         case F_LF:
680                                         case F_CRLF:
681                                                 state=END_OF_HEADER;
682                                                 goto end_via;
683                                         default:
684                                                 state=GEN_PARAM;
685                                 }
686                                 break;
687                         default:
688                                 switch(state){
689                                         case F_PARAM:
690                                                 state=GEN_PARAM;
691                                                 param->name.s=tmp;
692                                                 break;
693                                         case GEN_PARAM:
694                                                 break;
695                                         case F_CR:
696                                         case F_LF:
697                                         case F_CRLF:
698                                                 state=END_OF_HEADER;
699                                                 goto end_via;
700                                         default:
701                                                 state=GEN_PARAM;
702                                 }
703                 }
704         }/* for tmp*/
705
706         /* end of packet? => error, no cr/lf,',' found!!!*/
707         saved_state=state;
708         state=END_OF_HEADER;
709         goto error;
710         
711  find_value:
712         tmp++;
713         for(;*tmp;tmp++){
714                 switch(*tmp){
715                         case ' ':
716                         case '\t':
717                                 switch(state){
718                                         case L_VALUE:
719                                         case F_VALUE: /*eat space*/
720                                                 break; 
721                                         case P_VALUE:
722                                                 *tmp=0;
723                                                 state=L_PARAM;
724                                                 param->value.len=tmp-param->value.s;
725                                                 goto endofvalue;
726                                         case P_STRING:
727                                                 break;
728                                         case F_CR:
729                                         case F_LF:
730                                         case F_CRLF:
731                                                 state=saved_state;
732                                                 break;
733                                         default:
734                                                 LOG(L_ERR, "ERROR: parse_via: invalid char <%c>"
735                                                                 " in state %d\n", *tmp, state);
736                                                 goto error;
737                                 }
738                                 break;
739                         case '\n':
740                                 switch(state){
741                                         case L_VALUE:
742                                         case F_VALUE: /*eat space*/
743                                         case P_STRING:
744                                                 saved_state=state;
745                                                 param->size=tmp-param->start;
746                                                 state=F_LF;
747                                                 break;
748                                         case P_VALUE:
749                                                 *tmp=0;
750                                                 saved_state=L_PARAM;
751                                                 state=F_LF;
752                                                 param->value.len=tmp-param->value.s;
753                                                 goto endofvalue;
754                                         case F_LF:
755                                         case F_CRLF:
756                                                 state=END_OF_HEADER;
757                                                 goto end_via;
758                                         case F_CR:
759                                                 state=F_CRLF;
760                                                 break;
761                                         default:
762                                                 LOG(L_ERR, "ERROR: parse_via: invalid char <%c>"
763                                                                 " in state %d\n", *tmp, state);
764                                                 goto error;
765                                 }
766                                 break;
767                         case '\r':
768                                 switch(state){
769                                         case L_VALUE:
770                                         case F_VALUE: /*eat space*/
771                                         case P_STRING:
772                                                 saved_state=state;
773                                                 param->size=tmp-param->start;
774                                                 state=F_CR;
775                                                 break;
776                                         case P_VALUE:
777                                                 *tmp=0;
778                                                 param->value.len=tmp-param->value.s;
779                                                 saved_state=L_PARAM;
780                                                 state=F_CR;
781                                                 goto endofvalue;
782                                         case F_LF:
783                                         case F_CR:
784                                         case F_CRLF:
785                                                 state=END_OF_HEADER;
786                                                 goto end_via;
787                                         default:
788                                                 LOG(L_ERR, "ERROR: parse_via: invalid char <%c>"
789                                                                 " in state %d\n", *tmp, state);
790                                                 goto error;
791                                 }
792                                 break;
793
794                         case '=':
795                                 switch(state){
796                                         case L_VALUE:
797                                                 state=F_VALUE;
798                                                 break;
799                                         case P_STRING:
800                                                 break;
801                                         case F_LF:
802                                         case F_CR:
803                                         case F_CRLF:
804                                                 state=END_OF_HEADER;
805                                                 goto end_via;
806                                         default:
807                                                 LOG(L_ERR, "ERROR: parse_via: invalid char <%c>"
808                                                                 " in state %d\n", *tmp, state);
809                                                 goto error;
810                                 }
811                                 break;
812                         case ';':
813                                 switch(state){
814                                         case P_VALUE:
815                                                 *tmp=0;
816                                                 param->value.len=tmp-param->value.s;
817                                                 state=F_PARAM;
818                                                 goto endofvalue;
819                                         case F_VALUE:
820                                                 *tmp=0;
821                                                 param->value.len=0;
822                                                 state=F_PARAM;
823                                                 goto endofvalue;
824                                         case P_STRING:
825                                                 break; /* what to do? */
826                                         case F_LF:
827                                         case F_CR:
828                                         case F_CRLF:
829                                                 state=END_OF_HEADER;
830                                                 goto end_via;
831                                         case L_VALUE:
832                                                 if (param->type==FIN_RPORT){
833                                                         param->value.len=0;
834                                                         param->value.s=0; /* null value */
835                                                         state=F_PARAM;
836                                                         goto endofvalue;
837                                                 };
838                                                 /* no break */
839                                         default:
840                                                 LOG(L_ERR, "ERROR: parse_via: invalid char <%c>"
841                                                                 " in state %d\n", *tmp, state);
842                                                 goto error;
843                                 }
844                                 break;
845                         case ',':
846                                 switch(state){
847                                         case P_VALUE:
848                                                 *tmp=0;
849                                                 param->value.len=tmp-param->value.s;
850                                                 state=F_VIA;
851                                                 goto endofvalue;
852                                         case P_STRING:
853                                         case F_LF:
854                                         case F_CR:
855                                         case F_CRLF:
856                                                 state=END_OF_HEADER;
857                                                 goto end_via;
858                                         case L_VALUE:
859                                                 if (param->type==FIN_RPORT){
860                                                         param->value.len=0;
861                                                         param->value.s=0; /* null value */
862                                                         state=F_VIA;
863                                                         goto endofvalue;
864                                                 };
865                                                 /* no break */
866                                         default:
867                                                 LOG(L_ERR, "ERROR: parse_via: invalid char <%c>"
868                                                                 " in state %d\n", *tmp, state);
869                                                 goto error;
870                                 }
871                                 break; /* what to do? */
872                         case '"':
873                                 switch(state){
874                                         case F_VALUE:
875                                                 state=P_STRING;
876                                                 param->value.s=tmp+1;
877                                                 break;
878                                         case P_STRING:
879                                                 *tmp=0;
880                                                 state=L_PARAM;
881                                                 param->value.len=tmp-param->value.s;
882                                                 goto endofvalue;
883                                         case F_LF:
884                                         case F_CR:
885                                         case F_CRLF:
886                                                 state=END_OF_HEADER;
887                                                 goto end_via;
888                                         default:
889                                                 LOG(L_ERR, "ERROR: parse_via: invalid char <%c>"
890                                                                 " in state %d\n", *tmp, state);
891                                                 goto error;
892                                 }
893                                 break;
894                         default:
895                                 switch(state){
896                                         case F_VALUE:
897                                                 state=P_VALUE;
898                                                 param->value.s=tmp;
899                                                 break;
900                                         case P_VALUE:
901                                         case P_STRING:
902                                                 break;
903                                         case F_LF:
904                                         case F_CR:
905                                         case F_CRLF:
906                                                 state=END_OF_HEADER;
907                                                 goto end_via;
908                                         default:
909                                                 LOG(L_ERR, "ERROR: parse_via: invalid char <%c>"
910                                                                 " in state %d\n", *tmp, state);
911                                                 goto error;
912                                 }
913                 }
914         } /* for2 tmp*/
915
916         /* end of buff and no CR/LF =>error*/
917         saved_state=state;
918         state=END_OF_HEADER;
919         goto error;
920         
921  endofparam:
922  endofvalue:
923         param->size=tmp-param->start;
924 normal_exit:
925         *pstate=state;
926         *psaved_state=saved_state;
927         DBG("Found param type %d, <%s> = <%s>; state=%d\n", param->type,
928                         param->name.s, param->value.s, state);
929         return tmp;
930         
931  end_via:
932              /* if we are here we found an "unexpected" end of via
933               *  (cr/lf). This is valid only if the param type is GEN_PARAM or
934                   *  RPORT (the only ones which can miss the value; HIDDEN is a 
935                   *  special case )*/
936         if ((param->type==GEN_PARAM)||(param->type==PARAM_RPORT)){
937                 saved_state=L_PARAM; /* change the saved_state, we have an unknown
938                                         param. w/o a value */
939                 /* param->size should be computed before */
940                 goto normal_exit;
941         }
942         *pstate=state;
943         *psaved_state=saved_state;
944         DBG("Error on  param type %d, <%s>, state=%d, saved_state=%d\n",
945                 param->type, param->name.s, state, saved_state);
946
947  error:
948         LOG(L_ERR, "error: parse_via_param\n");
949         param->type=PARAM_ERROR;
950         *pstate=PARAM_ERROR;
951         *psaved_state=state;
952         return tmp;
953 }
954
955
956
957 char* parse_via(char* buffer, char* end, struct via_body *vb)
958 {
959         char* tmp;
960         char* param_start;
961         unsigned char state;
962         unsigned char saved_state;
963         int c_nest;
964         int err;
965
966         struct via_param* param;
967
968 parse_again:
969         vb->error=PARSE_ERROR;
970         /* parse start of via ( SIP/2.0/UDP    )*/
971         state=F_SIP;
972         param_start=0;
973         for(tmp=buffer;tmp<end;tmp++){
974                 switch(*tmp){
975                         case ' ':
976                         case'\t':
977                                 switch(state){
978                                         case L_VER: /* eat space */
979                                         case L_PROTO:
980                                         case F_SIP:
981                                         case F_VER:
982                                         case F_PROTO:
983                                                 break;
984                                         case FIN_UDP:
985                                                 *tmp=0;  /* finished proto parsing */
986                                                 vb->transport.len=tmp-vb->transport.s;
987                                                 vb->proto=PROTO_UDP;
988                                                 state=F_HOST; /* start looking for host*/
989                                                 goto main_via;
990                                         case FIN_TCP:
991                                                 *tmp=0;  /* finished proto parsing */
992                                                 vb->transport.len=tmp-vb->transport.s;
993                                                 vb->proto=PROTO_TCP;
994                                                 state=F_HOST; /* start looking for host*/
995                                                 goto main_via;
996                                         case FIN_SIP:
997                                                 *tmp=0;
998                                                 vb->name.len=tmp-vb->name.s;
999                                                 state=L_VER;
1000                                                 break;
1001                                         case FIN_VER:
1002                                                 *tmp=0;
1003                                                 vb->version.len=tmp-vb->version.s;
1004                                                 state=L_PROTO;
1005                                                 break;
1006                                         case F_LF:
1007                                         case F_CRLF:
1008                                         case F_CR: /* header continues on this line */
1009                                                 state=saved_state;
1010                                                 break;
1011                                         default:
1012                                                 LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
1013                                                                 " state %d\n", *tmp, state);
1014                                                 goto error;
1015                                 }
1016                                 break;
1017                         case '\n':
1018                                 switch(state){
1019                                         case L_VER:
1020                                         case F_SIP:
1021                                         case F_VER:
1022                                         case F_PROTO:
1023                                         case L_PROTO:
1024                                                 saved_state=state;
1025                                                 state=F_LF;
1026                                                 break;
1027                                         case FIN_UDP:
1028                                                 *tmp=0;
1029                                                 vb->transport.len=tmp-vb->transport.s;
1030                                                 vb->proto=PROTO_UDP;
1031                                                 state=F_LF;
1032                                                 saved_state=F_HOST; /* start looking for host*/
1033                                                 goto main_via;
1034                                         case FIN_TCP:
1035                                                 *tmp=0;
1036                                                 vb->transport.len=tmp-vb->transport.s;
1037                                                 vb->proto=PROTO_TCP;
1038                                                 state=F_LF;
1039                                                 saved_state=F_HOST; /* start looking for host*/
1040                                                 goto main_via;
1041                                         case FIN_SIP:
1042                                                 *tmp=0;
1043                                                 vb->name.len=tmp-vb->name.s;
1044                                                 state=F_LF;
1045                                                 saved_state=L_VER;
1046                                                 break;
1047                                         case FIN_VER:
1048                                                 *tmp=0;
1049                                                 vb->version.len=tmp-vb->version.s;
1050                                                 state=F_LF;
1051                                                 saved_state=L_PROTO;
1052                                                 break;
1053                                         case F_CR:
1054                                                 state=F_CRLF;
1055                                                 break;
1056                                         case F_LF:
1057                                         case F_CRLF:
1058                                                 state=saved_state;
1059                                                 goto endofheader;
1060                                         default:
1061                                                 LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
1062                                                                 " state %d\n", *tmp, state);
1063                                                 goto error;
1064                                 }
1065                                 break;
1066                         case '\r':
1067                                 switch(state){
1068                                         case L_VER:
1069                                         case F_SIP:
1070                                         case F_VER:
1071                                         case F_PROTO:
1072                                         case L_PROTO:
1073                                                 saved_state=state;
1074                                                 state=F_CR;
1075                                                 break;
1076                                         case FIN_UDP:
1077                                                 *tmp=0;
1078                                                 vb->transport.len=tmp-vb->transport.s;
1079                                                 vb->proto=PROTO_UDP;
1080                                                 state=F_CR;
1081                                                 saved_state=F_HOST;
1082                                                 goto main_via;
1083                                         case FIN_TCP:
1084                                                 *tmp=0;
1085                                                 vb->transport.len=tmp-vb->transport.s;
1086                                                 vb->proto=PROTO_TCP;
1087                                                 state=F_CR;
1088                                                 saved_state=F_HOST;
1089                                                 goto main_via;
1090                                         case FIN_SIP:
1091                                                 *tmp=0;
1092                                                 vb->name.len=tmp-vb->name.s;
1093                                                 state=F_CR;
1094                                                 saved_state=L_VER;
1095                                                 break;
1096                                         case FIN_VER:
1097                                                 *tmp=0;
1098                                                 vb->version.len=tmp-vb->version.s;
1099                                                 state=F_CR;
1100                                                 saved_state=L_PROTO;
1101                                                 break;
1102                                         case F_LF: /*end of line ?next header?*/
1103                                         case F_CR:
1104                                         case F_CRLF:
1105                                                 state=saved_state;
1106                                                 goto endofheader;
1107                                         default:
1108                                                 LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
1109                                                                 " state %d\n", *tmp, state);
1110                                                 goto error;
1111                                 }
1112                                 break;
1113                         
1114                         case '/':
1115                                 switch(state){
1116                                         case FIN_SIP:
1117                                                 *tmp=0;
1118                                                 vb->name.len=tmp-vb->name.s;
1119                                                 state=F_VER;
1120                                                 break;
1121                                         case FIN_VER:
1122                                                 *tmp=0;
1123                                                 vb->version.len=tmp-vb->version.s;
1124                                                 state=F_PROTO;
1125                                                 break;
1126                                         case L_VER:
1127                                                 state=F_VER;
1128                                                 break;
1129                                         case L_PROTO:
1130                                                 state=F_PROTO;
1131                                                 break;
1132                                         default:
1133                                                 LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
1134                                                                 " state %d\n", *tmp, state);
1135                                                 goto error;
1136                                 }
1137                                 break;
1138                                 /* match SIP*/
1139                         case 'S':
1140                         case 's':
1141                                 switch(state){
1142                                         case F_SIP:
1143                                                 state=SIP1;
1144                                                 vb->name.s=tmp;
1145                                                 break;
1146                                         default:
1147                                                 LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
1148                                                                 " state %d\n", *tmp, state);
1149                                                 goto error;
1150                                 }
1151                                 break;
1152                         case 'I':
1153                         case 'i':
1154                                 switch(state){
1155                                         case SIP1:
1156                                                 state=SIP2;
1157                                                 break;
1158                                         default:
1159                                                 LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
1160                                                                 " state %d\n", *tmp, state);
1161                                                 goto error;
1162                                 }
1163                                 break;
1164                         case 'p':
1165                         case 'P':
1166                                 switch(state){
1167                                         case SIP2:
1168                                                 state=FIN_SIP;
1169                                                 break;
1170                                         /* allow p in PROTO */
1171                                         case UDP2:
1172                                                 state=FIN_UDP;
1173                                                 break;
1174                                         case TCP2:
1175                                                 state=FIN_TCP;
1176                                                 break;
1177                                         default:
1178                                                 LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
1179                                                                 " state %d\n", *tmp, state);
1180                                                 goto error;
1181                                 }
1182                                 break;
1183                         case 'U':
1184                         case 'u':
1185                                 switch(state){
1186                                         case F_PROTO:
1187                                                 state=UDP1;
1188                                                 vb->transport.s=tmp;
1189                                                 break;
1190                                         default:
1191                                                 LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
1192                                                                 " state %d\n", *tmp, state);
1193                                                 goto error;
1194                                 }
1195                                 break;
1196                         case 'D':
1197                         case 'd':
1198                                 switch(state){
1199                                         case UDP1:
1200                                                 state=UDP2;
1201                                                 break;
1202                                         default:
1203                                                 LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
1204                                                                 " state %d\n", *tmp, state);
1205                                                 goto error;
1206                                 }
1207                                 break;
1208                         case 'T':
1209                         case 't':
1210                                 switch(state){
1211                                         case F_PROTO:
1212                                                 state=TCP1;
1213                                                 vb->transport.s=tmp;
1214                                                 break;
1215                                         default:
1216                                                 LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
1217                                                                 " state %d\n", *tmp, state);
1218                                                 goto error;
1219                                 }
1220                                 break;
1221                         case 'C':
1222                         case 'c':
1223                                 switch(state){
1224                                         case TCP1:
1225                                                 state=TCP2;
1226                                                 break;
1227                                         default:
1228                                                 LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
1229                                                                 " state %d\n", *tmp, state);
1230                                                 goto error;
1231                                 }
1232                                 break;
1233                         /*match 2.0*/
1234                         case '2':
1235                                 switch(state){
1236                                         case F_VER:
1237                                                 state=VER1;
1238                                                 vb->version.s=tmp;
1239                                                 break;
1240                                         default:
1241                                                 LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
1242                                                                 " state %d\n", *tmp, state);
1243                                                 goto error;
1244                                 }
1245                                 break;
1246                         case '.':
1247                                 switch(state){
1248                                         case VER1:
1249                                                 state=VER2;
1250                                                 break;
1251                                         default:
1252                                                 LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
1253                                                                 " state %d\n", *tmp, state);
1254                                                 goto error;
1255                                 }
1256                                  break;
1257                         case '0':
1258                                 switch(state){
1259                                         case VER2:
1260                                                 state=FIN_VER;
1261                                                 break;
1262                                         default:
1263                                                 LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
1264                                                                 " state %d\n", *tmp, state);
1265                                                 goto error;
1266                                 }
1267                                 break;
1268                         
1269                         default:
1270                                                 LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
1271                                                                 " state %d\n", *tmp, state);
1272                                                 goto error;
1273                                 break;
1274                 }
1275         } /* for tmp*/
1276
1277         /* we should not be here! if everything is ok > main_via*/
1278         LOG(L_ERR, "ERROR: parse_via: bad via: end of packet on state=%d\n",
1279                         state);
1280         goto error;
1281
1282  main_via:
1283         /* inc tmp to point to the next char*/
1284         tmp++;
1285         c_nest=0;
1286         /*state should always be F_HOST here*/;
1287         for(;*tmp;tmp++){
1288                 switch(*tmp){
1289                 case ' ':
1290                 case '\t':
1291                         switch(state){
1292                                         case F_HOST:/*eat the spaces*/
1293                                                 break;
1294                                         case P_HOST:
1295                                                  *tmp=0;/*mark end of host*/
1296                                                  vb->host.len=tmp-vb->host.s;
1297                                                  state=L_PORT;
1298                                                  break;
1299                                         case L_PORT: /*eat the spaces*/
1300                                         case F_PORT:
1301                                                 break;
1302                                         case P_PORT:
1303                                                 *tmp=0; /*end of port */
1304                                                 vb->port_str.len=tmp-vb->port_str.s;
1305                                                 state=L_PARAM;
1306                                                 break;
1307                                         case L_PARAM: /* eat the space */
1308                                         case F_PARAM:
1309                                                 break;
1310                                         case P_PARAM:
1311                                         /*      *tmp=0;*/ /*!?end of param*/
1312                                                 state=L_PARAM;
1313                                                 break;
1314                                         case L_VIA:
1315                                         case F_VIA: /* eat the space */
1316                                                 break;
1317                                         case F_COMMENT:
1318                                         case P_COMMENT:
1319                                                 break;
1320                                         case F_IP6HOST: /*eat the spaces*/
1321                                                 break;
1322                                         case P_IP6HOST:
1323                                                 *tmp=0; /*mark end of host*/
1324                                                 vb->host.len=tmp-vb->host.s;
1325                                                 state=L_PORT; 
1326                                                 break;
1327                                         case F_CRLF:
1328                                         case F_LF:
1329                                         case F_CR:
1330                                                 /*previous=crlf and now =' '*/
1331                                                 state=saved_state;
1332                                                 break;
1333                                         default:
1334                                                 LOG(L_CRIT,"BUG: parse_via"
1335                                                         " on <%c>, state=%d\n",*tmp, state);
1336                                                 goto  error;
1337                                 }
1338                         break;
1339                         case '\n':
1340                                 switch(state){
1341                                         case F_HOST:/*eat the spaces*/
1342                                         case L_PORT: /*eat the spaces*/
1343                                         case F_PORT:
1344                                         case L_PARAM: /* eat the space */
1345                                         case F_PARAM:
1346                                         case F_VIA: /* eat the space */
1347                                         case L_VIA:
1348                                         case F_COMMENT:
1349                                         case P_COMMENT:
1350                                         case F_IP6HOST:
1351                                         case P_IP6HOST:
1352                                                 saved_state=state;
1353                                                 state=F_LF;
1354                                                 break;
1355                                         case P_HOST:
1356                                                  *tmp=0;/*mark end of host*/
1357                                                  vb->host.len=tmp-vb->host.s;
1358                                                  saved_state=L_PORT;
1359                                                  state=F_LF;
1360                                                  break;
1361                                         case P_PORT:
1362                                                 *tmp=0; /*end of port */
1363                                                 vb->port_str.len=tmp-vb->port_str.s;
1364                                                 saved_state=L_PARAM;
1365                                                 state=F_LF;
1366                                                 break;
1367                                         case P_PARAM:
1368                                         /*      *tmp=0;*/ /*!?end of param*/
1369                                                 saved_state=L_PARAM;
1370                                                 state=F_LF;
1371                                                 break;
1372                                         case F_CR:
1373                                                 state=F_CRLF;
1374                                                 break;
1375                                         case F_CRLF:
1376                                         case F_LF:
1377                                                 state=saved_state;
1378                                                 goto endofheader;
1379                                         default:
1380                                                 LOG(L_CRIT,"BUG: parse_via"
1381                                                         " on <%c>\n",*tmp);
1382                                                 goto  error;
1383                                 }
1384                         break;
1385                 case '\r':
1386                                 switch(state){
1387                                         case F_HOST:/*eat the spaces*/
1388                                         case L_PORT: /*eat the spaces*/
1389                                         case F_PORT:
1390                                         case L_PARAM: /* eat the space */
1391                                         case F_PARAM:
1392                                         case F_VIA: /* eat the space */
1393                                         case L_VIA:
1394                                         case F_COMMENT:
1395                                         case P_COMMENT:
1396                                         case F_IP6HOST:
1397                                         case P_IP6HOST:
1398                                                 saved_state=state;
1399                                                 state=F_CR;
1400                                                 break;
1401                                         case P_HOST:
1402                                                  *tmp=0;/*mark end of host*/
1403                                                  vb->host.len=tmp-vb->host.s;
1404                                                  saved_state=L_PORT;
1405                                                  state=F_CR;
1406                                                  break;
1407                                         case P_PORT:
1408                                                 *tmp=0; /*end of port */
1409                                                 vb->port_str.len=tmp-vb->port_str.s;
1410                                                 saved_state=L_PARAM;
1411                                                 state=F_CR;
1412                                                 break;
1413                                         case P_PARAM:
1414                                         /*      *tmp=0;*/ /*!?end of param*/
1415                                                 saved_state=L_PARAM;
1416                                                 state=F_CR;
1417                                                 break;
1418                                         case F_CRLF:
1419                                         case F_CR:
1420                                         case F_LF:
1421                                                 state=saved_state;
1422                                                 goto endofheader;
1423                                         default:
1424                                                 LOG(L_CRIT,"BUG: parse_via"
1425                                                         " on <%c>\n",*tmp);
1426                                                 goto  error;
1427                                 }
1428                         break;
1429                         
1430                         case ':':
1431                                 switch(state){
1432                                         case F_HOST:
1433                                         case F_IP6HOST:
1434                                                 LOG(L_ERR,"ERROR:parse_via:"
1435                                                         " no host found\n");
1436                                                 goto error;
1437                                         case P_IP6HOST:
1438                                                 break;
1439                                         case P_HOST:
1440                                                 *tmp=0; /*mark  end of host*/
1441                                                 vb->host.len=tmp-vb->host.s;
1442                                                 state=F_PORT;
1443                                                 break;
1444                                         case L_PORT:
1445                                                 state=F_PORT;
1446                                                 break;
1447                                         case P_PORT:
1448                                                 LOG(L_ERR, "ERROR:parse_via:"
1449                                                         " bad port\n");
1450                                                 goto error;
1451                                         case L_PARAM:
1452                                         case F_PARAM:
1453                                         case P_PARAM:
1454                                                 LOG(L_ERR, "ERROR:parse_via:"
1455                                                 " bad char <%c> in state %d\n",
1456                                                         *tmp,state);
1457                                                 goto error;
1458                                         case L_VIA:
1459                                         case F_VIA:
1460                                                 LOG(L_ERR, "ERROR:parse_via:"
1461                                                 " bad char in compact via\n");
1462                                                 goto error;
1463                                         case F_CRLF:
1464                                         case F_LF:
1465                                         case F_CR:
1466                                                 /*previous=crlf and now !=' '*/
1467                                                 goto endofheader;
1468                                         case F_COMMENT:/*everything is allowed in a comment*/
1469                                                 vb->comment.s=tmp;
1470                                                 state=P_COMMENT;
1471                                                 break;
1472                                         case P_COMMENT: /*everything is allowed in a comment*/
1473                                                 break;
1474                                         default:
1475                                                 LOG(L_CRIT,"BUG: parse_via"
1476                                                         " on <%c> state %d\n",
1477                                                         *tmp, state);
1478                                                 goto error;
1479                                 }
1480                                 break;
1481                         case ';':
1482                                 switch(state){
1483                                         case F_HOST:
1484                                         case F_IP6HOST:
1485                                                 LOG(L_ERR,"ERROR:parse_via:"
1486                                                         " no host found\n");
1487                                                 goto error;
1488                                         case P_IP6HOST:
1489                                                 LOG(L_ERR, "ERROR:parse_via: bad ipv6 reference\n");
1490                                                 goto error;
1491                                         case P_HOST:
1492                                                 *tmp=0;
1493                                                 vb->host.len=tmp-vb->host.s;
1494                                                 state=F_PARAM;
1495                                                 param_start=tmp+1;
1496                                                 break;
1497                                         case P_PORT:
1498                                                 *tmp=0; /*mark the end*/
1499                                                 vb->port_str.len=tmp-vb->port_str.s;
1500                                         case L_PORT:
1501                                         case L_PARAM:
1502                                                 state=F_PARAM;
1503                                                 param_start=tmp+1;
1504                                                 break;
1505                                         case F_PORT:
1506                                                 LOG(L_ERR, "ERROR:parse_via:"
1507                                                 " bad char <%c> in state %d\n",
1508                                                         *tmp,state);
1509                                                 goto error;
1510                                         case F_PARAM:
1511                                                 LOG(L_ERR,  "ERROR:parse_via:"
1512                                                         " null param?\n");
1513                                                 goto error;
1514                                         case P_PARAM:
1515                                                 /*hmm next, param?*/
1516                                                 state=F_PARAM;
1517                                                 param_start=tmp+1;
1518                                                 break;
1519                                         case L_VIA:
1520                                         case F_VIA:
1521                                                 LOG(L_ERR, "ERROR:parse_via:"
1522                                                 " bad char <%c> in next via\n",
1523                                                         *tmp);
1524                                                 goto error;
1525                                         case F_CRLF:
1526                                         case F_LF:
1527                                         case F_CR:
1528                                                 /*previous=crlf and now !=' '*/
1529                                                 goto endofheader;
1530                                         case F_COMMENT:/*everything is allowed in a comment*/
1531                                                 vb->comment.s=tmp;
1532                                                 state=P_COMMENT;
1533                                                 break;
1534                                         case P_COMMENT: /*everything is allowed in a comment*/
1535                                                 break;
1536                                         
1537                                         default:
1538                                                 LOG(L_CRIT,"BUG: parse_via"
1539                                                         " on <%c> state %d\n",
1540                                                         *tmp, state);
1541                                                 goto  error;
1542                                 }
1543                         break;
1544                         case ',':
1545                                 switch(state){
1546                                         case F_HOST:
1547                                         case F_IP6HOST:
1548                                                 LOG(L_ERR,"ERROR:parse_via:"
1549                                                         " no host found\n");
1550                                                 goto error;
1551                                         case P_IP6HOST:
1552                                                 LOG(L_ERR, "ERROR:parse_via: bad ipv6 reference\n");
1553                                                 goto error;
1554                                         case P_HOST:
1555                                                 *tmp=0; /*mark the end*/
1556                                                 vb->host.len=tmp-vb->host.s;
1557                                                 state=F_VIA;
1558                                                 break;
1559                                         case P_PORT:
1560                                                 *tmp=0; /*mark the end*/
1561                                                 vb->port_str.len=tmp-vb->port_str.s;
1562                                                 state=F_VIA;
1563                                                 break;
1564                                         case L_PORT:
1565                                         case L_PARAM:
1566                                         case P_PARAM:
1567                                         case L_VIA:
1568                                                 state=F_VIA;
1569                                                 break;
1570                                         case F_PORT:
1571                                         case F_PARAM:
1572                                                 LOG(L_ERR, "ERROR:parse_via:"
1573                                                 " invalid char <%c> in state"
1574                                                 " %d\n", *tmp,state);
1575                                                 goto error;
1576                                         case F_VIA:
1577                                                 /* do  nothing,  eat ","*/
1578                                                 break;  
1579                                         case F_CRLF:
1580                                         case F_LF:
1581                                         case F_CR:
1582                                                 /*previous=crlf and now !=' '*/
1583                                                 goto endofheader;
1584                                         case F_COMMENT:/*everything is allowed in a comment*/
1585                                                 vb->comment.s=tmp;
1586                                                 state=P_COMMENT;
1587                                                 break;
1588                                         case P_COMMENT: /*everything is allowed in a comment*/
1589                                                 break;
1590                                         default:
1591                                                 LOG(L_CRIT,"BUG: parse_via"
1592                                                         " on <%c> state %d\n",
1593                                                         *tmp, state);
1594                                                 goto  error;
1595                                 }
1596                         break;
1597                         case '(':
1598                                 switch(state){
1599                                         case F_HOST:
1600                                         case F_PORT:
1601                                         case F_PARAM:
1602                                         case F_VIA:
1603                                         case F_IP6HOST:
1604                                         case P_IP6HOST: /*must be terminated in ']'*/
1605                                                 LOG(L_ERR,"ERROR:parse_via"
1606                                                         " on <%c> state %d\n",
1607                                                         *tmp, state);
1608                                                 goto  error;
1609                                         case P_HOST:
1610                                                 *tmp=0; /*mark the end*/
1611                                                 vb->host.len=tmp-vb->host.s;
1612                                                 state=F_COMMENT;
1613                                                 c_nest++;
1614                                                 break;
1615                                         case P_PORT:
1616                                                 *tmp=0; /*mark the end*/
1617                                                 vb->port_str.len=tmp-vb->port_str.s;
1618                                                 state=F_COMMENT;
1619                                                 c_nest++;
1620                                                 break;
1621                                         case P_PARAM:
1622                                                 *tmp=0; /*mark the end*/
1623                                                 vb->params.len=tmp-vb->params.s;
1624                                                 state=F_COMMENT;
1625                                                 c_nest++;
1626                                                 break;
1627                                         case L_PORT:
1628                                         case L_PARAM:
1629                                         case L_VIA:
1630                                                 state=F_COMMENT;
1631                                                 vb->params.len=tmp-vb->params.s;
1632                                                 c_nest++;
1633                                                 *tmp=0;
1634                                                 break;
1635                                         case P_COMMENT:
1636                                         case F_COMMENT:
1637                                                 c_nest++;
1638                                                 break;
1639                                         case F_CRLF:
1640                                         case F_LF:
1641                                         case F_CR:
1642                                                 /*previous=crlf and now !=' '*/
1643                                                 goto endofheader;
1644                                         default:
1645                                                 LOG(L_CRIT,"BUG: parse_via"
1646                                                         " on <%c> state %d\n",
1647                                                         *tmp, state);
1648                                                 goto  error;
1649                                 }
1650                         break;
1651                         case ')':
1652                                 switch(state){
1653                                         case F_COMMENT:
1654                                         case P_COMMENT:
1655                                                 if (c_nest){
1656                                                         c_nest--;
1657                                                         if(c_nest==0){
1658                                                                 state=L_VIA;
1659                                                                 *tmp=0;
1660                                                                 vb->comment.len=tmp-vb->comment.s;
1661                                                                 break;
1662                                                         }
1663                                                 }else{
1664                                                         LOG(L_ERR,"ERROR:"
1665                                                             "parse_via: "
1666                                                             "missing '(' - "
1667                                                             "nesting = %d\n",
1668                                                             c_nest);
1669                                                          goto error;
1670                                                 }
1671                                                 break;
1672                                         case F_HOST:
1673                                         case F_PORT:
1674                                         case F_PARAM:
1675                                         case F_VIA:
1676                                         case P_HOST:
1677                                         case P_PORT:
1678                                         case P_PARAM:
1679                                         case L_PORT:
1680                                         case L_PARAM:
1681                                         case L_VIA:
1682                                         case F_IP6HOST:
1683                                         case P_IP6HOST:
1684                                                 LOG(L_ERR,"ERROR:parse_via"
1685                                                         " on <%c> state %d\n",
1686                                                         *tmp, state);
1687                                                 goto  error;
1688                                         case F_CRLF:
1689                                         case F_LF:
1690                                         case F_CR:
1691                                                 /*previous=crlf and now !=' '*/
1692                                                 goto endofheader;
1693                                         default:
1694                                                 LOG(L_CRIT,"BUG: parse_via"
1695                                                         " on <%c> state %d\n",
1696                                                         *tmp, state);
1697                                                 goto  error;
1698                                 }
1699                                 break;
1700                         case '[':
1701                                 switch(state){
1702                                         case F_HOST:
1703                                                 state=F_IP6HOST;
1704                                                 break;
1705                                         case F_COMMENT:/*everything is allowed in a comment*/
1706                                                 vb->comment.s=tmp;
1707                                                 state=P_COMMENT;
1708                                                 break;
1709                                         case P_COMMENT:
1710                                                 break;
1711                                         case F_CRLF:
1712                                         case F_LF:
1713                                         case F_CR:
1714                                                 /*previous=crlf and now !=' '*/
1715                                                 goto endofheader;
1716                                         default:
1717                                                 LOG(L_ERR,"ERROR:parse_via"
1718                                                         " on <%c> state %d\n",
1719                                                         *tmp, state);
1720                                                 goto  error;
1721                                 }
1722                                 break;
1723                         case ']':
1724                                 switch(state){
1725                                         case P_IP6HOST:
1726                                                 *tmp=0; /*mark the end*/
1727                                                 vb->host.len=tmp-vb->host.s;
1728                                                 state=L_PORT;
1729                                                 break;
1730                                         case F_CRLF:
1731                                         case F_LF:
1732                                         case F_CR:
1733                                                 /*previous=crlf and now !=' '*/
1734                                                 goto endofheader;
1735                                         case F_COMMENT:/*everything is allowed in a comment*/
1736                                                 vb->comment.s=tmp;
1737                                                 state=P_COMMENT;
1738                                                 break;
1739                                         case P_COMMENT:
1740                                                 break;
1741                                         default:
1742                                                 LOG(L_ERR,"ERROR:parse_via"
1743                                                         " on <%c> state %d\n",
1744                                                         *tmp, state);
1745                                                 goto  error;
1746                                 }
1747                                 break;
1748                                                 
1749                         default:
1750                                 switch(state){
1751                                         case F_HOST:
1752                                                 state=P_HOST;
1753                                                 vb->host.s=tmp;
1754                                                 break;
1755                                         case P_HOST:
1756                                                 break;
1757                                         case F_PORT:
1758                                                 state=P_PORT;
1759                                                 vb->port_str.s=tmp;
1760                                                 break;
1761                                         case P_PORT:
1762                                                 /*check if number?*/
1763                                                 break;
1764                                         case F_PARAM:
1765                                                 /*state=P_PARAM*/;
1766                                                 if(vb->params.s==0) vb->params.s=param_start;
1767                                                 param=pkg_malloc(sizeof(struct via_param));
1768                                                 if (param==0){
1769                                                         LOG(L_ERR, "ERROR:parse_via: mem. allocation"
1770                                                                         " error\n");
1771                                                         goto error;
1772                                                 }
1773                                                 memset(param,0, sizeof(struct via_param));
1774                                                 param->start=param_start;
1775                                                 tmp=parse_via_param(tmp, end, &state, &saved_state,
1776                                                                                         param);
1777
1778                                                 switch(state){
1779                                                         case F_PARAM:
1780                                                                 param_start=tmp+1;
1781                                                         case L_PARAM:
1782                                                         case F_LF:
1783                                                         case F_CR:
1784                                                                 break;
1785                                                         case F_VIA:
1786                                                                 vb->params.len=param->start+param->size
1787                                                                                                 -vb->params.s;
1788                                                                 *tmp=0;
1789                                                                 break;
1790                                                         case END_OF_HEADER:
1791                                                                 vb->params.len=param->start+param->size
1792                                                                                                 -vb->params.s;
1793                                                                 break;
1794                                                         case PARAM_ERROR:
1795                                                                 pkg_free(param);
1796                                                                 goto error;
1797                                                         default:
1798                                                                 LOG(L_ERR, "ERROR: parse_via after"
1799                                                                                 " parse_via_param: invalid"
1800                                                                                 " char <%c> on state %d\n",
1801                                                                                 *tmp, state);
1802                                                                 goto error;
1803                                                 }
1804                                                 /*add param to the list*/
1805                                                 if (vb->last_param)     vb->last_param->next=param;
1806                                                 else                            vb->param_lst=param;
1807                                                 vb->last_param=param;
1808                                                 if (param->type==PARAM_BRANCH)
1809                                                         vb->branch=param;
1810                                                 else if (param->type==PARAM_RECEIVED)
1811                                                         vb->received=param;
1812                                                 else if (param->type==PARAM_RPORT)
1813                                                         vb->rport=param;
1814                                                 else if (param->type==PARAM_I)
1815                                                         vb->i=param;
1816                                                 
1817                                                 if (state==END_OF_HEADER){
1818                                                         state=saved_state;
1819                                                         goto endofheader;
1820                                                 }
1821                                                 break;
1822                                         case P_PARAM:
1823                                                 break;
1824                                         case F_VIA:
1825                                                 /*vb->next=tmp;*/ /*???*/
1826                                                 goto nextvia;
1827                                         case L_PORT:
1828                                         case L_PARAM:
1829                                         case L_VIA:
1830                                                 LOG(L_ERR,"ERROR:parse_via"
1831                                                         " on <%c> state %d (default)\n",
1832                                                         *tmp, state);
1833                                                 goto  error;
1834                                         case F_COMMENT:
1835                                                 state=P_COMMENT;
1836                                                 vb->comment.s=tmp;
1837                                                 break;
1838                                         case P_COMMENT:
1839                                                 break;
1840                                         case F_IP6HOST:
1841                                                 state=P_IP6HOST;
1842                                                 vb->host.s=tmp;
1843                                                 break;
1844                                         case P_IP6HOST:
1845                                                 break;
1846                                         case F_CRLF:
1847                                         case F_LF:
1848                                         case F_CR:
1849                                                 /*previous=crlf and now !=' '*/
1850                                                 goto endofheader;
1851                                         default:
1852                                                 LOG(L_ERR, "BUG:parse_via:"
1853                                                         " invalid char <%c>"
1854                                                         " in state %d\n",
1855                                                         *tmp, state);
1856                                                 goto error;
1857                                 }
1858
1859
1860                 }
1861         }
1862
1863         DBG("end of packet reached, state=%d\n", state);
1864         goto endofpacket; /*end of packet, probably should be goto error*/
1865         
1866 endofheader:
1867         state=saved_state;
1868         DBG("end of header reached, state=%d\n", state);
1869 endofpacket:
1870         /* check if error*/
1871         switch(state){
1872                 case P_HOST:
1873                 case L_PORT:
1874                 case P_PORT:
1875                 case L_PARAM:
1876                 case P_PARAM:
1877                 case P_VALUE:
1878                 case GEN_PARAM:
1879                 case FIN_HIDDEN:
1880                 case L_VIA:
1881                         break;
1882                 default:
1883                         LOG(L_ERR, "ERROR: parse_via: invalid via - end of header in"
1884                                         " state %d\n", state);
1885                         goto error;
1886         }
1887
1888
1889         /*
1890         if (proto) printf("<SIP/2.0/%s>\n", proto);
1891         if (host) printf("host= <%s>\n", host);
1892         if (port_str) printf("port= <%s>\n", port_str);
1893         if (param) printf("params= <%s>\n", param);
1894         if (comment) printf("comment= <%s>\n", comment);
1895         if(next_via) printf("next_via= <%s>\n", next_via);
1896         */
1897         /*DBG("parse_via: rest=<%s>\n", tmp);*/
1898
1899         vb->error=PARSE_OK;
1900         vb->bsize=tmp-buffer;
1901         if (vb->port_str.s){
1902                 vb->port=str2s((unsigned char*)vb->port_str.s, vb->port_str.len, &err);
1903                 if (err){
1904                                         LOG(L_ERR, "ERROR: parse_via: invalid port number <%s>\n",
1905                                                 vb->port_str.s);
1906                                         goto error;
1907                 }
1908         }
1909         return tmp;
1910 nextvia:
1911         DBG("parse_via: next_via\n");
1912         vb->error=PARSE_OK;
1913         vb->bsize=tmp-buffer;
1914         if (vb->port_str.s){
1915                 vb->port=str2s((unsigned char*)vb->port_str.s, vb->port_str.len, &err);
1916                 if (err){
1917                                         LOG(L_ERR, "ERROR: parse_via: invalid port number <%s>\n",
1918                                                 vb->port_str.s);
1919                                         goto error;
1920                 }
1921         }
1922         vb->next=pkg_malloc(sizeof(struct via_body));
1923         if (vb->next==0){
1924                 LOG(L_ERR, "ERROR: parse_via: out of memory\n");
1925                 goto error;
1926         }
1927         vb=vb->next;
1928         memset(vb, 0, sizeof(struct via_body));
1929         buffer=tmp;
1930         goto parse_again;
1931
1932 error:
1933         if (end>buffer){
1934                 LOG(L_ERR, "ERROR: parse_via on: <%.*s>\n", (int)(end-buffer), buffer);
1935         }
1936         if ((tmp>buffer)&&(tmp<end)){
1937                 LOG(L_ERR, "ERROR: parse_via parse error, parsed so far:<%.*s>\n",
1938                                 (int)(tmp-buffer), buffer );
1939         }else{
1940                 LOG(L_ERR, "ERROR: parse_via: via parse error\n");
1941         }
1942         vb->error=PARSE_ERROR;
1943         return tmp;
1944 }
1945
1946
1947 static inline void free_via_param_list(struct via_param* vp)
1948 {
1949         struct via_param* foo;
1950         while(vp){
1951                 foo=vp;
1952                 vp=vp->next;
1953                 pkg_free(foo);
1954         }
1955 }
1956
1957
1958 void free_via_list(struct via_body* vb)
1959 {
1960         struct via_body* foo;
1961         while(vb){
1962                 foo=vb;
1963                 vb=vb->next;
1964                 if (foo->param_lst) free_via_param_list(foo->param_lst);
1965                 pkg_free(foo);
1966         }
1967 }