diff options
author | Vlad Yasevich <vyasevich@gmail.com> | 2013-08-09 22:05:36 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-08-13 18:04:02 -0400 |
commit | 072017b41e49e2a8e8a4e0258837a614bb5daa8d (patch) | |
tree | f0231d484d9d7189d97927aa0a9db3799044986a /net | |
parent | 55d10a11aeeca48149d14fcc0b955017f3618882 (diff) |
net: sctp: Add rudimentary infrastructure to account for control chunks
This patch adds a base infrastructure that allows SCTP to do
memory accounting for control chunks. Real accounting code will
follow.
This patch alos fixes the following triggered bug ...
[ 553.109742] kernel BUG at include/linux/skbuff.h:1813!
[ 553.109766] invalid opcode: 0000 [#1] SMP
[ 553.109789] Modules linked in: sctp libcrc32c rfcomm [...]
[ 553.110259] uinput i915 i2c_algo_bit drm_kms_helper e1000e drm ptp
pps_core i2c_core wmi video sunrpc
[ 553.110320] CPU: 0 PID: 1636 Comm: lt-test_1_to_1_ Not tainted
3.11.0-rc3+ #2
[ 553.110350] Hardware name: LENOVO 74597D6/74597D6, BIOS 6DET60WW
(3.10 ) 09/17/2009
[ 553.110381] task: ffff88020a01dd40 ti: ffff880204ed0000 task.ti:
ffff880204ed0000
[ 553.110411] RIP: 0010:[<ffffffffa0698017>] [<ffffffffa0698017>]
skb_orphan.part.9+0x4/0x6 [sctp]
[ 553.110459] RSP: 0018:ffff880204ed1bb8 EFLAGS: 00010286
[ 553.110483] RAX: ffff8802086f5a40 RBX: ffff880204303300 RCX:
0000000000000000
[ 553.110487] RDX: ffff880204303c28 RSI: ffff8802086f5a40 RDI:
ffff880202158000
[ 553.110487] RBP: ffff880204ed1bb8 R08: 0000000000000000 R09:
0000000000000000
[ 553.110487] R10: ffff88022f2d9a04 R11: ffff880233001600 R12:
0000000000000000
[ 553.110487] R13: ffff880204303c00 R14: ffff8802293d0000 R15:
ffff880202158000
[ 553.110487] FS: 00007f31b31fe740(0000) GS:ffff88023bc00000(0000)
knlGS:0000000000000000
[ 553.110487] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b
[ 553.110487] CR2: 000000379980e3e0 CR3: 000000020d225000 CR4:
00000000000407f0
[ 553.110487] Stack:
[ 553.110487] ffff880204ed1ca8 ffffffffa068d7fc 0000000000000000
0000000000000000
[ 553.110487] 0000000000000000 ffff8802293d0000 ffff880202158000
ffffffff81cb7900
[ 553.110487] 0000000000000000 0000400000001c68 ffff8802086f5a40
000000000000000f
[ 553.110487] Call Trace:
[ 553.110487] [<ffffffffa068d7fc>] sctp_sendmsg+0x6bc/0xc80 [sctp]
[ 553.110487] [<ffffffff8128f185>] ? sock_has_perm+0x75/0x90
[ 553.110487] [<ffffffff815a3593>] inet_sendmsg+0x63/0xb0
[ 553.110487] [<ffffffff8128f2b3>] ? selinux_socket_sendmsg+0x23/0x30
[ 553.110487] [<ffffffff8151c5d6>] sock_sendmsg+0xa6/0xd0
[ 553.110487] [<ffffffff81637b05>] ? _raw_spin_unlock_bh+0x15/0x20
[ 553.110487] [<ffffffff8151cd38>] SYSC_sendto+0x128/0x180
[ 553.110487] [<ffffffff8151ce6b>] ? SYSC_connect+0xdb/0x100
[ 553.110487] [<ffffffffa0690031>] ? sctp_inet_listen+0x71/0x1f0
[sctp]
[ 553.110487] [<ffffffff8151d35e>] SyS_sendto+0xe/0x10
[ 553.110487] [<ffffffff81640202>] system_call_fastpath+0x16/0x1b
[ 553.110487] Code: e0 48 c7 c7 00 22 6a a0 e8 67 a3 f0 e0 48 c7 [...]
[ 553.110487] RIP [<ffffffffa0698017>] skb_orphan.part.9+0x4/0x6
[sctp]
[ 553.110487] RSP <ffff880204ed1bb8>
[ 553.121578] ---[ end trace 46c20c5903ef5be2 ]---
The approach taken here is to split data and control chunks
creation a bit. Data chunks already have memory accounting
so noting needs to happen. For control chunks, add stubs handlers.
Signed-off-by: Vlad Yasevich <vyasevich@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/sctp/sm_make_chunk.c | 99 |
1 files changed, 69 insertions, 30 deletions
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 9c131338ccfa..01e97836ca6c 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
@@ -62,8 +62,12 @@ | |||
62 | #include <net/sctp/sctp.h> | 62 | #include <net/sctp/sctp.h> |
63 | #include <net/sctp/sm.h> | 63 | #include <net/sctp/sm.h> |
64 | 64 | ||
65 | static struct sctp_chunk *sctp_make_chunk(const struct sctp_association *asoc, | 65 | static struct sctp_chunk *sctp_make_control(const struct sctp_association *asoc, |
66 | __u8 type, __u8 flags, int paylen); | 66 | __u8 type, __u8 flags, int paylen); |
67 | static struct sctp_chunk *sctp_make_data(const struct sctp_association *asoc, | ||
68 | __u8 flags, int paylen); | ||
69 | static struct sctp_chunk *_sctp_make_chunk(const struct sctp_association *asoc, | ||
70 | __u8 type, __u8 flags, int paylen); | ||
67 | static sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep, | 71 | static sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep, |
68 | const struct sctp_association *asoc, | 72 | const struct sctp_association *asoc, |
69 | const struct sctp_chunk *init_chunk, | 73 | const struct sctp_chunk *init_chunk, |
@@ -76,6 +80,28 @@ static int sctp_process_param(struct sctp_association *asoc, | |||
76 | static void *sctp_addto_param(struct sctp_chunk *chunk, int len, | 80 | static void *sctp_addto_param(struct sctp_chunk *chunk, int len, |
77 | const void *data); | 81 | const void *data); |
78 | 82 | ||
83 | /* Control chunk destructor */ | ||
84 | static void sctp_control_release_owner(struct sk_buff *skb) | ||
85 | { | ||
86 | /*TODO: do memory release */ | ||
87 | } | ||
88 | |||
89 | static void sctp_control_set_owner_w(struct sctp_chunk *chunk) | ||
90 | { | ||
91 | struct sctp_association *asoc = chunk->asoc; | ||
92 | struct sk_buff *skb = chunk->skb; | ||
93 | |||
94 | /* TODO: properly account for control chunks. | ||
95 | * To do it right we'll need: | ||
96 | * 1) endpoint if association isn't known. | ||
97 | * 2) proper memory accounting. | ||
98 | * | ||
99 | * For now don't do anything for now. | ||
100 | */ | ||
101 | skb->sk = asoc ? asoc->base.sk : NULL; | ||
102 | skb->destructor = sctp_control_release_owner; | ||
103 | } | ||
104 | |||
79 | /* What was the inbound interface for this chunk? */ | 105 | /* What was the inbound interface for this chunk? */ |
80 | int sctp_chunk_iif(const struct sctp_chunk *chunk) | 106 | int sctp_chunk_iif(const struct sctp_chunk *chunk) |
81 | { | 107 | { |
@@ -290,7 +316,7 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc, | |||
290 | * PLEASE DO NOT FIXME [This version does not support Host Name.] | 316 | * PLEASE DO NOT FIXME [This version does not support Host Name.] |
291 | */ | 317 | */ |
292 | 318 | ||
293 | retval = sctp_make_chunk(asoc, SCTP_CID_INIT, 0, chunksize); | 319 | retval = sctp_make_control(asoc, SCTP_CID_INIT, 0, chunksize); |
294 | if (!retval) | 320 | if (!retval) |
295 | goto nodata; | 321 | goto nodata; |
296 | 322 | ||
@@ -437,7 +463,7 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc, | |||
437 | num_ext); | 463 | num_ext); |
438 | 464 | ||
439 | /* Now allocate and fill out the chunk. */ | 465 | /* Now allocate and fill out the chunk. */ |
440 | retval = sctp_make_chunk(asoc, SCTP_CID_INIT_ACK, 0, chunksize); | 466 | retval = sctp_make_control(asoc, SCTP_CID_INIT_ACK, 0, chunksize); |
441 | if (!retval) | 467 | if (!retval) |
442 | goto nomem_chunk; | 468 | goto nomem_chunk; |
443 | 469 | ||
@@ -542,7 +568,7 @@ struct sctp_chunk *sctp_make_cookie_echo(const struct sctp_association *asoc, | |||
542 | cookie_len = asoc->peer.cookie_len; | 568 | cookie_len = asoc->peer.cookie_len; |
543 | 569 | ||
544 | /* Build a cookie echo chunk. */ | 570 | /* Build a cookie echo chunk. */ |
545 | retval = sctp_make_chunk(asoc, SCTP_CID_COOKIE_ECHO, 0, cookie_len); | 571 | retval = sctp_make_control(asoc, SCTP_CID_COOKIE_ECHO, 0, cookie_len); |
546 | if (!retval) | 572 | if (!retval) |
547 | goto nodata; | 573 | goto nodata; |
548 | retval->subh.cookie_hdr = | 574 | retval->subh.cookie_hdr = |
@@ -587,7 +613,7 @@ struct sctp_chunk *sctp_make_cookie_ack(const struct sctp_association *asoc, | |||
587 | { | 613 | { |
588 | struct sctp_chunk *retval; | 614 | struct sctp_chunk *retval; |
589 | 615 | ||
590 | retval = sctp_make_chunk(asoc, SCTP_CID_COOKIE_ACK, 0, 0); | 616 | retval = sctp_make_control(asoc, SCTP_CID_COOKIE_ACK, 0, 0); |
591 | 617 | ||
592 | /* RFC 2960 6.4 Multi-homed SCTP Endpoints | 618 | /* RFC 2960 6.4 Multi-homed SCTP Endpoints |
593 | * | 619 | * |
@@ -635,8 +661,8 @@ struct sctp_chunk *sctp_make_cwr(const struct sctp_association *asoc, | |||
635 | sctp_cwrhdr_t cwr; | 661 | sctp_cwrhdr_t cwr; |
636 | 662 | ||
637 | cwr.lowest_tsn = htonl(lowest_tsn); | 663 | cwr.lowest_tsn = htonl(lowest_tsn); |
638 | retval = sctp_make_chunk(asoc, SCTP_CID_ECN_CWR, 0, | 664 | retval = sctp_make_control(asoc, SCTP_CID_ECN_CWR, 0, |
639 | sizeof(sctp_cwrhdr_t)); | 665 | sizeof(sctp_cwrhdr_t)); |
640 | 666 | ||
641 | if (!retval) | 667 | if (!retval) |
642 | goto nodata; | 668 | goto nodata; |
@@ -669,8 +695,8 @@ struct sctp_chunk *sctp_make_ecne(const struct sctp_association *asoc, | |||
669 | sctp_ecnehdr_t ecne; | 695 | sctp_ecnehdr_t ecne; |
670 | 696 | ||
671 | ecne.lowest_tsn = htonl(lowest_tsn); | 697 | ecne.lowest_tsn = htonl(lowest_tsn); |
672 | retval = sctp_make_chunk(asoc, SCTP_CID_ECN_ECNE, 0, | 698 | retval = sctp_make_control(asoc, SCTP_CID_ECN_ECNE, 0, |
673 | sizeof(sctp_ecnehdr_t)); | 699 | sizeof(sctp_ecnehdr_t)); |
674 | if (!retval) | 700 | if (!retval) |
675 | goto nodata; | 701 | goto nodata; |
676 | retval->subh.ecne_hdr = | 702 | retval->subh.ecne_hdr = |
@@ -706,7 +732,7 @@ struct sctp_chunk *sctp_make_datafrag_empty(struct sctp_association *asoc, | |||
706 | dp.ssn = htons(ssn); | 732 | dp.ssn = htons(ssn); |
707 | 733 | ||
708 | chunk_len = sizeof(dp) + data_len; | 734 | chunk_len = sizeof(dp) + data_len; |
709 | retval = sctp_make_chunk(asoc, SCTP_CID_DATA, flags, chunk_len); | 735 | retval = sctp_make_data(asoc, flags, chunk_len); |
710 | if (!retval) | 736 | if (!retval) |
711 | goto nodata; | 737 | goto nodata; |
712 | 738 | ||
@@ -753,7 +779,7 @@ struct sctp_chunk *sctp_make_sack(const struct sctp_association *asoc) | |||
753 | + sizeof(__u32) * num_dup_tsns; | 779 | + sizeof(__u32) * num_dup_tsns; |
754 | 780 | ||
755 | /* Create the chunk. */ | 781 | /* Create the chunk. */ |
756 | retval = sctp_make_chunk(asoc, SCTP_CID_SACK, 0, len); | 782 | retval = sctp_make_control(asoc, SCTP_CID_SACK, 0, len); |
757 | if (!retval) | 783 | if (!retval) |
758 | goto nodata; | 784 | goto nodata; |
759 | 785 | ||
@@ -832,8 +858,8 @@ struct sctp_chunk *sctp_make_shutdown(const struct sctp_association *asoc, | |||
832 | ctsn = sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map); | 858 | ctsn = sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map); |
833 | shut.cum_tsn_ack = htonl(ctsn); | 859 | shut.cum_tsn_ack = htonl(ctsn); |
834 | 860 | ||
835 | retval = sctp_make_chunk(asoc, SCTP_CID_SHUTDOWN, 0, | 861 | retval = sctp_make_control(asoc, SCTP_CID_SHUTDOWN, 0, |
836 | sizeof(sctp_shutdownhdr_t)); | 862 | sizeof(sctp_shutdownhdr_t)); |
837 | if (!retval) | 863 | if (!retval) |
838 | goto nodata; | 864 | goto nodata; |
839 | 865 | ||
@@ -851,7 +877,7 @@ struct sctp_chunk *sctp_make_shutdown_ack(const struct sctp_association *asoc, | |||
851 | { | 877 | { |
852 | struct sctp_chunk *retval; | 878 | struct sctp_chunk *retval; |
853 | 879 | ||
854 | retval = sctp_make_chunk(asoc, SCTP_CID_SHUTDOWN_ACK, 0, 0); | 880 | retval = sctp_make_control(asoc, SCTP_CID_SHUTDOWN_ACK, 0, 0); |
855 | 881 | ||
856 | /* RFC 2960 6.4 Multi-homed SCTP Endpoints | 882 | /* RFC 2960 6.4 Multi-homed SCTP Endpoints |
857 | * | 883 | * |
@@ -880,7 +906,7 @@ struct sctp_chunk *sctp_make_shutdown_complete( | |||
880 | */ | 906 | */ |
881 | flags |= asoc ? 0 : SCTP_CHUNK_FLAG_T; | 907 | flags |= asoc ? 0 : SCTP_CHUNK_FLAG_T; |
882 | 908 | ||
883 | retval = sctp_make_chunk(asoc, SCTP_CID_SHUTDOWN_COMPLETE, flags, 0); | 909 | retval = sctp_make_control(asoc, SCTP_CID_SHUTDOWN_COMPLETE, flags, 0); |
884 | 910 | ||
885 | /* RFC 2960 6.4 Multi-homed SCTP Endpoints | 911 | /* RFC 2960 6.4 Multi-homed SCTP Endpoints |
886 | * | 912 | * |
@@ -919,7 +945,7 @@ struct sctp_chunk *sctp_make_abort(const struct sctp_association *asoc, | |||
919 | flags = SCTP_CHUNK_FLAG_T; | 945 | flags = SCTP_CHUNK_FLAG_T; |
920 | } | 946 | } |
921 | 947 | ||
922 | retval = sctp_make_chunk(asoc, SCTP_CID_ABORT, flags, hint); | 948 | retval = sctp_make_control(asoc, SCTP_CID_ABORT, flags, hint); |
923 | 949 | ||
924 | /* RFC 2960 6.4 Multi-homed SCTP Endpoints | 950 | /* RFC 2960 6.4 Multi-homed SCTP Endpoints |
925 | * | 951 | * |
@@ -1111,7 +1137,7 @@ struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *asoc, | |||
1111 | struct sctp_chunk *retval; | 1137 | struct sctp_chunk *retval; |
1112 | sctp_sender_hb_info_t hbinfo; | 1138 | sctp_sender_hb_info_t hbinfo; |
1113 | 1139 | ||
1114 | retval = sctp_make_chunk(asoc, SCTP_CID_HEARTBEAT, 0, sizeof(hbinfo)); | 1140 | retval = sctp_make_control(asoc, SCTP_CID_HEARTBEAT, 0, sizeof(hbinfo)); |
1115 | 1141 | ||
1116 | if (!retval) | 1142 | if (!retval) |
1117 | goto nodata; | 1143 | goto nodata; |
@@ -1139,7 +1165,7 @@ struct sctp_chunk *sctp_make_heartbeat_ack(const struct sctp_association *asoc, | |||
1139 | { | 1165 | { |
1140 | struct sctp_chunk *retval; | 1166 | struct sctp_chunk *retval; |
1141 | 1167 | ||
1142 | retval = sctp_make_chunk(asoc, SCTP_CID_HEARTBEAT_ACK, 0, paylen); | 1168 | retval = sctp_make_control(asoc, SCTP_CID_HEARTBEAT_ACK, 0, paylen); |
1143 | if (!retval) | 1169 | if (!retval) |
1144 | goto nodata; | 1170 | goto nodata; |
1145 | 1171 | ||
@@ -1171,8 +1197,8 @@ static struct sctp_chunk *sctp_make_op_error_space( | |||
1171 | { | 1197 | { |
1172 | struct sctp_chunk *retval; | 1198 | struct sctp_chunk *retval; |
1173 | 1199 | ||
1174 | retval = sctp_make_chunk(asoc, SCTP_CID_ERROR, 0, | 1200 | retval = sctp_make_control(asoc, SCTP_CID_ERROR, 0, |
1175 | sizeof(sctp_errhdr_t) + size); | 1201 | sizeof(sctp_errhdr_t) + size); |
1176 | if (!retval) | 1202 | if (!retval) |
1177 | goto nodata; | 1203 | goto nodata; |
1178 | 1204 | ||
@@ -1242,7 +1268,7 @@ struct sctp_chunk *sctp_make_auth(const struct sctp_association *asoc) | |||
1242 | if (unlikely(!hmac_desc)) | 1268 | if (unlikely(!hmac_desc)) |
1243 | return NULL; | 1269 | return NULL; |
1244 | 1270 | ||
1245 | retval = sctp_make_chunk(asoc, SCTP_CID_AUTH, 0, | 1271 | retval = sctp_make_control(asoc, SCTP_CID_AUTH, 0, |
1246 | hmac_desc->hmac_len + sizeof(sctp_authhdr_t)); | 1272 | hmac_desc->hmac_len + sizeof(sctp_authhdr_t)); |
1247 | if (!retval) | 1273 | if (!retval) |
1248 | return NULL; | 1274 | return NULL; |
@@ -1345,8 +1371,8 @@ const union sctp_addr *sctp_source(const struct sctp_chunk *chunk) | |||
1345 | /* Create a new chunk, setting the type and flags headers from the | 1371 | /* Create a new chunk, setting the type and flags headers from the |
1346 | * arguments, reserving enough space for a 'paylen' byte payload. | 1372 | * arguments, reserving enough space for a 'paylen' byte payload. |
1347 | */ | 1373 | */ |
1348 | static struct sctp_chunk *sctp_make_chunk(const struct sctp_association *asoc, | 1374 | static struct sctp_chunk *_sctp_make_chunk(const struct sctp_association *asoc, |
1349 | __u8 type, __u8 flags, int paylen) | 1375 | __u8 type, __u8 flags, int paylen) |
1350 | { | 1376 | { |
1351 | struct sctp_chunk *retval; | 1377 | struct sctp_chunk *retval; |
1352 | sctp_chunkhdr_t *chunk_hdr; | 1378 | sctp_chunkhdr_t *chunk_hdr; |
@@ -1379,14 +1405,27 @@ static struct sctp_chunk *sctp_make_chunk(const struct sctp_association *asoc, | |||
1379 | if (sctp_auth_send_cid(type, asoc)) | 1405 | if (sctp_auth_send_cid(type, asoc)) |
1380 | retval->auth = 1; | 1406 | retval->auth = 1; |
1381 | 1407 | ||
1382 | /* Set the skb to the belonging sock for accounting. */ | ||
1383 | skb->sk = sk; | ||
1384 | |||
1385 | return retval; | 1408 | return retval; |
1386 | nodata: | 1409 | nodata: |
1387 | return NULL; | 1410 | return NULL; |
1388 | } | 1411 | } |
1389 | 1412 | ||
1413 | static struct sctp_chunk *sctp_make_data(const struct sctp_association *asoc, | ||
1414 | __u8 flags, int paylen) | ||
1415 | { | ||
1416 | return _sctp_make_chunk(asoc, SCTP_CID_DATA, flags, paylen); | ||
1417 | } | ||
1418 | |||
1419 | static struct sctp_chunk *sctp_make_control(const struct sctp_association *asoc, | ||
1420 | __u8 type, __u8 flags, int paylen) | ||
1421 | { | ||
1422 | struct sctp_chunk *chunk = _sctp_make_chunk(asoc, type, flags, paylen); | ||
1423 | |||
1424 | if (chunk) | ||
1425 | sctp_control_set_owner_w(chunk); | ||
1426 | |||
1427 | return chunk; | ||
1428 | } | ||
1390 | 1429 | ||
1391 | /* Release the memory occupied by a chunk. */ | 1430 | /* Release the memory occupied by a chunk. */ |
1392 | static void sctp_chunk_destroy(struct sctp_chunk *chunk) | 1431 | static void sctp_chunk_destroy(struct sctp_chunk *chunk) |
@@ -2727,7 +2766,7 @@ static struct sctp_chunk *sctp_make_asconf(struct sctp_association *asoc, | |||
2727 | length += addrlen; | 2766 | length += addrlen; |
2728 | 2767 | ||
2729 | /* Create the chunk. */ | 2768 | /* Create the chunk. */ |
2730 | retval = sctp_make_chunk(asoc, SCTP_CID_ASCONF, 0, length); | 2769 | retval = sctp_make_control(asoc, SCTP_CID_ASCONF, 0, length); |
2731 | if (!retval) | 2770 | if (!retval) |
2732 | return NULL; | 2771 | return NULL; |
2733 | 2772 | ||
@@ -2911,7 +2950,7 @@ static struct sctp_chunk *sctp_make_asconf_ack(const struct sctp_association *as | |||
2911 | int length = sizeof(asconf) + vparam_len; | 2950 | int length = sizeof(asconf) + vparam_len; |
2912 | 2951 | ||
2913 | /* Create the chunk. */ | 2952 | /* Create the chunk. */ |
2914 | retval = sctp_make_chunk(asoc, SCTP_CID_ASCONF_ACK, 0, length); | 2953 | retval = sctp_make_control(asoc, SCTP_CID_ASCONF_ACK, 0, length); |
2915 | if (!retval) | 2954 | if (!retval) |
2916 | return NULL; | 2955 | return NULL; |
2917 | 2956 | ||
@@ -3442,7 +3481,7 @@ struct sctp_chunk *sctp_make_fwdtsn(const struct sctp_association *asoc, | |||
3442 | 3481 | ||
3443 | hint = (nstreams + 1) * sizeof(__u32); | 3482 | hint = (nstreams + 1) * sizeof(__u32); |
3444 | 3483 | ||
3445 | retval = sctp_make_chunk(asoc, SCTP_CID_FWD_TSN, 0, hint); | 3484 | retval = sctp_make_control(asoc, SCTP_CID_FWD_TSN, 0, hint); |
3446 | 3485 | ||
3447 | if (!retval) | 3486 | if (!retval) |
3448 | return NULL; | 3487 | return NULL; |