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