Coverage Report

Created: 2025-07-11 06:28

/src/opensips/parser/parse_fline.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * sip first line parsing automaton
3
 *
4
 * Copyright (C) 2001-2003 FhG Fokus
5
 *
6
 * This file is part of opensips, a free SIP server.
7
 *
8
 * opensips is free software; you can redistribute it and/or modify
9
 * it under the terms of the GNU General Public License as published by
10
 * the Free Software Foundation; either version 2 of the License, or
11
 * (at your option) any later version
12
 *
13
 * opensips is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
21
 *
22
 * History:
23
 * ---------
24
 * 2003-02-28 scratchpad compatibility abandoned (jiri)
25
 * 2003-01-28: removed 0-terminators from first line (jiri)
26
 * 2003-04-26 ZSW (jiri)
27
 */
28
29
30
#include "../dprint.h"
31
#include "msg_parser.h"
32
#include "parser_f.h"
33
#include "parse_methods.h"
34
#include "../mem/mem.h"
35
#include "../ut.h"
36
37
/* grammar:
38
  request  =  method SP uri SP version CRLF
39
  response =  version SP status  SP reason  CRLF
40
  (version = "SIP/2.0")
41
*/
42
43
/*known methods: INVITE, ACK, CANCEL, BYE*/
44
45
enum { START,
46
       INVITE1, INVITE2, INVITE3, INVITE4, INVITE5,
47
       ACK1, ACK2,
48
       CANCEL1, CANCEL2, CANCEL3, CANCEL4, CANCEL5,
49
       BYE1, BYE2,
50
       SIP1, SIP2, SIP3, SIP4, SIP5, SIP6,
51
       FIN_INVITE = 100, FIN_ACK, FIN_CANCEL, FIN_BYE, FIN_SIP,
52
       P_METHOD = 200, L_URI, P_URI, L_VER,
53
       VER1, VER2, VER3, VER4, VER5, VER6, FIN_VER,
54
       L_STATUS, P_STATUS, L_REASON, P_REASON,
55
       L_LF, F_CR, F_LF
56
};
57
58
59
#ifdef _CURRENTLY_UNUSED
60
char* parse_fline(char* buffer, char* end, struct msg_start* fl)
61
{
62
  char* tmp;
63
  register int state;
64
  unsigned short stat;
65
66
  stat=0;
67
  fl->type=SIP_REQUEST;
68
  state=START;
69
  for(tmp=buffer;tmp<end;tmp++){
70
    switch(*tmp){
71
      case ' ':
72
      case '\t':
73
        switch(state){
74
          case START: /*allow space at the beginning, although not
75
                  legal*/
76
            break;
77
          case L_URI:
78
          case L_VER:
79
          case L_STATUS:
80
          case L_REASON:
81
          case L_LF:
82
             /*eat  space*/
83
            break;
84
          case FIN_INVITE:
85
            *tmp=0;
86
            fl->u.request.method.len=tmp-fl->u.request.method.s;
87
            fl->u.request.method_value=METHOD_INVITE;
88
            state=L_URI;
89
            break;
90
          case FIN_ACK:
91
            *tmp=0;
92
            fl->u.request.method.len=tmp-fl->u.request.method.s;
93
            fl->u.request.method_value=METHOD_ACK;
94
            state=L_URI;
95
            break;
96
          case FIN_CANCEL:
97
            *tmp=0;
98
            fl->u.request.method.len=tmp-fl->u.request.method.s;
99
            fl->u.request.method_value=METHOD_CANCEL;
100
            state=L_URI;
101
            break;
102
          case FIN_BYE:
103
            *tmp=0;
104
            fl->u.request.method.len=tmp-fl->u.request.method.s;
105
            fl->u.request.method_value=METHOD_BYE;
106
            state=L_URI;
107
            break;
108
          case FIN_SIP:
109
            *tmp=0;
110
            fl->u.reply.version.len=tmp-fl->u.reply.version.s;
111
            state=L_STATUS;
112
            fl->type=SIP_REPLY;
113
            break;
114
          case P_URI:
115
            *tmp=0;
116
            fl->u.request.uri.len=tmp-fl->u.request.uri.s;
117
            state=L_VER;
118
            break;
119
          case FIN_VER:
120
            *tmp=0;
121
            fl->u.request.version.len=tmp-fl->u.request.version.s;
122
            state=L_LF;
123
            break;
124
          case P_STATUS:
125
            *tmp=0;
126
            fl->u.reply.status.len=tmp-fl->u.reply.status.s;
127
            state=L_REASON;
128
            break;
129
          case P_REASON:
130
           /* *tmp=0;
131
            fl->u.reply.reason.len=tmp-fl->u.reply.reason.s;
132
            */
133
            break;
134
          case VER1:
135
          case VER2:
136
          case VER3:
137
          case VER4:
138
          case VER5:
139
          case VER6:
140
            LM_ERR("invalid version in request\n");
141
            goto error;
142
          case P_METHOD:
143
          default:
144
            *tmp=0;
145
            fl->u.request.method.len=tmp-fl->u.request.method.s;
146
            fl->u.request.method_value=METHOD_OTHER;
147
            state=L_URI;
148
        }
149
        break;
150
      case 's':
151
      case 'S':
152
        switch(state){
153
          case START:
154
            state=SIP1;
155
            fl->u.reply.version.s=tmp;
156
            break;
157
          case P_URI:
158
          case P_REASON:
159
          case P_METHOD:
160
            break;
161
          case L_REASON:
162
            fl->u.reply.reason.s=tmp;
163
            state=P_REASON;
164
            break;
165
          case P_STATUS:
166
          case L_STATUS:
167
            LM_ERR("non-number character <%c> in request"
168
                "status\n", *tmp);
169
            goto error;
170
          case L_LF:
171
            LM_ERR("invalid character <%c> in request\n", *tmp);
172
            goto error;
173
          case L_URI:
174
            fl->u.request.uri.s=tmp;
175
            state=P_URI;
176
            break;
177
          case L_VER:
178
            fl->u.request.version.s=tmp;
179
            state=VER1;
180
            break;
181
          case VER1:
182
          case VER2:
183
          case VER3:
184
          case VER4:
185
          case VER5:
186
          case VER6:
187
          case FIN_VER:
188
            LM_ERR("invalid version in request\n");
189
            goto error;
190
          default:
191
            state=P_METHOD;
192
        }
193
        break;
194
195
      case 'i':
196
      case 'I':
197
        switch(state){
198
          case START:
199
            state=INVITE1;
200
            fl->u.request.method.s=tmp;
201
            break;
202
          case INVITE3:
203
            state=INVITE4;
204
            break;
205
          case SIP1:
206
            state=SIP2;
207
            break;
208
          case P_URI:
209
          case P_REASON:
210
          case P_METHOD:
211
            break;
212
          case L_REASON:
213
            fl->u.reply.reason.s=tmp;
214
            state=P_REASON;
215
            break;
216
          case P_STATUS:
217
          case L_STATUS:
218
            LM_ERR("non-number "
219
                "character <%c> in request status\n", *tmp);
220
            goto error;
221
          case L_LF:
222
            LM_ERR("invalid "
223
                "character <%c> in request\n", *tmp);
224
            goto error;
225
          case L_URI:
226
            fl->u.request.uri.s=tmp;
227
            state=P_URI;
228
            break;
229
          case VER1:
230
            state=VER2;
231
            break;
232
          case L_VER:
233
          case VER2:
234
          case VER3:
235
          case VER4:
236
          case VER5:
237
          case VER6:
238
          case FIN_VER:
239
            LM_ERR("invalid version in request\n");
240
            goto error;
241
          default:
242
            state=P_METHOD;
243
        }
244
        break;
245
246
      case 'p':
247
      case 'P':
248
        switch(state){
249
          case START:
250
            state=P_METHOD;
251
            fl->u.request.method.s=tmp;
252
            break;
253
          case SIP2:
254
            state=SIP3;
255
            break;
256
          case P_URI:
257
          case P_REASON:
258
          case P_METHOD:
259
            break;
260
          case L_REASON:
261
            fl->u.reply.reason.s=tmp;
262
            state=P_REASON;
263
            break;
264
          case P_STATUS:
265
          case L_STATUS:
266
            LM_ERR("non-number "
267
                "character <%c> in request status\n", *tmp);
268
            goto error;
269
          case L_LF:
270
            LM_ERR("invalid "
271
                "character <%c> in request\n", *tmp);
272
            goto error;
273
          case L_URI:
274
            fl->u.request.uri.s=tmp;
275
            state=P_URI;
276
            break;
277
          case VER2:
278
            state=VER3;
279
            break;
280
          case L_VER:
281
          case VER1:
282
          case VER3:
283
          case VER4:
284
          case VER5:
285
          case VER6:
286
          case FIN_VER:
287
            LM_ERR("invalid version in request\n");
288
            goto error;
289
          default:
290
            state=P_METHOD;
291
        }
292
        break;
293
294
295
      case '/':
296
        switch(state){
297
          case START:
298
            state=P_METHOD;
299
            fl->u.request.method.s=tmp;
300
            break;
301
          case SIP3:
302
            state=SIP4;
303
            break;
304
          case P_URI:
305
          case P_REASON:
306
          case P_METHOD:
307
            break;
308
          case L_REASON:
309
            fl->u.reply.reason.s=tmp;
310
            state=P_REASON;
311
            break;
312
          case P_STATUS:
313
          case L_STATUS:
314
            LM_ERR("non-number "
315
                "character <%c> in request status\n", *tmp);
316
            goto error;
317
          case L_LF:
318
            LM_ERR("invalid "
319
                "character <%c> in request\n", *tmp);
320
            goto error;
321
          case L_URI:
322
            fl->u.request.uri.s=tmp;
323
            state=P_URI;
324
            break;
325
          case VER3:
326
            state=VER4;
327
            break;
328
          case L_VER:
329
          case VER1:
330
          case VER2:
331
          case VER4:
332
          case VER5:
333
          case VER6:
334
          case FIN_VER:
335
            LM_ERR("invalid version in request\n");
336
            goto error;
337
          default:
338
            state=P_METHOD;
339
        }
340
        break;
341
342
      case '2':
343
        switch(state){
344
          case START:
345
            state=P_METHOD;
346
            fl->u.request.method.s=tmp;
347
            break;
348
          case SIP4:
349
            state=SIP5;
350
            break;
351
          case P_URI:
352
          case P_REASON:
353
          case P_METHOD:
354
            break;
355
          case L_REASON:
356
            fl->u.reply.reason.s=tmp;
357
            state=P_REASON;
358
            break;
359
          case P_STATUS:
360
            stat=stat*10+*tmp-'0';
361
            break;
362
          case L_STATUS:
363
            stat=*tmp-'0';
364
            fl->u.reply.status.s=tmp;
365
            break;
366
          case L_LF:
367
            LM_ERR("invalid "
368
                "character <%c> in request\n", *tmp);
369
            goto error;
370
          case L_URI:
371
            fl->u.request.uri.s=tmp;
372
            state=P_URI;
373
            break;
374
          case VER4:
375
            state=VER5;
376
            break;
377
          case L_VER:
378
          case VER1:
379
          case VER2:
380
          case VER3:
381
          case VER5:
382
          case VER6:
383
          case FIN_VER:
384
            LM_ERR("invalid version in request\n");
385
            goto error;
386
          default:
387
            state=P_METHOD;
388
        }
389
        break;
390
391
      case '.':
392
        switch(state){
393
          case START:
394
            state=P_METHOD;
395
            fl->u.request.method.s=tmp;
396
            break;
397
          case SIP5:
398
            state=SIP6;
399
            break;
400
          case P_URI:
401
          case P_REASON:
402
          case P_METHOD:
403
            break;
404
          case L_REASON:
405
            fl->u.reply.reason.s=tmp;
406
            state=P_REASON;
407
            break;
408
          case P_STATUS:
409
          case L_STATUS:
410
            LM_ERR("non-number "
411
                "character <%c> in request status\n", *tmp);
412
            goto error;
413
          case L_LF:
414
            LM_ERR("invalid "
415
                "character <%c> in request\n", *tmp);
416
            goto error;
417
          case L_URI:
418
            fl->u.request.uri.s=tmp;
419
            state=P_URI;
420
            break;
421
          case VER5:
422
            state=VER6;
423
            break;
424
          case L_VER:
425
          case VER1:
426
          case VER2:
427
          case VER3:
428
          case VER4:
429
          case VER6:
430
          case FIN_VER:
431
            LM_ERR("invalid version in request\n");
432
            goto error;
433
          default:
434
            state=P_METHOD;
435
        }
436
        break;
437
438
      case '0':
439
        switch(state){
440
          case START:
441
            state=P_METHOD;
442
            fl->u.request.method.s=tmp;
443
            break;
444
          case SIP6:
445
            state=FIN_SIP;
446
            break;
447
          case P_URI:
448
          case P_REASON:
449
          case P_METHOD:
450
            break;
451
          case L_REASON:
452
            fl->u.reply.reason.s=tmp;
453
            state=P_REASON;
454
            break;
455
          case P_STATUS:
456
            stat=stat*10;
457
            break;
458
          case L_STATUS:
459
            stat=0;
460
            fl->u.reply.status.s=tmp;
461
            break;
462
          case L_LF:
463
            LM_ERR("invalid "
464
                "character <%c> in request\n", *tmp);
465
            goto error;
466
          case L_URI:
467
            fl->u.request.uri.s=tmp;
468
            state=P_URI;
469
            break;
470
          case VER6:
471
            state=FIN_VER;
472
            break;
473
          case L_VER:
474
          case VER1:
475
          case VER2:
476
          case VER3:
477
          case VER4:
478
          case VER5:
479
          case FIN_VER:
480
            LM_ERR("invalid version "
481
                " in request\n");
482
            goto error;
483
          default:
484
            state=P_METHOD;
485
        }
486
        break;
487
488
      case 'n':
489
      case 'N':
490
        switch(state){
491
          case START:
492
            state=P_METHOD;
493
            fl->u.request.method.s=tmp;
494
            break;
495
          case INVITE1:
496
            state=INVITE2;
497
            break;
498
          case CANCEL2:
499
            state=CANCEL3;
500
            break;
501
          case P_URI:
502
          case P_REASON:
503
          case P_METHOD:
504
            break;
505
          case L_REASON:
506
            fl->u.reply.reason.s=tmp;
507
            state=P_REASON;
508
            break;
509
          case P_STATUS:
510
          case L_STATUS:
511
            LM_ERR("non-number "
512
                "character <%c> in request status\n", *tmp);
513
            goto error;
514
          case L_LF:
515
            LM_ERR("invalid "
516
                "character <%c> in request\n", *tmp);
517
            goto error;
518
          case L_URI:
519
            fl->u.request.uri.s=tmp;
520
            state=P_URI;
521
            break;
522
          case L_VER:
523
          case VER1:
524
          case VER2:
525
          case VER3:
526
          case VER4:
527
          case VER5:
528
          case VER6:
529
          case FIN_VER:
530
            LM_ERR("invalid version in request\n");
531
            goto error;
532
          default:
533
            state=P_METHOD;
534
        }
535
        break;
536
537
      case 'v':
538
      case 'V':
539
        switch(state){
540
          case START:
541
            state=P_METHOD;
542
            fl->u.request.method.s=tmp;
543
            break;
544
          case INVITE2:
545
            state=INVITE3;
546
            break;
547
          case P_URI:
548
          case P_REASON:
549
          case P_METHOD:
550
            break;
551
          case L_REASON:
552
            fl->u.reply.reason.s=tmp;
553
            state=P_REASON;
554
            break;
555
          case P_STATUS:
556
          case L_STATUS:
557
            LM_ERR("non-number "
558
                "character <%c> in request status\n", *tmp);
559
            goto error;
560
          case L_LF:
561
            LM_ERR("invalid "
562
                "character <%c> in request\n", *tmp);
563
            goto error;
564
          case L_URI:
565
            fl->u.request.uri.s=tmp;
566
            state=P_URI;
567
            break;
568
          case L_VER:
569
          case VER1:
570
          case VER2:
571
          case VER3:
572
          case VER4:
573
          case VER5:
574
          case VER6:
575
          case FIN_VER:
576
            LM_ERR("invalid version in request\n");
577
            goto error;
578
          default:
579
            state=P_METHOD;
580
        }
581
        break;
582
583
      case 't':
584
      case 'T':
585
        switch(state){
586
          case START:
587
            state=P_METHOD;
588
            fl->u.request.method.s=tmp;
589
            break;
590
          case INVITE4:
591
            state=INVITE5;
592
            break;
593
          case P_URI:
594
          case P_REASON:
595
          case P_METHOD:
596
            break;
597
          case L_REASON:
598
            fl->u.reply.reason.s=tmp;
599
            state=P_REASON;
600
            break;
601
          case P_STATUS:
602
          case L_STATUS:
603
            LM_ERR("non-number "
604
                "character <%c> in request status\n", *tmp);
605
            goto error;
606
          case L_LF:
607
            LM_ERR("invalid "
608
                "character <%c> in request\n", *tmp);
609
            goto error;
610
          case L_URI:
611
            fl->u.request.uri.s=tmp;
612
            state=P_URI;
613
            break;
614
          case L_VER:
615
          case VER1:
616
          case VER2:
617
          case VER3:
618
          case VER4:
619
          case VER5:
620
          case VER6:
621
          case FIN_VER:
622
            LM_ERR("invalid version in request\n");
623
            goto error;
624
          default:
625
            state=P_METHOD;
626
        }
627
        break;
628
629
      case 'e':
630
      case 'E':
631
        switch(state){
632
          case START:
633
            state=P_METHOD;
634
            fl->u.request.method.s=tmp;
635
            break;
636
          case INVITE5:
637
            state=FIN_INVITE;
638
            break;
639
          case CANCEL4:
640
            state=CANCEL5;
641
            break;
642
          case BYE2:
643
            state=FIN_BYE;
644
            break;
645
          case P_URI:
646
          case P_REASON:
647
          case P_METHOD:
648
            break;
649
          case L_REASON:
650
            fl->u.reply.reason.s=tmp;
651
            state=P_REASON;
652
            break;
653
          case P_STATUS:
654
          case L_STATUS:
655
            LM_ERR("non-number "
656
                "character <%c> in request status\n", *tmp);
657
            goto error;
658
          case L_LF:
659
            LM_ERR("invalid "
660
                "character <%c> in request\n", *tmp);
661
            goto error;
662
          case L_URI:
663
            fl->u.request.uri.s=tmp;
664
            state=P_URI;
665
            break;
666
          case L_VER:
667
          case VER1:
668
          case VER2:
669
          case VER3:
670
          case VER4:
671
          case VER5:
672
          case VER6:
673
          case FIN_VER:
674
            LM_ERR("invalid version in request\n");
675
            goto error;
676
          default:
677
            state=P_METHOD;
678
        }
679
        break;
680
681
      case 'a':
682
      case 'A':
683
        switch(state){
684
          case START:
685
            state=ACK1;
686
            fl->u.request.method.s=tmp;
687
            break;
688
          case CANCEL1:
689
            state=CANCEL2;
690
            break;
691
          case BYE2:
692
            state=FIN_BYE;
693
            break;
694
          case P_URI:
695
          case P_REASON:
696
          case P_METHOD:
697
            break;
698
          case L_REASON:
699
            fl->u.reply.reason.s=tmp;
700
            state=P_REASON;
701
            break;
702
          case P_STATUS:
703
          case L_STATUS:
704
            LM_ERR("non-number "
705
                "character <%c> in request status\n", *tmp);
706
            goto error;
707
          case L_LF:
708
            LM_ERR("invalid "
709
                "character <%c> in request\n", *tmp);
710
            goto error;
711
          case L_URI:
712
            fl->u.request.uri.s=tmp;
713
            state=P_URI;
714
            break;
715
          case L_VER:
716
          case VER1:
717
          case VER2:
718
          case VER3:
719
          case VER4:
720
          case VER5:
721
          case VER6:
722
          case FIN_VER:
723
            LM_ERR("invalid version in request\n");
724
            goto error;
725
          default:
726
            state=P_METHOD;
727
        }
728
        break;
729
730
      case 'c':
731
      case 'C':
732
        switch(state){
733
          case START:
734
            state=CANCEL1;
735
            fl->u.request.method.s=tmp;
736
            break;
737
          case CANCEL3:
738
            state=CANCEL4;
739
            break;
740
          case ACK1:
741
            state=ACK2;
742
            break;
743
          case P_URI:
744
          case P_REASON:
745
          case P_METHOD:
746
            break;
747
          case L_REASON:
748
            fl->u.reply.reason.s=tmp;
749
            state=P_REASON;
750
            break;
751
          case P_STATUS:
752
          case L_STATUS:
753
            LM_ERR("non-number "
754
                "character <%c> in request status\n", *tmp);
755
            goto error;
756
          case L_LF:
757
            LM_ERR("invalid "
758
                "character <%c> in request\n", *tmp);
759
            goto error;
760
          case L_URI:
761
            fl->u.request.uri.s=tmp;
762
            state=P_URI;
763
            break;
764
          case L_VER:
765
          case VER1:
766
          case VER2:
767
          case VER3:
768
          case VER4:
769
          case VER5:
770
          case VER6:
771
          case FIN_VER:
772
            LM_ERR("invalid version in request\n");
773
            goto error;
774
          default:
775
            state=P_METHOD;
776
        }
777
        break;
778
779
      case 'k':
780
      case 'K':
781
        switch(state){
782
          case START:
783
            state=P_METHOD;
784
            fl->u.request.method.s=tmp;
785
            break;
786
          case ACK2:
787
            state=FIN_ACK;
788
            break;
789
          case P_URI:
790
          case P_REASON:
791
          case P_METHOD:
792
            break;
793
          case L_REASON:
794
            fl->u.reply.reason.s=tmp;
795
            state=P_REASON;
796
            break;
797
          case P_STATUS:
798
          case L_STATUS:
799
            LM_ERR("non-number "
800
                "character <%c> in request status\n", *tmp);
801
            goto error;
802
          case L_LF:
803
            LM_ERR("invalid "
804
                "character <%c> in request\n", *tmp);
805
            goto error;
806
          case L_URI:
807
            fl->u.request.uri.s=tmp;
808
            state=P_URI;
809
            break;
810
          case L_VER:
811
          case VER1:
812
          case VER2:
813
          case VER3:
814
          case VER4:
815
          case VER5:
816
          case VER6:
817
          case FIN_VER:
818
            LM_ERR("invalid version in request\n");
819
            goto error;
820
          default:
821
            state=P_METHOD;
822
        }
823
        break;
824
825
      case 'l':
826
      case 'L':
827
        switch(state){
828
          case START:
829
            state=P_METHOD;
830
            fl->u.request.method.s=tmp;
831
            break;
832
          case CANCEL5:
833
            state=FIN_CANCEL;
834
            break;
835
          case P_URI:
836
          case P_REASON:
837
          case P_METHOD:
838
            break;
839
          case L_REASON:
840
            fl->u.reply.reason.s=tmp;
841
            state=P_REASON;
842
            break;
843
          case P_STATUS:
844
          case L_STATUS:
845
            LM_ERR("non-number "
846
                "character <%c> in request status\n", *tmp);
847
            goto error;
848
          case L_LF:
849
            LM_ERR("invalid "
850
                "character <%c> in request\n", *tmp);
851
            goto error;
852
          case L_URI:
853
            fl->u.request.uri.s=tmp;
854
            state=P_URI;
855
            break;
856
          case L_VER:
857
          case VER1:
858
          case VER2:
859
          case VER3:
860
          case VER4:
861
          case VER5:
862
          case VER6:
863
          case FIN_VER:
864
            LM_ERR("invalid version in request\n");
865
            goto error;
866
          default:
867
            state=P_METHOD;
868
        }
869
        break;
870
871
      case 'b':
872
      case 'B':
873
        switch(state){
874
          case START:
875
            state=BYE1;
876
            fl->u.request.method.s=tmp;
877
            break;
878
          case P_URI:
879
          case P_REASON:
880
          case P_METHOD:
881
            break;
882
          case L_REASON:
883
            fl->u.reply.reason.s=tmp;
884
            state=P_REASON;
885
            break;
886
          case P_STATUS:
887
          case L_STATUS:
888
            LM_ERR("non-number "
889
                "character <%c> in request status\n", *tmp);
890
            goto error;
891
          case L_LF:
892
            LM_ERR("invalid "
893
                "character <%c> in request\n", *tmp);
894
            goto error;
895
          case L_URI:
896
            fl->u.request.uri.s=tmp;
897
            state=P_URI;
898
            break;
899
          case L_VER:
900
          case VER1:
901
          case VER2:
902
          case VER3:
903
          case VER4:
904
          case VER5:
905
          case VER6:
906
          case FIN_VER:
907
            LM_ERR("invalid version in request\n");
908
            goto error;
909
          default:
910
            state=P_METHOD;
911
        }
912
        break;
913
914
      case 'y':
915
      case 'Y':
916
        switch(state){
917
          case START:
918
            state=P_METHOD;
919
            fl->u.request.method.s=tmp;
920
            break;
921
          case BYE1:
922
            state=BYE2;
923
            break;
924
          case P_URI:
925
          case P_REASON:
926
          case P_METHOD:
927
            break;
928
          case L_REASON:
929
            fl->u.reply.reason.s=tmp;
930
            state=P_REASON;
931
            break;
932
          case P_STATUS:
933
          case L_STATUS:
934
            LM_ERR("non-number "
935
                "character <%c> in request status\n", *tmp);
936
            goto error;
937
          case L_LF:
938
            LM_ERR("invalid "
939
                "character <%c> in request\n", *tmp);
940
            goto error;
941
          case L_URI:
942
            fl->u.request.uri.s=tmp;
943
            state=P_URI;
944
            break;
945
          case L_VER:
946
          case VER1:
947
          case VER2:
948
          case VER3:
949
          case VER4:
950
          case VER5:
951
          case VER6:
952
          case FIN_VER:
953
            LM_ERR("invalid version in request\n");
954
            goto error;
955
          default:
956
            state=P_METHOD;
957
        }
958
        break;
959
960
      case '\r':
961
        switch(state){
962
          case P_REASON:
963
            *tmp=0;
964
            fl->u.reply.reason.len=tmp-fl->u.reply.reason.s;
965
            state=F_CR;
966
            break;
967
          case L_LF:
968
            state=F_CR;
969
            break;
970
          case FIN_VER:
971
            *tmp=0;
972
            fl->u.request.version.len=tmp-fl->u.request.version.s;
973
            state=F_CR;
974
            break;
975
          case L_REASON:
976
            state=F_CR;
977
            break;
978
          default:
979
            LM_ERR("invalid message\n");
980
            goto error;
981
        }
982
        break;
983
984
      case '\n':
985
        switch(state){
986
          case P_REASON:
987
            *tmp=0;
988
            fl->u.reply.reason.len=tmp-fl->u.reply.reason.s;
989
            state=F_LF;
990
            goto skip;
991
          case FIN_VER:
992
            *tmp=0;
993
            fl->u.request.version.len=tmp-fl->u.request.version.s;
994
            state=F_LF;
995
            goto skip;
996
          case L_REASON:
997
          case L_LF:
998
          case F_CR:
999
            state=F_LF;
1000
            goto skip;
1001
          default:
1002
            LM_ERR("invalid message\n");
1003
            goto error;
1004
        }
1005
        break;
1006
1007
      case '1':
1008
      case '3':
1009
      case '4':
1010
      case '5':
1011
      case '6':
1012
      case '7':
1013
      case '8':
1014
      case '9':
1015
        switch(state){
1016
          case START:
1017
            state=P_METHOD;
1018
            fl->u.request.method.s=tmp;
1019
            break;
1020
          case P_URI:
1021
          case P_REASON:
1022
          case P_METHOD:
1023
            break;
1024
          case L_REASON:
1025
            fl->u.reply.reason.s=tmp;
1026
            state=P_REASON;
1027
            break;
1028
          case P_STATUS:
1029
            stat=stat*10+*tmp-'0';
1030
            break;
1031
          case L_STATUS:
1032
            stat=*tmp-'0';
1033
            state=P_STATUS;
1034
            fl->u.reply.status.s=tmp;
1035
            break;
1036
          case L_LF:
1037
            LM_ERR("invalid character <%c> in request\n", *tmp);
1038
            goto error;
1039
          case L_URI:
1040
            fl->u.request.uri.s=tmp;
1041
            state=P_URI;
1042
            break;
1043
          case L_VER:
1044
          case VER1:
1045
          case VER2:
1046
          case VER3:
1047
          case VER4:
1048
          case VER5:
1049
          case VER6:
1050
          case FIN_VER:
1051
            LM_ERR("invalid version in request\n");
1052
            goto error;
1053
          default:
1054
            state=P_METHOD;
1055
        }
1056
1057
      default:
1058
        switch(state){
1059
          case START:
1060
            state=P_METHOD;
1061
            fl->u.request.method.s=tmp;
1062
            break;
1063
          case P_URI:
1064
          case P_REASON:
1065
          case P_METHOD:
1066
            break;
1067
          case L_REASON:
1068
            fl->u.reply.reason.s=tmp;
1069
            state=P_REASON;
1070
            break;
1071
          case P_STATUS:
1072
          case L_STATUS:
1073
            LM_ERR("non-number "
1074
                "character <%c> in request status\n", *tmp);
1075
            goto error;
1076
          case L_LF:
1077
            LM_ERR("invalid character <%c> in request\n", *tmp);
1078
            goto error;
1079
          case L_URI:
1080
            fl->u.request.uri.s=tmp;
1081
            state=P_URI;
1082
            break;
1083
          case L_VER:
1084
          case VER1:
1085
          case VER2:
1086
          case VER3:
1087
          case VER4:
1088
          case VER5:
1089
          case VER6:
1090
          case FIN_VER:
1091
            LM_ERR("invalid version in request\n");
1092
            goto error;
1093
          default:
1094
            state=P_METHOD;
1095
        }
1096
    }
1097
  }
1098
skip:
1099
  fl->len=tmp-buf;
1100
  if (fl->type==SIP_REPLY){
1101
    fl->u.reply.statuscode=stat;
1102
    /* fl->u.reply.statusclass=stat/100; */
1103
  }
1104
  return tmp;
1105
1106
error:
1107
  LM_ERR("while parsing first line (state=%d)\n", state);
1108
  fl->type=SIP_INVALID;
1109
  return tmp;
1110
}
1111
1112
#endif /* currently unused */
1113
1114
/* parses the first line, returns pointer to  next line  & fills fl;
1115
   also  modifies buffer (to avoid extra copy ops) */
