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