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