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