148b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy/* 248b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy * Copyright (c) 2013 Patrick McHardy <kaber@trash.net> 348b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy * 448b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy * This program is free software; you can redistribute it and/or modify 548b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy * it under the terms of the GNU General Public License version 2 as 648b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy * published by the Free Software Foundation. 748b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy */ 848b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 948b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy#include <linux/module.h> 1048b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy#include <linux/skbuff.h> 1148b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy#include <asm/unaligned.h> 1248b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy#include <net/tcp.h> 1348b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy#include <net/netns/generic.h> 1448b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 1548b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy#include <linux/netfilter_ipv4/ip_tables.h> 1648b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy#include <linux/netfilter/x_tables.h> 1748b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy#include <linux/netfilter/xt_tcpudp.h> 1848b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy#include <linux/netfilter/xt_SYNPROXY.h> 1948b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy#include <net/netfilter/nf_conntrack.h> 2048b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy#include <net/netfilter/nf_conntrack_extend.h> 2148b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy#include <net/netfilter/nf_conntrack_seqadj.h> 2248b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy#include <net/netfilter/nf_conntrack_synproxy.h> 2348b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 2448b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardyint synproxy_net_id; 2548b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardyEXPORT_SYMBOL_GPL(synproxy_net_id); 2648b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 27f4a87e7bd2eaef26a3ca25437ce8b807de2966adPatrick McHardybool 2848b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardysynproxy_parse_options(const struct sk_buff *skb, unsigned int doff, 2948b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy const struct tcphdr *th, struct synproxy_options *opts) 3048b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy{ 3148b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy int length = (th->doff * 4) - sizeof(*th); 3248b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy u8 buf[40], *ptr; 3348b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 3448b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy ptr = skb_header_pointer(skb, doff + sizeof(*th), length, buf); 35f4a87e7bd2eaef26a3ca25437ce8b807de2966adPatrick McHardy if (ptr == NULL) 36f4a87e7bd2eaef26a3ca25437ce8b807de2966adPatrick McHardy return false; 3748b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 3848b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy opts->options = 0; 3948b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy while (length > 0) { 4048b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy int opcode = *ptr++; 4148b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy int opsize; 4248b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 4348b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy switch (opcode) { 4448b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy case TCPOPT_EOL: 45f4a87e7bd2eaef26a3ca25437ce8b807de2966adPatrick McHardy return true; 4648b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy case TCPOPT_NOP: 4748b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy length--; 4848b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy continue; 4948b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy default: 5048b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy opsize = *ptr++; 5148b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy if (opsize < 2) 52f4a87e7bd2eaef26a3ca25437ce8b807de2966adPatrick McHardy return true; 5348b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy if (opsize > length) 54f4a87e7bd2eaef26a3ca25437ce8b807de2966adPatrick McHardy return true; 5548b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 5648b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy switch (opcode) { 5748b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy case TCPOPT_MSS: 5848b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy if (opsize == TCPOLEN_MSS) { 5948b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy opts->mss = get_unaligned_be16(ptr); 6048b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy opts->options |= XT_SYNPROXY_OPT_MSS; 6148b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy } 6248b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy break; 6348b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy case TCPOPT_WINDOW: 6448b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy if (opsize == TCPOLEN_WINDOW) { 6548b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy opts->wscale = *ptr; 6648b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy if (opts->wscale > 14) 6748b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy opts->wscale = 14; 6848b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy opts->options |= XT_SYNPROXY_OPT_WSCALE; 6948b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy } 7048b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy break; 7148b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy case TCPOPT_TIMESTAMP: 7248b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy if (opsize == TCPOLEN_TIMESTAMP) { 7348b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy opts->tsval = get_unaligned_be32(ptr); 7448b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy opts->tsecr = get_unaligned_be32(ptr + 4); 7548b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy opts->options |= XT_SYNPROXY_OPT_TIMESTAMP; 7648b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy } 7748b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy break; 7848b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy case TCPOPT_SACK_PERM: 7948b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy if (opsize == TCPOLEN_SACK_PERM) 8048b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy opts->options |= XT_SYNPROXY_OPT_SACK_PERM; 8148b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy break; 8248b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy } 8348b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 8448b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy ptr += opsize - 2; 8548b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy length -= opsize; 8648b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy } 8748b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy } 88f4a87e7bd2eaef26a3ca25437ce8b807de2966adPatrick McHardy return true; 8948b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy} 9048b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardyEXPORT_SYMBOL_GPL(synproxy_parse_options); 9148b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 9248b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardyunsigned int synproxy_options_size(const struct synproxy_options *opts) 9348b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy{ 9448b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy unsigned int size = 0; 9548b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 9648b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy if (opts->options & XT_SYNPROXY_OPT_MSS) 9748b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy size += TCPOLEN_MSS_ALIGNED; 9848b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy if (opts->options & XT_SYNPROXY_OPT_TIMESTAMP) 9948b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy size += TCPOLEN_TSTAMP_ALIGNED; 10048b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy else if (opts->options & XT_SYNPROXY_OPT_SACK_PERM) 10148b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy size += TCPOLEN_SACKPERM_ALIGNED; 10248b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy if (opts->options & XT_SYNPROXY_OPT_WSCALE) 10348b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy size += TCPOLEN_WSCALE_ALIGNED; 10448b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 10548b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy return size; 10648b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy} 10748b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardyEXPORT_SYMBOL_GPL(synproxy_options_size); 10848b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 10948b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardyvoid 11048b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardysynproxy_build_options(struct tcphdr *th, const struct synproxy_options *opts) 11148b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy{ 11248b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy __be32 *ptr = (__be32 *)(th + 1); 11348b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy u8 options = opts->options; 11448b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 11548b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy if (options & XT_SYNPROXY_OPT_MSS) 11648b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy *ptr++ = htonl((TCPOPT_MSS << 24) | 11748b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy (TCPOLEN_MSS << 16) | 11848b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy opts->mss); 11948b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 12048b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy if (options & XT_SYNPROXY_OPT_TIMESTAMP) { 12148b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy if (options & XT_SYNPROXY_OPT_SACK_PERM) 12248b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy *ptr++ = htonl((TCPOPT_SACK_PERM << 24) | 12348b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy (TCPOLEN_SACK_PERM << 16) | 12448b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy (TCPOPT_TIMESTAMP << 8) | 12548b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy TCPOLEN_TIMESTAMP); 12648b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy else 12748b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy *ptr++ = htonl((TCPOPT_NOP << 24) | 12848b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy (TCPOPT_NOP << 16) | 12948b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy (TCPOPT_TIMESTAMP << 8) | 13048b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy TCPOLEN_TIMESTAMP); 13148b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 13248b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy *ptr++ = htonl(opts->tsval); 13348b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy *ptr++ = htonl(opts->tsecr); 13448b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy } else if (options & XT_SYNPROXY_OPT_SACK_PERM) 13548b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy *ptr++ = htonl((TCPOPT_NOP << 24) | 13648b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy (TCPOPT_NOP << 16) | 13748b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy (TCPOPT_SACK_PERM << 8) | 13848b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy TCPOLEN_SACK_PERM); 13948b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 14048b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy if (options & XT_SYNPROXY_OPT_WSCALE) 14148b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy *ptr++ = htonl((TCPOPT_NOP << 24) | 14248b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy (TCPOPT_WINDOW << 16) | 14348b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy (TCPOLEN_WINDOW << 8) | 14448b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy opts->wscale); 14548b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy} 14648b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardyEXPORT_SYMBOL_GPL(synproxy_build_options); 14748b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 14848b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardyvoid synproxy_init_timestamp_cookie(const struct xt_synproxy_info *info, 14948b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy struct synproxy_options *opts) 15048b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy{ 15148b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy opts->tsecr = opts->tsval; 15248b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy opts->tsval = tcp_time_stamp & ~0x3f; 15348b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 154c1898c4c295b735c05af4c09664993fd8f257c2bMartin Topholm if (opts->options & XT_SYNPROXY_OPT_WSCALE) { 155c1898c4c295b735c05af4c09664993fd8f257c2bMartin Topholm opts->tsval |= opts->wscale; 156c1898c4c295b735c05af4c09664993fd8f257c2bMartin Topholm opts->wscale = info->wscale; 157c1898c4c295b735c05af4c09664993fd8f257c2bMartin Topholm } else 15848b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy opts->tsval |= 0xf; 15948b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 16048b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy if (opts->options & XT_SYNPROXY_OPT_SACK_PERM) 16148b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy opts->tsval |= 1 << 4; 16248b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 16348b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy if (opts->options & XT_SYNPROXY_OPT_ECN) 16448b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy opts->tsval |= 1 << 5; 16548b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy} 16648b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardyEXPORT_SYMBOL_GPL(synproxy_init_timestamp_cookie); 16748b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 16848b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardyvoid synproxy_check_timestamp_cookie(struct synproxy_options *opts) 16948b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy{ 17048b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy opts->wscale = opts->tsecr & 0xf; 17148b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy if (opts->wscale != 0xf) 17248b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy opts->options |= XT_SYNPROXY_OPT_WSCALE; 17348b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 17448b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy opts->options |= opts->tsecr & (1 << 4) ? XT_SYNPROXY_OPT_SACK_PERM : 0; 17548b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 17648b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy opts->options |= opts->tsecr & (1 << 5) ? XT_SYNPROXY_OPT_ECN : 0; 17748b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy} 17848b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardyEXPORT_SYMBOL_GPL(synproxy_check_timestamp_cookie); 17948b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 18048b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardyunsigned int synproxy_tstamp_adjust(struct sk_buff *skb, 18148b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy unsigned int protoff, 18248b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy struct tcphdr *th, 18348b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy struct nf_conn *ct, 18448b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy enum ip_conntrack_info ctinfo, 18548b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy const struct nf_conn_synproxy *synproxy) 18648b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy{ 18748b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy unsigned int optoff, optend; 18848b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy u32 *ptr, old; 18948b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 19048b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy if (synproxy->tsoff == 0) 19148b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy return 1; 19248b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 19348b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy optoff = protoff + sizeof(struct tcphdr); 19448b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy optend = protoff + th->doff * 4; 19548b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 19648b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy if (!skb_make_writable(skb, optend)) 19748b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy return 0; 19848b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 19948b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy while (optoff < optend) { 20048b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy unsigned char *op = skb->data + optoff; 20148b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 20248b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy switch (op[0]) { 20348b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy case TCPOPT_EOL: 20448b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy return 1; 20548b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy case TCPOPT_NOP: 20648b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy optoff++; 20748b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy continue; 20848b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy default: 20948b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy if (optoff + 1 == optend || 21048b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy optoff + op[1] > optend || 21148b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy op[1] < 2) 21248b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy return 0; 21348b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy if (op[0] == TCPOPT_TIMESTAMP && 21448b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy op[1] == TCPOLEN_TIMESTAMP) { 21548b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy if (CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY) { 21648b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy ptr = (u32 *)&op[2]; 21748b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy old = *ptr; 21848b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy *ptr = htonl(ntohl(*ptr) - 21948b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy synproxy->tsoff); 22048b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy } else { 22148b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy ptr = (u32 *)&op[6]; 22248b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy old = *ptr; 22348b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy *ptr = htonl(ntohl(*ptr) + 22448b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy synproxy->tsoff); 22548b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy } 22648b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy inet_proto_csum_replace4(&th->check, skb, 22748b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy old, *ptr, 0); 22848b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy return 1; 22948b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy } 23048b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy optoff += op[1]; 23148b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy } 23248b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy } 23348b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy return 1; 23448b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy} 23548b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardyEXPORT_SYMBOL_GPL(synproxy_tstamp_adjust); 23648b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 23748b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardystatic struct nf_ct_ext_type nf_ct_synproxy_extend __read_mostly = { 23848b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy .len = sizeof(struct nf_conn_synproxy), 23948b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy .align = __alignof__(struct nf_conn_synproxy), 24048b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy .id = NF_CT_EXT_SYNPROXY, 24148b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy}; 24248b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 24348b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy#ifdef CONFIG_PROC_FS 24448b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardystatic void *synproxy_cpu_seq_start(struct seq_file *seq, loff_t *pos) 24548b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy{ 24648b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy struct synproxy_net *snet = synproxy_pernet(seq_file_net(seq)); 24748b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy int cpu; 24848b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 24948b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy if (*pos == 0) 25048b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy return SEQ_START_TOKEN; 25148b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 25248b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy for (cpu = *pos - 1; cpu < nr_cpu_ids; cpu++) { 25348b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy if (!cpu_possible(cpu)) 25448b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy continue; 25548b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy *pos = cpu + 1; 25648b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy return per_cpu_ptr(snet->stats, cpu); 25748b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy } 25848b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 25948b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy return NULL; 26048b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy} 26148b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 26248b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardystatic void *synproxy_cpu_seq_next(struct seq_file *seq, void *v, loff_t *pos) 26348b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy{ 26448b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy struct synproxy_net *snet = synproxy_pernet(seq_file_net(seq)); 26548b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy int cpu; 26648b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 26748b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy for (cpu = *pos; cpu < nr_cpu_ids; cpu++) { 26848b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy if (!cpu_possible(cpu)) 26948b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy continue; 27048b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy *pos = cpu + 1; 27148b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy return per_cpu_ptr(snet->stats, cpu); 27248b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy } 27348b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 27448b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy return NULL; 27548b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy} 27648b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 27748b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardystatic void synproxy_cpu_seq_stop(struct seq_file *seq, void *v) 27848b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy{ 27948b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy return; 28048b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy} 28148b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 28248b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardystatic int synproxy_cpu_seq_show(struct seq_file *seq, void *v) 28348b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy{ 28448b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy struct synproxy_stats *stats = v; 28548b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 28648b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy if (v == SEQ_START_TOKEN) { 28748b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy seq_printf(seq, "entries\t\tsyn_received\t" 28848b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy "cookie_invalid\tcookie_valid\t" 28948b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy "cookie_retrans\tconn_reopened\n"); 29048b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy return 0; 29148b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy } 29248b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 29348b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy seq_printf(seq, "%08x\t%08x\t%08x\t%08x\t%08x\t%08x\n", 0, 29448b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy stats->syn_received, 29548b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy stats->cookie_invalid, 29648b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy stats->cookie_valid, 29748b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy stats->cookie_retrans, 29848b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy stats->conn_reopened); 29948b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 30048b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy return 0; 30148b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy} 30248b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 30348b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardystatic const struct seq_operations synproxy_cpu_seq_ops = { 30448b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy .start = synproxy_cpu_seq_start, 30548b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy .next = synproxy_cpu_seq_next, 30648b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy .stop = synproxy_cpu_seq_stop, 30748b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy .show = synproxy_cpu_seq_show, 30848b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy}; 30948b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 31048b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardystatic int synproxy_cpu_seq_open(struct inode *inode, struct file *file) 31148b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy{ 31248b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy return seq_open_net(inode, file, &synproxy_cpu_seq_ops, 31348b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy sizeof(struct seq_net_private)); 31448b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy} 31548b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 31648b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardystatic const struct file_operations synproxy_cpu_seq_fops = { 31748b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy .owner = THIS_MODULE, 31848b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy .open = synproxy_cpu_seq_open, 31948b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy .read = seq_read, 32048b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy .llseek = seq_lseek, 32148b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy .release = seq_release_net, 32248b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy}; 32348b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 32448b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardystatic int __net_init synproxy_proc_init(struct net *net) 32548b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy{ 32648b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy if (!proc_create("synproxy", S_IRUGO, net->proc_net_stat, 32748b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy &synproxy_cpu_seq_fops)) 32848b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy return -ENOMEM; 32948b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy return 0; 33048b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy} 33148b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 33248b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardystatic void __net_exit synproxy_proc_exit(struct net *net) 33348b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy{ 33448b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy remove_proc_entry("synproxy", net->proc_net_stat); 33548b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy} 33648b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy#else 33748b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardystatic int __net_init synproxy_proc_init(struct net *net) 33848b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy{ 33948b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy return 0; 34048b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy} 34148b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 34248b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardystatic void __net_exit synproxy_proc_exit(struct net *net) 34348b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy{ 34448b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy return; 34548b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy} 34648b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy#endif /* CONFIG_PROC_FS */ 34748b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 34848b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardystatic int __net_init synproxy_net_init(struct net *net) 34948b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy{ 35048b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy struct synproxy_net *snet = synproxy_pernet(net); 35148b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy struct nf_conntrack_tuple t; 35248b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy struct nf_conn *ct; 35348b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy int err = -ENOMEM; 35448b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 35548b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy memset(&t, 0, sizeof(t)); 35648b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy ct = nf_conntrack_alloc(net, 0, &t, &t, GFP_KERNEL); 35748b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy if (IS_ERR(ct)) { 35848b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy err = PTR_ERR(ct); 35948b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy goto err1; 36048b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy } 36148b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 36248b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy if (!nfct_seqadj_ext_add(ct)) 36348b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy goto err2; 36448b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy if (!nfct_synproxy_ext_add(ct)) 36548b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy goto err2; 36648b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 367e53376bef2cd97d3e3f61fdc677fb8da7d03d0daPablo Neira Ayuso nf_conntrack_tmpl_insert(net, ct); 36848b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy snet->tmpl = ct; 36948b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 37048b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy snet->stats = alloc_percpu(struct synproxy_stats); 37148b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy if (snet->stats == NULL) 37248b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy goto err2; 37348b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 37448b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy err = synproxy_proc_init(net); 37548b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy if (err < 0) 37648b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy goto err3; 37748b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 37848b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy return 0; 37948b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 38048b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardyerr3: 38148b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy free_percpu(snet->stats); 38248b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardyerr2: 38348b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy nf_conntrack_free(ct); 38448b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardyerr1: 38548b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy return err; 38648b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy} 38748b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 38848b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardystatic void __net_exit synproxy_net_exit(struct net *net) 38948b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy{ 39048b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy struct synproxy_net *snet = synproxy_pernet(net); 39148b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 392e53376bef2cd97d3e3f61fdc677fb8da7d03d0daPablo Neira Ayuso nf_ct_put(snet->tmpl); 39348b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy synproxy_proc_exit(net); 39448b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy free_percpu(snet->stats); 39548b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy} 39648b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 39748b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardystatic struct pernet_operations synproxy_net_ops = { 39848b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy .init = synproxy_net_init, 39948b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy .exit = synproxy_net_exit, 40048b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy .id = &synproxy_net_id, 40148b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy .size = sizeof(struct synproxy_net), 40248b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy}; 40348b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 40448b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardystatic int __init synproxy_core_init(void) 40548b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy{ 40648b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy int err; 40748b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 40848b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy err = nf_ct_extend_register(&nf_ct_synproxy_extend); 40948b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy if (err < 0) 41048b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy goto err1; 41148b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 41248b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy err = register_pernet_subsys(&synproxy_net_ops); 41348b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy if (err < 0) 41448b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy goto err2; 41548b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 41648b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy return 0; 41748b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 41848b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardyerr2: 41948b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy nf_ct_extend_unregister(&nf_ct_synproxy_extend); 42048b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardyerr1: 42148b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy return err; 42248b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy} 42348b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 42448b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardystatic void __exit synproxy_core_exit(void) 42548b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy{ 42648b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy unregister_pernet_subsys(&synproxy_net_ops); 42748b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy nf_ct_extend_unregister(&nf_ct_synproxy_extend); 42848b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy} 42948b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 43048b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardymodule_init(synproxy_core_init); 43148b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardymodule_exit(synproxy_core_exit); 43248b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardy 43348b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardyMODULE_LICENSE("GPL"); 43448b1de4c110a7afa4b85862f6c75af817db26fadPatrick McHardyMODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); 435