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