1116
char* parse_first_line(char* buffer, unsigned int len, struct msg_start * fl)
1117
0
{
1118
1119
0
  char *tmp;
1120
0
  char* second;
1121
0
  char* third;
1122
0
  char* nl;
1123
0
  unsigned int offset;
1124
  /* int l; */
1125
0
  char* end;
1126
0
  char s1,s2,s3;
1127
0
  char *prn;
1128
0
  unsigned int t;
1129
1130
  /* grammar:
1131
    request  =  method SP uri SP version CRLF
1132
    response =  version SP status  SP reason  CRLF
1133
    (version = "SIP/2.0")
1134
  */
1135
1136
1137
0
  end=buffer+len;
1138
  /* see if it's a reply (status) */
1139
1140
  /* jku  -- parse well-known methods */
1141
1142
  /* drop messages which are so short they are for sure useless;
1143
           utilize knowledge of minimum size in parsing the first
1144
     token
1145
        */
1146
0
  if (len <=16 ) {
1147
0
    LM_INFO("message too short: %d\n", len);
1148
0
    goto error1;
1149
0
  }
1150
1151
0
  tmp=buffer;
1152
    /* is it perhaps a reply, ie does it start with "SIP...." ? */
1153
0
  if (  (*tmp=='S' || *tmp=='s') &&
1154
0
    strncasecmp( tmp+1, (char *)SIP_VERSION+1, SIP_VERSION_LEN-1)==0 &&
1155
0
    (*(tmp+SIP_VERSION_LEN)==' ')) {
1156
0
      fl->type=SIP_REPLY;
1157
0
      fl->u.reply.version.len=SIP_VERSION_LEN;
1158
0
      tmp=buffer+SIP_VERSION_LEN;
1159
0
  } else IFISMETHOD( INVITE, 'I' )
1160
0
  else IFISMETHOD( CANCEL, 'C')
1161
0
  else IFISMETHOD( ACK, 'A' )
1162
0
  else IFISMETHOD( BYE, 'B' )
1163
0
  else IFISMETHOD( INFO, 'I' )
1164
  /* if you want to add another method XXX, include METHOD_XXX in
1165
           H-file (this is the value which you will take later in
1166
           processing and define XXX_LEN as length of method name;
1167
     then just call IFISMETHOD( XXX, 'X' ) ... 'X' is the first
1168
     latter; everything must be capitals
1169
  */
1170
0
  else {
1171
    /* neither reply, nor any of known method requests,
1172
       let's believe it is an unknown method request
1173
          */
1174
0
    tmp=eat_token_end(buffer,buffer+len);
1175
0
    if ((tmp==buffer)||(tmp>=end)){
1176
0
      LM_INFO("empty  or bad first line\n");
1177
0
      goto error1;
1178
0
    }
1179
0
    if (*tmp!=' ') {
1180
0
      LM_INFO("method not followed by SP\n");
1181
0
      goto error1;
1182
0
    }
1183
0
    fl->type=SIP_REQUEST;
1184
    /* see if it is another known method */
1185
    /* fl->u.request.method_value=METHOD_OTHER; */
1186
0
    if(parse_method(buffer, tmp,
1187
0
        (unsigned int*)&fl->u.request.method_value)==0)
1188
0
    {
1189
0
      LM_INFO("failed to parse the method\n");
1190
0
      goto error1;
1191
0
    }
1192
0
    fl->u.request.method.len=tmp-buffer;
1193
0
  }
1194
1195
1196
  /* identifying type of message over now;
1197
     tmp points at space after; go ahead */
1198
1199
0
  fl->u.request.method.s=buffer;  /* store ptr to first token */
1200
0
  second=tmp+1;     /* jump to second token */
1201
0
  offset=second-buffer;
1202
1203
/* EoJku */
1204
1205
  /* next element */
1206
0
  tmp=eat_token_end(second, second+len-offset);
1207
0
  if (tmp>=end){
1208
0
    goto error;
1209
0
  }
1210
0
  offset+=tmp-second;
1211
0
  third=eat_space_end(tmp, tmp+len-offset);
1212
0
  offset+=third-tmp;
1213
0
  if ((third==tmp)||(tmp>=end)){
1214
0
    goto error;
1215
0
  }
1216
0
  fl->u.request.uri.s=second;
1217
0
  fl->u.request.uri.len=tmp-second;
1218
1219
  /* jku: parse status code */
1220
0
  if (fl->type==SIP_REPLY) {
1221
0
    if (fl->u.request.uri.len!=3) {
1222
0
      LM_INFO("len(status code)!=3: %.*s\n",
1223
0
        fl->u.request.uri.len, ZSW(second) );
1224
0
      goto error;
1225
0
    }
1226
0
    s1=*second; s2=*(second+1);s3=*(second+2);
1227
0
    if (s1>='0' && s1<='9' &&
1228
0
        s2>='0' && s2<='9' &&
1229
0
        s3>='0' && s3<='9' ) {
1230
0
      fl->u.reply.statuscode=(s1-'0')*100+10*(s2-'0')+(s3-'0');
1231
0
    } else {
1232
0
      LM_INFO("status_code non-numerical: %.*s\n",
1233
0
        fl->u.request.uri.len, ZSW(second) );
1234
0
      goto error;
1235
0
    }
1236
0
  }
1237
  /* EoJku */
1238
1239
  /*  last part: for a request it must be the version, for a reply
1240
   *  it can contain almost anything, including spaces, so we don't care
1241
   *  about it*/
1242
0
  if (fl->type==SIP_REQUEST){
1243
0
    tmp=eat_token_end(third,third+len-offset);
1244
0
    offset+=tmp-third;
1245
0
    if ((tmp==third)||(tmp>=end)){
1246
0
      goto error;
1247
0
    }
1248
0
    if (! is_empty_end(tmp, tmp+len-offset)){
1249
0
      goto error;
1250
0
    }
1251
0
  }else{
1252
0
    tmp=eat_token2_end(third,third+len-offset,'\r'); /* find end of line
1253
                          ('\n' or '\r') */
1254
0
    if (tmp>=end){ /* no crlf in packet => invalid */
1255
0
      goto error;
1256
0
    }
1257
0
    offset+=tmp-third;
1258
0
  }
1259
0
  nl=eat_line(tmp,len-offset);
1260
0
  if (nl>=end){ /* no crlf in packet or only 1 line > invalid */
1261
0
    goto error;
1262
0
  }
1263
0
  fl->u.request.version.s=third;
1264
0
  fl->u.request.version.len=tmp-third;
1265
0
  fl->len=nl-buffer;
1266
1267
0
  return nl;
1268
1269
0
error:
1270
0
  LM_ERR("bad %s first line\n",
1271
0
    (fl->type==SIP_REPLY)?"reply(status)":"request");
1272
1273
0
  LM_ERR("at line 0 char %d: \n", offset );
1274
0
  prn=pkg_malloc( offset );
1275
0
  if (prn) {
1276
0
    for (t=0; t<offset; t++)
1277
0
      if (*(buffer+t)) *(prn+t)=*(buffer+t);
1278
0
      else *(prn+t)=248U;
1279
0
    LM_ERR("parsed so far: %.*s\n", offset, ZSW(prn) );
1280
0
    pkg_free( prn );
1281
0
  };
1282
0
error1:
1283
0
  fl->type=SIP_INVALID;
1284
0
  LM_INFO("bad message\n");
1285
  /* skip  line */
1286
0
  nl=eat_line(buffer,len);
1287
0
  return nl;
1288
0
}