1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46#include <linux/types.h>
47#include <linux/skbuff.h>
48#include <net/sctp/structs.h>
49#include <net/sctp/sctp.h>
50#include <net/sctp/sm.h>
51
52static void sctp_ulpevent_receive_data(struct sctp_ulpevent *event,
53 struct sctp_association *asoc);
54static void sctp_ulpevent_release_data(struct sctp_ulpevent *event);
55static void sctp_ulpevent_release_frag_data(struct sctp_ulpevent *event);
56
57
58
59SCTP_STATIC void sctp_ulpevent_init(struct sctp_ulpevent *event,
60 int msg_flags,
61 unsigned int len)
62{
63 memset(event, 0, sizeof(struct sctp_ulpevent));
64 event->msg_flags = msg_flags;
65 event->rmem_len = len;
66}
67
68
69SCTP_STATIC struct sctp_ulpevent *sctp_ulpevent_new(int size, int msg_flags,
70 gfp_t gfp)
71{
72 struct sctp_ulpevent *event;
73 struct sk_buff *skb;
74
75 skb = alloc_skb(size, gfp);
76 if (!skb)
77 goto fail;
78
79 event = sctp_skb2event(skb);
80 sctp_ulpevent_init(event, msg_flags, skb->truesize);
81
82 return event;
83
84fail:
85 return NULL;
86}
87
88
89int sctp_ulpevent_is_notification(const struct sctp_ulpevent *event)
90{
91 return MSG_NOTIFICATION == (event->msg_flags & MSG_NOTIFICATION);
92}
93
94
95
96
97static inline void sctp_ulpevent_set_owner(struct sctp_ulpevent *event,
98 const struct sctp_association *asoc)
99{
100 struct sk_buff *skb;
101
102
103
104
105 sctp_association_hold((struct sctp_association *)asoc);
106 skb = sctp_event2skb(event);
107 event->asoc = (struct sctp_association *)asoc;
108 atomic_add(event->rmem_len, &event->asoc->rmem_alloc);
109 sctp_skb_set_owner_r(skb, asoc->base.sk);
110}
111
112
113static inline void sctp_ulpevent_release_owner(struct sctp_ulpevent *event)
114{
115 struct sctp_association *asoc = event->asoc;
116
117 atomic_sub(event->rmem_len, &asoc->rmem_alloc);
118 sctp_association_put(asoc);
119}
120
121
122
123
124
125
126
127
128
129
130
131
132struct sctp_ulpevent *sctp_ulpevent_make_assoc_change(
133 const struct sctp_association *asoc,
134 __u16 flags, __u16 state, __u16 error, __u16 outbound,
135 __u16 inbound, struct sctp_chunk *chunk, gfp_t gfp)
136{
137 struct sctp_ulpevent *event;
138 struct sctp_assoc_change *sac;
139 struct sk_buff *skb;
140
141
142
143
144 if (chunk) {
145
146
147
148 skb = skb_copy_expand(chunk->skb,
149 sizeof(struct sctp_assoc_change), 0, gfp);
150
151 if (!skb)
152 goto fail;
153
154
155 event = sctp_skb2event(skb);
156 sctp_ulpevent_init(event, MSG_NOTIFICATION, skb->truesize);
157
158
159 sac = (struct sctp_assoc_change *)
160 skb_push(skb, sizeof(struct sctp_assoc_change));
161
162
163 skb_trim(skb, sizeof(struct sctp_assoc_change) +
164 ntohs(chunk->chunk_hdr->length) -
165 sizeof(sctp_chunkhdr_t));
166 } else {
167 event = sctp_ulpevent_new(sizeof(struct sctp_assoc_change),
168 MSG_NOTIFICATION, gfp);
169 if (!event)
170 goto fail;
171
172 skb = sctp_event2skb(event);
173 sac = (struct sctp_assoc_change *) skb_put(skb,
174 sizeof(struct sctp_assoc_change));
175 }
176
177
178
179
180
181
182
183 sac->sac_type = SCTP_ASSOC_CHANGE;
184
185
186
187
188
189
190
191
192 sac->sac_state = state;
193
194
195
196
197
198
199
200 sac->sac_flags = 0;
201
202
203
204
205
206
207
208
209 sac->sac_length = skb->len;
210
211
212
213
214
215
216
217
218
219
220
221 sac->sac_error = error;
222
223
224
225
226
227
228
229
230
231
232 sac->sac_outbound_streams = outbound;
233 sac->sac_inbound_streams = inbound;
234
235
236
237
238
239
240
241
242
243
244 sctp_ulpevent_set_owner(event, asoc);
245 sac->sac_assoc_id = sctp_assoc2id(asoc);
246
247 return event;
248
249fail:
250 return NULL;
251}
252
253
254
255
256
257
258
259
260
261struct sctp_ulpevent *sctp_ulpevent_make_peer_addr_change(
262 const struct sctp_association *asoc,
263 const struct sockaddr_storage *aaddr,
264 int flags, int state, int error, gfp_t gfp)
265{
266 struct sctp_ulpevent *event;
267 struct sctp_paddr_change *spc;
268 struct sk_buff *skb;
269
270 event = sctp_ulpevent_new(sizeof(struct sctp_paddr_change),
271 MSG_NOTIFICATION, gfp);
272 if (!event)
273 goto fail;
274
275 skb = sctp_event2skb(event);
276 spc = (struct sctp_paddr_change *)
277 skb_put(skb, sizeof(struct sctp_paddr_change));
278
279
280
281
282
283
284
285
286 spc->spc_type = SCTP_PEER_ADDR_CHANGE;
287
288
289
290
291
292
293
294
295
296 spc->spc_length = sizeof(struct sctp_paddr_change);
297
298
299
300
301
302
303
304 spc->spc_flags = 0;
305
306
307
308
309
310
311
312
313
314 spc->spc_state = state;
315
316
317
318
319
320
321
322
323
324
325 spc->spc_error = error;
326
327
328
329
330
331
332
333
334
335
336 sctp_ulpevent_set_owner(event, asoc);
337 spc->spc_assoc_id = sctp_assoc2id(asoc);
338
339
340
341
342
343
344
345
346
347 memcpy(&spc->spc_aaddr, aaddr, sizeof(struct sockaddr_storage));
348
349
350 sctp_get_pf_specific(asoc->base.sk->sk_family)->addr_v4map(
351 sctp_sk(asoc->base.sk),
352 (union sctp_addr *)&spc->spc_aaddr);
353
354 return event;
355
356fail:
357 return NULL;
358}
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375struct sctp_ulpevent *sctp_ulpevent_make_remote_error(
376 const struct sctp_association *asoc, struct sctp_chunk *chunk,
377 __u16 flags, gfp_t gfp)
378{
379 struct sctp_ulpevent *event;
380 struct sctp_remote_error *sre;
381 struct sk_buff *skb;
382 sctp_errhdr_t *ch;
383 __be16 cause;
384 int elen;
385
386 ch = (sctp_errhdr_t *)(chunk->skb->data);
387 cause = ch->cause;
388 elen = WORD_ROUND(ntohs(ch->length)) - sizeof(sctp_errhdr_t);
389
390
391 skb_pull(chunk->skb, sizeof(sctp_errhdr_t));
392
393
394
395
396 skb = skb_copy_expand(chunk->skb, sizeof(struct sctp_remote_error),
397 0, gfp);
398
399
400 skb_pull(chunk->skb, elen);
401 if (!skb)
402 goto fail;
403
404
405 event = sctp_skb2event(skb);
406 sctp_ulpevent_init(event, MSG_NOTIFICATION, skb->truesize);
407
408 sre = (struct sctp_remote_error *)
409 skb_push(skb, sizeof(struct sctp_remote_error));
410
411
412 skb_trim(skb, sizeof(struct sctp_remote_error) + elen);
413
414
415
416
417
418
419
420 sre->sre_type = SCTP_REMOTE_ERROR;
421
422
423
424
425
426
427
428
429 sre->sre_flags = 0;
430
431
432
433
434
435
436
437
438
439 sre->sre_length = skb->len;
440
441
442
443
444
445
446
447
448 sre->sre_error = cause;
449
450
451
452
453
454
455
456
457
458
459 sctp_ulpevent_set_owner(event, asoc);
460 sre->sre_assoc_id = sctp_assoc2id(asoc);
461
462 return event;
463
464fail:
465 return NULL;
466}
467
468
469
470
471
472
473struct sctp_ulpevent *sctp_ulpevent_make_send_failed(
474 const struct sctp_association *asoc, struct sctp_chunk *chunk,
475 __u16 flags, __u32 error, gfp_t gfp)
476{
477 struct sctp_ulpevent *event;
478 struct sctp_send_failed *ssf;
479 struct sk_buff *skb;
480
481
482 int len = ntohs(chunk->chunk_hdr->length);
483
484
485 skb = skb_copy_expand(chunk->skb,
486 sizeof(struct sctp_send_failed),
487 0,
488 gfp);
489 if (!skb)
490 goto fail;
491
492
493 skb_pull(skb, sizeof(struct sctp_data_chunk));
494 len -= sizeof(struct sctp_data_chunk);
495
496
497 event = sctp_skb2event(skb);
498 sctp_ulpevent_init(event, MSG_NOTIFICATION, skb->truesize);
499
500 ssf = (struct sctp_send_failed *)
501 skb_push(skb, sizeof(struct sctp_send_failed));
502
503
504
505
506
507
508
509 ssf->ssf_type = SCTP_SEND_FAILED;
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524 ssf->ssf_flags = flags;
525
526
527
528
529
530
531
532
533 ssf->ssf_length = sizeof(struct sctp_send_failed) + len;
534 skb_trim(skb, ssf->ssf_length);
535
536
537
538
539
540
541
542
543
544 ssf->ssf_error = error;
545
546
547
548
549
550
551
552
553 memcpy(&ssf->ssf_info, &chunk->sinfo, sizeof(struct sctp_sndrcvinfo));
554
555
556
557
558 ssf->ssf_info.sinfo_flags = chunk->chunk_hdr->flags;
559
560
561
562
563
564
565
566
567
568
569 sctp_ulpevent_set_owner(event, asoc);
570 ssf->ssf_assoc_id = sctp_assoc2id(asoc);
571 return event;
572
573fail:
574 return NULL;
575}
576
577
578
579
580
581
582struct sctp_ulpevent *sctp_ulpevent_make_shutdown_event(
583 const struct sctp_association *asoc,
584 __u16 flags, gfp_t gfp)
585{
586 struct sctp_ulpevent *event;
587 struct sctp_shutdown_event *sse;
588 struct sk_buff *skb;
589
590 event = sctp_ulpevent_new(sizeof(struct sctp_shutdown_event),
591 MSG_NOTIFICATION, gfp);
592 if (!event)
593 goto fail;
594
595 skb = sctp_event2skb(event);
596 sse = (struct sctp_shutdown_event *)
597 skb_put(skb, sizeof(struct sctp_shutdown_event));
598
599
600
601
602
603
604
605 sse->sse_type = SCTP_SHUTDOWN_EVENT;
606
607
608
609
610
611
612
613 sse->sse_flags = 0;
614
615
616
617
618
619
620
621
622 sse->sse_length = sizeof(struct sctp_shutdown_event);
623
624
625
626
627
628
629
630
631
632 sctp_ulpevent_set_owner(event, asoc);
633 sse->sse_assoc_id = sctp_assoc2id(asoc);
634
635 return event;
636
637fail:
638 return NULL;
639}
640
641
642
643
644
645
646struct sctp_ulpevent *sctp_ulpevent_make_adaptation_indication(
647 const struct sctp_association *asoc, gfp_t gfp)
648{
649 struct sctp_ulpevent *event;
650 struct sctp_adaptation_event *sai;
651 struct sk_buff *skb;
652
653 event = sctp_ulpevent_new(sizeof(struct sctp_adaptation_event),
654 MSG_NOTIFICATION, gfp);
655 if (!event)
656 goto fail;
657
658 skb = sctp_event2skb(event);
659 sai = (struct sctp_adaptation_event *)
660 skb_put(skb, sizeof(struct sctp_adaptation_event));
661
662 sai->sai_type = SCTP_ADAPTATION_INDICATION;
663 sai->sai_flags = 0;
664 sai->sai_length = sizeof(struct sctp_adaptation_event);
665 sai->sai_adaptation_ind = asoc->peer.adaptation_ind;
666 sctp_ulpevent_set_owner(event, asoc);
667 sai->sai_assoc_id = sctp_assoc2id(asoc);
668
669 return event;
670
671fail:
672 return NULL;
673}
674
675
676
677
678
679
680
681
682struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(struct sctp_association *asoc,
683 struct sctp_chunk *chunk,
684 gfp_t gfp)
685{
686 struct sctp_ulpevent *event = NULL;
687 struct sk_buff *skb;
688 size_t padding, len;
689 int rx_count;
690
691
692
693
694
695
696 if (asoc->ep->rcvbuf_policy)
697 rx_count = atomic_read(&asoc->rmem_alloc);
698 else
699 rx_count = atomic_read(&asoc->base.sk->sk_rmem_alloc);
700
701 if (rx_count >= asoc->base.sk->sk_rcvbuf) {
702
703 if ((asoc->base.sk->sk_userlocks & SOCK_RCVBUF_LOCK) ||
704 (!sk_rmem_schedule(asoc->base.sk, chunk->skb->truesize)))
705 goto fail;
706 }
707
708
709 skb = skb_clone(chunk->skb, gfp);
710 if (!skb)
711 goto fail;
712
713
714
715
716 if (sctp_tsnmap_mark(&asoc->peer.tsn_map,
717 ntohl(chunk->subh.data_hdr->tsn)))
718 goto fail_mark;
719
720
721
722
723
724
725
726
727
728
729
730
731
732 len = ntohs(chunk->chunk_hdr->length);
733 padding = WORD_ROUND(len) - len;
734
735
736 skb_trim(skb, chunk->chunk_end - padding - skb->data);
737
738
739 event = sctp_skb2event(skb);
740
741
742
743
744
745 sctp_ulpevent_init(event, 0, skb->len + sizeof(struct sk_buff));
746
747 sctp_ulpevent_receive_data(event, asoc);
748
749 event->stream = ntohs(chunk->subh.data_hdr->stream);
750 event->ssn = ntohs(chunk->subh.data_hdr->ssn);
751 event->ppid = chunk->subh.data_hdr->ppid;
752 if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) {
753 event->flags |= SCTP_UNORDERED;
754 event->cumtsn = sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map);
755 }
756 event->tsn = ntohl(chunk->subh.data_hdr->tsn);
757 event->msg_flags |= chunk->chunk_hdr->flags;
758 event->iif = sctp_chunk_iif(chunk);
759
760 return event;
761
762fail_mark:
763 kfree_skb(skb);
764fail:
765 return NULL;
766}
767
768
769
770
771
772
773
774
775
776struct sctp_ulpevent *sctp_ulpevent_make_pdapi(
777 const struct sctp_association *asoc, __u32 indication,
778 gfp_t gfp)
779{
780 struct sctp_ulpevent *event;
781 struct sctp_pdapi_event *pd;
782 struct sk_buff *skb;
783
784 event = sctp_ulpevent_new(sizeof(struct sctp_pdapi_event),
785 MSG_NOTIFICATION, gfp);
786 if (!event)
787 goto fail;
788
789 skb = sctp_event2skb(event);
790 pd = (struct sctp_pdapi_event *)
791 skb_put(skb, sizeof(struct sctp_pdapi_event));
792
793
794
795
796
797
798
799 pd->pdapi_type = SCTP_PARTIAL_DELIVERY_EVENT;
800 pd->pdapi_flags = 0;
801
802
803
804
805
806
807
808 pd->pdapi_length = sizeof(struct sctp_pdapi_event);
809
810
811
812
813
814 pd->pdapi_indication = indication;
815
816
817
818
819
820 sctp_ulpevent_set_owner(event, asoc);
821 pd->pdapi_assoc_id = sctp_assoc2id(asoc);
822
823 return event;
824fail:
825 return NULL;
826}
827
828struct sctp_ulpevent *sctp_ulpevent_make_authkey(
829 const struct sctp_association *asoc, __u16 key_id,
830 __u32 indication, gfp_t gfp)
831{
832 struct sctp_ulpevent *event;
833 struct sctp_authkey_event *ak;
834 struct sk_buff *skb;
835
836 event = sctp_ulpevent_new(sizeof(struct sctp_authkey_event),
837 MSG_NOTIFICATION, gfp);
838 if (!event)
839 goto fail;
840
841 skb = sctp_event2skb(event);
842 ak = (struct sctp_authkey_event *)
843 skb_put(skb, sizeof(struct sctp_authkey_event));
844
845 ak->auth_type = SCTP_AUTHENTICATION_INDICATION;
846 ak->auth_flags = 0;
847 ak->auth_length = sizeof(struct sctp_authkey_event);
848
849 ak->auth_keynumber = key_id;
850 ak->auth_altkeynumber = 0;
851 ak->auth_indication = indication;
852
853
854
855
856 sctp_ulpevent_set_owner(event, asoc);
857 ak->auth_assoc_id = sctp_assoc2id(asoc);
858
859 return event;
860fail:
861 return NULL;
862}
863
864
865
866
867
868__u16 sctp_ulpevent_get_notification_type(const struct sctp_ulpevent *event)
869{
870 union sctp_notification *notification;
871 struct sk_buff *skb;
872
873 skb = sctp_event2skb(event);
874 notification = (union sctp_notification *) skb->data;
875 return notification->sn_header.sn_type;
876}
877
878
879void sctp_ulpevent_read_sndrcvinfo(const struct sctp_ulpevent *event,
880 struct msghdr *msghdr)
881{
882 struct sctp_sndrcvinfo sinfo;
883
884 if (sctp_ulpevent_is_notification(event))
885 return;
886
887
888
889
890
891
892
893
894
895 sinfo.sinfo_stream = event->stream;
896
897
898
899
900
901
902
903 sinfo.sinfo_ssn = event->ssn;
904
905
906
907
908
909
910
911
912 sinfo.sinfo_ppid = event->ppid;
913
914
915
916
917
918
919
920
921
922
923 sinfo.sinfo_flags = event->flags;
924
925
926
927
928
929 sinfo.sinfo_tsn = event->tsn;
930
931
932
933
934
935
936
937 sinfo.sinfo_cumtsn = event->cumtsn;
938
939
940
941
942
943
944
945 sinfo.sinfo_assoc_id = sctp_assoc2id(event->asoc);
946
947
948 sinfo.sinfo_context = event->asoc->default_rcv_context;
949
950
951 sinfo.sinfo_timetolive = 0;
952
953 put_cmsg(msghdr, IPPROTO_SCTP, SCTP_SNDRCV,
954 sizeof(struct sctp_sndrcvinfo), (void *)&sinfo);
955}
956
957
958
959
960static void sctp_ulpevent_receive_data(struct sctp_ulpevent *event,
961 struct sctp_association *asoc)
962{
963 struct sk_buff *skb, *frag;
964
965 skb = sctp_event2skb(event);
966
967 sctp_ulpevent_set_owner(event, asoc);
968 sctp_assoc_rwnd_decrease(asoc, skb_headlen(skb));
969
970 if (!skb->data_len)
971 return;
972
973
974
975
976
977
978
979 skb_walk_frags(skb, frag)
980 sctp_ulpevent_receive_data(sctp_skb2event(frag), asoc);
981}
982
983
984
985
986static void sctp_ulpevent_release_data(struct sctp_ulpevent *event)
987{
988 struct sk_buff *skb, *frag;
989 unsigned int len;
990
991
992
993
994
995
996
997
998 skb = sctp_event2skb(event);
999 len = skb->len;
1000
1001 if (!skb->data_len)
1002 goto done;
1003
1004
1005 skb_walk_frags(skb, frag) {
1006
1007
1008
1009
1010 sctp_ulpevent_release_frag_data(sctp_skb2event(frag));
1011 }
1012
1013done:
1014 sctp_assoc_rwnd_increase(event->asoc, len);
1015 sctp_ulpevent_release_owner(event);
1016}
1017
1018static void sctp_ulpevent_release_frag_data(struct sctp_ulpevent *event)
1019{
1020 struct sk_buff *skb, *frag;
1021
1022 skb = sctp_event2skb(event);
1023
1024 if (!skb->data_len)
1025 goto done;
1026
1027
1028 skb_walk_frags(skb, frag) {
1029
1030
1031
1032
1033 sctp_ulpevent_release_frag_data(sctp_skb2event(frag));
1034 }
1035
1036done:
1037 sctp_ulpevent_release_owner(event);
1038}
1039
1040
1041
1042
1043
1044void sctp_ulpevent_free(struct sctp_ulpevent *event)
1045{
1046 if (sctp_ulpevent_is_notification(event))
1047 sctp_ulpevent_release_owner(event);
1048 else
1049 sctp_ulpevent_release_data(event);
1050
1051 kfree_skb(sctp_event2skb(event));
1052}
1053
1054
1055void sctp_queue_purge_ulpevents(struct sk_buff_head *list)
1056{
1057 struct sk_buff *skb;
1058 while ((skb = skb_dequeue(list)) != NULL)
1059 sctp_ulpevent_free(sctp_skb2event(skb));
1060}
1061