OSDN Git Service

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