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