12bc78049SPatrick McHardy /* 22bc78049SPatrick McHardy * DCCP connection tracking protocol helper 32bc78049SPatrick McHardy * 42bc78049SPatrick McHardy * Copyright (c) 2005, 2006, 2008 Patrick McHardy <kaber@trash.net> 52bc78049SPatrick McHardy * 62bc78049SPatrick McHardy * This program is free software; you can redistribute it and/or modify 72bc78049SPatrick McHardy * it under the terms of the GNU General Public License version 2 as 82bc78049SPatrick McHardy * published by the Free Software Foundation. 92bc78049SPatrick McHardy * 102bc78049SPatrick McHardy */ 112bc78049SPatrick McHardy #include <linux/kernel.h> 122bc78049SPatrick McHardy #include <linux/module.h> 132bc78049SPatrick McHardy #include <linux/init.h> 142bc78049SPatrick McHardy #include <linux/sysctl.h> 152bc78049SPatrick McHardy #include <linux/spinlock.h> 162bc78049SPatrick McHardy #include <linux/skbuff.h> 172bc78049SPatrick McHardy #include <linux/dccp.h> 182bc78049SPatrick McHardy 192bc78049SPatrick McHardy #include <linux/netfilter/nfnetlink_conntrack.h> 202bc78049SPatrick McHardy #include <net/netfilter/nf_conntrack.h> 212bc78049SPatrick McHardy #include <net/netfilter/nf_conntrack_l4proto.h> 222bc78049SPatrick McHardy #include <net/netfilter/nf_log.h> 232bc78049SPatrick McHardy 242bc78049SPatrick McHardy static DEFINE_RWLOCK(dccp_lock); 252bc78049SPatrick McHardy 262bc78049SPatrick McHardy static int nf_ct_dccp_loose __read_mostly = 1; 272bc78049SPatrick McHardy 282bc78049SPatrick McHardy /* Timeouts are based on values from RFC4340: 292bc78049SPatrick McHardy * 302bc78049SPatrick McHardy * - REQUEST: 312bc78049SPatrick McHardy * 322bc78049SPatrick McHardy * 8.1.2. Client Request 332bc78049SPatrick McHardy * 342bc78049SPatrick McHardy * A client MAY give up on its DCCP-Requests after some time 352bc78049SPatrick McHardy * (3 minutes, for example). 362bc78049SPatrick McHardy * 372bc78049SPatrick McHardy * - RESPOND: 382bc78049SPatrick McHardy * 392bc78049SPatrick McHardy * 8.1.3. Server Response 402bc78049SPatrick McHardy * 412bc78049SPatrick McHardy * It MAY also leave the RESPOND state for CLOSED after a timeout of 422bc78049SPatrick McHardy * not less than 4MSL (8 minutes); 432bc78049SPatrick McHardy * 442bc78049SPatrick McHardy * - PARTOPEN: 452bc78049SPatrick McHardy * 462bc78049SPatrick McHardy * 8.1.5. Handshake Completion 472bc78049SPatrick McHardy * 482bc78049SPatrick McHardy * If the client remains in PARTOPEN for more than 4MSL (8 minutes), 492bc78049SPatrick McHardy * it SHOULD reset the connection with Reset Code 2, "Aborted". 502bc78049SPatrick McHardy * 512bc78049SPatrick McHardy * - OPEN: 522bc78049SPatrick McHardy * 532bc78049SPatrick McHardy * The DCCP timestamp overflows after 11.9 hours. If the connection 542bc78049SPatrick McHardy * stays idle this long the sequence number won't be recognized 552bc78049SPatrick McHardy * as valid anymore. 562bc78049SPatrick McHardy * 572bc78049SPatrick McHardy * - CLOSEREQ/CLOSING: 582bc78049SPatrick McHardy * 592bc78049SPatrick McHardy * 8.3. Termination 602bc78049SPatrick McHardy * 612bc78049SPatrick McHardy * The retransmission timer should initially be set to go off in two 622bc78049SPatrick McHardy * round-trip times and should back off to not less than once every 632bc78049SPatrick McHardy * 64 seconds ... 642bc78049SPatrick McHardy * 652bc78049SPatrick McHardy * - TIMEWAIT: 662bc78049SPatrick McHardy * 672bc78049SPatrick McHardy * 4.3. States 682bc78049SPatrick McHardy * 692bc78049SPatrick McHardy * A server or client socket remains in this state for 2MSL (4 minutes) 702bc78049SPatrick McHardy * after the connection has been town down, ... 712bc78049SPatrick McHardy */ 722bc78049SPatrick McHardy 732bc78049SPatrick McHardy #define DCCP_MSL (2 * 60 * HZ) 742bc78049SPatrick McHardy 752bc78049SPatrick McHardy static unsigned int dccp_timeout[CT_DCCP_MAX + 1] __read_mostly = { 762bc78049SPatrick McHardy [CT_DCCP_REQUEST] = 2 * DCCP_MSL, 772bc78049SPatrick McHardy [CT_DCCP_RESPOND] = 4 * DCCP_MSL, 782bc78049SPatrick McHardy [CT_DCCP_PARTOPEN] = 4 * DCCP_MSL, 792bc78049SPatrick McHardy [CT_DCCP_OPEN] = 12 * 3600 * HZ, 802bc78049SPatrick McHardy [CT_DCCP_CLOSEREQ] = 64 * HZ, 812bc78049SPatrick McHardy [CT_DCCP_CLOSING] = 64 * HZ, 822bc78049SPatrick McHardy [CT_DCCP_TIMEWAIT] = 2 * DCCP_MSL, 832bc78049SPatrick McHardy }; 842bc78049SPatrick McHardy 852bc78049SPatrick McHardy static const char * const dccp_state_names[] = { 862bc78049SPatrick McHardy [CT_DCCP_NONE] = "NONE", 872bc78049SPatrick McHardy [CT_DCCP_REQUEST] = "REQUEST", 882bc78049SPatrick McHardy [CT_DCCP_RESPOND] = "RESPOND", 892bc78049SPatrick McHardy [CT_DCCP_PARTOPEN] = "PARTOPEN", 902bc78049SPatrick McHardy [CT_DCCP_OPEN] = "OPEN", 912bc78049SPatrick McHardy [CT_DCCP_CLOSEREQ] = "CLOSEREQ", 922bc78049SPatrick McHardy [CT_DCCP_CLOSING] = "CLOSING", 932bc78049SPatrick McHardy [CT_DCCP_TIMEWAIT] = "TIMEWAIT", 942bc78049SPatrick McHardy [CT_DCCP_IGNORE] = "IGNORE", 952bc78049SPatrick McHardy [CT_DCCP_INVALID] = "INVALID", 962bc78049SPatrick McHardy }; 972bc78049SPatrick McHardy 982bc78049SPatrick McHardy #define sNO CT_DCCP_NONE 992bc78049SPatrick McHardy #define sRQ CT_DCCP_REQUEST 1002bc78049SPatrick McHardy #define sRS CT_DCCP_RESPOND 1012bc78049SPatrick McHardy #define sPO CT_DCCP_PARTOPEN 1022bc78049SPatrick McHardy #define sOP CT_DCCP_OPEN 1032bc78049SPatrick McHardy #define sCR CT_DCCP_CLOSEREQ 1042bc78049SPatrick McHardy #define sCG CT_DCCP_CLOSING 1052bc78049SPatrick McHardy #define sTW CT_DCCP_TIMEWAIT 1062bc78049SPatrick McHardy #define sIG CT_DCCP_IGNORE 1072bc78049SPatrick McHardy #define sIV CT_DCCP_INVALID 1082bc78049SPatrick McHardy 1092bc78049SPatrick McHardy /* 1102bc78049SPatrick McHardy * DCCP state transistion table 1112bc78049SPatrick McHardy * 1122bc78049SPatrick McHardy * The assumption is the same as for TCP tracking: 1132bc78049SPatrick McHardy * 1142bc78049SPatrick McHardy * We are the man in the middle. All the packets go through us but might 1152bc78049SPatrick McHardy * get lost in transit to the destination. It is assumed that the destination 1162bc78049SPatrick McHardy * can't receive segments we haven't seen. 1172bc78049SPatrick McHardy * 1182bc78049SPatrick McHardy * The following states exist: 1192bc78049SPatrick McHardy * 1202bc78049SPatrick McHardy * NONE: Initial state, expecting Request 1212bc78049SPatrick McHardy * REQUEST: Request seen, waiting for Response from server 1222bc78049SPatrick McHardy * RESPOND: Response from server seen, waiting for Ack from client 1232bc78049SPatrick McHardy * PARTOPEN: Ack after Response seen, waiting for packet other than Response, 1242bc78049SPatrick McHardy * Reset or Sync from server 1252bc78049SPatrick McHardy * OPEN: Packet other than Response, Reset or Sync seen 1262bc78049SPatrick McHardy * CLOSEREQ: CloseReq from server seen, expecting Close from client 1272bc78049SPatrick McHardy * CLOSING: Close seen, expecting Reset 1282bc78049SPatrick McHardy * TIMEWAIT: Reset seen 1292bc78049SPatrick McHardy * IGNORE: Not determinable whether packet is valid 1302bc78049SPatrick McHardy * 1312bc78049SPatrick McHardy * Some states exist only on one side of the connection: REQUEST, RESPOND, 1322bc78049SPatrick McHardy * PARTOPEN, CLOSEREQ. For the other side these states are equivalent to 1332bc78049SPatrick McHardy * the one it was in before. 1342bc78049SPatrick McHardy * 1352bc78049SPatrick McHardy * Packets are marked as ignored (sIG) if we don't know if they're valid 1362bc78049SPatrick McHardy * (for example a reincarnation of a connection we didn't notice is dead 1372bc78049SPatrick McHardy * already) and the server may send back a connection closing Reset or a 1382bc78049SPatrick McHardy * Response. They're also used for Sync/SyncAck packets, which we don't 1392bc78049SPatrick McHardy * care about. 1402bc78049SPatrick McHardy */ 1412bc78049SPatrick McHardy static const u_int8_t 1422bc78049SPatrick McHardy dccp_state_table[CT_DCCP_ROLE_MAX + 1][DCCP_PKT_SYNCACK + 1][CT_DCCP_MAX + 1] = { 1432bc78049SPatrick McHardy [CT_DCCP_ROLE_CLIENT] = { 1442bc78049SPatrick McHardy [DCCP_PKT_REQUEST] = { 1452bc78049SPatrick McHardy /* 1462bc78049SPatrick McHardy * sNO -> sRQ Regular Request 1472bc78049SPatrick McHardy * sRQ -> sRQ Retransmitted Request or reincarnation 1482bc78049SPatrick McHardy * sRS -> sRS Retransmitted Request (apparently Response 1492bc78049SPatrick McHardy * got lost after we saw it) or reincarnation 1502bc78049SPatrick McHardy * sPO -> sIG Ignore, conntrack might be out of sync 1512bc78049SPatrick McHardy * sOP -> sIG Ignore, conntrack might be out of sync 1522bc78049SPatrick McHardy * sCR -> sIG Ignore, conntrack might be out of sync 1532bc78049SPatrick McHardy * sCG -> sIG Ignore, conntrack might be out of sync 1542bc78049SPatrick McHardy * sTW -> sRQ Reincarnation 1552bc78049SPatrick McHardy * 1562bc78049SPatrick McHardy * sNO, sRQ, sRS, sPO. sOP, sCR, sCG, sTW, */ 1572bc78049SPatrick McHardy sRQ, sRQ, sRS, sIG, sIG, sIG, sIG, sRQ, 1582bc78049SPatrick McHardy }, 1592bc78049SPatrick McHardy [DCCP_PKT_RESPONSE] = { 1602bc78049SPatrick McHardy /* 1612bc78049SPatrick McHardy * sNO -> sIV Invalid 1622bc78049SPatrick McHardy * sRQ -> sIG Ignore, might be response to ignored Request 1632bc78049SPatrick McHardy * sRS -> sIG Ignore, might be response to ignored Request 1642bc78049SPatrick McHardy * sPO -> sIG Ignore, might be response to ignored Request 1652bc78049SPatrick McHardy * sOP -> sIG Ignore, might be response to ignored Request 1662bc78049SPatrick McHardy * sCR -> sIG Ignore, might be response to ignored Request 1672bc78049SPatrick McHardy * sCG -> sIG Ignore, might be response to ignored Request 1682bc78049SPatrick McHardy * sTW -> sIV Invalid, reincarnation in reverse direction 1692bc78049SPatrick McHardy * goes through sRQ 1702bc78049SPatrick McHardy * 1712bc78049SPatrick McHardy * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */ 1722bc78049SPatrick McHardy sIV, sIG, sIG, sIG, sIG, sIG, sIG, sIV, 1732bc78049SPatrick McHardy }, 1742bc78049SPatrick McHardy [DCCP_PKT_ACK] = { 1752bc78049SPatrick McHardy /* 1762bc78049SPatrick McHardy * sNO -> sIV No connection 1772bc78049SPatrick McHardy * sRQ -> sIV No connection 1782bc78049SPatrick McHardy * sRS -> sPO Ack for Response, move to PARTOPEN (8.1.5.) 1792bc78049SPatrick McHardy * sPO -> sPO Retransmitted Ack for Response, remain in PARTOPEN 1802bc78049SPatrick McHardy * sOP -> sOP Regular ACK, remain in OPEN 1812bc78049SPatrick McHardy * sCR -> sCR Ack in CLOSEREQ MAY be processed (8.3.) 1822bc78049SPatrick McHardy * sCG -> sCG Ack in CLOSING MAY be processed (8.3.) 1832bc78049SPatrick McHardy * sTW -> sIV 1842bc78049SPatrick McHardy * 1852bc78049SPatrick McHardy * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */ 1862bc78049SPatrick McHardy sIV, sIV, sPO, sPO, sOP, sCR, sCG, sIV 1872bc78049SPatrick McHardy }, 1882bc78049SPatrick McHardy [DCCP_PKT_DATA] = { 1892bc78049SPatrick McHardy /* 1902bc78049SPatrick McHardy * sNO -> sIV No connection 1912bc78049SPatrick McHardy * sRQ -> sIV No connection 1922bc78049SPatrick McHardy * sRS -> sIV No connection 1932bc78049SPatrick McHardy * sPO -> sIV MUST use DataAck in PARTOPEN state (8.1.5.) 1942bc78049SPatrick McHardy * sOP -> sOP Regular Data packet 1952bc78049SPatrick McHardy * sCR -> sCR Data in CLOSEREQ MAY be processed (8.3.) 1962bc78049SPatrick McHardy * sCG -> sCG Data in CLOSING MAY be processed (8.3.) 1972bc78049SPatrick McHardy * sTW -> sIV 1982bc78049SPatrick McHardy * 1992bc78049SPatrick McHardy * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */ 2002bc78049SPatrick McHardy sIV, sIV, sIV, sIV, sOP, sCR, sCG, sIV, 2012bc78049SPatrick McHardy }, 2022bc78049SPatrick McHardy [DCCP_PKT_DATAACK] = { 2032bc78049SPatrick McHardy /* 2042bc78049SPatrick McHardy * sNO -> sIV No connection 2052bc78049SPatrick McHardy * sRQ -> sIV No connection 2062bc78049SPatrick McHardy * sRS -> sPO Ack for Response, move to PARTOPEN (8.1.5.) 2072bc78049SPatrick McHardy * sPO -> sPO Remain in PARTOPEN state 2082bc78049SPatrick McHardy * sOP -> sOP Regular DataAck packet in OPEN state 2092bc78049SPatrick McHardy * sCR -> sCR DataAck in CLOSEREQ MAY be processed (8.3.) 2102bc78049SPatrick McHardy * sCG -> sCG DataAck in CLOSING MAY be processed (8.3.) 2112bc78049SPatrick McHardy * sTW -> sIV 2122bc78049SPatrick McHardy * 2132bc78049SPatrick McHardy * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */ 2142bc78049SPatrick McHardy sIV, sIV, sPO, sPO, sOP, sCR, sCG, sIV 2152bc78049SPatrick McHardy }, 2162bc78049SPatrick McHardy [DCCP_PKT_CLOSEREQ] = { 2172bc78049SPatrick McHardy /* 2182bc78049SPatrick McHardy * CLOSEREQ may only be sent by the server. 2192bc78049SPatrick McHardy * 2202bc78049SPatrick McHardy * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */ 2212bc78049SPatrick McHardy sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV 2222bc78049SPatrick McHardy }, 2232bc78049SPatrick McHardy [DCCP_PKT_CLOSE] = { 2242bc78049SPatrick McHardy /* 2252bc78049SPatrick McHardy * sNO -> sIV No connection 2262bc78049SPatrick McHardy * sRQ -> sIV No connection 2272bc78049SPatrick McHardy * sRS -> sIV No connection 2282bc78049SPatrick McHardy * sPO -> sCG Client-initiated close 2292bc78049SPatrick McHardy * sOP -> sCG Client-initiated close 2302bc78049SPatrick McHardy * sCR -> sCG Close in response to CloseReq (8.3.) 2312bc78049SPatrick McHardy * sCG -> sCG Retransmit 2322bc78049SPatrick McHardy * sTW -> sIV Late retransmit, already in TIME_WAIT 2332bc78049SPatrick McHardy * 2342bc78049SPatrick McHardy * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */ 2352bc78049SPatrick McHardy sIV, sIV, sIV, sCG, sCG, sCG, sIV, sIV 2362bc78049SPatrick McHardy }, 2372bc78049SPatrick McHardy [DCCP_PKT_RESET] = { 2382bc78049SPatrick McHardy /* 2392bc78049SPatrick McHardy * sNO -> sIV No connection 2402bc78049SPatrick McHardy * sRQ -> sTW Sync received or timeout, SHOULD send Reset (8.1.1.) 2412bc78049SPatrick McHardy * sRS -> sTW Response received without Request 2422bc78049SPatrick McHardy * sPO -> sTW Timeout, SHOULD send Reset (8.1.5.) 2432bc78049SPatrick McHardy * sOP -> sTW Connection reset 2442bc78049SPatrick McHardy * sCR -> sTW Connection reset 2452bc78049SPatrick McHardy * sCG -> sTW Connection reset 2462bc78049SPatrick McHardy * sTW -> sIG Ignore (don't refresh timer) 2472bc78049SPatrick McHardy * 2482bc78049SPatrick McHardy * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */ 2492bc78049SPatrick McHardy sIV, sTW, sTW, sTW, sTW, sTW, sTW, sIG 2502bc78049SPatrick McHardy }, 2512bc78049SPatrick McHardy [DCCP_PKT_SYNC] = { 2522bc78049SPatrick McHardy /* 2532bc78049SPatrick McHardy * We currently ignore Sync packets 2542bc78049SPatrick McHardy * 2552bc78049SPatrick McHardy * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */ 2562bc78049SPatrick McHardy sIG, sIG, sIG, sIG, sIG, sIG, sIG, sIG, 2572bc78049SPatrick McHardy }, 2582bc78049SPatrick McHardy [DCCP_PKT_SYNCACK] = { 2592bc78049SPatrick McHardy /* 2602bc78049SPatrick McHardy * We currently ignore SyncAck packets 2612bc78049SPatrick McHardy * 2622bc78049SPatrick McHardy * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */ 2632bc78049SPatrick McHardy sIG, sIG, sIG, sIG, sIG, sIG, sIG, sIG, 2642bc78049SPatrick McHardy }, 2652bc78049SPatrick McHardy }, 2662bc78049SPatrick McHardy [CT_DCCP_ROLE_SERVER] = { 2672bc78049SPatrick McHardy [DCCP_PKT_REQUEST] = { 2682bc78049SPatrick McHardy /* 2692bc78049SPatrick McHardy * sNO -> sIV Invalid 2702bc78049SPatrick McHardy * sRQ -> sIG Ignore, conntrack might be out of sync 2712bc78049SPatrick McHardy * sRS -> sIG Ignore, conntrack might be out of sync 2722bc78049SPatrick McHardy * sPO -> sIG Ignore, conntrack might be out of sync 2732bc78049SPatrick McHardy * sOP -> sIG Ignore, conntrack might be out of sync 2742bc78049SPatrick McHardy * sCR -> sIG Ignore, conntrack might be out of sync 2752bc78049SPatrick McHardy * sCG -> sIG Ignore, conntrack might be out of sync 2762bc78049SPatrick McHardy * sTW -> sRQ Reincarnation, must reverse roles 2772bc78049SPatrick McHardy * 2782bc78049SPatrick McHardy * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */ 2792bc78049SPatrick McHardy sIV, sIG, sIG, sIG, sIG, sIG, sIG, sRQ 2802bc78049SPatrick McHardy }, 2812bc78049SPatrick McHardy [DCCP_PKT_RESPONSE] = { 2822bc78049SPatrick McHardy /* 2832bc78049SPatrick McHardy * sNO -> sIV Response without Request 2842bc78049SPatrick McHardy * sRQ -> sRS Response to clients Request 2852bc78049SPatrick McHardy * sRS -> sRS Retransmitted Response (8.1.3. SHOULD NOT) 2862bc78049SPatrick McHardy * sPO -> sIG Response to an ignored Request or late retransmit 2872bc78049SPatrick McHardy * sOP -> sIG Ignore, might be response to ignored Request 2882bc78049SPatrick McHardy * sCR -> sIG Ignore, might be response to ignored Request 2892bc78049SPatrick McHardy * sCG -> sIG Ignore, might be response to ignored Request 2902bc78049SPatrick McHardy * sTW -> sIV Invalid, Request from client in sTW moves to sRQ 2912bc78049SPatrick McHardy * 2922bc78049SPatrick McHardy * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */ 2932bc78049SPatrick McHardy sIV, sRS, sRS, sIG, sIG, sIG, sIG, sIV 2942bc78049SPatrick McHardy }, 2952bc78049SPatrick McHardy [DCCP_PKT_ACK] = { 2962bc78049SPatrick McHardy /* 2972bc78049SPatrick McHardy * sNO -> sIV No connection 2982bc78049SPatrick McHardy * sRQ -> sIV No connection 2992bc78049SPatrick McHardy * sRS -> sIV No connection 3002bc78049SPatrick McHardy * sPO -> sOP Enter OPEN state (8.1.5.) 3012bc78049SPatrick McHardy * sOP -> sOP Regular Ack in OPEN state 3022bc78049SPatrick McHardy * sCR -> sIV Waiting for Close from client 3032bc78049SPatrick McHardy * sCG -> sCG Ack in CLOSING MAY be processed (8.3.) 3042bc78049SPatrick McHardy * sTW -> sIV 3052bc78049SPatrick McHardy * 3062bc78049SPatrick McHardy * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */ 3072bc78049SPatrick McHardy sIV, sIV, sIV, sOP, sOP, sIV, sCG, sIV 3082bc78049SPatrick McHardy }, 3092bc78049SPatrick McHardy [DCCP_PKT_DATA] = { 3102bc78049SPatrick McHardy /* 3112bc78049SPatrick McHardy * sNO -> sIV No connection 3122bc78049SPatrick McHardy * sRQ -> sIV No connection 3132bc78049SPatrick McHardy * sRS -> sIV No connection 3142bc78049SPatrick McHardy * sPO -> sOP Enter OPEN state (8.1.5.) 3152bc78049SPatrick McHardy * sOP -> sOP Regular Data packet in OPEN state 3162bc78049SPatrick McHardy * sCR -> sIV Waiting for Close from client 3172bc78049SPatrick McHardy * sCG -> sCG Data in CLOSING MAY be processed (8.3.) 3182bc78049SPatrick McHardy * sTW -> sIV 3192bc78049SPatrick McHardy * 3202bc78049SPatrick McHardy * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */ 3212bc78049SPatrick McHardy sIV, sIV, sIV, sOP, sOP, sIV, sCG, sIV 3222bc78049SPatrick McHardy }, 3232bc78049SPatrick McHardy [DCCP_PKT_DATAACK] = { 3242bc78049SPatrick McHardy /* 3252bc78049SPatrick McHardy * sNO -> sIV No connection 3262bc78049SPatrick McHardy * sRQ -> sIV No connection 3272bc78049SPatrick McHardy * sRS -> sIV No connection 3282bc78049SPatrick McHardy * sPO -> sOP Enter OPEN state (8.1.5.) 3292bc78049SPatrick McHardy * sOP -> sOP Regular DataAck in OPEN state 3302bc78049SPatrick McHardy * sCR -> sIV Waiting for Close from client 3312bc78049SPatrick McHardy * sCG -> sCG Data in CLOSING MAY be processed (8.3.) 3322bc78049SPatrick McHardy * sTW -> sIV 3332bc78049SPatrick McHardy * 3342bc78049SPatrick McHardy * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */ 3352bc78049SPatrick McHardy sIV, sIV, sIV, sOP, sOP, sIV, sCG, sIV 3362bc78049SPatrick McHardy }, 3372bc78049SPatrick McHardy [DCCP_PKT_CLOSEREQ] = { 3382bc78049SPatrick McHardy /* 3392bc78049SPatrick McHardy * sNO -> sIV No connection 3402bc78049SPatrick McHardy * sRQ -> sIV No connection 3412bc78049SPatrick McHardy * sRS -> sIV No connection 3422bc78049SPatrick McHardy * sPO -> sOP -> sCR Move directly to CLOSEREQ (8.1.5.) 3432bc78049SPatrick McHardy * sOP -> sCR CloseReq in OPEN state 3442bc78049SPatrick McHardy * sCR -> sCR Retransmit 3452bc78049SPatrick McHardy * sCG -> sCR Simultaneous close, client sends another Close 3462bc78049SPatrick McHardy * sTW -> sIV Already closed 3472bc78049SPatrick McHardy * 3482bc78049SPatrick McHardy * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */ 3492bc78049SPatrick McHardy sIV, sIV, sIV, sCR, sCR, sCR, sCR, sIV 3502bc78049SPatrick McHardy }, 3512bc78049SPatrick McHardy [DCCP_PKT_CLOSE] = { 3522bc78049SPatrick McHardy /* 3532bc78049SPatrick McHardy * sNO -> sIV No connection 3542bc78049SPatrick McHardy * sRQ -> sIV No connection 3552bc78049SPatrick McHardy * sRS -> sIV No connection 3562bc78049SPatrick McHardy * sPO -> sOP -> sCG Move direcly to CLOSING 3572bc78049SPatrick McHardy * sOP -> sCG Move to CLOSING 3582bc78049SPatrick McHardy * sCR -> sIV Close after CloseReq is invalid 3592bc78049SPatrick McHardy * sCG -> sCG Retransmit 3602bc78049SPatrick McHardy * sTW -> sIV Already closed 3612bc78049SPatrick McHardy * 3622bc78049SPatrick McHardy * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */ 3632bc78049SPatrick McHardy sIV, sIV, sIV, sCG, sCG, sIV, sCG, sIV 3642bc78049SPatrick McHardy }, 3652bc78049SPatrick McHardy [DCCP_PKT_RESET] = { 3662bc78049SPatrick McHardy /* 3672bc78049SPatrick McHardy * sNO -> sIV No connection 3682bc78049SPatrick McHardy * sRQ -> sTW Reset in response to Request 3692bc78049SPatrick McHardy * sRS -> sTW Timeout, SHOULD send Reset (8.1.3.) 3702bc78049SPatrick McHardy * sPO -> sTW Timeout, SHOULD send Reset (8.1.3.) 3712bc78049SPatrick McHardy * sOP -> sTW 3722bc78049SPatrick McHardy * sCR -> sTW 3732bc78049SPatrick McHardy * sCG -> sTW 3742bc78049SPatrick McHardy * sTW -> sIG Ignore (don't refresh timer) 3752bc78049SPatrick McHardy * 3762bc78049SPatrick McHardy * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW, sTW */ 3772bc78049SPatrick McHardy sIV, sTW, sTW, sTW, sTW, sTW, sTW, sTW, sIG 3782bc78049SPatrick McHardy }, 3792bc78049SPatrick McHardy [DCCP_PKT_SYNC] = { 3802bc78049SPatrick McHardy /* 3812bc78049SPatrick McHardy * We currently ignore Sync packets 3822bc78049SPatrick McHardy * 3832bc78049SPatrick McHardy * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */ 3842bc78049SPatrick McHardy sIG, sIG, sIG, sIG, sIG, sIG, sIG, sIG, 3852bc78049SPatrick McHardy }, 3862bc78049SPatrick McHardy [DCCP_PKT_SYNCACK] = { 3872bc78049SPatrick McHardy /* 3882bc78049SPatrick McHardy * We currently ignore SyncAck packets 3892bc78049SPatrick McHardy * 3902bc78049SPatrick McHardy * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */ 3912bc78049SPatrick McHardy sIG, sIG, sIG, sIG, sIG, sIG, sIG, sIG, 3922bc78049SPatrick McHardy }, 3932bc78049SPatrick McHardy }, 3942bc78049SPatrick McHardy }; 3952bc78049SPatrick McHardy 3962bc78049SPatrick McHardy static int dccp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff, 3972bc78049SPatrick McHardy struct nf_conntrack_tuple *tuple) 3982bc78049SPatrick McHardy { 3992bc78049SPatrick McHardy struct dccp_hdr _hdr, *dh; 4002bc78049SPatrick McHardy 4012bc78049SPatrick McHardy dh = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr); 4022bc78049SPatrick McHardy if (dh == NULL) 4032bc78049SPatrick McHardy return 0; 4042bc78049SPatrick McHardy 4052bc78049SPatrick McHardy tuple->src.u.dccp.port = dh->dccph_sport; 4062bc78049SPatrick McHardy tuple->dst.u.dccp.port = dh->dccph_dport; 4072bc78049SPatrick McHardy return 1; 4082bc78049SPatrick McHardy } 4092bc78049SPatrick McHardy 4102bc78049SPatrick McHardy static int dccp_invert_tuple(struct nf_conntrack_tuple *inv, 4112bc78049SPatrick McHardy const struct nf_conntrack_tuple *tuple) 4122bc78049SPatrick McHardy { 4132bc78049SPatrick McHardy inv->src.u.dccp.port = tuple->dst.u.dccp.port; 4142bc78049SPatrick McHardy inv->dst.u.dccp.port = tuple->src.u.dccp.port; 4152bc78049SPatrick McHardy return 1; 4162bc78049SPatrick McHardy } 4172bc78049SPatrick McHardy 4182bc78049SPatrick McHardy static int dccp_new(struct nf_conn *ct, const struct sk_buff *skb, 4192bc78049SPatrick McHardy unsigned int dataoff) 4202bc78049SPatrick McHardy { 4212bc78049SPatrick McHardy struct dccp_hdr _dh, *dh; 4222bc78049SPatrick McHardy const char *msg; 4232bc78049SPatrick McHardy u_int8_t state; 4242bc78049SPatrick McHardy 4252bc78049SPatrick McHardy dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &dh); 4262bc78049SPatrick McHardy BUG_ON(dh == NULL); 4272bc78049SPatrick McHardy 4282bc78049SPatrick McHardy state = dccp_state_table[CT_DCCP_ROLE_CLIENT][dh->dccph_type][CT_DCCP_NONE]; 4292bc78049SPatrick McHardy switch (state) { 4302bc78049SPatrick McHardy default: 4312bc78049SPatrick McHardy if (nf_ct_dccp_loose == 0) { 4322bc78049SPatrick McHardy msg = "nf_ct_dccp: not picking up existing connection "; 4332bc78049SPatrick McHardy goto out_invalid; 4342bc78049SPatrick McHardy } 4352bc78049SPatrick McHardy case CT_DCCP_REQUEST: 4362bc78049SPatrick McHardy break; 4372bc78049SPatrick McHardy case CT_DCCP_INVALID: 4382bc78049SPatrick McHardy msg = "nf_ct_dccp: invalid state transition "; 4392bc78049SPatrick McHardy goto out_invalid; 4402bc78049SPatrick McHardy } 4412bc78049SPatrick McHardy 4422bc78049SPatrick McHardy ct->proto.dccp.role[IP_CT_DIR_ORIGINAL] = CT_DCCP_ROLE_CLIENT; 4432bc78049SPatrick McHardy ct->proto.dccp.role[IP_CT_DIR_REPLY] = CT_DCCP_ROLE_SERVER; 4442bc78049SPatrick McHardy ct->proto.dccp.state = CT_DCCP_NONE; 4452bc78049SPatrick McHardy return 1; 4462bc78049SPatrick McHardy 4472bc78049SPatrick McHardy out_invalid: 4482bc78049SPatrick McHardy if (LOG_INVALID(IPPROTO_DCCP)) 4495e8fbe2aSPatrick McHardy nf_log_packet(nf_ct_l3num(ct), 0, skb, NULL, NULL, NULL, msg); 4502bc78049SPatrick McHardy return 0; 4512bc78049SPatrick McHardy } 4522bc78049SPatrick McHardy 4532bc78049SPatrick McHardy static u64 dccp_ack_seq(const struct dccp_hdr *dh) 4542bc78049SPatrick McHardy { 4552bc78049SPatrick McHardy const struct dccp_hdr_ack_bits *dhack; 4562bc78049SPatrick McHardy 4572bc78049SPatrick McHardy dhack = (void *)dh + __dccp_basic_hdr_len(dh); 4582bc78049SPatrick McHardy return ((u64)ntohs(dhack->dccph_ack_nr_high) << 32) + 4592bc78049SPatrick McHardy ntohl(dhack->dccph_ack_nr_low); 4602bc78049SPatrick McHardy } 4612bc78049SPatrick McHardy 4622bc78049SPatrick McHardy static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb, 4632bc78049SPatrick McHardy unsigned int dataoff, enum ip_conntrack_info ctinfo, 4642bc78049SPatrick McHardy int pf, unsigned int hooknum) 4652bc78049SPatrick McHardy { 4662bc78049SPatrick McHardy enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); 4672bc78049SPatrick McHardy struct dccp_hdr _dh, *dh; 4682bc78049SPatrick McHardy u_int8_t type, old_state, new_state; 4692bc78049SPatrick McHardy enum ct_dccp_roles role; 4702bc78049SPatrick McHardy 4712bc78049SPatrick McHardy dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &dh); 4722bc78049SPatrick McHardy BUG_ON(dh == NULL); 4732bc78049SPatrick McHardy type = dh->dccph_type; 4742bc78049SPatrick McHardy 4752bc78049SPatrick McHardy if (type == DCCP_PKT_RESET && 4762bc78049SPatrick McHardy !test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) { 4772bc78049SPatrick McHardy /* Tear down connection immediately if only reply is a RESET */ 4782bc78049SPatrick McHardy if (del_timer(&ct->timeout)) 4792bc78049SPatrick McHardy ct->timeout.function((unsigned long)ct); 4802bc78049SPatrick McHardy return NF_ACCEPT; 4812bc78049SPatrick McHardy } 4822bc78049SPatrick McHardy 4832bc78049SPatrick McHardy write_lock_bh(&dccp_lock); 4842bc78049SPatrick McHardy 4852bc78049SPatrick McHardy role = ct->proto.dccp.role[dir]; 4862bc78049SPatrick McHardy old_state = ct->proto.dccp.state; 4872bc78049SPatrick McHardy new_state = dccp_state_table[role][type][old_state]; 4882bc78049SPatrick McHardy 4892bc78049SPatrick McHardy switch (new_state) { 4902bc78049SPatrick McHardy case CT_DCCP_REQUEST: 4912bc78049SPatrick McHardy if (old_state == CT_DCCP_TIMEWAIT && 4922bc78049SPatrick McHardy role == CT_DCCP_ROLE_SERVER) { 4932bc78049SPatrick McHardy /* Reincarnation in the reverse direction: reopen and 4942bc78049SPatrick McHardy * reverse client/server roles. */ 4952bc78049SPatrick McHardy ct->proto.dccp.role[dir] = CT_DCCP_ROLE_CLIENT; 4962bc78049SPatrick McHardy ct->proto.dccp.role[!dir] = CT_DCCP_ROLE_SERVER; 4972bc78049SPatrick McHardy } 4982bc78049SPatrick McHardy break; 4992bc78049SPatrick McHardy case CT_DCCP_RESPOND: 5002bc78049SPatrick McHardy if (old_state == CT_DCCP_REQUEST) 5012bc78049SPatrick McHardy ct->proto.dccp.handshake_seq = dccp_hdr_seq(dh); 5022bc78049SPatrick McHardy break; 5032bc78049SPatrick McHardy case CT_DCCP_PARTOPEN: 5042bc78049SPatrick McHardy if (old_state == CT_DCCP_RESPOND && 5052bc78049SPatrick McHardy type == DCCP_PKT_ACK && 5062bc78049SPatrick McHardy dccp_ack_seq(dh) == ct->proto.dccp.handshake_seq) 5072bc78049SPatrick McHardy set_bit(IPS_ASSURED_BIT, &ct->status); 5082bc78049SPatrick McHardy break; 5092bc78049SPatrick McHardy case CT_DCCP_IGNORE: 5102bc78049SPatrick McHardy /* 5112bc78049SPatrick McHardy * Connection tracking might be out of sync, so we ignore 5122bc78049SPatrick McHardy * packets that might establish a new connection and resync 5132bc78049SPatrick McHardy * if the server responds with a valid Response. 5142bc78049SPatrick McHardy */ 5152bc78049SPatrick McHardy if (ct->proto.dccp.last_dir == !dir && 5162bc78049SPatrick McHardy ct->proto.dccp.last_pkt == DCCP_PKT_REQUEST && 5172bc78049SPatrick McHardy type == DCCP_PKT_RESPONSE) { 5182bc78049SPatrick McHardy ct->proto.dccp.role[!dir] = CT_DCCP_ROLE_CLIENT; 5192bc78049SPatrick McHardy ct->proto.dccp.role[dir] = CT_DCCP_ROLE_SERVER; 5202bc78049SPatrick McHardy ct->proto.dccp.handshake_seq = dccp_hdr_seq(dh); 5212bc78049SPatrick McHardy new_state = CT_DCCP_RESPOND; 5222bc78049SPatrick McHardy break; 5232bc78049SPatrick McHardy } 5242bc78049SPatrick McHardy ct->proto.dccp.last_dir = dir; 5252bc78049SPatrick McHardy ct->proto.dccp.last_pkt = type; 5262bc78049SPatrick McHardy 5272bc78049SPatrick McHardy write_unlock_bh(&dccp_lock); 5282bc78049SPatrick McHardy if (LOG_INVALID(IPPROTO_DCCP)) 5292bc78049SPatrick McHardy nf_log_packet(pf, 0, skb, NULL, NULL, NULL, 5302bc78049SPatrick McHardy "nf_ct_dccp: invalid packet ignored "); 5312bc78049SPatrick McHardy return NF_ACCEPT; 5322bc78049SPatrick McHardy case CT_DCCP_INVALID: 5332bc78049SPatrick McHardy write_unlock_bh(&dccp_lock); 5342bc78049SPatrick McHardy if (LOG_INVALID(IPPROTO_DCCP)) 5352bc78049SPatrick McHardy nf_log_packet(pf, 0, skb, NULL, NULL, NULL, 5362bc78049SPatrick McHardy "nf_ct_dccp: invalid state transition "); 5372bc78049SPatrick McHardy return -NF_ACCEPT; 5382bc78049SPatrick McHardy } 5392bc78049SPatrick McHardy 5402bc78049SPatrick McHardy ct->proto.dccp.last_dir = dir; 5412bc78049SPatrick McHardy ct->proto.dccp.last_pkt = type; 5422bc78049SPatrick McHardy ct->proto.dccp.state = new_state; 5432bc78049SPatrick McHardy write_unlock_bh(&dccp_lock); 5442bc78049SPatrick McHardy nf_ct_refresh_acct(ct, ctinfo, skb, dccp_timeout[new_state]); 5452bc78049SPatrick McHardy 5462bc78049SPatrick McHardy return NF_ACCEPT; 5472bc78049SPatrick McHardy } 5482bc78049SPatrick McHardy 5492bc78049SPatrick McHardy static int dccp_error(struct sk_buff *skb, unsigned int dataoff, 5502bc78049SPatrick McHardy enum ip_conntrack_info *ctinfo, int pf, 5512bc78049SPatrick McHardy unsigned int hooknum) 5522bc78049SPatrick McHardy { 5532bc78049SPatrick McHardy struct dccp_hdr _dh, *dh; 5542bc78049SPatrick McHardy unsigned int dccp_len = skb->len - dataoff; 5552bc78049SPatrick McHardy unsigned int cscov; 5562bc78049SPatrick McHardy const char *msg; 5572bc78049SPatrick McHardy 5582bc78049SPatrick McHardy dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &dh); 5592bc78049SPatrick McHardy if (dh == NULL) { 5602bc78049SPatrick McHardy msg = "nf_ct_dccp: short packet "; 5612bc78049SPatrick McHardy goto out_invalid; 5622bc78049SPatrick McHardy } 5632bc78049SPatrick McHardy 5642bc78049SPatrick McHardy if (dh->dccph_doff * 4 < sizeof(struct dccp_hdr) || 5652bc78049SPatrick McHardy dh->dccph_doff * 4 > dccp_len) { 5662bc78049SPatrick McHardy msg = "nf_ct_dccp: truncated/malformed packet "; 5672bc78049SPatrick McHardy goto out_invalid; 5682bc78049SPatrick McHardy } 5692bc78049SPatrick McHardy 5702bc78049SPatrick McHardy cscov = dccp_len; 5712bc78049SPatrick McHardy if (dh->dccph_cscov) { 5722bc78049SPatrick McHardy cscov = (dh->dccph_cscov - 1) * 4; 5732bc78049SPatrick McHardy if (cscov > dccp_len) { 5742bc78049SPatrick McHardy msg = "nf_ct_dccp: bad checksum coverage "; 5752bc78049SPatrick McHardy goto out_invalid; 5762bc78049SPatrick McHardy } 5772bc78049SPatrick McHardy } 5782bc78049SPatrick McHardy 5792bc78049SPatrick McHardy if (nf_conntrack_checksum && hooknum == NF_INET_PRE_ROUTING && 5802bc78049SPatrick McHardy nf_checksum_partial(skb, hooknum, dataoff, cscov, IPPROTO_DCCP, 5812bc78049SPatrick McHardy pf)) { 5822bc78049SPatrick McHardy msg = "nf_ct_dccp: bad checksum "; 5832bc78049SPatrick McHardy goto out_invalid; 5842bc78049SPatrick McHardy } 5852bc78049SPatrick McHardy 5862bc78049SPatrick McHardy if (dh->dccph_type >= DCCP_PKT_INVALID) { 5872bc78049SPatrick McHardy msg = "nf_ct_dccp: reserved packet type "; 5882bc78049SPatrick McHardy goto out_invalid; 5892bc78049SPatrick McHardy } 5902bc78049SPatrick McHardy 5912bc78049SPatrick McHardy return NF_ACCEPT; 5922bc78049SPatrick McHardy 5932bc78049SPatrick McHardy out_invalid: 5942bc78049SPatrick McHardy if (LOG_INVALID(IPPROTO_DCCP)) 5952bc78049SPatrick McHardy nf_log_packet(pf, 0, skb, NULL, NULL, NULL, msg); 5962bc78049SPatrick McHardy return -NF_ACCEPT; 5972bc78049SPatrick McHardy } 5982bc78049SPatrick McHardy 5992bc78049SPatrick McHardy static int dccp_print_tuple(struct seq_file *s, 6002bc78049SPatrick McHardy const struct nf_conntrack_tuple *tuple) 6012bc78049SPatrick McHardy { 6022bc78049SPatrick McHardy return seq_printf(s, "sport=%hu dport=%hu ", 6032bc78049SPatrick McHardy ntohs(tuple->src.u.dccp.port), 6042bc78049SPatrick McHardy ntohs(tuple->dst.u.dccp.port)); 6052bc78049SPatrick McHardy } 6062bc78049SPatrick McHardy 6072bc78049SPatrick McHardy static int dccp_print_conntrack(struct seq_file *s, const struct nf_conn *ct) 6082bc78049SPatrick McHardy { 6092bc78049SPatrick McHardy return seq_printf(s, "%s ", dccp_state_names[ct->proto.dccp.state]); 6102bc78049SPatrick McHardy } 6112bc78049SPatrick McHardy 6122bc78049SPatrick McHardy #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) 6132bc78049SPatrick McHardy static int dccp_to_nlattr(struct sk_buff *skb, struct nlattr *nla, 6142bc78049SPatrick McHardy const struct nf_conn *ct) 6152bc78049SPatrick McHardy { 6162bc78049SPatrick McHardy struct nlattr *nest_parms; 6172bc78049SPatrick McHardy 6182bc78049SPatrick McHardy read_lock_bh(&dccp_lock); 6192bc78049SPatrick McHardy nest_parms = nla_nest_start(skb, CTA_PROTOINFO_DCCP | NLA_F_NESTED); 6202bc78049SPatrick McHardy if (!nest_parms) 6212bc78049SPatrick McHardy goto nla_put_failure; 6222bc78049SPatrick McHardy NLA_PUT_U8(skb, CTA_PROTOINFO_DCCP_STATE, ct->proto.dccp.state); 6232bc78049SPatrick McHardy nla_nest_end(skb, nest_parms); 6242bc78049SPatrick McHardy read_unlock_bh(&dccp_lock); 6252bc78049SPatrick McHardy return 0; 6262bc78049SPatrick McHardy 6272bc78049SPatrick McHardy nla_put_failure: 6282bc78049SPatrick McHardy read_unlock_bh(&dccp_lock); 6292bc78049SPatrick McHardy return -1; 6302bc78049SPatrick McHardy } 6312bc78049SPatrick McHardy 6322bc78049SPatrick McHardy static const struct nla_policy dccp_nla_policy[CTA_PROTOINFO_DCCP_MAX + 1] = { 6332bc78049SPatrick McHardy [CTA_PROTOINFO_DCCP_STATE] = { .type = NLA_U8 }, 6342bc78049SPatrick McHardy }; 6352bc78049SPatrick McHardy 6362bc78049SPatrick McHardy static int nlattr_to_dccp(struct nlattr *cda[], struct nf_conn *ct) 6372bc78049SPatrick McHardy { 6382bc78049SPatrick McHardy struct nlattr *attr = cda[CTA_PROTOINFO_DCCP]; 6392bc78049SPatrick McHardy struct nlattr *tb[CTA_PROTOINFO_DCCP_MAX + 1]; 6402bc78049SPatrick McHardy int err; 6412bc78049SPatrick McHardy 6422bc78049SPatrick McHardy if (!attr) 6432bc78049SPatrick McHardy return 0; 6442bc78049SPatrick McHardy 6452bc78049SPatrick McHardy err = nla_parse_nested(tb, CTA_PROTOINFO_DCCP_MAX, attr, 6462bc78049SPatrick McHardy dccp_nla_policy); 6472bc78049SPatrick McHardy if (err < 0) 6482bc78049SPatrick McHardy return err; 6492bc78049SPatrick McHardy 6502bc78049SPatrick McHardy if (!tb[CTA_PROTOINFO_DCCP_STATE] || 6512bc78049SPatrick McHardy nla_get_u8(tb[CTA_PROTOINFO_DCCP_STATE]) >= CT_DCCP_IGNORE) 6522bc78049SPatrick McHardy return -EINVAL; 6532bc78049SPatrick McHardy 6542bc78049SPatrick McHardy write_lock_bh(&dccp_lock); 6552bc78049SPatrick McHardy ct->proto.dccp.state = nla_get_u8(tb[CTA_PROTOINFO_DCCP_STATE]); 6562bc78049SPatrick McHardy write_unlock_bh(&dccp_lock); 6572bc78049SPatrick McHardy return 0; 6582bc78049SPatrick McHardy } 6592bc78049SPatrick McHardy #endif 6602bc78049SPatrick McHardy 6612bc78049SPatrick McHardy #ifdef CONFIG_SYSCTL 6622bc78049SPatrick McHardy static unsigned int dccp_sysctl_table_users; 6632bc78049SPatrick McHardy static struct ctl_table_header *dccp_sysctl_header; 6642bc78049SPatrick McHardy static ctl_table dccp_sysctl_table[] = { 6652bc78049SPatrick McHardy { 6662bc78049SPatrick McHardy .ctl_name = CTL_UNNUMBERED, 6672bc78049SPatrick McHardy .procname = "nf_conntrack_dccp_timeout_request", 6682bc78049SPatrick McHardy .data = &dccp_timeout[CT_DCCP_REQUEST], 6692bc78049SPatrick McHardy .maxlen = sizeof(unsigned int), 6702bc78049SPatrick McHardy .mode = 0644, 6712bc78049SPatrick McHardy .proc_handler = proc_dointvec_jiffies, 6722bc78049SPatrick McHardy }, 6732bc78049SPatrick McHardy { 6742bc78049SPatrick McHardy .ctl_name = CTL_UNNUMBERED, 6752bc78049SPatrick McHardy .procname = "nf_conntrack_dccp_timeout_respond", 6762bc78049SPatrick McHardy .data = &dccp_timeout[CT_DCCP_RESPOND], 6772bc78049SPatrick McHardy .maxlen = sizeof(unsigned int), 6782bc78049SPatrick McHardy .mode = 0644, 6792bc78049SPatrick McHardy .proc_handler = proc_dointvec_jiffies, 6802bc78049SPatrick McHardy }, 6812bc78049SPatrick McHardy { 6822bc78049SPatrick McHardy .ctl_name = CTL_UNNUMBERED, 6832bc78049SPatrick McHardy .procname = "nf_conntrack_dccp_timeout_partopen", 6842bc78049SPatrick McHardy .data = &dccp_timeout[CT_DCCP_PARTOPEN], 6852bc78049SPatrick McHardy .maxlen = sizeof(unsigned int), 6862bc78049SPatrick McHardy .mode = 0644, 6872bc78049SPatrick McHardy .proc_handler = proc_dointvec_jiffies, 6882bc78049SPatrick McHardy }, 6892bc78049SPatrick McHardy { 6902bc78049SPatrick McHardy .ctl_name = CTL_UNNUMBERED, 6912bc78049SPatrick McHardy .procname = "nf_conntrack_dccp_timeout_open", 6922bc78049SPatrick McHardy .data = &dccp_timeout[CT_DCCP_OPEN], 6932bc78049SPatrick McHardy .maxlen = sizeof(unsigned int), 6942bc78049SPatrick McHardy .mode = 0644, 6952bc78049SPatrick McHardy .proc_handler = proc_dointvec_jiffies, 6962bc78049SPatrick McHardy }, 6972bc78049SPatrick McHardy { 6982bc78049SPatrick McHardy .ctl_name = CTL_UNNUMBERED, 6992bc78049SPatrick McHardy .procname = "nf_conntrack_dccp_timeout_closereq", 7002bc78049SPatrick McHardy .data = &dccp_timeout[CT_DCCP_CLOSEREQ], 7012bc78049SPatrick McHardy .maxlen = sizeof(unsigned int), 7022bc78049SPatrick McHardy .mode = 0644, 7032bc78049SPatrick McHardy .proc_handler = proc_dointvec_jiffies, 7042bc78049SPatrick McHardy }, 7052bc78049SPatrick McHardy { 7062bc78049SPatrick McHardy .ctl_name = CTL_UNNUMBERED, 7072bc78049SPatrick McHardy .procname = "nf_conntrack_dccp_timeout_closing", 7082bc78049SPatrick McHardy .data = &dccp_timeout[CT_DCCP_CLOSING], 7092bc78049SPatrick McHardy .maxlen = sizeof(unsigned int), 7102bc78049SPatrick McHardy .mode = 0644, 7112bc78049SPatrick McHardy .proc_handler = proc_dointvec_jiffies, 7122bc78049SPatrick McHardy }, 7132bc78049SPatrick McHardy { 7142bc78049SPatrick McHardy .ctl_name = CTL_UNNUMBERED, 7152bc78049SPatrick McHardy .procname = "nf_conntrack_dccp_timeout_timewait", 7162bc78049SPatrick McHardy .data = &dccp_timeout[CT_DCCP_TIMEWAIT], 7172bc78049SPatrick McHardy .maxlen = sizeof(unsigned int), 7182bc78049SPatrick McHardy .mode = 0644, 7192bc78049SPatrick McHardy .proc_handler = proc_dointvec_jiffies, 7202bc78049SPatrick McHardy }, 7212bc78049SPatrick McHardy { 7222bc78049SPatrick McHardy .ctl_name = CTL_UNNUMBERED, 7232bc78049SPatrick McHardy .procname = "nf_conntrack_dccp_loose", 7242bc78049SPatrick McHardy .data = &nf_ct_dccp_loose, 7252bc78049SPatrick McHardy .maxlen = sizeof(nf_ct_dccp_loose), 7262bc78049SPatrick McHardy .mode = 0644, 7272bc78049SPatrick McHardy .proc_handler = proc_dointvec, 7282bc78049SPatrick McHardy }, 7292bc78049SPatrick McHardy { 7302bc78049SPatrick McHardy .ctl_name = 0, 7312bc78049SPatrick McHardy } 7322bc78049SPatrick McHardy }; 7332bc78049SPatrick McHardy #endif /* CONFIG_SYSCTL */ 7342bc78049SPatrick McHardy 7352bc78049SPatrick McHardy static struct nf_conntrack_l4proto dccp_proto4 __read_mostly = { 7362bc78049SPatrick McHardy .l3proto = AF_INET, 7372bc78049SPatrick McHardy .l4proto = IPPROTO_DCCP, 7382bc78049SPatrick McHardy .name = "dccp", 7392bc78049SPatrick McHardy .pkt_to_tuple = dccp_pkt_to_tuple, 7402bc78049SPatrick McHardy .invert_tuple = dccp_invert_tuple, 7412bc78049SPatrick McHardy .new = dccp_new, 7422bc78049SPatrick McHardy .packet = dccp_packet, 7432bc78049SPatrick McHardy .error = dccp_error, 7442bc78049SPatrick McHardy .print_tuple = dccp_print_tuple, 7452bc78049SPatrick McHardy .print_conntrack = dccp_print_conntrack, 7462bc78049SPatrick McHardy #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) 7472bc78049SPatrick McHardy .to_nlattr = dccp_to_nlattr, 7482bc78049SPatrick McHardy .from_nlattr = nlattr_to_dccp, 7492bc78049SPatrick McHardy .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, 7502bc78049SPatrick McHardy .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, 7512bc78049SPatrick McHardy .nla_policy = nf_ct_port_nla_policy, 7522bc78049SPatrick McHardy #endif 7532bc78049SPatrick McHardy #ifdef CONFIG_SYSCTL 7542bc78049SPatrick McHardy .ctl_table_users = &dccp_sysctl_table_users, 7552bc78049SPatrick McHardy .ctl_table_header = &dccp_sysctl_header, 7562bc78049SPatrick McHardy .ctl_table = dccp_sysctl_table, 7572bc78049SPatrick McHardy #endif 7582bc78049SPatrick McHardy }; 7592bc78049SPatrick McHardy 7602bc78049SPatrick McHardy static struct nf_conntrack_l4proto dccp_proto6 __read_mostly = { 7612bc78049SPatrick McHardy .l3proto = AF_INET6, 7622bc78049SPatrick McHardy .l4proto = IPPROTO_DCCP, 7632bc78049SPatrick McHardy .name = "dccp", 7642bc78049SPatrick McHardy .pkt_to_tuple = dccp_pkt_to_tuple, 7652bc78049SPatrick McHardy .invert_tuple = dccp_invert_tuple, 7662bc78049SPatrick McHardy .new = dccp_new, 7672bc78049SPatrick McHardy .packet = dccp_packet, 7682bc78049SPatrick McHardy .error = dccp_error, 7692bc78049SPatrick McHardy .print_tuple = dccp_print_tuple, 7702bc78049SPatrick McHardy .print_conntrack = dccp_print_conntrack, 7712bc78049SPatrick McHardy #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) 7722bc78049SPatrick McHardy .to_nlattr = dccp_to_nlattr, 7732bc78049SPatrick McHardy .from_nlattr = nlattr_to_dccp, 7742bc78049SPatrick McHardy .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, 7752bc78049SPatrick McHardy .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, 7762bc78049SPatrick McHardy .nla_policy = nf_ct_port_nla_policy, 7772bc78049SPatrick McHardy #endif 7782bc78049SPatrick McHardy #ifdef CONFIG_SYSCTL 7792bc78049SPatrick McHardy .ctl_table_users = &dccp_sysctl_table_users, 7802bc78049SPatrick McHardy .ctl_table_header = &dccp_sysctl_header, 7812bc78049SPatrick McHardy .ctl_table = dccp_sysctl_table, 7822bc78049SPatrick McHardy #endif 7832bc78049SPatrick McHardy }; 7842bc78049SPatrick McHardy 7852bc78049SPatrick McHardy static int __init nf_conntrack_proto_dccp_init(void) 7862bc78049SPatrick McHardy { 7872bc78049SPatrick McHardy int err; 7882bc78049SPatrick McHardy 7892bc78049SPatrick McHardy err = nf_conntrack_l4proto_register(&dccp_proto4); 7902bc78049SPatrick McHardy if (err < 0) 7912bc78049SPatrick McHardy goto err1; 7922bc78049SPatrick McHardy 7932bc78049SPatrick McHardy err = nf_conntrack_l4proto_register(&dccp_proto6); 7942bc78049SPatrick McHardy if (err < 0) 7952bc78049SPatrick McHardy goto err2; 7962bc78049SPatrick McHardy return 0; 7972bc78049SPatrick McHardy 7982bc78049SPatrick McHardy err2: 7992bc78049SPatrick McHardy nf_conntrack_l4proto_unregister(&dccp_proto4); 8002bc78049SPatrick McHardy err1: 8012bc78049SPatrick McHardy return err; 8022bc78049SPatrick McHardy } 8032bc78049SPatrick McHardy 8042bc78049SPatrick McHardy static void __exit nf_conntrack_proto_dccp_fini(void) 8052bc78049SPatrick McHardy { 8062bc78049SPatrick McHardy nf_conntrack_l4proto_unregister(&dccp_proto6); 8072bc78049SPatrick McHardy nf_conntrack_l4proto_unregister(&dccp_proto4); 8082bc78049SPatrick McHardy } 8092bc78049SPatrick McHardy 8102bc78049SPatrick McHardy module_init(nf_conntrack_proto_dccp_init); 8112bc78049SPatrick McHardy module_exit(nf_conntrack_proto_dccp_fini); 8122bc78049SPatrick McHardy 8132bc78049SPatrick McHardy MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); 8142bc78049SPatrick McHardy MODULE_DESCRIPTION("DCCP connection tracking protocol helper"); 8152bc78049SPatrick McHardy MODULE_LICENSE("GPL"); 816